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