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