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