radv: don't leak the fd if radv_physical_device_init() succeeds
[mesa.git] / src / amd / vulkan / radv_device.c
1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * IN THE SOFTWARE.
26 */
27
28 #include <dlfcn.h>
29 #include <stdbool.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <sys/stat.h>
34 #include "radv_private.h"
35 #include "util/strtod.h"
36
37 #include <xf86drm.h>
38 #include <amdgpu.h>
39 #include <amdgpu_drm.h>
40 #include "amdgpu_id.h"
41 #include "winsys/amdgpu/radv_amdgpu_winsys_public.h"
42 #include "ac_llvm_util.h"
43 #include "vk_format.h"
44 #include "sid.h"
45 #include "util/debug.h"
46 struct radv_dispatch_table dtable;
47
48 static int
49 radv_get_function_timestamp(void *ptr, uint32_t* timestamp)
50 {
51 Dl_info info;
52 struct stat st;
53 if (!dladdr(ptr, &info) || !info.dli_fname) {
54 return -1;
55 }
56 if (stat(info.dli_fname, &st)) {
57 return -1;
58 }
59 *timestamp = st.st_mtim.tv_sec;
60 return 0;
61 }
62
63 static int
64 radv_device_get_cache_uuid(enum radeon_family family, void *uuid)
65 {
66 uint32_t mesa_timestamp, llvm_timestamp;
67 uint16_t f = family;
68 memset(uuid, 0, VK_UUID_SIZE);
69 if (radv_get_function_timestamp(radv_device_get_cache_uuid, &mesa_timestamp) ||
70 radv_get_function_timestamp(LLVMInitializeAMDGPUTargetInfo, &llvm_timestamp))
71 return -1;
72
73 memcpy(uuid, &mesa_timestamp, 4);
74 memcpy((char*)uuid + 4, &llvm_timestamp, 4);
75 memcpy((char*)uuid + 8, &f, 2);
76 snprintf((char*)uuid + 10, VK_UUID_SIZE - 10, "radv");
77 return 0;
78 }
79
80 static VkResult
81 radv_physical_device_init(struct radv_physical_device *device,
82 struct radv_instance *instance,
83 const char *path)
84 {
85 VkResult result;
86 drmVersionPtr version;
87 int fd;
88
89 fd = open(path, O_RDWR | O_CLOEXEC);
90 if (fd < 0)
91 return vk_errorf(VK_ERROR_INCOMPATIBLE_DRIVER,
92 "failed to open %s: %m", path);
93
94 version = drmGetVersion(fd);
95 if (!version) {
96 close(fd);
97 return vk_errorf(VK_ERROR_INCOMPATIBLE_DRIVER,
98 "failed to get version %s: %m", path);
99 }
100
101 if (strcmp(version->name, "amdgpu")) {
102 drmFreeVersion(version);
103 close(fd);
104 return VK_ERROR_INCOMPATIBLE_DRIVER;
105 }
106 drmFreeVersion(version);
107
108 device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
109 device->instance = instance;
110 assert(strlen(path) < ARRAY_SIZE(device->path));
111 strncpy(device->path, path, ARRAY_SIZE(device->path));
112
113 device->ws = radv_amdgpu_winsys_create(fd);
114 if (!device->ws) {
115 result = VK_ERROR_INCOMPATIBLE_DRIVER;
116 goto fail;
117 }
118 device->ws->query_info(device->ws, &device->rad_info);
119 result = radv_init_wsi(device);
120 if (result != VK_SUCCESS) {
121 device->ws->destroy(device->ws);
122 goto fail;
123 }
124
125 if (radv_device_get_cache_uuid(device->rad_info.family, device->uuid)) {
126 radv_finish_wsi(device);
127 device->ws->destroy(device->ws);
128 goto fail;
129 }
130
131 fprintf(stderr, "WARNING: radv is not a conformant vulkan implementation, testing use only.\n");
132 device->name = device->rad_info.name;
133 close(fd);
134 return VK_SUCCESS;
135
136 fail:
137 close(fd);
138 return result;
139 }
140
141 static void
142 radv_physical_device_finish(struct radv_physical_device *device)
143 {
144 radv_finish_wsi(device);
145 device->ws->destroy(device->ws);
146 }
147
148 static const VkExtensionProperties global_extensions[] = {
149 {
150 .extensionName = VK_KHR_SURFACE_EXTENSION_NAME,
151 .specVersion = 25,
152 },
153 #ifdef VK_USE_PLATFORM_XCB_KHR
154 {
155 .extensionName = VK_KHR_XCB_SURFACE_EXTENSION_NAME,
156 .specVersion = 6,
157 },
158 #endif
159 #ifdef VK_USE_PLATFORM_XLIB_KHR
160 {
161 .extensionName = VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
162 .specVersion = 6,
163 },
164 #endif
165 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
166 {
167 .extensionName = VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
168 .specVersion = 5,
169 },
170 #endif
171 };
172
173 static const VkExtensionProperties device_extensions[] = {
174 {
175 .extensionName = VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,
176 .specVersion = 1,
177 },
178 {
179 .extensionName = VK_KHR_SWAPCHAIN_EXTENSION_NAME,
180 .specVersion = 68,
181 },
182 {
183 .extensionName = VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME,
184 .specVersion = 1,
185 },
186 {
187 .extensionName = VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME,
188 .specVersion = 1,
189 },
190 };
191
192 static void *
193 default_alloc_func(void *pUserData, size_t size, size_t align,
194 VkSystemAllocationScope allocationScope)
195 {
196 return malloc(size);
197 }
198
199 static void *
200 default_realloc_func(void *pUserData, void *pOriginal, size_t size,
201 size_t align, VkSystemAllocationScope allocationScope)
202 {
203 return realloc(pOriginal, size);
204 }
205
206 static void
207 default_free_func(void *pUserData, void *pMemory)
208 {
209 free(pMemory);
210 }
211
212 static const VkAllocationCallbacks default_alloc = {
213 .pUserData = NULL,
214 .pfnAllocation = default_alloc_func,
215 .pfnReallocation = default_realloc_func,
216 .pfnFree = default_free_func,
217 };
218
219 VkResult radv_CreateInstance(
220 const VkInstanceCreateInfo* pCreateInfo,
221 const VkAllocationCallbacks* pAllocator,
222 VkInstance* pInstance)
223 {
224 struct radv_instance *instance;
225
226 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
227
228 uint32_t client_version;
229 if (pCreateInfo->pApplicationInfo &&
230 pCreateInfo->pApplicationInfo->apiVersion != 0) {
231 client_version = pCreateInfo->pApplicationInfo->apiVersion;
232 } else {
233 client_version = VK_MAKE_VERSION(1, 0, 0);
234 }
235
236 if (VK_MAKE_VERSION(1, 0, 0) > client_version ||
237 client_version > VK_MAKE_VERSION(1, 0, 0xfff)) {
238 return vk_errorf(VK_ERROR_INCOMPATIBLE_DRIVER,
239 "Client requested version %d.%d.%d",
240 VK_VERSION_MAJOR(client_version),
241 VK_VERSION_MINOR(client_version),
242 VK_VERSION_PATCH(client_version));
243 }
244
245 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
246 bool found = false;
247 for (uint32_t j = 0; j < ARRAY_SIZE(global_extensions); j++) {
248 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
249 global_extensions[j].extensionName) == 0) {
250 found = true;
251 break;
252 }
253 }
254 if (!found)
255 return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
256 }
257
258 instance = vk_alloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
259 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
260 if (!instance)
261 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
262
263 instance->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
264
265 if (pAllocator)
266 instance->alloc = *pAllocator;
267 else
268 instance->alloc = default_alloc;
269
270 instance->apiVersion = client_version;
271 instance->physicalDeviceCount = -1;
272
273 _mesa_locale_init();
274
275 VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
276
277 *pInstance = radv_instance_to_handle(instance);
278
279 return VK_SUCCESS;
280 }
281
282 void radv_DestroyInstance(
283 VkInstance _instance,
284 const VkAllocationCallbacks* pAllocator)
285 {
286 RADV_FROM_HANDLE(radv_instance, instance, _instance);
287
288 if (instance->physicalDeviceCount > 0) {
289 /* We support at most one physical device. */
290 assert(instance->physicalDeviceCount == 1);
291 radv_physical_device_finish(&instance->physicalDevice);
292 }
293
294 VG(VALGRIND_DESTROY_MEMPOOL(instance));
295
296 _mesa_locale_fini();
297
298 vk_free(&instance->alloc, instance);
299 }
300
301 VkResult radv_EnumeratePhysicalDevices(
302 VkInstance _instance,
303 uint32_t* pPhysicalDeviceCount,
304 VkPhysicalDevice* pPhysicalDevices)
305 {
306 RADV_FROM_HANDLE(radv_instance, instance, _instance);
307 VkResult result;
308
309 if (instance->physicalDeviceCount < 0) {
310 char path[20];
311 for (unsigned i = 0; i < 8; i++) {
312 snprintf(path, sizeof(path), "/dev/dri/renderD%d", 128 + i);
313 result = radv_physical_device_init(&instance->physicalDevice,
314 instance, path);
315 if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
316 break;
317 }
318
319 if (result == VK_ERROR_INCOMPATIBLE_DRIVER) {
320 instance->physicalDeviceCount = 0;
321 } else if (result == VK_SUCCESS) {
322 instance->physicalDeviceCount = 1;
323 } else {
324 return result;
325 }
326 }
327
328 /* pPhysicalDeviceCount is an out parameter if pPhysicalDevices is NULL;
329 * otherwise it's an inout parameter.
330 *
331 * The Vulkan spec (git aaed022) says:
332 *
333 * pPhysicalDeviceCount is a pointer to an unsigned integer variable
334 * that is initialized with the number of devices the application is
335 * prepared to receive handles to. pname:pPhysicalDevices is pointer to
336 * an array of at least this many VkPhysicalDevice handles [...].
337 *
338 * Upon success, if pPhysicalDevices is NULL, vkEnumeratePhysicalDevices
339 * overwrites the contents of the variable pointed to by
340 * pPhysicalDeviceCount with the number of physical devices in in the
341 * instance; otherwise, vkEnumeratePhysicalDevices overwrites
342 * pPhysicalDeviceCount with the number of physical handles written to
343 * pPhysicalDevices.
344 */
345 if (!pPhysicalDevices) {
346 *pPhysicalDeviceCount = instance->physicalDeviceCount;
347 } else if (*pPhysicalDeviceCount >= 1) {
348 pPhysicalDevices[0] = radv_physical_device_to_handle(&instance->physicalDevice);
349 *pPhysicalDeviceCount = 1;
350 } else if (*pPhysicalDeviceCount < instance->physicalDeviceCount) {
351 return VK_INCOMPLETE;
352 } else {
353 *pPhysicalDeviceCount = 0;
354 }
355
356 return VK_SUCCESS;
357 }
358
359 void radv_GetPhysicalDeviceFeatures(
360 VkPhysicalDevice physicalDevice,
361 VkPhysicalDeviceFeatures* pFeatures)
362 {
363 // RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice);
364
365 memset(pFeatures, 0, sizeof(*pFeatures));
366
367 *pFeatures = (VkPhysicalDeviceFeatures) {
368 .robustBufferAccess = true,
369 .fullDrawIndexUint32 = true,
370 .imageCubeArray = true,
371 .independentBlend = true,
372 .geometryShader = false,
373 .tessellationShader = false,
374 .sampleRateShading = false,
375 .dualSrcBlend = true,
376 .logicOp = true,
377 .multiDrawIndirect = true,
378 .drawIndirectFirstInstance = true,
379 .depthClamp = true,
380 .depthBiasClamp = true,
381 .fillModeNonSolid = true,
382 .depthBounds = true,
383 .wideLines = true,
384 .largePoints = true,
385 .alphaToOne = true,
386 .multiViewport = false,
387 .samplerAnisotropy = true,
388 .textureCompressionETC2 = false,
389 .textureCompressionASTC_LDR = false,
390 .textureCompressionBC = true,
391 .occlusionQueryPrecise = true,
392 .pipelineStatisticsQuery = false,
393 .vertexPipelineStoresAndAtomics = true,
394 .fragmentStoresAndAtomics = true,
395 .shaderTessellationAndGeometryPointSize = true,
396 .shaderImageGatherExtended = false,
397 .shaderStorageImageExtendedFormats = false,
398 .shaderStorageImageMultisample = false,
399 .shaderUniformBufferArrayDynamicIndexing = true,
400 .shaderSampledImageArrayDynamicIndexing = true,
401 .shaderStorageBufferArrayDynamicIndexing = true,
402 .shaderStorageImageArrayDynamicIndexing = true,
403 .shaderStorageImageReadWithoutFormat = false,
404 .shaderStorageImageWriteWithoutFormat = true,
405 .shaderClipDistance = true,
406 .shaderCullDistance = true,
407 .shaderFloat64 = false,
408 .shaderInt64 = false,
409 .shaderInt16 = false,
410 .alphaToOne = true,
411 .variableMultisampleRate = false,
412 .inheritedQueries = false,
413 };
414 }
415
416 void radv_GetPhysicalDeviceProperties(
417 VkPhysicalDevice physicalDevice,
418 VkPhysicalDeviceProperties* pProperties)
419 {
420 RADV_FROM_HANDLE(radv_physical_device, pdevice, physicalDevice);
421 VkSampleCountFlags sample_counts = 0xf;
422 VkPhysicalDeviceLimits limits = {
423 .maxImageDimension1D = (1 << 14),
424 .maxImageDimension2D = (1 << 14),
425 .maxImageDimension3D = (1 << 11),
426 .maxImageDimensionCube = (1 << 14),
427 .maxImageArrayLayers = (1 << 11),
428 .maxTexelBufferElements = 128 * 1024 * 1024,
429 .maxUniformBufferRange = UINT32_MAX,
430 .maxStorageBufferRange = UINT32_MAX,
431 .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
432 .maxMemoryAllocationCount = UINT32_MAX,
433 .maxSamplerAllocationCount = 64 * 1024,
434 .bufferImageGranularity = 64, /* A cache line */
435 .sparseAddressSpaceSize = 0,
436 .maxBoundDescriptorSets = MAX_SETS,
437 .maxPerStageDescriptorSamplers = 64,
438 .maxPerStageDescriptorUniformBuffers = 64,
439 .maxPerStageDescriptorStorageBuffers = 64,
440 .maxPerStageDescriptorSampledImages = 64,
441 .maxPerStageDescriptorStorageImages = 64,
442 .maxPerStageDescriptorInputAttachments = 64,
443 .maxPerStageResources = 128,
444 .maxDescriptorSetSamplers = 256,
445 .maxDescriptorSetUniformBuffers = 256,
446 .maxDescriptorSetUniformBuffersDynamic = 256,
447 .maxDescriptorSetStorageBuffers = 256,
448 .maxDescriptorSetStorageBuffersDynamic = 256,
449 .maxDescriptorSetSampledImages = 256,
450 .maxDescriptorSetStorageImages = 256,
451 .maxDescriptorSetInputAttachments = 256,
452 .maxVertexInputAttributes = 32,
453 .maxVertexInputBindings = 32,
454 .maxVertexInputAttributeOffset = 2047,
455 .maxVertexInputBindingStride = 2048,
456 .maxVertexOutputComponents = 128,
457 .maxTessellationGenerationLevel = 0,
458 .maxTessellationPatchSize = 0,
459 .maxTessellationControlPerVertexInputComponents = 0,
460 .maxTessellationControlPerVertexOutputComponents = 0,
461 .maxTessellationControlPerPatchOutputComponents = 0,
462 .maxTessellationControlTotalOutputComponents = 0,
463 .maxTessellationEvaluationInputComponents = 0,
464 .maxTessellationEvaluationOutputComponents = 0,
465 .maxGeometryShaderInvocations = 32,
466 .maxGeometryInputComponents = 64,
467 .maxGeometryOutputComponents = 128,
468 .maxGeometryOutputVertices = 256,
469 .maxGeometryTotalOutputComponents = 1024,
470 .maxFragmentInputComponents = 128,
471 .maxFragmentOutputAttachments = 8,
472 .maxFragmentDualSrcAttachments = 2,
473 .maxFragmentCombinedOutputResources = 8,
474 .maxComputeSharedMemorySize = 32768,
475 .maxComputeWorkGroupCount = { 65535, 65535, 65535 },
476 .maxComputeWorkGroupInvocations = 16 * 1024,
477 .maxComputeWorkGroupSize = {
478 16 * 1024/*devinfo->max_cs_threads*/,
479 16 * 1024,
480 16 * 1024
481 },
482 .subPixelPrecisionBits = 4 /* FIXME */,
483 .subTexelPrecisionBits = 4 /* FIXME */,
484 .mipmapPrecisionBits = 4 /* FIXME */,
485 .maxDrawIndexedIndexValue = UINT32_MAX,
486 .maxDrawIndirectCount = UINT32_MAX,
487 .maxSamplerLodBias = 16,
488 .maxSamplerAnisotropy = 16,
489 .maxViewports = MAX_VIEWPORTS,
490 .maxViewportDimensions = { (1 << 14), (1 << 14) },
491 .viewportBoundsRange = { INT16_MIN, INT16_MAX },
492 .viewportSubPixelBits = 13, /* We take a float? */
493 .minMemoryMapAlignment = 4096, /* A page */
494 .minTexelBufferOffsetAlignment = 1,
495 .minUniformBufferOffsetAlignment = 4,
496 .minStorageBufferOffsetAlignment = 4,
497 .minTexelOffset = -8,
498 .maxTexelOffset = 7,
499 .minTexelGatherOffset = -8,
500 .maxTexelGatherOffset = 7,
501 .minInterpolationOffset = 0, /* FIXME */
502 .maxInterpolationOffset = 0, /* FIXME */
503 .subPixelInterpolationOffsetBits = 0, /* FIXME */
504 .maxFramebufferWidth = (1 << 14),
505 .maxFramebufferHeight = (1 << 14),
506 .maxFramebufferLayers = (1 << 10),
507 .framebufferColorSampleCounts = sample_counts,
508 .framebufferDepthSampleCounts = sample_counts,
509 .framebufferStencilSampleCounts = sample_counts,
510 .framebufferNoAttachmentsSampleCounts = sample_counts,
511 .maxColorAttachments = MAX_RTS,
512 .sampledImageColorSampleCounts = sample_counts,
513 .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,
514 .sampledImageDepthSampleCounts = sample_counts,
515 .sampledImageStencilSampleCounts = sample_counts,
516 .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,
517 .maxSampleMaskWords = 1,
518 .timestampComputeAndGraphics = false,
519 .timestampPeriod = 100000.0 / pdevice->rad_info.clock_crystal_freq,
520 .maxClipDistances = 8,
521 .maxCullDistances = 8,
522 .maxCombinedClipAndCullDistances = 8,
523 .discreteQueuePriorities = 1,
524 .pointSizeRange = { 0.125, 255.875 },
525 .lineWidthRange = { 0.0, 7.9921875 },
526 .pointSizeGranularity = (1.0 / 8.0),
527 .lineWidthGranularity = (1.0 / 128.0),
528 .strictLines = false, /* FINISHME */
529 .standardSampleLocations = true,
530 .optimalBufferCopyOffsetAlignment = 128,
531 .optimalBufferCopyRowPitchAlignment = 128,
532 .nonCoherentAtomSize = 64,
533 };
534
535 *pProperties = (VkPhysicalDeviceProperties) {
536 .apiVersion = VK_MAKE_VERSION(1, 0, 5),
537 .driverVersion = 1,
538 .vendorID = 0x1002,
539 .deviceID = pdevice->rad_info.pci_id,
540 .deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
541 .limits = limits,
542 .sparseProperties = {0}, /* Broadwell doesn't do sparse. */
543 };
544
545 strcpy(pProperties->deviceName, pdevice->name);
546 memcpy(pProperties->pipelineCacheUUID, pdevice->uuid, VK_UUID_SIZE);
547 }
548
549 void radv_GetPhysicalDeviceQueueFamilyProperties(
550 VkPhysicalDevice physicalDevice,
551 uint32_t* pCount,
552 VkQueueFamilyProperties* pQueueFamilyProperties)
553 {
554 if (pQueueFamilyProperties == NULL) {
555 *pCount = 1;
556 return;
557 }
558 assert(*pCount >= 1);
559
560 *pQueueFamilyProperties = (VkQueueFamilyProperties) {
561 .queueFlags = VK_QUEUE_GRAPHICS_BIT |
562 VK_QUEUE_COMPUTE_BIT |
563 VK_QUEUE_TRANSFER_BIT,
564 .queueCount = 1,
565 .timestampValidBits = 64,
566 .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 },
567 };
568 }
569
570 void radv_GetPhysicalDeviceMemoryProperties(
571 VkPhysicalDevice physicalDevice,
572 VkPhysicalDeviceMemoryProperties* pMemoryProperties)
573 {
574 RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);
575
576 pMemoryProperties->memoryTypeCount = 4;
577 pMemoryProperties->memoryTypes[0] = (VkMemoryType) {
578 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
579 .heapIndex = 0,
580 };
581 pMemoryProperties->memoryTypes[1] = (VkMemoryType) {
582 .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
583 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
584 .heapIndex = 2,
585 };
586 pMemoryProperties->memoryTypes[2] = (VkMemoryType) {
587 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
588 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
589 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
590 .heapIndex = 1,
591 };
592 pMemoryProperties->memoryTypes[3] = (VkMemoryType) {
593 .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
594 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
595 VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
596 .heapIndex = 2,
597 };
598
599 pMemoryProperties->memoryHeapCount = 3;
600 pMemoryProperties->memoryHeaps[0] = (VkMemoryHeap) {
601 .size = physical_device->rad_info.vram_size -
602 physical_device->rad_info.visible_vram_size,
603 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
604 };
605 pMemoryProperties->memoryHeaps[1] = (VkMemoryHeap) {
606 .size = physical_device->rad_info.visible_vram_size,
607 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
608 };
609 pMemoryProperties->memoryHeaps[2] = (VkMemoryHeap) {
610 .size = physical_device->rad_info.gart_size,
611 .flags = 0,
612 };
613 }
614
615 static void
616 radv_queue_init(struct radv_device *device, struct radv_queue *queue)
617 {
618 queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
619 queue->device = device;
620 }
621
622 static void
623 radv_queue_finish(struct radv_queue *queue)
624 {
625 }
626
627 VkResult radv_CreateDevice(
628 VkPhysicalDevice physicalDevice,
629 const VkDeviceCreateInfo* pCreateInfo,
630 const VkAllocationCallbacks* pAllocator,
631 VkDevice* pDevice)
632 {
633 RADV_FROM_HANDLE(radv_physical_device, physical_device, physicalDevice);
634 VkResult result;
635 struct radv_device *device;
636
637 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
638 bool found = false;
639 for (uint32_t j = 0; j < ARRAY_SIZE(device_extensions); j++) {
640 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
641 device_extensions[j].extensionName) == 0) {
642 found = true;
643 break;
644 }
645 }
646 if (!found)
647 return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
648 }
649
650 device = vk_alloc2(&physical_device->instance->alloc, pAllocator,
651 sizeof(*device), 8,
652 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
653 if (!device)
654 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
655
656 device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
657 device->instance = physical_device->instance;
658
659 device->ws = physical_device->ws;
660 if (pAllocator)
661 device->alloc = *pAllocator;
662 else
663 device->alloc = physical_device->instance->alloc;
664
665 device->hw_ctx = device->ws->ctx_create(device->ws);
666 if (!device->hw_ctx) {
667 result = VK_ERROR_OUT_OF_HOST_MEMORY;
668 goto fail_free;
669 }
670
671 radv_queue_init(device, &device->queue);
672
673 result = radv_device_init_meta(device);
674 if (result != VK_SUCCESS) {
675 device->ws->ctx_destroy(device->hw_ctx);
676 goto fail_free;
677 }
678 device->allow_fast_clears = env_var_as_boolean("RADV_FAST_CLEARS", false);
679 device->allow_dcc = !env_var_as_boolean("RADV_DCC_DISABLE", false);
680 device->shader_stats_dump = env_var_as_boolean("RADV_SHADER_STATS", false);
681
682 if (device->allow_fast_clears && device->allow_dcc)
683 radv_finishme("DCC fast clears have not been tested\n");
684
685 radv_device_init_msaa(device);
686 device->empty_cs = device->ws->cs_create(device->ws, RING_GFX);
687 radeon_emit(device->empty_cs, PKT3(PKT3_CONTEXT_CONTROL, 1, 0));
688 radeon_emit(device->empty_cs, CONTEXT_CONTROL_LOAD_ENABLE(1));
689 radeon_emit(device->empty_cs, CONTEXT_CONTROL_SHADOW_ENABLE(1));
690 device->ws->cs_finalize(device->empty_cs);
691 *pDevice = radv_device_to_handle(device);
692 return VK_SUCCESS;
693 fail_free:
694 vk_free(&device->alloc, device);
695 return result;
696 }
697
698 void radv_DestroyDevice(
699 VkDevice _device,
700 const VkAllocationCallbacks* pAllocator)
701 {
702 RADV_FROM_HANDLE(radv_device, device, _device);
703
704 device->ws->ctx_destroy(device->hw_ctx);
705 radv_queue_finish(&device->queue);
706 radv_device_finish_meta(device);
707
708 vk_free(&device->alloc, device);
709 }
710
711 VkResult radv_EnumerateInstanceExtensionProperties(
712 const char* pLayerName,
713 uint32_t* pPropertyCount,
714 VkExtensionProperties* pProperties)
715 {
716 if (pProperties == NULL) {
717 *pPropertyCount = ARRAY_SIZE(global_extensions);
718 return VK_SUCCESS;
719 }
720
721 *pPropertyCount = MIN2(*pPropertyCount, ARRAY_SIZE(global_extensions));
722 typed_memcpy(pProperties, global_extensions, *pPropertyCount);
723
724 if (*pPropertyCount < ARRAY_SIZE(global_extensions))
725 return VK_INCOMPLETE;
726
727 return VK_SUCCESS;
728 }
729
730 VkResult radv_EnumerateDeviceExtensionProperties(
731 VkPhysicalDevice physicalDevice,
732 const char* pLayerName,
733 uint32_t* pPropertyCount,
734 VkExtensionProperties* pProperties)
735 {
736 if (pProperties == NULL) {
737 *pPropertyCount = ARRAY_SIZE(device_extensions);
738 return VK_SUCCESS;
739 }
740
741 *pPropertyCount = MIN2(*pPropertyCount, ARRAY_SIZE(device_extensions));
742 typed_memcpy(pProperties, device_extensions, *pPropertyCount);
743
744 if (*pPropertyCount < ARRAY_SIZE(device_extensions))
745 return VK_INCOMPLETE;
746
747 return VK_SUCCESS;
748 }
749
750 VkResult radv_EnumerateInstanceLayerProperties(
751 uint32_t* pPropertyCount,
752 VkLayerProperties* pProperties)
753 {
754 if (pProperties == NULL) {
755 *pPropertyCount = 0;
756 return VK_SUCCESS;
757 }
758
759 /* None supported at this time */
760 return vk_error(VK_ERROR_LAYER_NOT_PRESENT);
761 }
762
763 VkResult radv_EnumerateDeviceLayerProperties(
764 VkPhysicalDevice physicalDevice,
765 uint32_t* pPropertyCount,
766 VkLayerProperties* pProperties)
767 {
768 if (pProperties == NULL) {
769 *pPropertyCount = 0;
770 return VK_SUCCESS;
771 }
772
773 /* None supported at this time */
774 return vk_error(VK_ERROR_LAYER_NOT_PRESENT);
775 }
776
777 void radv_GetDeviceQueue(
778 VkDevice _device,
779 uint32_t queueNodeIndex,
780 uint32_t queueIndex,
781 VkQueue* pQueue)
782 {
783 RADV_FROM_HANDLE(radv_device, device, _device);
784
785 assert(queueIndex == 0);
786
787 *pQueue = radv_queue_to_handle(&device->queue);
788 }
789
790 VkResult radv_QueueSubmit(
791 VkQueue _queue,
792 uint32_t submitCount,
793 const VkSubmitInfo* pSubmits,
794 VkFence _fence)
795 {
796 RADV_FROM_HANDLE(radv_queue, queue, _queue);
797 RADV_FROM_HANDLE(radv_fence, fence, _fence);
798 struct radeon_winsys_fence *base_fence = fence ? fence->fence : NULL;
799 struct radeon_winsys_ctx *ctx = queue->device->hw_ctx;
800 int ret;
801
802 for (uint32_t i = 0; i < submitCount; i++) {
803 struct radeon_winsys_cs **cs_array;
804 bool can_patch = true;
805
806 if (!pSubmits[i].commandBufferCount)
807 continue;
808
809 cs_array = malloc(sizeof(struct radeon_winsys_cs *) *
810 pSubmits[i].commandBufferCount);
811
812 for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j++) {
813 RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer,
814 pSubmits[i].pCommandBuffers[j]);
815 assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
816
817 cs_array[j] = cmd_buffer->cs;
818 if ((cmd_buffer->usage_flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT))
819 can_patch = false;
820 }
821 ret = queue->device->ws->cs_submit(ctx, cs_array,
822 pSubmits[i].commandBufferCount,
823 can_patch, base_fence);
824 if (ret)
825 radv_loge("failed to submit CS %d\n", i);
826 free(cs_array);
827 }
828
829 if (fence) {
830 if (!submitCount)
831 ret = queue->device->ws->cs_submit(ctx, &queue->device->empty_cs,
832 1, false, base_fence);
833
834 fence->submitted = true;
835 }
836
837 return VK_SUCCESS;
838 }
839
840 VkResult radv_QueueWaitIdle(
841 VkQueue _queue)
842 {
843 RADV_FROM_HANDLE(radv_queue, queue, _queue);
844
845 queue->device->ws->ctx_wait_idle(queue->device->hw_ctx);
846 return VK_SUCCESS;
847 }
848
849 VkResult radv_DeviceWaitIdle(
850 VkDevice _device)
851 {
852 RADV_FROM_HANDLE(radv_device, device, _device);
853
854 device->ws->ctx_wait_idle(device->hw_ctx);
855 return VK_SUCCESS;
856 }
857
858 PFN_vkVoidFunction radv_GetInstanceProcAddr(
859 VkInstance instance,
860 const char* pName)
861 {
862 return radv_lookup_entrypoint(pName);
863 }
864
865 /* The loader wants us to expose a second GetInstanceProcAddr function
866 * to work around certain LD_PRELOAD issues seen in apps.
867 */
868 PUBLIC
869 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(
870 VkInstance instance,
871 const char* pName);
872
873 PUBLIC
874 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(
875 VkInstance instance,
876 const char* pName)
877 {
878 return radv_GetInstanceProcAddr(instance, pName);
879 }
880
881 PFN_vkVoidFunction radv_GetDeviceProcAddr(
882 VkDevice device,
883 const char* pName)
884 {
885 return radv_lookup_entrypoint(pName);
886 }
887
888 VkResult radv_AllocateMemory(
889 VkDevice _device,
890 const VkMemoryAllocateInfo* pAllocateInfo,
891 const VkAllocationCallbacks* pAllocator,
892 VkDeviceMemory* pMem)
893 {
894 RADV_FROM_HANDLE(radv_device, device, _device);
895 struct radv_device_memory *mem;
896 VkResult result;
897 enum radeon_bo_domain domain;
898 uint32_t flags = 0;
899 assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
900
901 if (pAllocateInfo->allocationSize == 0) {
902 /* Apparently, this is allowed */
903 *pMem = VK_NULL_HANDLE;
904 return VK_SUCCESS;
905 }
906
907 mem = vk_alloc2(&device->alloc, pAllocator, sizeof(*mem), 8,
908 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
909 if (mem == NULL)
910 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
911
912 uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize, 4096);
913 if (pAllocateInfo->memoryTypeIndex == 1 || pAllocateInfo->memoryTypeIndex == 3)
914 domain = RADEON_DOMAIN_GTT;
915 else
916 domain = RADEON_DOMAIN_VRAM;
917
918 if (pAllocateInfo->memoryTypeIndex == 0)
919 flags |= RADEON_FLAG_NO_CPU_ACCESS;
920 else
921 flags |= RADEON_FLAG_CPU_ACCESS;
922
923 if (pAllocateInfo->memoryTypeIndex == 1)
924 flags |= RADEON_FLAG_GTT_WC;
925
926 mem->bo = device->ws->buffer_create(device->ws, alloc_size, 32768,
927 domain, flags);
928
929 if (!mem->bo) {
930 result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
931 goto fail;
932 }
933 mem->type_index = pAllocateInfo->memoryTypeIndex;
934
935 *pMem = radv_device_memory_to_handle(mem);
936
937 return VK_SUCCESS;
938
939 fail:
940 vk_free2(&device->alloc, pAllocator, mem);
941
942 return result;
943 }
944
945 void radv_FreeMemory(
946 VkDevice _device,
947 VkDeviceMemory _mem,
948 const VkAllocationCallbacks* pAllocator)
949 {
950 RADV_FROM_HANDLE(radv_device, device, _device);
951 RADV_FROM_HANDLE(radv_device_memory, mem, _mem);
952
953 if (mem == NULL)
954 return;
955
956 device->ws->buffer_destroy(mem->bo);
957 mem->bo = NULL;
958
959 vk_free2(&device->alloc, pAllocator, mem);
960 }
961
962 VkResult radv_MapMemory(
963 VkDevice _device,
964 VkDeviceMemory _memory,
965 VkDeviceSize offset,
966 VkDeviceSize size,
967 VkMemoryMapFlags flags,
968 void** ppData)
969 {
970 RADV_FROM_HANDLE(radv_device, device, _device);
971 RADV_FROM_HANDLE(radv_device_memory, mem, _memory);
972
973 if (mem == NULL) {
974 *ppData = NULL;
975 return VK_SUCCESS;
976 }
977
978 *ppData = device->ws->buffer_map(mem->bo);
979 if (*ppData) {
980 *ppData += offset;
981 return VK_SUCCESS;
982 }
983
984 return VK_ERROR_MEMORY_MAP_FAILED;
985 }
986
987 void radv_UnmapMemory(
988 VkDevice _device,
989 VkDeviceMemory _memory)
990 {
991 RADV_FROM_HANDLE(radv_device, device, _device);
992 RADV_FROM_HANDLE(radv_device_memory, mem, _memory);
993
994 if (mem == NULL)
995 return;
996
997 device->ws->buffer_unmap(mem->bo);
998 }
999
1000 VkResult radv_FlushMappedMemoryRanges(
1001 VkDevice _device,
1002 uint32_t memoryRangeCount,
1003 const VkMappedMemoryRange* pMemoryRanges)
1004 {
1005 return VK_SUCCESS;
1006 }
1007
1008 VkResult radv_InvalidateMappedMemoryRanges(
1009 VkDevice _device,
1010 uint32_t memoryRangeCount,
1011 const VkMappedMemoryRange* pMemoryRanges)
1012 {
1013 return VK_SUCCESS;
1014 }
1015
1016 void radv_GetBufferMemoryRequirements(
1017 VkDevice device,
1018 VkBuffer _buffer,
1019 VkMemoryRequirements* pMemoryRequirements)
1020 {
1021 RADV_FROM_HANDLE(radv_buffer, buffer, _buffer);
1022
1023 /* The Vulkan spec (git aaed022) says:
1024 *
1025 * memoryTypeBits is a bitfield and contains one bit set for every
1026 * supported memory type for the resource. The bit `1<<i` is set if and
1027 * only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
1028 * structure for the physical device is supported.
1029 *
1030 * We support exactly one memory type.
1031 */
1032 pMemoryRequirements->memoryTypeBits = 0x7;
1033
1034 pMemoryRequirements->size = buffer->size;
1035 pMemoryRequirements->alignment = 16;
1036 }
1037
1038 void radv_GetImageMemoryRequirements(
1039 VkDevice device,
1040 VkImage _image,
1041 VkMemoryRequirements* pMemoryRequirements)
1042 {
1043 RADV_FROM_HANDLE(radv_image, image, _image);
1044
1045 /* The Vulkan spec (git aaed022) says:
1046 *
1047 * memoryTypeBits is a bitfield and contains one bit set for every
1048 * supported memory type for the resource. The bit `1<<i` is set if and
1049 * only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
1050 * structure for the physical device is supported.
1051 *
1052 * We support exactly one memory type.
1053 */
1054 pMemoryRequirements->memoryTypeBits = 0x7;
1055
1056 pMemoryRequirements->size = image->size;
1057 pMemoryRequirements->alignment = image->alignment;
1058 }
1059
1060 void radv_GetImageSparseMemoryRequirements(
1061 VkDevice device,
1062 VkImage image,
1063 uint32_t* pSparseMemoryRequirementCount,
1064 VkSparseImageMemoryRequirements* pSparseMemoryRequirements)
1065 {
1066 stub();
1067 }
1068
1069 void radv_GetDeviceMemoryCommitment(
1070 VkDevice device,
1071 VkDeviceMemory memory,
1072 VkDeviceSize* pCommittedMemoryInBytes)
1073 {
1074 *pCommittedMemoryInBytes = 0;
1075 }
1076
1077 VkResult radv_BindBufferMemory(
1078 VkDevice device,
1079 VkBuffer _buffer,
1080 VkDeviceMemory _memory,
1081 VkDeviceSize memoryOffset)
1082 {
1083 RADV_FROM_HANDLE(radv_device_memory, mem, _memory);
1084 RADV_FROM_HANDLE(radv_buffer, buffer, _buffer);
1085
1086 if (mem) {
1087 buffer->bo = mem->bo;
1088 buffer->offset = memoryOffset;
1089 } else {
1090 buffer->bo = NULL;
1091 buffer->offset = 0;
1092 }
1093
1094 return VK_SUCCESS;
1095 }
1096
1097 VkResult radv_BindImageMemory(
1098 VkDevice device,
1099 VkImage _image,
1100 VkDeviceMemory _memory,
1101 VkDeviceSize memoryOffset)
1102 {
1103 RADV_FROM_HANDLE(radv_device_memory, mem, _memory);
1104 RADV_FROM_HANDLE(radv_image, image, _image);
1105
1106 if (mem) {
1107 image->bo = mem->bo;
1108 image->offset = memoryOffset;
1109 } else {
1110 image->bo = NULL;
1111 image->offset = 0;
1112 }
1113
1114 return VK_SUCCESS;
1115 }
1116
1117 VkResult radv_QueueBindSparse(
1118 VkQueue queue,
1119 uint32_t bindInfoCount,
1120 const VkBindSparseInfo* pBindInfo,
1121 VkFence fence)
1122 {
1123 stub_return(VK_ERROR_INCOMPATIBLE_DRIVER);
1124 }
1125
1126 VkResult radv_CreateFence(
1127 VkDevice _device,
1128 const VkFenceCreateInfo* pCreateInfo,
1129 const VkAllocationCallbacks* pAllocator,
1130 VkFence* pFence)
1131 {
1132 RADV_FROM_HANDLE(radv_device, device, _device);
1133 struct radv_fence *fence = vk_alloc2(&device->alloc, pAllocator,
1134 sizeof(*fence), 8,
1135 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1136
1137 if (!fence)
1138 return VK_ERROR_OUT_OF_HOST_MEMORY;
1139
1140 memset(fence, 0, sizeof(*fence));
1141 fence->submitted = false;
1142 fence->signalled = !!(pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT);
1143 fence->fence = device->ws->create_fence();
1144
1145
1146 *pFence = radv_fence_to_handle(fence);
1147
1148 return VK_SUCCESS;
1149 }
1150
1151 void radv_DestroyFence(
1152 VkDevice _device,
1153 VkFence _fence,
1154 const VkAllocationCallbacks* pAllocator)
1155 {
1156 RADV_FROM_HANDLE(radv_device, device, _device);
1157 RADV_FROM_HANDLE(radv_fence, fence, _fence);
1158
1159 if (!fence)
1160 return;
1161 device->ws->destroy_fence(fence->fence);
1162 vk_free2(&device->alloc, pAllocator, fence);
1163 }
1164
1165 static uint64_t radv_get_absolute_timeout(uint64_t timeout)
1166 {
1167 uint64_t current_time;
1168 struct timespec tv;
1169
1170 clock_gettime(CLOCK_MONOTONIC, &tv);
1171 current_time = tv.tv_nsec + tv.tv_sec*1000000000ull;
1172
1173 timeout = MIN2(UINT64_MAX - current_time, timeout);
1174
1175 return current_time + timeout;
1176 }
1177
1178 VkResult radv_WaitForFences(
1179 VkDevice _device,
1180 uint32_t fenceCount,
1181 const VkFence* pFences,
1182 VkBool32 waitAll,
1183 uint64_t timeout)
1184 {
1185 RADV_FROM_HANDLE(radv_device, device, _device);
1186 timeout = radv_get_absolute_timeout(timeout);
1187
1188 if (!waitAll && fenceCount > 1) {
1189 fprintf(stderr, "radv: WaitForFences without waitAll not implemented yet\n");
1190 }
1191
1192 for (uint32_t i = 0; i < fenceCount; ++i) {
1193 RADV_FROM_HANDLE(radv_fence, fence, pFences[i]);
1194 bool expired = false;
1195
1196 if (fence->signalled)
1197 continue;
1198
1199 if (!fence->submitted)
1200 return VK_TIMEOUT;
1201
1202 expired = device->ws->fence_wait(device->ws, fence->fence, true, timeout);
1203 if (!expired)
1204 return VK_TIMEOUT;
1205
1206 fence->signalled = true;
1207 }
1208
1209 return VK_SUCCESS;
1210 }
1211
1212 VkResult radv_ResetFences(VkDevice device,
1213 uint32_t fenceCount,
1214 const VkFence *pFences)
1215 {
1216 for (unsigned i = 0; i < fenceCount; ++i) {
1217 RADV_FROM_HANDLE(radv_fence, fence, pFences[i]);
1218 fence->submitted = fence->signalled = false;
1219 }
1220
1221 return VK_SUCCESS;
1222 }
1223
1224 VkResult radv_GetFenceStatus(VkDevice _device, VkFence _fence)
1225 {
1226 RADV_FROM_HANDLE(radv_device, device, _device);
1227 RADV_FROM_HANDLE(radv_fence, fence, _fence);
1228
1229 if (fence->signalled)
1230 return VK_SUCCESS;
1231 if (!fence->submitted)
1232 return VK_NOT_READY;
1233
1234 if (!device->ws->fence_wait(device->ws, fence->fence, false, 0))
1235 return VK_NOT_READY;
1236
1237 return VK_SUCCESS;
1238 }
1239
1240
1241 // Queue semaphore functions
1242
1243 VkResult radv_CreateSemaphore(
1244 VkDevice device,
1245 const VkSemaphoreCreateInfo* pCreateInfo,
1246 const VkAllocationCallbacks* pAllocator,
1247 VkSemaphore* pSemaphore)
1248 {
1249 /* The DRM execbuffer ioctl always execute in-oder, even between different
1250 * rings. As such, there's nothing to do for the user space semaphore.
1251 */
1252
1253 *pSemaphore = (VkSemaphore)1;
1254
1255 return VK_SUCCESS;
1256 }
1257
1258 void radv_DestroySemaphore(
1259 VkDevice device,
1260 VkSemaphore semaphore,
1261 const VkAllocationCallbacks* pAllocator)
1262 {
1263 }
1264
1265 VkResult radv_CreateEvent(
1266 VkDevice _device,
1267 const VkEventCreateInfo* pCreateInfo,
1268 const VkAllocationCallbacks* pAllocator,
1269 VkEvent* pEvent)
1270 {
1271 RADV_FROM_HANDLE(radv_device, device, _device);
1272 struct radv_event *event = vk_alloc2(&device->alloc, pAllocator,
1273 sizeof(*event), 8,
1274 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1275
1276 if (!event)
1277 return VK_ERROR_OUT_OF_HOST_MEMORY;
1278
1279 event->bo = device->ws->buffer_create(device->ws, 8, 8,
1280 RADEON_DOMAIN_GTT,
1281 RADEON_FLAG_CPU_ACCESS);
1282 if (!event->bo) {
1283 vk_free2(&device->alloc, pAllocator, event);
1284 return VK_ERROR_OUT_OF_DEVICE_MEMORY;
1285 }
1286
1287 event->map = (uint64_t*)device->ws->buffer_map(event->bo);
1288
1289 *pEvent = radv_event_to_handle(event);
1290
1291 return VK_SUCCESS;
1292 }
1293
1294 void radv_DestroyEvent(
1295 VkDevice _device,
1296 VkEvent _event,
1297 const VkAllocationCallbacks* pAllocator)
1298 {
1299 RADV_FROM_HANDLE(radv_device, device, _device);
1300 RADV_FROM_HANDLE(radv_event, event, _event);
1301
1302 if (!event)
1303 return;
1304 device->ws->buffer_destroy(event->bo);
1305 vk_free2(&device->alloc, pAllocator, event);
1306 }
1307
1308 VkResult radv_GetEventStatus(
1309 VkDevice _device,
1310 VkEvent _event)
1311 {
1312 RADV_FROM_HANDLE(radv_event, event, _event);
1313
1314 if (*event->map == 1)
1315 return VK_EVENT_SET;
1316 return VK_EVENT_RESET;
1317 }
1318
1319 VkResult radv_SetEvent(
1320 VkDevice _device,
1321 VkEvent _event)
1322 {
1323 RADV_FROM_HANDLE(radv_event, event, _event);
1324 *event->map = 1;
1325
1326 return VK_SUCCESS;
1327 }
1328
1329 VkResult radv_ResetEvent(
1330 VkDevice _device,
1331 VkEvent _event)
1332 {
1333 RADV_FROM_HANDLE(radv_event, event, _event);
1334 *event->map = 0;
1335
1336 return VK_SUCCESS;
1337 }
1338
1339 VkResult radv_CreateBuffer(
1340 VkDevice _device,
1341 const VkBufferCreateInfo* pCreateInfo,
1342 const VkAllocationCallbacks* pAllocator,
1343 VkBuffer* pBuffer)
1344 {
1345 RADV_FROM_HANDLE(radv_device, device, _device);
1346 struct radv_buffer *buffer;
1347
1348 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
1349
1350 buffer = vk_alloc2(&device->alloc, pAllocator, sizeof(*buffer), 8,
1351 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1352 if (buffer == NULL)
1353 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
1354
1355 buffer->size = pCreateInfo->size;
1356 buffer->usage = pCreateInfo->usage;
1357 buffer->bo = NULL;
1358 buffer->offset = 0;
1359
1360 *pBuffer = radv_buffer_to_handle(buffer);
1361
1362 return VK_SUCCESS;
1363 }
1364
1365 void radv_DestroyBuffer(
1366 VkDevice _device,
1367 VkBuffer _buffer,
1368 const VkAllocationCallbacks* pAllocator)
1369 {
1370 RADV_FROM_HANDLE(radv_device, device, _device);
1371 RADV_FROM_HANDLE(radv_buffer, buffer, _buffer);
1372
1373 if (!buffer)
1374 return;
1375
1376 vk_free2(&device->alloc, pAllocator, buffer);
1377 }
1378
1379 static inline unsigned
1380 si_tile_mode_index(const struct radv_image *image, unsigned level, bool stencil)
1381 {
1382 if (stencil)
1383 return image->surface.stencil_tiling_index[level];
1384 else
1385 return image->surface.tiling_index[level];
1386 }
1387
1388 static void
1389 radv_initialise_color_surface(struct radv_device *device,
1390 struct radv_color_buffer_info *cb,
1391 struct radv_image_view *iview)
1392 {
1393 const struct vk_format_description *desc;
1394 unsigned ntype, format, swap, endian;
1395 unsigned blend_clamp = 0, blend_bypass = 0;
1396 unsigned pitch_tile_max, slice_tile_max, tile_mode_index;
1397 uint64_t va;
1398 const struct radeon_surf *surf = &iview->image->surface;
1399 const struct radeon_surf_level *level_info = &surf->level[iview->base_mip];
1400
1401 desc = vk_format_description(iview->vk_format);
1402
1403 memset(cb, 0, sizeof(*cb));
1404
1405 va = device->ws->buffer_get_va(iview->bo) + iview->image->offset;
1406 va += level_info->offset;
1407 cb->cb_color_base = va >> 8;
1408
1409 /* CMASK variables */
1410 va = device->ws->buffer_get_va(iview->bo) + iview->image->offset;
1411 va += iview->image->cmask.offset;
1412 cb->cb_color_cmask = va >> 8;
1413 cb->cb_color_cmask_slice = iview->image->cmask.slice_tile_max;
1414
1415 va = device->ws->buffer_get_va(iview->bo) + iview->image->offset;
1416 va += iview->image->dcc_offset;
1417 cb->cb_dcc_base = va >> 8;
1418
1419 cb->cb_color_view = S_028C6C_SLICE_START(iview->base_layer) |
1420 S_028C6C_SLICE_MAX(iview->base_layer + iview->extent.depth - 1);
1421
1422 cb->micro_tile_mode = iview->image->surface.micro_tile_mode;
1423 pitch_tile_max = level_info->nblk_x / 8 - 1;
1424 slice_tile_max = (level_info->nblk_x * level_info->nblk_y) / 64 - 1;
1425 tile_mode_index = si_tile_mode_index(iview->image, iview->base_mip, false);
1426
1427 cb->cb_color_pitch = S_028C64_TILE_MAX(pitch_tile_max);
1428 cb->cb_color_slice = S_028C68_TILE_MAX(slice_tile_max);
1429
1430 /* Intensity is implemented as Red, so treat it that way. */
1431 cb->cb_color_attrib = S_028C74_FORCE_DST_ALPHA_1(desc->swizzle[3] == VK_SWIZZLE_1) |
1432 S_028C74_TILE_MODE_INDEX(tile_mode_index);
1433
1434 if (iview->image->samples > 1) {
1435 unsigned log_samples = util_logbase2(iview->image->samples);
1436
1437 cb->cb_color_attrib |= S_028C74_NUM_SAMPLES(log_samples) |
1438 S_028C74_NUM_FRAGMENTS(log_samples);
1439 }
1440
1441 if (iview->image->fmask.size) {
1442 va = device->ws->buffer_get_va(iview->bo) + iview->image->offset + iview->image->fmask.offset;
1443 if (device->instance->physicalDevice.rad_info.chip_class >= CIK)
1444 cb->cb_color_pitch |= S_028C64_FMASK_TILE_MAX(iview->image->fmask.pitch_in_pixels / 8 - 1);
1445 cb->cb_color_attrib |= S_028C74_FMASK_TILE_MODE_INDEX(iview->image->fmask.tile_mode_index);
1446 cb->cb_color_fmask = va >> 8;
1447 cb->cb_color_fmask_slice = S_028C88_TILE_MAX(iview->image->fmask.slice_tile_max);
1448 } else {
1449 /* This must be set for fast clear to work without FMASK. */
1450 if (device->instance->physicalDevice.rad_info.chip_class >= CIK)
1451 cb->cb_color_pitch |= S_028C64_FMASK_TILE_MAX(pitch_tile_max);
1452 cb->cb_color_attrib |= S_028C74_FMASK_TILE_MODE_INDEX(tile_mode_index);
1453 cb->cb_color_fmask = cb->cb_color_base;
1454 cb->cb_color_fmask_slice = S_028C88_TILE_MAX(slice_tile_max);
1455 }
1456
1457 ntype = radv_translate_color_numformat(iview->vk_format,
1458 desc,
1459 vk_format_get_first_non_void_channel(iview->vk_format));
1460 format = radv_translate_colorformat(iview->vk_format);
1461 if (format == V_028C70_COLOR_INVALID || ntype == ~0u)
1462 radv_finishme("Illegal color\n");
1463 swap = radv_translate_colorswap(iview->vk_format, FALSE);
1464 endian = radv_colorformat_endian_swap(format);
1465
1466 /* blend clamp should be set for all NORM/SRGB types */
1467 if (ntype == V_028C70_NUMBER_UNORM ||
1468 ntype == V_028C70_NUMBER_SNORM ||
1469 ntype == V_028C70_NUMBER_SRGB)
1470 blend_clamp = 1;
1471
1472 /* set blend bypass according to docs if SINT/UINT or
1473 8/24 COLOR variants */
1474 if (ntype == V_028C70_NUMBER_UINT || ntype == V_028C70_NUMBER_SINT ||
1475 format == V_028C70_COLOR_8_24 || format == V_028C70_COLOR_24_8 ||
1476 format == V_028C70_COLOR_X24_8_32_FLOAT) {
1477 blend_clamp = 0;
1478 blend_bypass = 1;
1479 }
1480 #if 0
1481 if ((ntype == V_028C70_NUMBER_UINT || ntype == V_028C70_NUMBER_SINT) &&
1482 (format == V_028C70_COLOR_8 ||
1483 format == V_028C70_COLOR_8_8 ||
1484 format == V_028C70_COLOR_8_8_8_8))
1485 ->color_is_int8 = true;
1486 #endif
1487 cb->cb_color_info = S_028C70_FORMAT(format) |
1488 S_028C70_COMP_SWAP(swap) |
1489 S_028C70_BLEND_CLAMP(blend_clamp) |
1490 S_028C70_BLEND_BYPASS(blend_bypass) |
1491 S_028C70_SIMPLE_FLOAT(1) |
1492 S_028C70_ROUND_MODE(ntype != V_028C70_NUMBER_UNORM &&
1493 ntype != V_028C70_NUMBER_SNORM &&
1494 ntype != V_028C70_NUMBER_SRGB &&
1495 format != V_028C70_COLOR_8_24 &&
1496 format != V_028C70_COLOR_24_8) |
1497 S_028C70_NUMBER_TYPE(ntype) |
1498 S_028C70_ENDIAN(endian);
1499 if (iview->image->samples > 1)
1500 if (iview->image->fmask.size)
1501 cb->cb_color_info |= S_028C70_COMPRESSION(1);
1502
1503 if (iview->image->cmask.size && device->allow_fast_clears)
1504 cb->cb_color_info |= S_028C70_FAST_CLEAR(1);
1505
1506 if (iview->image->surface.dcc_size && level_info->dcc_enabled)
1507 cb->cb_color_info |= S_028C70_DCC_ENABLE(1);
1508
1509 if (device->instance->physicalDevice.rad_info.chip_class >= VI) {
1510 unsigned max_uncompressed_block_size = 2;
1511 if (iview->image->samples > 1) {
1512 if (iview->image->surface.bpe == 1)
1513 max_uncompressed_block_size = 0;
1514 else if (iview->image->surface.bpe == 2)
1515 max_uncompressed_block_size = 1;
1516 }
1517
1518 cb->cb_dcc_control = S_028C78_MAX_UNCOMPRESSED_BLOCK_SIZE(max_uncompressed_block_size) |
1519 S_028C78_INDEPENDENT_64B_BLOCKS(1);
1520 }
1521
1522 /* This must be set for fast clear to work without FMASK. */
1523 if (!iview->image->fmask.size &&
1524 device->instance->physicalDevice.rad_info.chip_class == SI) {
1525 unsigned bankh = util_logbase2(iview->image->surface.bankh);
1526 cb->cb_color_attrib |= S_028C74_FMASK_BANK_HEIGHT(bankh);
1527 }
1528 }
1529
1530 static void
1531 radv_initialise_ds_surface(struct radv_device *device,
1532 struct radv_ds_buffer_info *ds,
1533 struct radv_image_view *iview)
1534 {
1535 unsigned level = iview->base_mip;
1536 unsigned format;
1537 uint64_t va, s_offs, z_offs;
1538 const struct radeon_surf_level *level_info = &iview->image->surface.level[level];
1539 memset(ds, 0, sizeof(*ds));
1540 switch (iview->vk_format) {
1541 case VK_FORMAT_D24_UNORM_S8_UINT:
1542 case VK_FORMAT_X8_D24_UNORM_PACK32:
1543 ds->pa_su_poly_offset_db_fmt_cntl = S_028B78_POLY_OFFSET_NEG_NUM_DB_BITS(-24);
1544 ds->offset_scale = 2.0f;
1545 break;
1546 case VK_FORMAT_D16_UNORM:
1547 case VK_FORMAT_D16_UNORM_S8_UINT:
1548 ds->pa_su_poly_offset_db_fmt_cntl = S_028B78_POLY_OFFSET_NEG_NUM_DB_BITS(-16);
1549 ds->offset_scale = 4.0f;
1550 break;
1551 case VK_FORMAT_D32_SFLOAT:
1552 case VK_FORMAT_D32_SFLOAT_S8_UINT:
1553 ds->pa_su_poly_offset_db_fmt_cntl = S_028B78_POLY_OFFSET_NEG_NUM_DB_BITS(-23) |
1554 S_028B78_POLY_OFFSET_DB_IS_FLOAT_FMT(1);
1555 ds->offset_scale = 1.0f;
1556 break;
1557 default:
1558 break;
1559 }
1560
1561 format = radv_translate_dbformat(iview->vk_format);
1562 if (format == V_028040_Z_INVALID) {
1563 fprintf(stderr, "Invalid DB format: %d, disabling DB.\n", iview->vk_format);
1564 }
1565
1566 va = device->ws->buffer_get_va(iview->bo) + iview->image->offset;
1567 s_offs = z_offs = va;
1568 z_offs += iview->image->surface.level[level].offset;
1569 s_offs += iview->image->surface.stencil_level[level].offset;
1570
1571 ds->db_depth_view = S_028008_SLICE_START(iview->base_layer) |
1572 S_028008_SLICE_MAX(iview->base_layer + iview->extent.depth - 1);
1573 ds->db_depth_info = S_02803C_ADDR5_SWIZZLE_MASK(1);
1574 ds->db_z_info = S_028040_FORMAT(format) | S_028040_ZRANGE_PRECISION(1);
1575
1576 if (iview->image->samples > 1)
1577 ds->db_z_info |= S_028040_NUM_SAMPLES(util_logbase2(iview->image->samples));
1578
1579 if (iview->image->surface.flags & RADEON_SURF_SBUFFER)
1580 ds->db_stencil_info = S_028044_FORMAT(V_028044_STENCIL_8);
1581 else
1582 ds->db_stencil_info = S_028044_FORMAT(V_028044_STENCIL_INVALID);
1583
1584 if (device->instance->physicalDevice.rad_info.chip_class >= CIK) {
1585 struct radeon_info *info = &device->instance->physicalDevice.rad_info;
1586 unsigned tiling_index = iview->image->surface.tiling_index[level];
1587 unsigned stencil_index = iview->image->surface.stencil_tiling_index[level];
1588 unsigned macro_index = iview->image->surface.macro_tile_index;
1589 unsigned tile_mode = info->si_tile_mode_array[tiling_index];
1590 unsigned stencil_tile_mode = info->si_tile_mode_array[stencil_index];
1591 unsigned macro_mode = info->cik_macrotile_mode_array[macro_index];
1592
1593 ds->db_depth_info |=
1594 S_02803C_ARRAY_MODE(G_009910_ARRAY_MODE(tile_mode)) |
1595 S_02803C_PIPE_CONFIG(G_009910_PIPE_CONFIG(tile_mode)) |
1596 S_02803C_BANK_WIDTH(G_009990_BANK_WIDTH(macro_mode)) |
1597 S_02803C_BANK_HEIGHT(G_009990_BANK_HEIGHT(macro_mode)) |
1598 S_02803C_MACRO_TILE_ASPECT(G_009990_MACRO_TILE_ASPECT(macro_mode)) |
1599 S_02803C_NUM_BANKS(G_009990_NUM_BANKS(macro_mode));
1600 ds->db_z_info |= S_028040_TILE_SPLIT(G_009910_TILE_SPLIT(tile_mode));
1601 ds->db_stencil_info |= S_028044_TILE_SPLIT(G_009910_TILE_SPLIT(stencil_tile_mode));
1602 } else {
1603 unsigned tile_mode_index = si_tile_mode_index(iview->image, level, false);
1604 ds->db_z_info |= S_028040_TILE_MODE_INDEX(tile_mode_index);
1605 tile_mode_index = si_tile_mode_index(iview->image, level, true);
1606 ds->db_stencil_info |= S_028044_TILE_MODE_INDEX(tile_mode_index);
1607 }
1608
1609 if (iview->image->htile.size && !level) {
1610 ds->db_z_info |= S_028040_TILE_SURFACE_ENABLE(1) |
1611 S_028040_ALLOW_EXPCLEAR(1);
1612
1613 if (iview->image->surface.flags & RADEON_SURF_SBUFFER) {
1614 /* Workaround: For a not yet understood reason, the
1615 * combination of MSAA, fast stencil clear and stencil
1616 * decompress messes with subsequent stencil buffer
1617 * uses. Problem was reproduced on Verde, Bonaire,
1618 * Tonga, and Carrizo.
1619 *
1620 * Disabling EXPCLEAR works around the problem.
1621 *
1622 * Check piglit's arb_texture_multisample-stencil-clear
1623 * test if you want to try changing this.
1624 */
1625 if (iview->image->samples <= 1)
1626 ds->db_stencil_info |= S_028044_ALLOW_EXPCLEAR(1);
1627 } else
1628 /* Use all of the htile_buffer for depth if there's no stencil. */
1629 ds->db_stencil_info |= S_028044_TILE_STENCIL_DISABLE(1);
1630
1631 va = device->ws->buffer_get_va(iview->bo) + iview->image->offset +
1632 iview->image->htile.offset;
1633 ds->db_htile_data_base = va >> 8;
1634 ds->db_htile_surface = S_028ABC_FULL_CACHE(1);
1635 } else {
1636 ds->db_htile_data_base = 0;
1637 ds->db_htile_surface = 0;
1638 }
1639
1640 ds->db_z_read_base = ds->db_z_write_base = z_offs >> 8;
1641 ds->db_stencil_read_base = ds->db_stencil_write_base = s_offs >> 8;
1642
1643 ds->db_depth_size = S_028058_PITCH_TILE_MAX((level_info->nblk_x / 8) - 1) |
1644 S_028058_HEIGHT_TILE_MAX((level_info->nblk_y / 8) - 1);
1645 ds->db_depth_slice = S_02805C_SLICE_TILE_MAX((level_info->nblk_x * level_info->nblk_y) / 64 - 1);
1646 }
1647
1648 VkResult radv_CreateFramebuffer(
1649 VkDevice _device,
1650 const VkFramebufferCreateInfo* pCreateInfo,
1651 const VkAllocationCallbacks* pAllocator,
1652 VkFramebuffer* pFramebuffer)
1653 {
1654 RADV_FROM_HANDLE(radv_device, device, _device);
1655 struct radv_framebuffer *framebuffer;
1656
1657 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
1658
1659 size_t size = sizeof(*framebuffer) +
1660 sizeof(struct radv_attachment_info) * pCreateInfo->attachmentCount;
1661 framebuffer = vk_alloc2(&device->alloc, pAllocator, size, 8,
1662 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1663 if (framebuffer == NULL)
1664 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
1665
1666 framebuffer->attachment_count = pCreateInfo->attachmentCount;
1667 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
1668 VkImageView _iview = pCreateInfo->pAttachments[i];
1669 struct radv_image_view *iview = radv_image_view_from_handle(_iview);
1670 framebuffer->attachments[i].attachment = iview;
1671 if (iview->aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) {
1672 radv_initialise_color_surface(device, &framebuffer->attachments[i].cb, iview);
1673 } else if (iview->aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
1674 radv_initialise_ds_surface(device, &framebuffer->attachments[i].ds, iview);
1675 }
1676 }
1677
1678 framebuffer->width = pCreateInfo->width;
1679 framebuffer->height = pCreateInfo->height;
1680 framebuffer->layers = pCreateInfo->layers;
1681
1682 *pFramebuffer = radv_framebuffer_to_handle(framebuffer);
1683 return VK_SUCCESS;
1684 }
1685
1686 void radv_DestroyFramebuffer(
1687 VkDevice _device,
1688 VkFramebuffer _fb,
1689 const VkAllocationCallbacks* pAllocator)
1690 {
1691 RADV_FROM_HANDLE(radv_device, device, _device);
1692 RADV_FROM_HANDLE(radv_framebuffer, fb, _fb);
1693
1694 if (!fb)
1695 return;
1696 vk_free2(&device->alloc, pAllocator, fb);
1697 }
1698
1699 static unsigned radv_tex_wrap(VkSamplerAddressMode address_mode)
1700 {
1701 switch (address_mode) {
1702 case VK_SAMPLER_ADDRESS_MODE_REPEAT:
1703 return V_008F30_SQ_TEX_WRAP;
1704 case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:
1705 return V_008F30_SQ_TEX_MIRROR;
1706 case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
1707 return V_008F30_SQ_TEX_CLAMP_LAST_TEXEL;
1708 case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER:
1709 return V_008F30_SQ_TEX_CLAMP_BORDER;
1710 case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE:
1711 return V_008F30_SQ_TEX_MIRROR_ONCE_LAST_TEXEL;
1712 default:
1713 unreachable("illegal tex wrap mode");
1714 break;
1715 }
1716 }
1717
1718 static unsigned
1719 radv_tex_compare(VkCompareOp op)
1720 {
1721 switch (op) {
1722 case VK_COMPARE_OP_NEVER:
1723 return V_008F30_SQ_TEX_DEPTH_COMPARE_NEVER;
1724 case VK_COMPARE_OP_LESS:
1725 return V_008F30_SQ_TEX_DEPTH_COMPARE_LESS;
1726 case VK_COMPARE_OP_EQUAL:
1727 return V_008F30_SQ_TEX_DEPTH_COMPARE_EQUAL;
1728 case VK_COMPARE_OP_LESS_OR_EQUAL:
1729 return V_008F30_SQ_TEX_DEPTH_COMPARE_LESSEQUAL;
1730 case VK_COMPARE_OP_GREATER:
1731 return V_008F30_SQ_TEX_DEPTH_COMPARE_GREATER;
1732 case VK_COMPARE_OP_NOT_EQUAL:
1733 return V_008F30_SQ_TEX_DEPTH_COMPARE_NOTEQUAL;
1734 case VK_COMPARE_OP_GREATER_OR_EQUAL:
1735 return V_008F30_SQ_TEX_DEPTH_COMPARE_GREATEREQUAL;
1736 case VK_COMPARE_OP_ALWAYS:
1737 return V_008F30_SQ_TEX_DEPTH_COMPARE_ALWAYS;
1738 default:
1739 unreachable("illegal compare mode");
1740 break;
1741 }
1742 }
1743
1744 static unsigned
1745 radv_tex_filter(VkFilter filter, unsigned max_ansio)
1746 {
1747 switch (filter) {
1748 case VK_FILTER_NEAREST:
1749 return (max_ansio > 1 ? V_008F38_SQ_TEX_XY_FILTER_ANISO_POINT :
1750 V_008F38_SQ_TEX_XY_FILTER_POINT);
1751 case VK_FILTER_LINEAR:
1752 return (max_ansio > 1 ? V_008F38_SQ_TEX_XY_FILTER_ANISO_BILINEAR :
1753 V_008F38_SQ_TEX_XY_FILTER_BILINEAR);
1754 case VK_FILTER_CUBIC_IMG:
1755 default:
1756 fprintf(stderr, "illegal texture filter");
1757 return 0;
1758 }
1759 }
1760
1761 static unsigned
1762 radv_tex_mipfilter(VkSamplerMipmapMode mode)
1763 {
1764 switch (mode) {
1765 case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1766 return V_008F38_SQ_TEX_Z_FILTER_POINT;
1767 case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1768 return V_008F38_SQ_TEX_Z_FILTER_LINEAR;
1769 default:
1770 return V_008F38_SQ_TEX_Z_FILTER_NONE;
1771 }
1772 }
1773
1774 static unsigned
1775 radv_tex_bordercolor(VkBorderColor bcolor)
1776 {
1777 switch (bcolor) {
1778 case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
1779 case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
1780 return V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK;
1781 case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
1782 case VK_BORDER_COLOR_INT_OPAQUE_BLACK:
1783 return V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_BLACK;
1784 case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
1785 case VK_BORDER_COLOR_INT_OPAQUE_WHITE:
1786 return V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_WHITE;
1787 default:
1788 break;
1789 }
1790 return 0;
1791 }
1792
1793 static unsigned
1794 radv_tex_aniso_filter(unsigned filter)
1795 {
1796 if (filter < 2)
1797 return 0;
1798 if (filter < 4)
1799 return 1;
1800 if (filter < 8)
1801 return 2;
1802 if (filter < 16)
1803 return 3;
1804 return 4;
1805 }
1806
1807 static void
1808 radv_init_sampler(struct radv_device *device,
1809 struct radv_sampler *sampler,
1810 const VkSamplerCreateInfo *pCreateInfo)
1811 {
1812 uint32_t max_aniso = pCreateInfo->anisotropyEnable && pCreateInfo->maxAnisotropy > 1.0 ?
1813 (uint32_t) pCreateInfo->maxAnisotropy : 0;
1814 uint32_t max_aniso_ratio = radv_tex_aniso_filter(max_aniso);
1815 bool is_vi = (device->instance->physicalDevice.rad_info.chip_class >= VI);
1816
1817 sampler->state[0] = (S_008F30_CLAMP_X(radv_tex_wrap(pCreateInfo->addressModeU)) |
1818 S_008F30_CLAMP_Y(radv_tex_wrap(pCreateInfo->addressModeV)) |
1819 S_008F30_CLAMP_Z(radv_tex_wrap(pCreateInfo->addressModeW)) |
1820 S_008F30_MAX_ANISO_RATIO(max_aniso_ratio) |
1821 S_008F30_DEPTH_COMPARE_FUNC(radv_tex_compare(pCreateInfo->compareOp)) |
1822 S_008F30_FORCE_UNNORMALIZED(pCreateInfo->unnormalizedCoordinates ? 1 : 0) |
1823 S_008F30_ANISO_THRESHOLD(max_aniso_ratio >> 1) |
1824 S_008F30_ANISO_BIAS(max_aniso_ratio) |
1825 S_008F30_DISABLE_CUBE_WRAP(0) |
1826 S_008F30_COMPAT_MODE(is_vi));
1827 sampler->state[1] = (S_008F34_MIN_LOD(S_FIXED(CLAMP(pCreateInfo->minLod, 0, 15), 8)) |
1828 S_008F34_MAX_LOD(S_FIXED(CLAMP(pCreateInfo->maxLod, 0, 15), 8)) |
1829 S_008F34_PERF_MIP(max_aniso_ratio ? max_aniso_ratio + 6 : 0));
1830 sampler->state[2] = (S_008F38_LOD_BIAS(S_FIXED(CLAMP(pCreateInfo->mipLodBias, -16, 16), 8)) |
1831 S_008F38_XY_MAG_FILTER(radv_tex_filter(pCreateInfo->magFilter, max_aniso)) |
1832 S_008F38_XY_MIN_FILTER(radv_tex_filter(pCreateInfo->minFilter, max_aniso)) |
1833 S_008F38_MIP_FILTER(radv_tex_mipfilter(pCreateInfo->mipmapMode)) |
1834 S_008F38_MIP_POINT_PRECLAMP(1) |
1835 S_008F38_DISABLE_LSB_CEIL(1) |
1836 S_008F38_FILTER_PREC_FIX(1) |
1837 S_008F38_ANISO_OVERRIDE(is_vi));
1838 sampler->state[3] = (S_008F3C_BORDER_COLOR_PTR(0) |
1839 S_008F3C_BORDER_COLOR_TYPE(radv_tex_bordercolor(pCreateInfo->borderColor)));
1840 }
1841
1842 VkResult radv_CreateSampler(
1843 VkDevice _device,
1844 const VkSamplerCreateInfo* pCreateInfo,
1845 const VkAllocationCallbacks* pAllocator,
1846 VkSampler* pSampler)
1847 {
1848 RADV_FROM_HANDLE(radv_device, device, _device);
1849 struct radv_sampler *sampler;
1850
1851 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
1852
1853 sampler = vk_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
1854 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1855 if (!sampler)
1856 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
1857
1858 radv_init_sampler(device, sampler, pCreateInfo);
1859 *pSampler = radv_sampler_to_handle(sampler);
1860
1861 return VK_SUCCESS;
1862 }
1863
1864 void radv_DestroySampler(
1865 VkDevice _device,
1866 VkSampler _sampler,
1867 const VkAllocationCallbacks* pAllocator)
1868 {
1869 RADV_FROM_HANDLE(radv_device, device, _device);
1870 RADV_FROM_HANDLE(radv_sampler, sampler, _sampler);
1871
1872 if (!sampler)
1873 return;
1874 vk_free2(&device->alloc, pAllocator, sampler);
1875 }