1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "dzn_private.h"
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "vk_alloc.h"
27bf215546Sopenharmony_ci#include "vk_common_entrypoints.h"
28bf215546Sopenharmony_ci#include "vk_cmd_enqueue_entrypoints.h"
29bf215546Sopenharmony_ci#include "vk_debug_report.h"
30bf215546Sopenharmony_ci#include "vk_format.h"
31bf215546Sopenharmony_ci#include "vk_sync_dummy.h"
32bf215546Sopenharmony_ci#include "vk_util.h"
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#include "git_sha1.h"
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci#include "util/debug.h"
37bf215546Sopenharmony_ci#include "util/disk_cache.h"
38bf215546Sopenharmony_ci#include "util/macros.h"
39bf215546Sopenharmony_ci#include "util/mesa-sha1.h"
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#include "glsl_types.h"
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci#include "dxil_validator.h"
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#include "git_sha1.h"
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci#include <string.h>
48bf215546Sopenharmony_ci#include <stdio.h>
49bf215546Sopenharmony_ci#include <stdlib.h>
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci#ifdef _WIN32
52bf215546Sopenharmony_ci#include <windows.h>
53bf215546Sopenharmony_ci#include <shlobj.h>
54bf215546Sopenharmony_ci#include "dzn_dxgi.h"
55bf215546Sopenharmony_ci#endif
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci#include <directx/d3d12sdklayers.h>
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ci#if defined(VK_USE_PLATFORM_WIN32_KHR) || \
60bf215546Sopenharmony_ci    defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
61bf215546Sopenharmony_ci    defined(VK_USE_PLATFORM_XCB_KHR) || \
62bf215546Sopenharmony_ci    defined(VK_USE_PLATFORM_XLIB_KHR)
63bf215546Sopenharmony_ci#define DZN_USE_WSI_PLATFORM
64bf215546Sopenharmony_ci#endif
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci#define DZN_API_VERSION VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION)
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci#define MAX_TIER2_MEMORY_TYPES 3
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_cistatic const struct vk_instance_extension_table instance_extensions = {
71bf215546Sopenharmony_ci   .KHR_get_physical_device_properties2      = true,
72bf215546Sopenharmony_ci#ifdef DZN_USE_WSI_PLATFORM
73bf215546Sopenharmony_ci   .KHR_surface                              = true,
74bf215546Sopenharmony_ci#endif
75bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WIN32_KHR
76bf215546Sopenharmony_ci   .KHR_win32_surface                        = true,
77bf215546Sopenharmony_ci#endif
78bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XCB_KHR
79bf215546Sopenharmony_ci   .KHR_xcb_surface                          = true,
80bf215546Sopenharmony_ci#endif
81bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WAYLAND_KHR
82bf215546Sopenharmony_ci   .KHR_wayland_surface                      = true,
83bf215546Sopenharmony_ci#endif
84bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XLIB_KHR
85bf215546Sopenharmony_ci   .KHR_xlib_surface                         = true,
86bf215546Sopenharmony_ci#endif
87bf215546Sopenharmony_ci   .EXT_debug_report                         = true,
88bf215546Sopenharmony_ci   .EXT_debug_utils                          = true,
89bf215546Sopenharmony_ci};
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_cistatic void
92bf215546Sopenharmony_cidzn_physical_device_get_extensions(struct dzn_physical_device *pdev)
93bf215546Sopenharmony_ci{
94bf215546Sopenharmony_ci   pdev->vk.supported_extensions = (struct vk_device_extension_table) {
95bf215546Sopenharmony_ci      .KHR_create_renderpass2                = true,
96bf215546Sopenharmony_ci      .KHR_depth_stencil_resolve             = true,
97bf215546Sopenharmony_ci      .KHR_descriptor_update_template        = true,
98bf215546Sopenharmony_ci      .KHR_draw_indirect_count               = true,
99bf215546Sopenharmony_ci      .KHR_driver_properties                 = true,
100bf215546Sopenharmony_ci      .KHR_dynamic_rendering                 = true,
101bf215546Sopenharmony_ci      .KHR_shader_draw_parameters            = true,
102bf215546Sopenharmony_ci#ifdef DZN_USE_WSI_PLATFORM
103bf215546Sopenharmony_ci      .KHR_swapchain                         = true,
104bf215546Sopenharmony_ci#endif
105bf215546Sopenharmony_ci      .EXT_vertex_attribute_divisor          = true,
106bf215546Sopenharmony_ci   };
107bf215546Sopenharmony_ci}
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
110bf215546Sopenharmony_cidzn_EnumerateInstanceExtensionProperties(const char *pLayerName,
111bf215546Sopenharmony_ci                                         uint32_t *pPropertyCount,
112bf215546Sopenharmony_ci                                         VkExtensionProperties *pProperties)
113bf215546Sopenharmony_ci{
114bf215546Sopenharmony_ci   /* We don't support any layers  */
115bf215546Sopenharmony_ci   if (pLayerName)
116bf215546Sopenharmony_ci      return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci   return vk_enumerate_instance_extension_properties(
119bf215546Sopenharmony_ci      &instance_extensions, pPropertyCount, pProperties);
120bf215546Sopenharmony_ci}
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_cistatic const struct debug_control dzn_debug_options[] = {
123bf215546Sopenharmony_ci   { "sync", DZN_DEBUG_SYNC },
124bf215546Sopenharmony_ci   { "nir", DZN_DEBUG_NIR },
125bf215546Sopenharmony_ci   { "dxil", DZN_DEBUG_DXIL },
126bf215546Sopenharmony_ci   { "warp", DZN_DEBUG_WARP },
127bf215546Sopenharmony_ci   { "internal", DZN_DEBUG_INTERNAL },
128bf215546Sopenharmony_ci   { "signature", DZN_DEBUG_SIG },
129bf215546Sopenharmony_ci   { "gbv", DZN_DEBUG_GBV },
130bf215546Sopenharmony_ci   { "d3d12", DZN_DEBUG_D3D12 },
131bf215546Sopenharmony_ci   { "debugger", DZN_DEBUG_DEBUGGER },
132bf215546Sopenharmony_ci   { "redirects", DZN_DEBUG_REDIRECTS },
133bf215546Sopenharmony_ci   { NULL, 0 }
134bf215546Sopenharmony_ci};
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_cistatic void
137bf215546Sopenharmony_cidzn_physical_device_destroy(struct dzn_physical_device *pdev)
138bf215546Sopenharmony_ci{
139bf215546Sopenharmony_ci   struct dzn_instance *instance = container_of(pdev->vk.instance, struct dzn_instance, vk);
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci   list_del(&pdev->link);
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   if (pdev->dev)
144bf215546Sopenharmony_ci      ID3D12Device1_Release(pdev->dev);
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   if (pdev->adapter)
147bf215546Sopenharmony_ci      IUnknown_Release(pdev->adapter);
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   dzn_wsi_finish(pdev);
150bf215546Sopenharmony_ci   vk_physical_device_finish(&pdev->vk);
151bf215546Sopenharmony_ci   vk_free(&instance->vk.alloc, pdev);
152bf215546Sopenharmony_ci}
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_cistatic void
155bf215546Sopenharmony_cidzn_instance_destroy(struct dzn_instance *instance, const VkAllocationCallbacks *alloc)
156bf215546Sopenharmony_ci{
157bf215546Sopenharmony_ci   if (!instance)
158bf215546Sopenharmony_ci      return;
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci#ifdef _WIN32
161bf215546Sopenharmony_ci   if (instance->dxil_validator)
162bf215546Sopenharmony_ci      dxil_destroy_validator(instance->dxil_validator);
163bf215546Sopenharmony_ci#endif
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   list_for_each_entry_safe(struct dzn_physical_device, pdev,
166bf215546Sopenharmony_ci                            &instance->physical_devices, link) {
167bf215546Sopenharmony_ci      dzn_physical_device_destroy(pdev);
168bf215546Sopenharmony_ci   }
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci   vk_instance_finish(&instance->vk);
171bf215546Sopenharmony_ci   vk_free2(vk_default_allocator(), alloc, instance);
172bf215546Sopenharmony_ci}
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_cistatic VkResult
175bf215546Sopenharmony_cidzn_instance_create(const VkInstanceCreateInfo *pCreateInfo,
176bf215546Sopenharmony_ci                    const VkAllocationCallbacks *pAllocator,
177bf215546Sopenharmony_ci                    VkInstance *out)
178bf215546Sopenharmony_ci{
179bf215546Sopenharmony_ci   struct dzn_instance *instance =
180bf215546Sopenharmony_ci      vk_zalloc2(vk_default_allocator(), pAllocator, sizeof(*instance), 8,
181bf215546Sopenharmony_ci                 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
182bf215546Sopenharmony_ci   if (!instance)
183bf215546Sopenharmony_ci      return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci   struct vk_instance_dispatch_table dispatch_table;
186bf215546Sopenharmony_ci   vk_instance_dispatch_table_from_entrypoints(&dispatch_table,
187bf215546Sopenharmony_ci                                               &dzn_instance_entrypoints,
188bf215546Sopenharmony_ci                                               true);
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci   VkResult result =
191bf215546Sopenharmony_ci      vk_instance_init(&instance->vk, &instance_extensions,
192bf215546Sopenharmony_ci                       &dispatch_table, pCreateInfo,
193bf215546Sopenharmony_ci                       pAllocator ? pAllocator : vk_default_allocator());
194bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
195bf215546Sopenharmony_ci      vk_free2(vk_default_allocator(), pAllocator, instance);
196bf215546Sopenharmony_ci      return result;
197bf215546Sopenharmony_ci   }
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   list_inithead(&instance->physical_devices);
200bf215546Sopenharmony_ci   instance->physical_devices_enumerated = false;
201bf215546Sopenharmony_ci   instance->debug_flags =
202bf215546Sopenharmony_ci      parse_debug_string(getenv("DZN_DEBUG"), dzn_debug_options);
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci#ifdef _WIN32
205bf215546Sopenharmony_ci   if (instance->debug_flags & DZN_DEBUG_DEBUGGER) {
206bf215546Sopenharmony_ci      /* wait for debugger to attach... */
207bf215546Sopenharmony_ci      while (!IsDebuggerPresent()) {
208bf215546Sopenharmony_ci         Sleep(100);
209bf215546Sopenharmony_ci      }
210bf215546Sopenharmony_ci   }
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci   if (instance->debug_flags & DZN_DEBUG_REDIRECTS) {
213bf215546Sopenharmony_ci      char home[MAX_PATH], path[MAX_PATH];
214bf215546Sopenharmony_ci      if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, home))) {
215bf215546Sopenharmony_ci         snprintf(path, sizeof(path), "%s\\stderr.txt", home);
216bf215546Sopenharmony_ci         freopen(path, "w", stderr);
217bf215546Sopenharmony_ci         snprintf(path, sizeof(path), "%s\\stdout.txt", home);
218bf215546Sopenharmony_ci         freopen(path, "w", stdout);
219bf215546Sopenharmony_ci      }
220bf215546Sopenharmony_ci   }
221bf215546Sopenharmony_ci#endif
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci   bool missing_validator = false;
224bf215546Sopenharmony_ci#ifdef _WIN32
225bf215546Sopenharmony_ci   instance->dxil_validator = dxil_create_validator(NULL);
226bf215546Sopenharmony_ci   missing_validator = !instance->dxil_validator;
227bf215546Sopenharmony_ci#endif
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci   instance->d3d12.serialize_root_sig = d3d12_get_serialize_root_sig();
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci   if (missing_validator ||
232bf215546Sopenharmony_ci       !instance->d3d12.serialize_root_sig) {
233bf215546Sopenharmony_ci      dzn_instance_destroy(instance, pAllocator);
234bf215546Sopenharmony_ci      return vk_error(NULL, VK_ERROR_INITIALIZATION_FAILED);
235bf215546Sopenharmony_ci   }
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci   if (instance->debug_flags & DZN_DEBUG_D3D12)
238bf215546Sopenharmony_ci      d3d12_enable_debug_layer();
239bf215546Sopenharmony_ci   if (instance->debug_flags & DZN_DEBUG_GBV)
240bf215546Sopenharmony_ci      d3d12_enable_gpu_validation();
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci   instance->sync_binary_type = vk_sync_binary_get_type(&dzn_sync_type);
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci   *out = dzn_instance_to_handle(instance);
245bf215546Sopenharmony_ci   return VK_SUCCESS;
246bf215546Sopenharmony_ci}
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
249bf215546Sopenharmony_cidzn_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
250bf215546Sopenharmony_ci                   const VkAllocationCallbacks *pAllocator,
251bf215546Sopenharmony_ci                   VkInstance *pInstance)
252bf215546Sopenharmony_ci{
253bf215546Sopenharmony_ci   return dzn_instance_create(pCreateInfo, pAllocator, pInstance);
254bf215546Sopenharmony_ci}
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
257bf215546Sopenharmony_cidzn_DestroyInstance(VkInstance instance,
258bf215546Sopenharmony_ci                    const VkAllocationCallbacks *pAllocator)
259bf215546Sopenharmony_ci{
260bf215546Sopenharmony_ci   dzn_instance_destroy(dzn_instance_from_handle(instance), pAllocator);
261bf215546Sopenharmony_ci}
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_cistatic void
264bf215546Sopenharmony_cidzn_physical_device_init_uuids(struct dzn_physical_device *pdev)
265bf215546Sopenharmony_ci{
266bf215546Sopenharmony_ci   const char *mesa_version = "Mesa " PACKAGE_VERSION MESA_GIT_SHA1;
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci   struct mesa_sha1 sha1_ctx;
269bf215546Sopenharmony_ci   uint8_t sha1[SHA1_DIGEST_LENGTH];
270bf215546Sopenharmony_ci   STATIC_ASSERT(VK_UUID_SIZE <= sizeof(sha1));
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci   /* The pipeline cache UUID is used for determining when a pipeline cache is
273bf215546Sopenharmony_ci    * invalid. Our cache is device-agnostic, but it does depend on the features
274bf215546Sopenharmony_ci    * provided by the D3D12 driver, so let's hash the build ID plus some
275bf215546Sopenharmony_ci    * caps that might impact our NIR lowering passes.
276bf215546Sopenharmony_ci    */
277bf215546Sopenharmony_ci   _mesa_sha1_init(&sha1_ctx);
278bf215546Sopenharmony_ci   _mesa_sha1_update(&sha1_ctx,  mesa_version, strlen(mesa_version));
279bf215546Sopenharmony_ci   disk_cache_get_function_identifier(dzn_physical_device_init_uuids, &sha1_ctx);
280bf215546Sopenharmony_ci   _mesa_sha1_update(&sha1_ctx,  &pdev->options, sizeof(pdev->options));
281bf215546Sopenharmony_ci   _mesa_sha1_update(&sha1_ctx,  &pdev->options2, sizeof(pdev->options2));
282bf215546Sopenharmony_ci   _mesa_sha1_final(&sha1_ctx, sha1);
283bf215546Sopenharmony_ci   memcpy(pdev->pipeline_cache_uuid, sha1, VK_UUID_SIZE);
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci   /* The driver UUID is used for determining sharability of images and memory
286bf215546Sopenharmony_ci    * between two Vulkan instances in separate processes.  People who want to
287bf215546Sopenharmony_ci    * share memory need to also check the device UUID (below) so all this
288bf215546Sopenharmony_ci    * needs to be is the build-id.
289bf215546Sopenharmony_ci    */
290bf215546Sopenharmony_ci   _mesa_sha1_compute(mesa_version, strlen(mesa_version), sha1);
291bf215546Sopenharmony_ci   memcpy(pdev->driver_uuid, sha1, VK_UUID_SIZE);
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   /* The device UUID uniquely identifies the given device within the machine. */
294bf215546Sopenharmony_ci   _mesa_sha1_init(&sha1_ctx);
295bf215546Sopenharmony_ci   _mesa_sha1_update(&sha1_ctx, &pdev->desc.vendor_id, sizeof(pdev->desc.vendor_id));
296bf215546Sopenharmony_ci   _mesa_sha1_update(&sha1_ctx, &pdev->desc.device_id, sizeof(pdev->desc.device_id));
297bf215546Sopenharmony_ci   _mesa_sha1_update(&sha1_ctx, &pdev->desc.subsys_id, sizeof(pdev->desc.subsys_id));
298bf215546Sopenharmony_ci   _mesa_sha1_update(&sha1_ctx, &pdev->desc.revision, sizeof(pdev->desc.revision));
299bf215546Sopenharmony_ci   _mesa_sha1_final(&sha1_ctx, sha1);
300bf215546Sopenharmony_ci   memcpy(pdev->device_uuid, sha1, VK_UUID_SIZE);
301bf215546Sopenharmony_ci}
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ciconst struct vk_pipeline_cache_object_ops *const dzn_pipeline_cache_import_ops[] = {
304bf215546Sopenharmony_ci   &dzn_cached_blob_ops,
305bf215546Sopenharmony_ci   NULL,
306bf215546Sopenharmony_ci};
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_cistatic VkResult
309bf215546Sopenharmony_cidzn_physical_device_create(struct dzn_instance *instance,
310bf215546Sopenharmony_ci                           IUnknown *adapter,
311bf215546Sopenharmony_ci                           const struct dzn_physical_device_desc *desc)
312bf215546Sopenharmony_ci{
313bf215546Sopenharmony_ci   struct dzn_physical_device *pdev =
314bf215546Sopenharmony_ci      vk_zalloc(&instance->vk.alloc, sizeof(*pdev), 8,
315bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   if (!pdev)
318bf215546Sopenharmony_ci      return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_ci   struct vk_physical_device_dispatch_table dispatch_table;
321bf215546Sopenharmony_ci   vk_physical_device_dispatch_table_from_entrypoints(&dispatch_table,
322bf215546Sopenharmony_ci                                                      &dzn_physical_device_entrypoints,
323bf215546Sopenharmony_ci                                                      true);
324bf215546Sopenharmony_ci   vk_physical_device_dispatch_table_from_entrypoints(&dispatch_table,
325bf215546Sopenharmony_ci                                                      &wsi_physical_device_entrypoints,
326bf215546Sopenharmony_ci                                                      false);
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci   VkResult result =
329bf215546Sopenharmony_ci      vk_physical_device_init(&pdev->vk, &instance->vk,
330bf215546Sopenharmony_ci                              NULL, /* We set up extensions later */
331bf215546Sopenharmony_ci                              &dispatch_table);
332bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
333bf215546Sopenharmony_ci      vk_free(&instance->vk.alloc, pdev);
334bf215546Sopenharmony_ci      return result;
335bf215546Sopenharmony_ci   }
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci   mtx_init(&pdev->dev_lock, mtx_plain);
338bf215546Sopenharmony_ci   pdev->desc = *desc;
339bf215546Sopenharmony_ci   pdev->adapter = adapter;
340bf215546Sopenharmony_ci   IUnknown_AddRef(adapter);
341bf215546Sopenharmony_ci   list_addtail(&pdev->link, &instance->physical_devices);
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   vk_warn_non_conformant_implementation("dzn");
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   uint32_t num_sync_types = 0;
346bf215546Sopenharmony_ci   pdev->sync_types[num_sync_types++] = &dzn_sync_type;
347bf215546Sopenharmony_ci   pdev->sync_types[num_sync_types++] = &instance->sync_binary_type.sync;
348bf215546Sopenharmony_ci   pdev->sync_types[num_sync_types++] = &vk_sync_dummy_type;
349bf215546Sopenharmony_ci   pdev->sync_types[num_sync_types] = NULL;
350bf215546Sopenharmony_ci   assert(num_sync_types <= MAX_SYNC_TYPES);
351bf215546Sopenharmony_ci   pdev->vk.supported_sync_types = pdev->sync_types;
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci   pdev->vk.pipeline_cache_import_ops = dzn_pipeline_cache_import_ops;
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   /* TODO: something something queue families */
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci   result = dzn_wsi_init(pdev);
358bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
359bf215546Sopenharmony_ci      dzn_physical_device_destroy(pdev);
360bf215546Sopenharmony_ci      return result;
361bf215546Sopenharmony_ci   }
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci   dzn_physical_device_get_extensions(pdev);
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci   return VK_SUCCESS;
366bf215546Sopenharmony_ci}
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_cistatic void
369bf215546Sopenharmony_cidzn_physical_device_cache_caps(struct dzn_physical_device *pdev)
370bf215546Sopenharmony_ci{
371bf215546Sopenharmony_ci   D3D_FEATURE_LEVEL checklist[] = {
372bf215546Sopenharmony_ci      D3D_FEATURE_LEVEL_11_0,
373bf215546Sopenharmony_ci      D3D_FEATURE_LEVEL_11_1,
374bf215546Sopenharmony_ci      D3D_FEATURE_LEVEL_12_0,
375bf215546Sopenharmony_ci      D3D_FEATURE_LEVEL_12_1,
376bf215546Sopenharmony_ci      D3D_FEATURE_LEVEL_12_2,
377bf215546Sopenharmony_ci   };
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   D3D12_FEATURE_DATA_FEATURE_LEVELS levels = {
380bf215546Sopenharmony_ci      .NumFeatureLevels = ARRAY_SIZE(checklist),
381bf215546Sopenharmony_ci      .pFeatureLevelsRequested = checklist,
382bf215546Sopenharmony_ci   };
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci   ID3D12Device1_CheckFeatureSupport(pdev->dev, D3D12_FEATURE_FEATURE_LEVELS, &levels, sizeof(levels));
385bf215546Sopenharmony_ci   pdev->feature_level = levels.MaxSupportedFeatureLevel;
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci   ID3D12Device1_CheckFeatureSupport(pdev->dev, D3D12_FEATURE_ARCHITECTURE1, &pdev->architecture, sizeof(pdev->architecture));
388bf215546Sopenharmony_ci   ID3D12Device1_CheckFeatureSupport(pdev->dev, D3D12_FEATURE_D3D12_OPTIONS, &pdev->options, sizeof(pdev->options));
389bf215546Sopenharmony_ci   ID3D12Device1_CheckFeatureSupport(pdev->dev, D3D12_FEATURE_D3D12_OPTIONS2, &pdev->options2, sizeof(pdev->options2));
390bf215546Sopenharmony_ci   ID3D12Device1_CheckFeatureSupport(pdev->dev, D3D12_FEATURE_D3D12_OPTIONS3, &pdev->options3, sizeof(pdev->options3));
391bf215546Sopenharmony_ci
392bf215546Sopenharmony_ci   pdev->queue_families[pdev->queue_family_count++] = (struct dzn_queue_family) {
393bf215546Sopenharmony_ci      .props = {
394bf215546Sopenharmony_ci         .queueFlags = VK_QUEUE_GRAPHICS_BIT |
395bf215546Sopenharmony_ci                       VK_QUEUE_COMPUTE_BIT |
396bf215546Sopenharmony_ci                       VK_QUEUE_TRANSFER_BIT,
397bf215546Sopenharmony_ci         .queueCount = 1,
398bf215546Sopenharmony_ci         .timestampValidBits = 64,
399bf215546Sopenharmony_ci         .minImageTransferGranularity = { 0, 0, 0 },
400bf215546Sopenharmony_ci      },
401bf215546Sopenharmony_ci      .desc = {
402bf215546Sopenharmony_ci         .Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
403bf215546Sopenharmony_ci      },
404bf215546Sopenharmony_ci   };
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ci   pdev->queue_families[pdev->queue_family_count++] = (struct dzn_queue_family) {
407bf215546Sopenharmony_ci      .props = {
408bf215546Sopenharmony_ci         .queueFlags = VK_QUEUE_COMPUTE_BIT |
409bf215546Sopenharmony_ci                       VK_QUEUE_TRANSFER_BIT,
410bf215546Sopenharmony_ci         .queueCount = 8,
411bf215546Sopenharmony_ci         .timestampValidBits = 64,
412bf215546Sopenharmony_ci         .minImageTransferGranularity = { 0, 0, 0 },
413bf215546Sopenharmony_ci      },
414bf215546Sopenharmony_ci      .desc = {
415bf215546Sopenharmony_ci         .Type = D3D12_COMMAND_LIST_TYPE_COMPUTE,
416bf215546Sopenharmony_ci      },
417bf215546Sopenharmony_ci   };
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_ci   pdev->queue_families[pdev->queue_family_count++] = (struct dzn_queue_family) {
420bf215546Sopenharmony_ci      .props = {
421bf215546Sopenharmony_ci         .queueFlags = VK_QUEUE_TRANSFER_BIT,
422bf215546Sopenharmony_ci         .queueCount = 1,
423bf215546Sopenharmony_ci         .timestampValidBits = 0,
424bf215546Sopenharmony_ci         .minImageTransferGranularity = { 0, 0, 0 },
425bf215546Sopenharmony_ci      },
426bf215546Sopenharmony_ci      .desc = {
427bf215546Sopenharmony_ci         .Type = D3D12_COMMAND_LIST_TYPE_COPY,
428bf215546Sopenharmony_ci      },
429bf215546Sopenharmony_ci   };
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci   assert(pdev->queue_family_count <= ARRAY_SIZE(pdev->queue_families));
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci   D3D12_COMMAND_QUEUE_DESC queue_desc = {
434bf215546Sopenharmony_ci      .Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
435bf215546Sopenharmony_ci      .Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
436bf215546Sopenharmony_ci      .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
437bf215546Sopenharmony_ci      .NodeMask = 0,
438bf215546Sopenharmony_ci   };
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   ID3D12CommandQueue *cmdqueue;
441bf215546Sopenharmony_ci   ID3D12Device1_CreateCommandQueue(pdev->dev, &queue_desc,
442bf215546Sopenharmony_ci                                    &IID_ID3D12CommandQueue,
443bf215546Sopenharmony_ci                                    (void **)&cmdqueue);
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci   uint64_t ts_freq;
446bf215546Sopenharmony_ci   ID3D12CommandQueue_GetTimestampFrequency(cmdqueue, &ts_freq);
447bf215546Sopenharmony_ci   pdev->timestamp_period = 1000000000.0f / ts_freq;
448bf215546Sopenharmony_ci   ID3D12CommandQueue_Release(cmdqueue);
449bf215546Sopenharmony_ci}
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_cistatic void
452bf215546Sopenharmony_cidzn_physical_device_init_memory(struct dzn_physical_device *pdev)
453bf215546Sopenharmony_ci{
454bf215546Sopenharmony_ci   VkPhysicalDeviceMemoryProperties *mem = &pdev->memory;
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_ci   mem->memoryHeapCount = 1;
457bf215546Sopenharmony_ci   mem->memoryHeaps[0] = (VkMemoryHeap) {
458bf215546Sopenharmony_ci      .size = pdev->desc.shared_system_memory,
459bf215546Sopenharmony_ci      .flags = 0,
460bf215546Sopenharmony_ci   };
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci   mem->memoryTypes[mem->memoryTypeCount++] = (VkMemoryType) {
463bf215546Sopenharmony_ci      .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
464bf215546Sopenharmony_ci                       VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
465bf215546Sopenharmony_ci      .heapIndex = 0,
466bf215546Sopenharmony_ci   };
467bf215546Sopenharmony_ci   mem->memoryTypes[mem->memoryTypeCount++] = (VkMemoryType) {
468bf215546Sopenharmony_ci      .propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
469bf215546Sopenharmony_ci                       VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
470bf215546Sopenharmony_ci                       VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
471bf215546Sopenharmony_ci     .heapIndex = 0,
472bf215546Sopenharmony_ci   };
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_ci   if (!pdev->architecture.UMA) {
475bf215546Sopenharmony_ci      mem->memoryHeaps[mem->memoryHeapCount++] = (VkMemoryHeap) {
476bf215546Sopenharmony_ci         .size = pdev->desc.dedicated_video_memory,
477bf215546Sopenharmony_ci         .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
478bf215546Sopenharmony_ci      };
479bf215546Sopenharmony_ci      mem->memoryTypes[mem->memoryTypeCount++] = (VkMemoryType) {
480bf215546Sopenharmony_ci         .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
481bf215546Sopenharmony_ci         .heapIndex = mem->memoryHeapCount - 1,
482bf215546Sopenharmony_ci      };
483bf215546Sopenharmony_ci   } else {
484bf215546Sopenharmony_ci      mem->memoryHeaps[0].flags |= VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
485bf215546Sopenharmony_ci      mem->memoryTypes[0].propertyFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
486bf215546Sopenharmony_ci      mem->memoryTypes[1].propertyFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
487bf215546Sopenharmony_ci   }
488bf215546Sopenharmony_ci
489bf215546Sopenharmony_ci   assert(mem->memoryTypeCount <= MAX_TIER2_MEMORY_TYPES);
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci   if (pdev->options.ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1) {
492bf215546Sopenharmony_ci      unsigned oldMemoryTypeCount = mem->memoryTypeCount;
493bf215546Sopenharmony_ci      VkMemoryType oldMemoryTypes[MAX_TIER2_MEMORY_TYPES];
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_ci      memcpy(oldMemoryTypes, mem->memoryTypes, oldMemoryTypeCount * sizeof(VkMemoryType));
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci      mem->memoryTypeCount = 0;
498bf215546Sopenharmony_ci      for (unsigned oldMemoryTypeIdx = 0; oldMemoryTypeIdx < oldMemoryTypeCount; ++oldMemoryTypeIdx) {
499bf215546Sopenharmony_ci         D3D12_HEAP_FLAGS flags[] = {
500bf215546Sopenharmony_ci            D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS,
501bf215546Sopenharmony_ci            D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES,
502bf215546Sopenharmony_ci            /* Note: Vulkan requires *all* images to come from the same memory type as long as
503bf215546Sopenharmony_ci             * the tiling property (and a few other misc properties) are the same. So, this
504bf215546Sopenharmony_ci             * non-RT/DS texture flag will only be used for TILING_LINEAR textures, which
505bf215546Sopenharmony_ci             * can't be render targets.
506bf215546Sopenharmony_ci             */
507bf215546Sopenharmony_ci            D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES
508bf215546Sopenharmony_ci         };
509bf215546Sopenharmony_ci         for (int i = 0; i < ARRAY_SIZE(flags); ++i) {
510bf215546Sopenharmony_ci            D3D12_HEAP_FLAGS flag = flags[i];
511bf215546Sopenharmony_ci            pdev->heap_flags_for_mem_type[mem->memoryTypeCount] = flag;
512bf215546Sopenharmony_ci            mem->memoryTypes[mem->memoryTypeCount] = oldMemoryTypes[oldMemoryTypeIdx];
513bf215546Sopenharmony_ci            mem->memoryTypeCount++;
514bf215546Sopenharmony_ci         }
515bf215546Sopenharmony_ci      }
516bf215546Sopenharmony_ci   }
517bf215546Sopenharmony_ci}
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_cistatic D3D12_HEAP_FLAGS
520bf215546Sopenharmony_cidzn_physical_device_get_heap_flags_for_mem_type(const struct dzn_physical_device *pdev,
521bf215546Sopenharmony_ci                                                uint32_t mem_type)
522bf215546Sopenharmony_ci{
523bf215546Sopenharmony_ci   return pdev->heap_flags_for_mem_type[mem_type];
524bf215546Sopenharmony_ci}
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ciuint32_t
527bf215546Sopenharmony_cidzn_physical_device_get_mem_type_mask_for_resource(const struct dzn_physical_device *pdev,
528bf215546Sopenharmony_ci                                                   const D3D12_RESOURCE_DESC *desc)
529bf215546Sopenharmony_ci{
530bf215546Sopenharmony_ci   if (pdev->options.ResourceHeapTier > D3D12_RESOURCE_HEAP_TIER_1)
531bf215546Sopenharmony_ci      return (1u << pdev->memory.memoryTypeCount) - 1;
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci   D3D12_HEAP_FLAGS deny_flag;
534bf215546Sopenharmony_ci   if (desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
535bf215546Sopenharmony_ci      deny_flag = D3D12_HEAP_FLAG_DENY_BUFFERS;
536bf215546Sopenharmony_ci   else if (desc->Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))
537bf215546Sopenharmony_ci      deny_flag = D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES;
538bf215546Sopenharmony_ci   else
539bf215546Sopenharmony_ci      deny_flag = D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES;
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci   uint32_t mask = 0;
542bf215546Sopenharmony_ci   for (unsigned i = 0; i < pdev->memory.memoryTypeCount; ++i) {
543bf215546Sopenharmony_ci      if ((pdev->heap_flags_for_mem_type[i] & deny_flag) == D3D12_HEAP_FLAG_NONE)
544bf215546Sopenharmony_ci         mask |= (1 << i);
545bf215546Sopenharmony_ci   }
546bf215546Sopenharmony_ci   return mask;
547bf215546Sopenharmony_ci}
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_cistatic uint32_t
550bf215546Sopenharmony_cidzn_physical_device_get_max_mip_level(bool is_3d)
551bf215546Sopenharmony_ci{
552bf215546Sopenharmony_ci   return is_3d ? 11 : 14;
553bf215546Sopenharmony_ci}
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_cistatic uint32_t
556bf215546Sopenharmony_cidzn_physical_device_get_max_extent(bool is_3d)
557bf215546Sopenharmony_ci{
558bf215546Sopenharmony_ci   uint32_t max_mip = dzn_physical_device_get_max_mip_level(is_3d);
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_ci   return 1 << max_mip;
561bf215546Sopenharmony_ci}
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_cistatic uint32_t
564bf215546Sopenharmony_cidzn_physical_device_get_max_array_layers()
565bf215546Sopenharmony_ci{
566bf215546Sopenharmony_ci   return dzn_physical_device_get_max_extent(false);
567bf215546Sopenharmony_ci}
568bf215546Sopenharmony_ci
569bf215546Sopenharmony_cistatic ID3D12Device2 *
570bf215546Sopenharmony_cidzn_physical_device_get_d3d12_dev(struct dzn_physical_device *pdev)
571bf215546Sopenharmony_ci{
572bf215546Sopenharmony_ci   struct dzn_instance *instance = container_of(pdev->vk.instance, struct dzn_instance, vk);
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci   mtx_lock(&pdev->dev_lock);
575bf215546Sopenharmony_ci   if (!pdev->dev) {
576bf215546Sopenharmony_ci      pdev->dev = d3d12_create_device(pdev->adapter, !instance->dxil_validator);
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci      dzn_physical_device_cache_caps(pdev);
579bf215546Sopenharmony_ci      dzn_physical_device_init_memory(pdev);
580bf215546Sopenharmony_ci      dzn_physical_device_init_uuids(pdev);
581bf215546Sopenharmony_ci   }
582bf215546Sopenharmony_ci   mtx_unlock(&pdev->dev_lock);
583bf215546Sopenharmony_ci
584bf215546Sopenharmony_ci   return pdev->dev;
585bf215546Sopenharmony_ci}
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_ciD3D12_FEATURE_DATA_FORMAT_SUPPORT
588bf215546Sopenharmony_cidzn_physical_device_get_format_support(struct dzn_physical_device *pdev,
589bf215546Sopenharmony_ci                                       VkFormat format)
590bf215546Sopenharmony_ci{
591bf215546Sopenharmony_ci   VkImageUsageFlags usage =
592bf215546Sopenharmony_ci      vk_format_is_depth_or_stencil(format) ?
593bf215546Sopenharmony_ci      VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0;
594bf215546Sopenharmony_ci   VkImageAspectFlags aspects = 0;
595bf215546Sopenharmony_ci   VkFormat patched_format =
596bf215546Sopenharmony_ci      dzn_graphics_pipeline_patch_vi_format(format);
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci   if (patched_format != format) {
599bf215546Sopenharmony_ci      D3D12_FEATURE_DATA_FORMAT_SUPPORT dfmt_info = {
600bf215546Sopenharmony_ci         .Format = dzn_buffer_get_dxgi_format(patched_format),
601bf215546Sopenharmony_ci         .Support1 = D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER,
602bf215546Sopenharmony_ci      };
603bf215546Sopenharmony_ci
604bf215546Sopenharmony_ci      return dfmt_info;
605bf215546Sopenharmony_ci   }
606bf215546Sopenharmony_ci
607bf215546Sopenharmony_ci   if (vk_format_has_depth(format))
608bf215546Sopenharmony_ci      aspects = VK_IMAGE_ASPECT_DEPTH_BIT;
609bf215546Sopenharmony_ci   if (vk_format_has_stencil(format))
610bf215546Sopenharmony_ci      aspects = VK_IMAGE_ASPECT_STENCIL_BIT;
611bf215546Sopenharmony_ci
612bf215546Sopenharmony_ci   D3D12_FEATURE_DATA_FORMAT_SUPPORT dfmt_info = {
613bf215546Sopenharmony_ci     .Format = dzn_image_get_dxgi_format(format, usage, aspects),
614bf215546Sopenharmony_ci   };
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_ci   ID3D12Device2 *dev = dzn_physical_device_get_d3d12_dev(pdev);
617bf215546Sopenharmony_ci   ASSERTED HRESULT hres =
618bf215546Sopenharmony_ci      ID3D12Device1_CheckFeatureSupport(dev, D3D12_FEATURE_FORMAT_SUPPORT,
619bf215546Sopenharmony_ci                                        &dfmt_info, sizeof(dfmt_info));
620bf215546Sopenharmony_ci   assert(!FAILED(hres));
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ci   if (usage != VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
623bf215546Sopenharmony_ci      return dfmt_info;
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci   /* Depth/stencil resources have different format when they're accessed
626bf215546Sopenharmony_ci    * as textures, query the capabilities for this format too.
627bf215546Sopenharmony_ci    */
628bf215546Sopenharmony_ci   dzn_foreach_aspect(aspect, aspects) {
629bf215546Sopenharmony_ci      D3D12_FEATURE_DATA_FORMAT_SUPPORT dfmt_info2 = {
630bf215546Sopenharmony_ci        .Format = dzn_image_get_dxgi_format(format, 0, aspect),
631bf215546Sopenharmony_ci      };
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci      hres = ID3D12Device1_CheckFeatureSupport(dev, D3D12_FEATURE_FORMAT_SUPPORT,
634bf215546Sopenharmony_ci                                      &dfmt_info2, sizeof(dfmt_info2));
635bf215546Sopenharmony_ci      assert(!FAILED(hres));
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_ci#define DS_SRV_FORMAT_SUPPORT1_MASK \
638bf215546Sopenharmony_ci        (D3D12_FORMAT_SUPPORT1_SHADER_LOAD | \
639bf215546Sopenharmony_ci         D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE | \
640bf215546Sopenharmony_ci         D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE_COMPARISON | \
641bf215546Sopenharmony_ci         D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE_MONO_TEXT | \
642bf215546Sopenharmony_ci         D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE | \
643bf215546Sopenharmony_ci         D3D12_FORMAT_SUPPORT1_MULTISAMPLE_LOAD | \
644bf215546Sopenharmony_ci         D3D12_FORMAT_SUPPORT1_SHADER_GATHER | \
645bf215546Sopenharmony_ci         D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW | \
646bf215546Sopenharmony_ci         D3D12_FORMAT_SUPPORT1_SHADER_GATHER_COMPARISON)
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_ci      dfmt_info.Support1 |= dfmt_info2.Support1 & DS_SRV_FORMAT_SUPPORT1_MASK;
649bf215546Sopenharmony_ci      dfmt_info.Support2 |= dfmt_info2.Support2;
650bf215546Sopenharmony_ci   }
651bf215546Sopenharmony_ci
652bf215546Sopenharmony_ci   return dfmt_info;
653bf215546Sopenharmony_ci}
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_cistatic void
656bf215546Sopenharmony_cidzn_physical_device_get_format_properties(struct dzn_physical_device *pdev,
657bf215546Sopenharmony_ci                                          VkFormat format,
658bf215546Sopenharmony_ci                                          VkFormatProperties2 *properties)
659bf215546Sopenharmony_ci{
660bf215546Sopenharmony_ci   D3D12_FEATURE_DATA_FORMAT_SUPPORT dfmt_info =
661bf215546Sopenharmony_ci      dzn_physical_device_get_format_support(pdev, format);
662bf215546Sopenharmony_ci   VkFormatProperties *base_props = &properties->formatProperties;
663bf215546Sopenharmony_ci
664bf215546Sopenharmony_ci   vk_foreach_struct(ext, properties->pNext) {
665bf215546Sopenharmony_ci      dzn_debug_ignored_stype(ext->sType);
666bf215546Sopenharmony_ci   }
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_ci   if (dfmt_info.Format == DXGI_FORMAT_UNKNOWN) {
669bf215546Sopenharmony_ci      *base_props = (VkFormatProperties) { 0 };
670bf215546Sopenharmony_ci      return;
671bf215546Sopenharmony_ci   }
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci   *base_props = (VkFormatProperties) {
674bf215546Sopenharmony_ci      .linearTilingFeatures = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
675bf215546Sopenharmony_ci      .optimalTilingFeatures = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
676bf215546Sopenharmony_ci      .bufferFeatures = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
677bf215546Sopenharmony_ci   };
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci   if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_IA_VERTEX_BUFFER)
680bf215546Sopenharmony_ci      base_props->bufferFeatures |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_ci#define TEX_FLAGS (D3D12_FORMAT_SUPPORT1_TEXTURE1D | \
683bf215546Sopenharmony_ci                   D3D12_FORMAT_SUPPORT1_TEXTURE2D | \
684bf215546Sopenharmony_ci                   D3D12_FORMAT_SUPPORT1_TEXTURE3D | \
685bf215546Sopenharmony_ci                   D3D12_FORMAT_SUPPORT1_TEXTURECUBE)
686bf215546Sopenharmony_ci   if (dfmt_info.Support1 & TEX_FLAGS) {
687bf215546Sopenharmony_ci      base_props->optimalTilingFeatures |=
688bf215546Sopenharmony_ci         VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT;
689bf215546Sopenharmony_ci   }
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci   if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE) {
692bf215546Sopenharmony_ci      base_props->optimalTilingFeatures |=
693bf215546Sopenharmony_ci         VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
694bf215546Sopenharmony_ci   }
695bf215546Sopenharmony_ci
696bf215546Sopenharmony_ci   if ((dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD) &&
697bf215546Sopenharmony_ci       (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW)) {
698bf215546Sopenharmony_ci      base_props->optimalTilingFeatures |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
699bf215546Sopenharmony_ci      base_props->bufferFeatures |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
700bf215546Sopenharmony_ci   }
701bf215546Sopenharmony_ci
702bf215546Sopenharmony_ci#define ATOMIC_FLAGS (D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_ADD | \
703bf215546Sopenharmony_ci                      D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS | \
704bf215546Sopenharmony_ci                      D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE | \
705bf215546Sopenharmony_ci                      D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE | \
706bf215546Sopenharmony_ci                      D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX | \
707bf215546Sopenharmony_ci                      D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX)
708bf215546Sopenharmony_ci   if ((dfmt_info.Support2 & ATOMIC_FLAGS) == ATOMIC_FLAGS) {
709bf215546Sopenharmony_ci      base_props->optimalTilingFeatures |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
710bf215546Sopenharmony_ci      base_props->bufferFeatures |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
711bf215546Sopenharmony_ci   }
712bf215546Sopenharmony_ci
713bf215546Sopenharmony_ci   if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD)
714bf215546Sopenharmony_ci      base_props->bufferFeatures |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
715bf215546Sopenharmony_ci
716bf215546Sopenharmony_ci   /* Color/depth/stencil attachment cap implies input attachement cap, and input
717bf215546Sopenharmony_ci    * attachment loads are lowered to texture loads in dozen, hence the requirement
718bf215546Sopenharmony_ci    * to have shader-load support.
719bf215546Sopenharmony_ci    */
720bf215546Sopenharmony_ci   if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD) {
721bf215546Sopenharmony_ci      if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET) {
722bf215546Sopenharmony_ci         base_props->optimalTilingFeatures |=
723bf215546Sopenharmony_ci            VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
724bf215546Sopenharmony_ci      }
725bf215546Sopenharmony_ci
726bf215546Sopenharmony_ci      if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_BLENDABLE)
727bf215546Sopenharmony_ci         base_props->optimalTilingFeatures |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_ci      if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL) {
730bf215546Sopenharmony_ci         base_props->optimalTilingFeatures |=
731bf215546Sopenharmony_ci            VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
732bf215546Sopenharmony_ci      }
733bf215546Sopenharmony_ci   }
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_ci   /* B4G4R4A4 support is required, but d3d12 doesn't support it. We map this
736bf215546Sopenharmony_ci    * format to R4G4B4A4 and adjust the SRV component-mapping to fake
737bf215546Sopenharmony_ci    * B4G4R4A4, but that forces us to limit the usage to sampling, which,
738bf215546Sopenharmony_ci    * luckily, is exactly what we need to support the required features.
739bf215546Sopenharmony_ci    */
740bf215546Sopenharmony_ci   if (format == VK_FORMAT_B4G4R4A4_UNORM_PACK16) {
741bf215546Sopenharmony_ci      VkFormatFeatureFlags bgra4_req_features =
742bf215546Sopenharmony_ci         VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
743bf215546Sopenharmony_ci         VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
744bf215546Sopenharmony_ci         VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
745bf215546Sopenharmony_ci         VK_FORMAT_FEATURE_BLIT_SRC_BIT |
746bf215546Sopenharmony_ci         VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
747bf215546Sopenharmony_ci      base_props->optimalTilingFeatures &= bgra4_req_features;
748bf215546Sopenharmony_ci      base_props->bufferFeatures =
749bf215546Sopenharmony_ci         VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
750bf215546Sopenharmony_ci   }
751bf215546Sopenharmony_ci
752bf215546Sopenharmony_ci   /* depth/stencil format shouldn't advertise buffer features */
753bf215546Sopenharmony_ci   if (vk_format_is_depth_or_stencil(format))
754bf215546Sopenharmony_ci      base_props->bufferFeatures = 0;
755bf215546Sopenharmony_ci}
756bf215546Sopenharmony_ci
757bf215546Sopenharmony_cistatic VkResult
758bf215546Sopenharmony_cidzn_physical_device_get_image_format_properties(struct dzn_physical_device *pdev,
759bf215546Sopenharmony_ci                                                const VkPhysicalDeviceImageFormatInfo2 *info,
760bf215546Sopenharmony_ci                                                VkImageFormatProperties2 *properties)
761bf215546Sopenharmony_ci{
762bf215546Sopenharmony_ci   const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
763bf215546Sopenharmony_ci   VkExternalImageFormatProperties *external_props = NULL;
764bf215546Sopenharmony_ci
765bf215546Sopenharmony_ci   *properties = (VkImageFormatProperties2) {
766bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
767bf215546Sopenharmony_ci   };
768bf215546Sopenharmony_ci
769bf215546Sopenharmony_ci   /* Extract input structs */
770bf215546Sopenharmony_ci   vk_foreach_struct_const(s, info->pNext) {
771bf215546Sopenharmony_ci      switch (s->sType) {
772bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
773bf215546Sopenharmony_ci         external_info = (const VkPhysicalDeviceExternalImageFormatInfo *)s;
774bf215546Sopenharmony_ci         break;
775bf215546Sopenharmony_ci      default:
776bf215546Sopenharmony_ci         dzn_debug_ignored_stype(s->sType);
777bf215546Sopenharmony_ci         break;
778bf215546Sopenharmony_ci      }
779bf215546Sopenharmony_ci   }
780bf215546Sopenharmony_ci
781bf215546Sopenharmony_ci   assert(info->tiling == VK_IMAGE_TILING_OPTIMAL || info->tiling == VK_IMAGE_TILING_LINEAR);
782bf215546Sopenharmony_ci
783bf215546Sopenharmony_ci   /* Extract output structs */
784bf215546Sopenharmony_ci   vk_foreach_struct(s, properties->pNext) {
785bf215546Sopenharmony_ci      switch (s->sType) {
786bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
787bf215546Sopenharmony_ci         external_props = (VkExternalImageFormatProperties *)s;
788bf215546Sopenharmony_ci         external_props->externalMemoryProperties = (VkExternalMemoryProperties) { 0 };
789bf215546Sopenharmony_ci         break;
790bf215546Sopenharmony_ci      default:
791bf215546Sopenharmony_ci         dzn_debug_ignored_stype(s->sType);
792bf215546Sopenharmony_ci         break;
793bf215546Sopenharmony_ci      }
794bf215546Sopenharmony_ci   }
795bf215546Sopenharmony_ci
796bf215546Sopenharmony_ci   /* TODO: support image import */
797bf215546Sopenharmony_ci   if (external_info && external_info->handleType != 0)
798bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
799bf215546Sopenharmony_ci
800bf215546Sopenharmony_ci   if (info->tiling != VK_IMAGE_TILING_OPTIMAL &&
801bf215546Sopenharmony_ci       (info->usage & ~(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)))
802bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
803bf215546Sopenharmony_ci
804bf215546Sopenharmony_ci   if (info->tiling != VK_IMAGE_TILING_OPTIMAL &&
805bf215546Sopenharmony_ci       vk_format_is_depth_or_stencil(info->format))
806bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
807bf215546Sopenharmony_ci
808bf215546Sopenharmony_ci   D3D12_FEATURE_DATA_FORMAT_SUPPORT dfmt_info =
809bf215546Sopenharmony_ci      dzn_physical_device_get_format_support(pdev, info->format);
810bf215546Sopenharmony_ci   if (dfmt_info.Format == DXGI_FORMAT_UNKNOWN)
811bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
812bf215546Sopenharmony_ci
813bf215546Sopenharmony_ci   bool is_bgra4 = info->format == VK_FORMAT_B4G4R4A4_UNORM_PACK16;
814bf215546Sopenharmony_ci   ID3D12Device2 *dev = dzn_physical_device_get_d3d12_dev(pdev);
815bf215546Sopenharmony_ci
816bf215546Sopenharmony_ci   if ((info->type == VK_IMAGE_TYPE_1D && !(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE1D)) ||
817bf215546Sopenharmony_ci       (info->type == VK_IMAGE_TYPE_2D && !(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D)) ||
818bf215546Sopenharmony_ci       (info->type == VK_IMAGE_TYPE_3D && !(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE3D)) ||
819bf215546Sopenharmony_ci       ((info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
820bf215546Sopenharmony_ci        !(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURECUBE)))
821bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
822bf215546Sopenharmony_ci
823bf215546Sopenharmony_ci   if ((info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) &&
824bf215546Sopenharmony_ci       !(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE))
825bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
826bf215546Sopenharmony_ci
827bf215546Sopenharmony_ci   if ((info->usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) &&
828bf215546Sopenharmony_ci       (!(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD) || is_bgra4))
829bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
830bf215546Sopenharmony_ci
831bf215546Sopenharmony_ci   if ((info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) &&
832bf215546Sopenharmony_ci       (!(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET) || is_bgra4))
833bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
834bf215546Sopenharmony_ci
835bf215546Sopenharmony_ci   if ((info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) &&
836bf215546Sopenharmony_ci       (!(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL) || is_bgra4))
837bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
838bf215546Sopenharmony_ci
839bf215546Sopenharmony_ci   if ((info->usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
840bf215546Sopenharmony_ci       (!(dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW) || is_bgra4))
841bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
842bf215546Sopenharmony_ci
843bf215546Sopenharmony_ci   if (info->type == VK_IMAGE_TYPE_3D && info->tiling != VK_IMAGE_TILING_OPTIMAL)
844bf215546Sopenharmony_ci      return VK_ERROR_FORMAT_NOT_SUPPORTED;
845bf215546Sopenharmony_ci
846bf215546Sopenharmony_ci   bool is_3d = info->type == VK_IMAGE_TYPE_3D;
847bf215546Sopenharmony_ci   uint32_t max_extent = dzn_physical_device_get_max_extent(is_3d);
848bf215546Sopenharmony_ci
849bf215546Sopenharmony_ci   if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
850bf215546Sopenharmony_ci       dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_MIP)
851bf215546Sopenharmony_ci      properties->imageFormatProperties.maxMipLevels = dzn_physical_device_get_max_mip_level(is_3d) + 1;
852bf215546Sopenharmony_ci   else
853bf215546Sopenharmony_ci      properties->imageFormatProperties.maxMipLevels = 1;
854bf215546Sopenharmony_ci
855bf215546Sopenharmony_ci   if (info->tiling == VK_IMAGE_TILING_OPTIMAL && info->type != VK_IMAGE_TYPE_3D)
856bf215546Sopenharmony_ci      properties->imageFormatProperties.maxArrayLayers = dzn_physical_device_get_max_array_layers();
857bf215546Sopenharmony_ci   else
858bf215546Sopenharmony_ci      properties->imageFormatProperties.maxArrayLayers = 1;
859bf215546Sopenharmony_ci
860bf215546Sopenharmony_ci   switch (info->type) {
861bf215546Sopenharmony_ci   case VK_IMAGE_TYPE_1D:
862bf215546Sopenharmony_ci      properties->imageFormatProperties.maxExtent.width = max_extent;
863bf215546Sopenharmony_ci      properties->imageFormatProperties.maxExtent.height = 1;
864bf215546Sopenharmony_ci      properties->imageFormatProperties.maxExtent.depth = 1;
865bf215546Sopenharmony_ci      break;
866bf215546Sopenharmony_ci   case VK_IMAGE_TYPE_2D:
867bf215546Sopenharmony_ci      properties->imageFormatProperties.maxExtent.width = max_extent;
868bf215546Sopenharmony_ci      properties->imageFormatProperties.maxExtent.height = max_extent;
869bf215546Sopenharmony_ci      properties->imageFormatProperties.maxExtent.depth = 1;
870bf215546Sopenharmony_ci      break;
871bf215546Sopenharmony_ci   case VK_IMAGE_TYPE_3D:
872bf215546Sopenharmony_ci      properties->imageFormatProperties.maxExtent.width = max_extent;
873bf215546Sopenharmony_ci      properties->imageFormatProperties.maxExtent.height = max_extent;
874bf215546Sopenharmony_ci      properties->imageFormatProperties.maxExtent.depth = max_extent;
875bf215546Sopenharmony_ci      break;
876bf215546Sopenharmony_ci   default:
877bf215546Sopenharmony_ci      unreachable("bad VkImageType");
878bf215546Sopenharmony_ci   }
879bf215546Sopenharmony_ci
880bf215546Sopenharmony_ci   /* From the Vulkan 1.0 spec, section 34.1.1. Supported Sample Counts:
881bf215546Sopenharmony_ci    *
882bf215546Sopenharmony_ci    * sampleCounts will be set to VK_SAMPLE_COUNT_1_BIT if at least one of the
883bf215546Sopenharmony_ci    * following conditions is true:
884bf215546Sopenharmony_ci    *
885bf215546Sopenharmony_ci    *   - tiling is VK_IMAGE_TILING_LINEAR
886bf215546Sopenharmony_ci    *   - type is not VK_IMAGE_TYPE_2D
887bf215546Sopenharmony_ci    *   - flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
888bf215546Sopenharmony_ci    *   - neither the VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT flag nor the
889bf215546Sopenharmony_ci    *     VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT flag in
890bf215546Sopenharmony_ci    *     VkFormatProperties::optimalTilingFeatures returned by
891bf215546Sopenharmony_ci    *     vkGetPhysicalDeviceFormatProperties is set.
892bf215546Sopenharmony_ci    *
893bf215546Sopenharmony_ci    * D3D12 has a few more constraints:
894bf215546Sopenharmony_ci    *   - no UAVs on multisample resources
895bf215546Sopenharmony_ci    */
896bf215546Sopenharmony_ci   bool rt_or_ds_cap =
897bf215546Sopenharmony_ci      dfmt_info.Support1 &
898bf215546Sopenharmony_ci      (D3D12_FORMAT_SUPPORT1_RENDER_TARGET | D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL);
899bf215546Sopenharmony_ci
900bf215546Sopenharmony_ci   properties->imageFormatProperties.sampleCounts = VK_SAMPLE_COUNT_1_BIT;
901bf215546Sopenharmony_ci   if (info->tiling != VK_IMAGE_TILING_LINEAR &&
902bf215546Sopenharmony_ci       info->type == VK_IMAGE_TYPE_2D &&
903bf215546Sopenharmony_ci       !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
904bf215546Sopenharmony_ci       rt_or_ds_cap && !is_bgra4 &&
905bf215546Sopenharmony_ci       !(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
906bf215546Sopenharmony_ci      for (uint32_t s = VK_SAMPLE_COUNT_2_BIT; s < VK_SAMPLE_COUNT_64_BIT; s <<= 1) {
907bf215546Sopenharmony_ci         D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS ms_info = {
908bf215546Sopenharmony_ci            .Format = dfmt_info.Format,
909bf215546Sopenharmony_ci            .SampleCount = s,
910bf215546Sopenharmony_ci         };
911bf215546Sopenharmony_ci
912bf215546Sopenharmony_ci         HRESULT hres =
913bf215546Sopenharmony_ci            ID3D12Device1_CheckFeatureSupport(dev, D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
914bf215546Sopenharmony_ci                                     &ms_info, sizeof(ms_info));
915bf215546Sopenharmony_ci         if (!FAILED(hres) && ms_info.NumQualityLevels > 0)
916bf215546Sopenharmony_ci            properties->imageFormatProperties.sampleCounts |= s;
917bf215546Sopenharmony_ci      }
918bf215546Sopenharmony_ci   }
919bf215546Sopenharmony_ci
920bf215546Sopenharmony_ci   /* TODO: set correct value here */
921bf215546Sopenharmony_ci   properties->imageFormatProperties.maxResourceSize = UINT32_MAX;
922bf215546Sopenharmony_ci
923bf215546Sopenharmony_ci   return VK_SUCCESS;
924bf215546Sopenharmony_ci}
925bf215546Sopenharmony_ci
926bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
927bf215546Sopenharmony_cidzn_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
928bf215546Sopenharmony_ci                                       VkFormat format,
929bf215546Sopenharmony_ci                                       VkFormatProperties2 *pFormatProperties)
930bf215546Sopenharmony_ci{
931bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice);
932bf215546Sopenharmony_ci
933bf215546Sopenharmony_ci   dzn_physical_device_get_format_properties(pdev, format, pFormatProperties);
934bf215546Sopenharmony_ci}
935bf215546Sopenharmony_ci
936bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
937bf215546Sopenharmony_cidzn_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
938bf215546Sopenharmony_ci                                            const VkPhysicalDeviceImageFormatInfo2 *info,
939bf215546Sopenharmony_ci                                            VkImageFormatProperties2 *props)
940bf215546Sopenharmony_ci{
941bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice);
942bf215546Sopenharmony_ci
943bf215546Sopenharmony_ci   return dzn_physical_device_get_image_format_properties(pdev, info, props);
944bf215546Sopenharmony_ci}
945bf215546Sopenharmony_ci
946bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
947bf215546Sopenharmony_cidzn_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,
948bf215546Sopenharmony_ci                                           VkFormat format,
949bf215546Sopenharmony_ci                                           VkImageType type,
950bf215546Sopenharmony_ci                                           VkImageTiling tiling,
951bf215546Sopenharmony_ci                                           VkImageUsageFlags usage,
952bf215546Sopenharmony_ci                                           VkImageCreateFlags createFlags,
953bf215546Sopenharmony_ci                                           VkImageFormatProperties *pImageFormatProperties)
954bf215546Sopenharmony_ci{
955bf215546Sopenharmony_ci   const VkPhysicalDeviceImageFormatInfo2 info = {
956bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
957bf215546Sopenharmony_ci      .format = format,
958bf215546Sopenharmony_ci      .type = type,
959bf215546Sopenharmony_ci      .tiling = tiling,
960bf215546Sopenharmony_ci      .usage = usage,
961bf215546Sopenharmony_ci      .flags = createFlags,
962bf215546Sopenharmony_ci   };
963bf215546Sopenharmony_ci
964bf215546Sopenharmony_ci   VkImageFormatProperties2 props = { 0 };
965bf215546Sopenharmony_ci
966bf215546Sopenharmony_ci   VkResult result =
967bf215546Sopenharmony_ci      dzn_GetPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &props);
968bf215546Sopenharmony_ci   *pImageFormatProperties = props.imageFormatProperties;
969bf215546Sopenharmony_ci
970bf215546Sopenharmony_ci   return result;
971bf215546Sopenharmony_ci}
972bf215546Sopenharmony_ci
973bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
974bf215546Sopenharmony_cidzn_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,
975bf215546Sopenharmony_ci                                                 VkFormat format,
976bf215546Sopenharmony_ci                                                 VkImageType type,
977bf215546Sopenharmony_ci                                                 VkSampleCountFlagBits samples,
978bf215546Sopenharmony_ci                                                 VkImageUsageFlags usage,
979bf215546Sopenharmony_ci                                                 VkImageTiling tiling,
980bf215546Sopenharmony_ci                                                 uint32_t *pPropertyCount,
981bf215546Sopenharmony_ci                                                 VkSparseImageFormatProperties *pProperties)
982bf215546Sopenharmony_ci{
983bf215546Sopenharmony_ci   *pPropertyCount = 0;
984bf215546Sopenharmony_ci}
985bf215546Sopenharmony_ci
986bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
987bf215546Sopenharmony_cidzn_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,
988bf215546Sopenharmony_ci                                                  const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
989bf215546Sopenharmony_ci                                                  uint32_t *pPropertyCount,
990bf215546Sopenharmony_ci                                                  VkSparseImageFormatProperties2 *pProperties)
991bf215546Sopenharmony_ci{
992bf215546Sopenharmony_ci   *pPropertyCount = 0;
993bf215546Sopenharmony_ci}
994bf215546Sopenharmony_ci
995bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
996bf215546Sopenharmony_cidzn_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,
997bf215546Sopenharmony_ci                                              const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
998bf215546Sopenharmony_ci                                              VkExternalBufferProperties *pExternalBufferProperties)
999bf215546Sopenharmony_ci{
1000bf215546Sopenharmony_ci   pExternalBufferProperties->externalMemoryProperties =
1001bf215546Sopenharmony_ci      (VkExternalMemoryProperties) {
1002bf215546Sopenharmony_ci         .compatibleHandleTypes = (VkExternalMemoryHandleTypeFlags)pExternalBufferInfo->handleType,
1003bf215546Sopenharmony_ci      };
1004bf215546Sopenharmony_ci}
1005bf215546Sopenharmony_ci
1006bf215546Sopenharmony_ciVkResult
1007bf215546Sopenharmony_cidzn_instance_add_physical_device(struct dzn_instance *instance,
1008bf215546Sopenharmony_ci                                 IUnknown *adapter,
1009bf215546Sopenharmony_ci                                 const struct dzn_physical_device_desc *desc)
1010bf215546Sopenharmony_ci{
1011bf215546Sopenharmony_ci   if ((instance->debug_flags & DZN_DEBUG_WARP) &&
1012bf215546Sopenharmony_ci       !desc->is_warp)
1013bf215546Sopenharmony_ci      return VK_SUCCESS;
1014bf215546Sopenharmony_ci
1015bf215546Sopenharmony_ci   return dzn_physical_device_create(instance, adapter, desc);
1016bf215546Sopenharmony_ci}
1017bf215546Sopenharmony_ci
1018bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
1019bf215546Sopenharmony_cidzn_EnumeratePhysicalDevices(VkInstance inst,
1020bf215546Sopenharmony_ci                             uint32_t *pPhysicalDeviceCount,
1021bf215546Sopenharmony_ci                             VkPhysicalDevice *pPhysicalDevices)
1022bf215546Sopenharmony_ci{
1023bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_instance, instance, inst);
1024bf215546Sopenharmony_ci
1025bf215546Sopenharmony_ci   if (!instance->physical_devices_enumerated) {
1026bf215546Sopenharmony_ci      VkResult result = dzn_enumerate_physical_devices_dxcore(instance);
1027bf215546Sopenharmony_ci#ifdef _WIN32
1028bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1029bf215546Sopenharmony_ci         result = dzn_enumerate_physical_devices_dxgi(instance);
1030bf215546Sopenharmony_ci#endif
1031bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1032bf215546Sopenharmony_ci         return result;
1033bf215546Sopenharmony_ci   }
1034bf215546Sopenharmony_ci
1035bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkPhysicalDevice, out, pPhysicalDevices,
1036bf215546Sopenharmony_ci                          pPhysicalDeviceCount);
1037bf215546Sopenharmony_ci
1038bf215546Sopenharmony_ci   list_for_each_entry(struct dzn_physical_device, pdev, &instance->physical_devices, link) {
1039bf215546Sopenharmony_ci      vk_outarray_append_typed(VkPhysicalDevice, &out, i)
1040bf215546Sopenharmony_ci         *i = dzn_physical_device_to_handle(pdev);
1041bf215546Sopenharmony_ci   }
1042bf215546Sopenharmony_ci
1043bf215546Sopenharmony_ci   instance->physical_devices_enumerated = true;
1044bf215546Sopenharmony_ci   return vk_outarray_status(&out);
1045bf215546Sopenharmony_ci}
1046bf215546Sopenharmony_ci
1047bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
1048bf215546Sopenharmony_cidzn_EnumerateInstanceVersion(uint32_t *pApiVersion)
1049bf215546Sopenharmony_ci{
1050bf215546Sopenharmony_ci   *pApiVersion = DZN_API_VERSION;
1051bf215546Sopenharmony_ci   return VK_SUCCESS;
1052bf215546Sopenharmony_ci}
1053bf215546Sopenharmony_ci
1054bf215546Sopenharmony_cistatic bool
1055bf215546Sopenharmony_cidzn_physical_device_supports_compressed_format(struct dzn_physical_device *pdev,
1056bf215546Sopenharmony_ci                                               const VkFormat *formats,
1057bf215546Sopenharmony_ci                                               uint32_t format_count)
1058bf215546Sopenharmony_ci{
1059bf215546Sopenharmony_ci#define REQUIRED_COMPRESSED_CAPS \
1060bf215546Sopenharmony_ci        (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | \
1061bf215546Sopenharmony_ci         VK_FORMAT_FEATURE_BLIT_SRC_BIT | \
1062bf215546Sopenharmony_ci         VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)
1063bf215546Sopenharmony_ci   for (uint32_t i = 0; i < format_count; i++) {
1064bf215546Sopenharmony_ci      VkFormatProperties2 props = { 0 };
1065bf215546Sopenharmony_ci      dzn_physical_device_get_format_properties(pdev, formats[i], &props);
1066bf215546Sopenharmony_ci      if ((props.formatProperties.optimalTilingFeatures & REQUIRED_COMPRESSED_CAPS) != REQUIRED_COMPRESSED_CAPS)
1067bf215546Sopenharmony_ci         return false;
1068bf215546Sopenharmony_ci   }
1069bf215546Sopenharmony_ci
1070bf215546Sopenharmony_ci   return true;
1071bf215546Sopenharmony_ci}
1072bf215546Sopenharmony_ci
1073bf215546Sopenharmony_cistatic bool
1074bf215546Sopenharmony_cidzn_physical_device_supports_bc(struct dzn_physical_device *pdev)
1075bf215546Sopenharmony_ci{
1076bf215546Sopenharmony_ci   static const VkFormat formats[] = {
1077bf215546Sopenharmony_ci      VK_FORMAT_BC1_RGB_UNORM_BLOCK,
1078bf215546Sopenharmony_ci      VK_FORMAT_BC1_RGB_SRGB_BLOCK,
1079bf215546Sopenharmony_ci      VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
1080bf215546Sopenharmony_ci      VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
1081bf215546Sopenharmony_ci      VK_FORMAT_BC2_UNORM_BLOCK,
1082bf215546Sopenharmony_ci      VK_FORMAT_BC2_SRGB_BLOCK,
1083bf215546Sopenharmony_ci      VK_FORMAT_BC3_UNORM_BLOCK,
1084bf215546Sopenharmony_ci      VK_FORMAT_BC3_SRGB_BLOCK,
1085bf215546Sopenharmony_ci      VK_FORMAT_BC4_UNORM_BLOCK,
1086bf215546Sopenharmony_ci      VK_FORMAT_BC4_SNORM_BLOCK,
1087bf215546Sopenharmony_ci      VK_FORMAT_BC5_UNORM_BLOCK,
1088bf215546Sopenharmony_ci      VK_FORMAT_BC5_SNORM_BLOCK,
1089bf215546Sopenharmony_ci      VK_FORMAT_BC6H_UFLOAT_BLOCK,
1090bf215546Sopenharmony_ci      VK_FORMAT_BC6H_SFLOAT_BLOCK,
1091bf215546Sopenharmony_ci      VK_FORMAT_BC7_UNORM_BLOCK,
1092bf215546Sopenharmony_ci      VK_FORMAT_BC7_SRGB_BLOCK,
1093bf215546Sopenharmony_ci   };
1094bf215546Sopenharmony_ci
1095bf215546Sopenharmony_ci   return dzn_physical_device_supports_compressed_format(pdev, formats, ARRAY_SIZE(formats));
1096bf215546Sopenharmony_ci}
1097bf215546Sopenharmony_ci
1098bf215546Sopenharmony_cistatic bool
1099bf215546Sopenharmony_cidzn_physical_device_supports_depth_bounds(struct dzn_physical_device *pdev)
1100bf215546Sopenharmony_ci{
1101bf215546Sopenharmony_ci   dzn_physical_device_get_d3d12_dev(pdev);
1102bf215546Sopenharmony_ci
1103bf215546Sopenharmony_ci   return pdev->options2.DepthBoundsTestSupported;
1104bf215546Sopenharmony_ci}
1105bf215546Sopenharmony_ci
1106bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1107bf215546Sopenharmony_cidzn_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
1108bf215546Sopenharmony_ci                               VkPhysicalDeviceFeatures2 *pFeatures)
1109bf215546Sopenharmony_ci{
1110bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice);
1111bf215546Sopenharmony_ci
1112bf215546Sopenharmony_ci   pFeatures->features = (VkPhysicalDeviceFeatures) {
1113bf215546Sopenharmony_ci      .robustBufferAccess = true, /* This feature is mandatory */
1114bf215546Sopenharmony_ci      .fullDrawIndexUint32 = false,
1115bf215546Sopenharmony_ci      .imageCubeArray = true,
1116bf215546Sopenharmony_ci      .independentBlend = false,
1117bf215546Sopenharmony_ci      .geometryShader = true,
1118bf215546Sopenharmony_ci      .tessellationShader = false,
1119bf215546Sopenharmony_ci      .sampleRateShading = true,
1120bf215546Sopenharmony_ci      .dualSrcBlend = false,
1121bf215546Sopenharmony_ci      .logicOp = false,
1122bf215546Sopenharmony_ci      .multiDrawIndirect = true,
1123bf215546Sopenharmony_ci      .drawIndirectFirstInstance = true,
1124bf215546Sopenharmony_ci      .depthClamp = true,
1125bf215546Sopenharmony_ci      .depthBiasClamp = true,
1126bf215546Sopenharmony_ci      .fillModeNonSolid = false,
1127bf215546Sopenharmony_ci      .depthBounds = dzn_physical_device_supports_depth_bounds(pdev),
1128bf215546Sopenharmony_ci      .wideLines = false,
1129bf215546Sopenharmony_ci      .largePoints = false,
1130bf215546Sopenharmony_ci      .alphaToOne = false,
1131bf215546Sopenharmony_ci      .multiViewport = false,
1132bf215546Sopenharmony_ci      .samplerAnisotropy = true,
1133bf215546Sopenharmony_ci      .textureCompressionETC2 = false,
1134bf215546Sopenharmony_ci      .textureCompressionASTC_LDR = false,
1135bf215546Sopenharmony_ci      .textureCompressionBC = dzn_physical_device_supports_bc(pdev),
1136bf215546Sopenharmony_ci      .occlusionQueryPrecise = true,
1137bf215546Sopenharmony_ci      .pipelineStatisticsQuery = true,
1138bf215546Sopenharmony_ci      .vertexPipelineStoresAndAtomics = true,
1139bf215546Sopenharmony_ci      .fragmentStoresAndAtomics = true,
1140bf215546Sopenharmony_ci      .shaderTessellationAndGeometryPointSize = false,
1141bf215546Sopenharmony_ci      .shaderImageGatherExtended = true,
1142bf215546Sopenharmony_ci      .shaderStorageImageExtendedFormats = false,
1143bf215546Sopenharmony_ci      .shaderStorageImageMultisample = false,
1144bf215546Sopenharmony_ci      .shaderStorageImageReadWithoutFormat = false,
1145bf215546Sopenharmony_ci      .shaderStorageImageWriteWithoutFormat = false,
1146bf215546Sopenharmony_ci      .shaderUniformBufferArrayDynamicIndexing = true,
1147bf215546Sopenharmony_ci      .shaderSampledImageArrayDynamicIndexing = true,
1148bf215546Sopenharmony_ci      .shaderStorageBufferArrayDynamicIndexing = true,
1149bf215546Sopenharmony_ci      .shaderStorageImageArrayDynamicIndexing = true,
1150bf215546Sopenharmony_ci      .shaderClipDistance = true,
1151bf215546Sopenharmony_ci      .shaderCullDistance = true,
1152bf215546Sopenharmony_ci      .shaderFloat64 = false,
1153bf215546Sopenharmony_ci      .shaderInt64 = false,
1154bf215546Sopenharmony_ci      .shaderInt16 = false,
1155bf215546Sopenharmony_ci      .shaderResourceResidency = false,
1156bf215546Sopenharmony_ci      .shaderResourceMinLod = false,
1157bf215546Sopenharmony_ci      .sparseBinding = false,
1158bf215546Sopenharmony_ci      .sparseResidencyBuffer = false,
1159bf215546Sopenharmony_ci      .sparseResidencyImage2D = false,
1160bf215546Sopenharmony_ci      .sparseResidencyImage3D = false,
1161bf215546Sopenharmony_ci      .sparseResidency2Samples = false,
1162bf215546Sopenharmony_ci      .sparseResidency4Samples = false,
1163bf215546Sopenharmony_ci      .sparseResidency8Samples = false,
1164bf215546Sopenharmony_ci      .sparseResidency16Samples = false,
1165bf215546Sopenharmony_ci      .sparseResidencyAliased = false,
1166bf215546Sopenharmony_ci      .variableMultisampleRate = false,
1167bf215546Sopenharmony_ci      .inheritedQueries = false,
1168bf215546Sopenharmony_ci   };
1169bf215546Sopenharmony_ci
1170bf215546Sopenharmony_ci   VkPhysicalDeviceVulkan11Features core_1_1 = {
1171bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
1172bf215546Sopenharmony_ci      .storageBuffer16BitAccess           = false,
1173bf215546Sopenharmony_ci      .uniformAndStorageBuffer16BitAccess = false,
1174bf215546Sopenharmony_ci      .storagePushConstant16              = false,
1175bf215546Sopenharmony_ci      .storageInputOutput16               = false,
1176bf215546Sopenharmony_ci      .multiview                          = false,
1177bf215546Sopenharmony_ci      .multiviewGeometryShader            = false,
1178bf215546Sopenharmony_ci      .multiviewTessellationShader        = false,
1179bf215546Sopenharmony_ci      .variablePointersStorageBuffer      = true,
1180bf215546Sopenharmony_ci      .variablePointers                   = true,
1181bf215546Sopenharmony_ci      .protectedMemory                    = false,
1182bf215546Sopenharmony_ci      .samplerYcbcrConversion             = false,
1183bf215546Sopenharmony_ci      .shaderDrawParameters               = true,
1184bf215546Sopenharmony_ci   };
1185bf215546Sopenharmony_ci
1186bf215546Sopenharmony_ci   const VkPhysicalDeviceVulkan12Features core_1_2 = {
1187bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
1188bf215546Sopenharmony_ci      .samplerMirrorClampToEdge           = false,
1189bf215546Sopenharmony_ci      .drawIndirectCount                  = false,
1190bf215546Sopenharmony_ci      .storageBuffer8BitAccess            = false,
1191bf215546Sopenharmony_ci      .uniformAndStorageBuffer8BitAccess  = false,
1192bf215546Sopenharmony_ci      .storagePushConstant8               = false,
1193bf215546Sopenharmony_ci      .shaderBufferInt64Atomics           = false,
1194bf215546Sopenharmony_ci      .shaderSharedInt64Atomics           = false,
1195bf215546Sopenharmony_ci      .shaderFloat16                      = false,
1196bf215546Sopenharmony_ci      .shaderInt8                         = false,
1197bf215546Sopenharmony_ci
1198bf215546Sopenharmony_ci      .descriptorIndexing                                   = false,
1199bf215546Sopenharmony_ci      .shaderInputAttachmentArrayDynamicIndexing            = true,
1200bf215546Sopenharmony_ci      .shaderUniformTexelBufferArrayDynamicIndexing         = true,
1201bf215546Sopenharmony_ci      .shaderStorageTexelBufferArrayDynamicIndexing         = true,
1202bf215546Sopenharmony_ci      .shaderUniformBufferArrayNonUniformIndexing           = false,
1203bf215546Sopenharmony_ci      .shaderSampledImageArrayNonUniformIndexing            = false,
1204bf215546Sopenharmony_ci      .shaderStorageBufferArrayNonUniformIndexing           = false,
1205bf215546Sopenharmony_ci      .shaderStorageImageArrayNonUniformIndexing            = false,
1206bf215546Sopenharmony_ci      .shaderInputAttachmentArrayNonUniformIndexing         = false,
1207bf215546Sopenharmony_ci      .shaderUniformTexelBufferArrayNonUniformIndexing      = false,
1208bf215546Sopenharmony_ci      .shaderStorageTexelBufferArrayNonUniformIndexing      = false,
1209bf215546Sopenharmony_ci      .descriptorBindingUniformBufferUpdateAfterBind        = false,
1210bf215546Sopenharmony_ci      .descriptorBindingSampledImageUpdateAfterBind         = false,
1211bf215546Sopenharmony_ci      .descriptorBindingStorageImageUpdateAfterBind         = false,
1212bf215546Sopenharmony_ci      .descriptorBindingStorageBufferUpdateAfterBind        = false,
1213bf215546Sopenharmony_ci      .descriptorBindingUniformTexelBufferUpdateAfterBind   = false,
1214bf215546Sopenharmony_ci      .descriptorBindingStorageTexelBufferUpdateAfterBind   = false,
1215bf215546Sopenharmony_ci      .descriptorBindingUpdateUnusedWhilePending            = false,
1216bf215546Sopenharmony_ci      .descriptorBindingPartiallyBound                      = false,
1217bf215546Sopenharmony_ci      .descriptorBindingVariableDescriptorCount             = false,
1218bf215546Sopenharmony_ci      .runtimeDescriptorArray                               = false,
1219bf215546Sopenharmony_ci
1220bf215546Sopenharmony_ci      .samplerFilterMinmax                = false,
1221bf215546Sopenharmony_ci      .scalarBlockLayout                  = false,
1222bf215546Sopenharmony_ci      .imagelessFramebuffer               = false,
1223bf215546Sopenharmony_ci      .uniformBufferStandardLayout        = false,
1224bf215546Sopenharmony_ci      .shaderSubgroupExtendedTypes        = false,
1225bf215546Sopenharmony_ci      .separateDepthStencilLayouts        = false,
1226bf215546Sopenharmony_ci      .hostQueryReset                     = false,
1227bf215546Sopenharmony_ci      .timelineSemaphore                  = false,
1228bf215546Sopenharmony_ci      .bufferDeviceAddress                = false,
1229bf215546Sopenharmony_ci      .bufferDeviceAddressCaptureReplay   = false,
1230bf215546Sopenharmony_ci      .bufferDeviceAddressMultiDevice     = false,
1231bf215546Sopenharmony_ci      .vulkanMemoryModel                  = false,
1232bf215546Sopenharmony_ci      .vulkanMemoryModelDeviceScope       = false,
1233bf215546Sopenharmony_ci      .vulkanMemoryModelAvailabilityVisibilityChains = false,
1234bf215546Sopenharmony_ci      .shaderOutputViewportIndex          = false,
1235bf215546Sopenharmony_ci      .shaderOutputLayer                  = false,
1236bf215546Sopenharmony_ci      .subgroupBroadcastDynamicId         = false,
1237bf215546Sopenharmony_ci   };
1238bf215546Sopenharmony_ci
1239bf215546Sopenharmony_ci   const VkPhysicalDeviceVulkan13Features core_1_3 = {
1240bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
1241bf215546Sopenharmony_ci      .robustImageAccess                  = false,
1242bf215546Sopenharmony_ci      .inlineUniformBlock                 = false,
1243bf215546Sopenharmony_ci      .descriptorBindingInlineUniformBlockUpdateAfterBind = false,
1244bf215546Sopenharmony_ci      .pipelineCreationCacheControl       = false,
1245bf215546Sopenharmony_ci      .privateData                        = true,
1246bf215546Sopenharmony_ci      .shaderDemoteToHelperInvocation     = false,
1247bf215546Sopenharmony_ci      .shaderTerminateInvocation          = false,
1248bf215546Sopenharmony_ci      .subgroupSizeControl                = false,
1249bf215546Sopenharmony_ci      .computeFullSubgroups               = false,
1250bf215546Sopenharmony_ci      .synchronization2                   = true,
1251bf215546Sopenharmony_ci      .textureCompressionASTC_HDR         = false,
1252bf215546Sopenharmony_ci      .shaderZeroInitializeWorkgroupMemory = false,
1253bf215546Sopenharmony_ci      .dynamicRendering                   = false,
1254bf215546Sopenharmony_ci      .shaderIntegerDotProduct            = false,
1255bf215546Sopenharmony_ci      .maintenance4                       = false,
1256bf215546Sopenharmony_ci   };
1257bf215546Sopenharmony_ci
1258bf215546Sopenharmony_ci   vk_foreach_struct(ext, pFeatures->pNext) {
1259bf215546Sopenharmony_ci      if (vk_get_physical_device_core_1_1_feature_ext(ext, &core_1_1) ||
1260bf215546Sopenharmony_ci          vk_get_physical_device_core_1_2_feature_ext(ext, &core_1_2) ||
1261bf215546Sopenharmony_ci          vk_get_physical_device_core_1_3_feature_ext(ext, &core_1_3))
1262bf215546Sopenharmony_ci         continue;
1263bf215546Sopenharmony_ci
1264bf215546Sopenharmony_ci      switch (ext->sType) {
1265bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
1266bf215546Sopenharmony_ci         VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =
1267bf215546Sopenharmony_ci            (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext;
1268bf215546Sopenharmony_ci         features->vertexAttributeInstanceRateDivisor = true;
1269bf215546Sopenharmony_ci         features->vertexAttributeInstanceRateZeroDivisor = true;
1270bf215546Sopenharmony_ci         break;
1271bf215546Sopenharmony_ci      }
1272bf215546Sopenharmony_ci      default:
1273bf215546Sopenharmony_ci         dzn_debug_ignored_stype(ext->sType);
1274bf215546Sopenharmony_ci         break;
1275bf215546Sopenharmony_ci      }
1276bf215546Sopenharmony_ci   }
1277bf215546Sopenharmony_ci}
1278bf215546Sopenharmony_ci
1279bf215546Sopenharmony_ci
1280bf215546Sopenharmony_ciVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1281bf215546Sopenharmony_cidzn_GetInstanceProcAddr(VkInstance _instance,
1282bf215546Sopenharmony_ci                        const char *pName)
1283bf215546Sopenharmony_ci{
1284bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_instance, instance, _instance);
1285bf215546Sopenharmony_ci   return vk_instance_get_proc_addr(&instance->vk,
1286bf215546Sopenharmony_ci                                    &dzn_instance_entrypoints,
1287bf215546Sopenharmony_ci                                    pName);
1288bf215546Sopenharmony_ci}
1289bf215546Sopenharmony_ci
1290bf215546Sopenharmony_ci/* Windows will use a dll definition file to avoid build errors. */
1291bf215546Sopenharmony_ci#ifdef _WIN32
1292bf215546Sopenharmony_ci#undef PUBLIC
1293bf215546Sopenharmony_ci#define PUBLIC
1294bf215546Sopenharmony_ci#endif
1295bf215546Sopenharmony_ci
1296bf215546Sopenharmony_ci/* With version 1+ of the loader interface the ICD should expose
1297bf215546Sopenharmony_ci * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps.
1298bf215546Sopenharmony_ci */
1299bf215546Sopenharmony_ciPUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1300bf215546Sopenharmony_civk_icdGetInstanceProcAddr(VkInstance instance,
1301bf215546Sopenharmony_ci                          const char *pName);
1302bf215546Sopenharmony_ci
1303bf215546Sopenharmony_ciPUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1304bf215546Sopenharmony_civk_icdGetInstanceProcAddr(VkInstance instance,
1305bf215546Sopenharmony_ci                          const char *pName)
1306bf215546Sopenharmony_ci{
1307bf215546Sopenharmony_ci   return dzn_GetInstanceProcAddr(instance, pName);
1308bf215546Sopenharmony_ci}
1309bf215546Sopenharmony_ci
1310bf215546Sopenharmony_ci/* With version 4+ of the loader interface the ICD should expose
1311bf215546Sopenharmony_ci * vk_icdGetPhysicalDeviceProcAddr()
1312bf215546Sopenharmony_ci */
1313bf215546Sopenharmony_ciPUBLIC VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1314bf215546Sopenharmony_civk_icdGetPhysicalDeviceProcAddr(VkInstance  _instance,
1315bf215546Sopenharmony_ci                                const char *pName);
1316bf215546Sopenharmony_ci
1317bf215546Sopenharmony_ciVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1318bf215546Sopenharmony_civk_icdGetPhysicalDeviceProcAddr(VkInstance  _instance,
1319bf215546Sopenharmony_ci                                const char *pName)
1320bf215546Sopenharmony_ci{
1321bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_instance, instance, _instance);
1322bf215546Sopenharmony_ci   return vk_instance_get_physical_device_proc_addr(&instance->vk, pName);
1323bf215546Sopenharmony_ci}
1324bf215546Sopenharmony_ci
1325bf215546Sopenharmony_ci/* vk_icd.h does not declare this function, so we declare it here to
1326bf215546Sopenharmony_ci * suppress Wmissing-prototypes.
1327bf215546Sopenharmony_ci */
1328bf215546Sopenharmony_ciPUBLIC VKAPI_ATTR VkResult VKAPI_CALL
1329bf215546Sopenharmony_civk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion);
1330bf215546Sopenharmony_ci
1331bf215546Sopenharmony_ciPUBLIC VKAPI_ATTR VkResult VKAPI_CALL
1332bf215546Sopenharmony_civk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)
1333bf215546Sopenharmony_ci{
1334bf215546Sopenharmony_ci   /* For the full details on loader interface versioning, see
1335bf215546Sopenharmony_ci    * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
1336bf215546Sopenharmony_ci    * What follows is a condensed summary, to help you navigate the large and
1337bf215546Sopenharmony_ci    * confusing official doc.
1338bf215546Sopenharmony_ci    *
1339bf215546Sopenharmony_ci    *   - Loader interface v0 is incompatible with later versions. We don't
1340bf215546Sopenharmony_ci    *     support it.
1341bf215546Sopenharmony_ci    *
1342bf215546Sopenharmony_ci    *   - In loader interface v1:
1343bf215546Sopenharmony_ci    *       - The first ICD entrypoint called by the loader is
1344bf215546Sopenharmony_ci    *         vk_icdGetInstanceProcAddr(). The ICD must statically expose this
1345bf215546Sopenharmony_ci    *         entrypoint.
1346bf215546Sopenharmony_ci    *       - The ICD must statically expose no other Vulkan symbol unless it is
1347bf215546Sopenharmony_ci    *         linked with -Bsymbolic.
1348bf215546Sopenharmony_ci    *       - Each dispatchable Vulkan handle created by the ICD must be
1349bf215546Sopenharmony_ci    *         a pointer to a struct whose first member is VK_LOADER_DATA. The
1350bf215546Sopenharmony_ci    *         ICD must initialize VK_LOADER_DATA.loadMagic to ICD_LOADER_MAGIC.
1351bf215546Sopenharmony_ci    *       - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
1352bf215546Sopenharmony_ci    *         vkDestroySurfaceKHR(). The ICD must be capable of working with
1353bf215546Sopenharmony_ci    *         such loader-managed surfaces.
1354bf215546Sopenharmony_ci    *
1355bf215546Sopenharmony_ci    *    - Loader interface v2 differs from v1 in:
1356bf215546Sopenharmony_ci    *       - The first ICD entrypoint called by the loader is
1357bf215546Sopenharmony_ci    *         vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
1358bf215546Sopenharmony_ci    *         statically expose this entrypoint.
1359bf215546Sopenharmony_ci    *
1360bf215546Sopenharmony_ci    *    - Loader interface v3 differs from v2 in:
1361bf215546Sopenharmony_ci    *        - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
1362bf215546Sopenharmony_ci    *          vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
1363bf215546Sopenharmony_ci    *          because the loader no longer does so.
1364bf215546Sopenharmony_ci    *
1365bf215546Sopenharmony_ci    *    - Loader interface v4 differs from v3 in:
1366bf215546Sopenharmony_ci    *        - The ICD must implement vk_icdGetPhysicalDeviceProcAddr().
1367bf215546Sopenharmony_ci    *
1368bf215546Sopenharmony_ci    *    - Loader interface v5 differs from v4 in:
1369bf215546Sopenharmony_ci    *        - The ICD must support Vulkan API version 1.1 and must not return
1370bf215546Sopenharmony_ci    *          VK_ERROR_INCOMPATIBLE_DRIVER from vkCreateInstance() unless a
1371bf215546Sopenharmony_ci    *          Vulkan Loader with interface v4 or smaller is being used and the
1372bf215546Sopenharmony_ci    *          application provides an API version that is greater than 1.0.
1373bf215546Sopenharmony_ci    */
1374bf215546Sopenharmony_ci   *pSupportedVersion = MIN2(*pSupportedVersion, 5u);
1375bf215546Sopenharmony_ci   return VK_SUCCESS;
1376bf215546Sopenharmony_ci}
1377bf215546Sopenharmony_ci
1378bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1379bf215546Sopenharmony_cidzn_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1380bf215546Sopenharmony_ci                                 VkPhysicalDeviceProperties2 *pProperties)
1381bf215546Sopenharmony_ci{
1382bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_physical_device, pdevice, physicalDevice);
1383bf215546Sopenharmony_ci
1384bf215546Sopenharmony_ci   (void)dzn_physical_device_get_d3d12_dev(pdevice);
1385bf215546Sopenharmony_ci
1386bf215546Sopenharmony_ci   /* minimum from the spec */
1387bf215546Sopenharmony_ci   const VkSampleCountFlags supported_sample_counts =
1388bf215546Sopenharmony_ci      VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT |
1389bf215546Sopenharmony_ci      VK_SAMPLE_COUNT_8_BIT | VK_SAMPLE_COUNT_16_BIT;
1390bf215546Sopenharmony_ci
1391bf215546Sopenharmony_ci   /* FIXME: this is mostly bunk for now */
1392bf215546Sopenharmony_ci   VkPhysicalDeviceLimits limits = {
1393bf215546Sopenharmony_ci
1394bf215546Sopenharmony_ci      /* TODO: support older feature levels */
1395bf215546Sopenharmony_ci      .maxImageDimension1D                      = (1 << 14),
1396bf215546Sopenharmony_ci      .maxImageDimension2D                      = (1 << 14),
1397bf215546Sopenharmony_ci      .maxImageDimension3D                      = (1 << 11),
1398bf215546Sopenharmony_ci      .maxImageDimensionCube                    = (1 << 14),
1399bf215546Sopenharmony_ci      .maxImageArrayLayers                      = (1 << 11),
1400bf215546Sopenharmony_ci
1401bf215546Sopenharmony_ci      /* from here on, we simply use the minimum values from the spec for now */
1402bf215546Sopenharmony_ci      .maxTexelBufferElements                   = 65536,
1403bf215546Sopenharmony_ci      .maxUniformBufferRange                    = 16384,
1404bf215546Sopenharmony_ci      .maxStorageBufferRange                    = (1ul << 27),
1405bf215546Sopenharmony_ci      .maxPushConstantsSize                     = 128,
1406bf215546Sopenharmony_ci      .maxMemoryAllocationCount                 = 4096,
1407bf215546Sopenharmony_ci      .maxSamplerAllocationCount                = 4000,
1408bf215546Sopenharmony_ci      .bufferImageGranularity                   = 131072,
1409bf215546Sopenharmony_ci      .sparseAddressSpaceSize                   = 0,
1410bf215546Sopenharmony_ci      .maxBoundDescriptorSets                   = MAX_SETS,
1411bf215546Sopenharmony_ci      .maxPerStageDescriptorSamplers            =
1412bf215546Sopenharmony_ci         pdevice->options.ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1 ?
1413bf215546Sopenharmony_ci         16u : MAX_DESCS_PER_SAMPLER_HEAP,
1414bf215546Sopenharmony_ci      .maxPerStageDescriptorUniformBuffers      =
1415bf215546Sopenharmony_ci         pdevice->options.ResourceHeapTier <= D3D12_RESOURCE_HEAP_TIER_2 ?
1416bf215546Sopenharmony_ci         14u : MAX_DESCS_PER_CBV_SRV_UAV_HEAP,
1417bf215546Sopenharmony_ci      .maxPerStageDescriptorStorageBuffers      =
1418bf215546Sopenharmony_ci         pdevice->options.ResourceHeapTier <= D3D12_RESOURCE_HEAP_TIER_2 ?
1419bf215546Sopenharmony_ci         64u : MAX_DESCS_PER_CBV_SRV_UAV_HEAP,
1420bf215546Sopenharmony_ci      .maxPerStageDescriptorSampledImages       =
1421bf215546Sopenharmony_ci         pdevice->options.ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1 ?
1422bf215546Sopenharmony_ci         128u : MAX_DESCS_PER_CBV_SRV_UAV_HEAP,
1423bf215546Sopenharmony_ci      .maxPerStageDescriptorStorageImages       =
1424bf215546Sopenharmony_ci         pdevice->options.ResourceHeapTier <= D3D12_RESOURCE_HEAP_TIER_2 ?
1425bf215546Sopenharmony_ci         64u : MAX_DESCS_PER_CBV_SRV_UAV_HEAP,
1426bf215546Sopenharmony_ci      .maxPerStageDescriptorInputAttachments    =
1427bf215546Sopenharmony_ci         pdevice->options.ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1 ?
1428bf215546Sopenharmony_ci         128u : MAX_DESCS_PER_CBV_SRV_UAV_HEAP,
1429bf215546Sopenharmony_ci      .maxPerStageResources                     = MAX_DESCS_PER_CBV_SRV_UAV_HEAP,
1430bf215546Sopenharmony_ci      .maxDescriptorSetSamplers                 = MAX_DESCS_PER_SAMPLER_HEAP,
1431bf215546Sopenharmony_ci      .maxDescriptorSetUniformBuffers           = MAX_DESCS_PER_CBV_SRV_UAV_HEAP,
1432bf215546Sopenharmony_ci      .maxDescriptorSetUniformBuffersDynamic    = MAX_DYNAMIC_UNIFORM_BUFFERS,
1433bf215546Sopenharmony_ci      .maxDescriptorSetStorageBuffers           = MAX_DESCS_PER_CBV_SRV_UAV_HEAP,
1434bf215546Sopenharmony_ci      .maxDescriptorSetStorageBuffersDynamic    = MAX_DYNAMIC_STORAGE_BUFFERS,
1435bf215546Sopenharmony_ci      .maxDescriptorSetSampledImages            = MAX_DESCS_PER_CBV_SRV_UAV_HEAP,
1436bf215546Sopenharmony_ci      .maxDescriptorSetStorageImages            = MAX_DESCS_PER_CBV_SRV_UAV_HEAP,
1437bf215546Sopenharmony_ci      .maxDescriptorSetInputAttachments         = MAX_DESCS_PER_CBV_SRV_UAV_HEAP,
1438bf215546Sopenharmony_ci      .maxVertexInputAttributes                 = MIN2(D3D12_STANDARD_VERTEX_ELEMENT_COUNT, MAX_VERTEX_GENERIC_ATTRIBS),
1439bf215546Sopenharmony_ci      .maxVertexInputBindings                   = MAX_VBS,
1440bf215546Sopenharmony_ci      .maxVertexInputAttributeOffset            = 2047,
1441bf215546Sopenharmony_ci      .maxVertexInputBindingStride              = 2048,
1442bf215546Sopenharmony_ci      .maxVertexOutputComponents                = 64,
1443bf215546Sopenharmony_ci      .maxTessellationGenerationLevel           = 0,
1444bf215546Sopenharmony_ci      .maxTessellationPatchSize                 = 0,
1445bf215546Sopenharmony_ci      .maxTessellationControlPerVertexInputComponents = 0,
1446bf215546Sopenharmony_ci      .maxTessellationControlPerVertexOutputComponents = 0,
1447bf215546Sopenharmony_ci      .maxTessellationControlPerPatchOutputComponents = 0,
1448bf215546Sopenharmony_ci      .maxTessellationControlTotalOutputComponents = 0,
1449bf215546Sopenharmony_ci      .maxTessellationEvaluationInputComponents = 0,
1450bf215546Sopenharmony_ci      .maxTessellationEvaluationOutputComponents = 0,
1451bf215546Sopenharmony_ci      .maxGeometryShaderInvocations             = 0,
1452bf215546Sopenharmony_ci      .maxGeometryInputComponents               = 0,
1453bf215546Sopenharmony_ci      .maxGeometryOutputComponents              = 0,
1454bf215546Sopenharmony_ci      .maxGeometryOutputVertices                = 0,
1455bf215546Sopenharmony_ci      .maxGeometryTotalOutputComponents         = 0,
1456bf215546Sopenharmony_ci      .maxFragmentInputComponents               = 64,
1457bf215546Sopenharmony_ci      .maxFragmentOutputAttachments             = 4,
1458bf215546Sopenharmony_ci      .maxFragmentDualSrcAttachments            = 0,
1459bf215546Sopenharmony_ci      .maxFragmentCombinedOutputResources       = 4,
1460bf215546Sopenharmony_ci      .maxComputeSharedMemorySize               = 16384,
1461bf215546Sopenharmony_ci      .maxComputeWorkGroupCount                 = { 65535, 65535, 65535 },
1462bf215546Sopenharmony_ci      .maxComputeWorkGroupInvocations           = 128,
1463bf215546Sopenharmony_ci      .maxComputeWorkGroupSize                  = { 128, 128, 64 },
1464bf215546Sopenharmony_ci      .subPixelPrecisionBits                    = 4,
1465bf215546Sopenharmony_ci      .subTexelPrecisionBits                    = 4,
1466bf215546Sopenharmony_ci      .mipmapPrecisionBits                      = 4,
1467bf215546Sopenharmony_ci      .maxDrawIndexedIndexValue                 = 0x00ffffff,
1468bf215546Sopenharmony_ci      .maxDrawIndirectCount                     = UINT32_MAX,
1469bf215546Sopenharmony_ci      .maxSamplerLodBias                        = 2.0f,
1470bf215546Sopenharmony_ci      .maxSamplerAnisotropy                     = 1.0f,
1471bf215546Sopenharmony_ci      .maxViewports                             = 1,
1472bf215546Sopenharmony_ci      .maxViewportDimensions                    = { 4096, 4096 },
1473bf215546Sopenharmony_ci      .viewportBoundsRange                      = { -8192, 8191 },
1474bf215546Sopenharmony_ci      .viewportSubPixelBits                     = 0,
1475bf215546Sopenharmony_ci      .minMemoryMapAlignment                    = 64,
1476bf215546Sopenharmony_ci      .minTexelBufferOffsetAlignment            = 256,
1477bf215546Sopenharmony_ci      .minUniformBufferOffsetAlignment          = 256,
1478bf215546Sopenharmony_ci      .minStorageBufferOffsetAlignment          = 256,
1479bf215546Sopenharmony_ci      .minTexelOffset                           = -8,
1480bf215546Sopenharmony_ci      .maxTexelOffset                           = 7,
1481bf215546Sopenharmony_ci      .minTexelGatherOffset                     = 0,
1482bf215546Sopenharmony_ci      .maxTexelGatherOffset                     = 0,
1483bf215546Sopenharmony_ci      .minInterpolationOffset                   = -0.5f,
1484bf215546Sopenharmony_ci      .maxInterpolationOffset                   = 0.5f,
1485bf215546Sopenharmony_ci      .subPixelInterpolationOffsetBits          = 4,
1486bf215546Sopenharmony_ci      .maxFramebufferWidth                      = 4096,
1487bf215546Sopenharmony_ci      .maxFramebufferHeight                     = 4096,
1488bf215546Sopenharmony_ci      .maxFramebufferLayers                     = 256,
1489bf215546Sopenharmony_ci      .framebufferColorSampleCounts             = supported_sample_counts,
1490bf215546Sopenharmony_ci      .framebufferDepthSampleCounts             = supported_sample_counts,
1491bf215546Sopenharmony_ci      .framebufferStencilSampleCounts           = supported_sample_counts,
1492bf215546Sopenharmony_ci      .framebufferNoAttachmentsSampleCounts     = supported_sample_counts,
1493bf215546Sopenharmony_ci      .maxColorAttachments                      = MAX_RTS,
1494bf215546Sopenharmony_ci      .sampledImageColorSampleCounts            = supported_sample_counts,
1495bf215546Sopenharmony_ci      .sampledImageIntegerSampleCounts          = VK_SAMPLE_COUNT_1_BIT,
1496bf215546Sopenharmony_ci      .sampledImageDepthSampleCounts            = supported_sample_counts,
1497bf215546Sopenharmony_ci      .sampledImageStencilSampleCounts          = supported_sample_counts,
1498bf215546Sopenharmony_ci      .storageImageSampleCounts                 = VK_SAMPLE_COUNT_1_BIT,
1499bf215546Sopenharmony_ci      .maxSampleMaskWords                       = 1,
1500bf215546Sopenharmony_ci      .timestampComputeAndGraphics              = true,
1501bf215546Sopenharmony_ci      .timestampPeriod                          = pdevice->timestamp_period,
1502bf215546Sopenharmony_ci      .maxClipDistances                         = 8,
1503bf215546Sopenharmony_ci      .maxCullDistances                         = 8,
1504bf215546Sopenharmony_ci      .maxCombinedClipAndCullDistances          = 8,
1505bf215546Sopenharmony_ci      .discreteQueuePriorities                  = 2,
1506bf215546Sopenharmony_ci      .pointSizeRange                           = { 1.0f, 1.0f },
1507bf215546Sopenharmony_ci      .lineWidthRange                           = { 1.0f, 1.0f },
1508bf215546Sopenharmony_ci      .pointSizeGranularity                     = 0.0f,
1509bf215546Sopenharmony_ci      .lineWidthGranularity                     = 0.0f,
1510bf215546Sopenharmony_ci      .strictLines                              = 0,
1511bf215546Sopenharmony_ci      .standardSampleLocations                  = false,
1512bf215546Sopenharmony_ci      .optimalBufferCopyOffsetAlignment         = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT,
1513bf215546Sopenharmony_ci      .optimalBufferCopyRowPitchAlignment       = D3D12_TEXTURE_DATA_PITCH_ALIGNMENT,
1514bf215546Sopenharmony_ci      .nonCoherentAtomSize                      = 256,
1515bf215546Sopenharmony_ci   };
1516bf215546Sopenharmony_ci
1517bf215546Sopenharmony_ci   VkPhysicalDeviceType devtype = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
1518bf215546Sopenharmony_ci   if (pdevice->desc.is_warp)
1519bf215546Sopenharmony_ci      devtype = VK_PHYSICAL_DEVICE_TYPE_CPU;
1520bf215546Sopenharmony_ci   else if (false) { // TODO: detect discreete GPUs
1521bf215546Sopenharmony_ci      /* This is a tad tricky to get right, because we need to have the
1522bf215546Sopenharmony_ci       * actual ID3D12Device before we can query the
1523bf215546Sopenharmony_ci       * D3D12_FEATURE_DATA_ARCHITECTURE structure... So for now, let's
1524bf215546Sopenharmony_ci       * just pretend everything is integrated, because... well, that's
1525bf215546Sopenharmony_ci       * what I have at hand right now ;)
1526bf215546Sopenharmony_ci       */
1527bf215546Sopenharmony_ci      devtype = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
1528bf215546Sopenharmony_ci   }
1529bf215546Sopenharmony_ci
1530bf215546Sopenharmony_ci   pProperties->properties = (VkPhysicalDeviceProperties) {
1531bf215546Sopenharmony_ci      .apiVersion = DZN_API_VERSION,
1532bf215546Sopenharmony_ci      .driverVersion = vk_get_driver_version(),
1533bf215546Sopenharmony_ci
1534bf215546Sopenharmony_ci      .vendorID = pdevice->desc.vendor_id,
1535bf215546Sopenharmony_ci      .deviceID = pdevice->desc.device_id,
1536bf215546Sopenharmony_ci      .deviceType = devtype,
1537bf215546Sopenharmony_ci
1538bf215546Sopenharmony_ci      .limits = limits,
1539bf215546Sopenharmony_ci      .sparseProperties = { 0 },
1540bf215546Sopenharmony_ci   };
1541bf215546Sopenharmony_ci
1542bf215546Sopenharmony_ci   snprintf(pProperties->properties.deviceName,
1543bf215546Sopenharmony_ci            sizeof(pProperties->properties.deviceName),
1544bf215546Sopenharmony_ci            "Microsoft Direct3D12 (%s)", pdevice->desc.description);
1545bf215546Sopenharmony_ci   memcpy(pProperties->properties.pipelineCacheUUID,
1546bf215546Sopenharmony_ci          pdevice->pipeline_cache_uuid, VK_UUID_SIZE);
1547bf215546Sopenharmony_ci
1548bf215546Sopenharmony_ci   VkPhysicalDeviceVulkan11Properties core_1_1 = {
1549bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES,
1550bf215546Sopenharmony_ci      .deviceLUIDValid                       = true,
1551bf215546Sopenharmony_ci      .pointClippingBehavior                 = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES,
1552bf215546Sopenharmony_ci      .maxMultiviewViewCount                 = 0,
1553bf215546Sopenharmony_ci      .maxMultiviewInstanceIndex             = 0,
1554bf215546Sopenharmony_ci      .protectedNoFault                      = false,
1555bf215546Sopenharmony_ci      /* Vulkan 1.1 wants this value to be at least 1024. Let's stick to this
1556bf215546Sopenharmony_ci       * minimum requirement for now, and hope the total number of samplers
1557bf215546Sopenharmony_ci       * across all descriptor sets doesn't exceed 2048, otherwise we'd exceed
1558bf215546Sopenharmony_ci       * the maximum number of samplers per heap. For any descriptor set
1559bf215546Sopenharmony_ci       * containing more than 1024 descriptors,
1560bf215546Sopenharmony_ci       * vkGetDescriptorSetLayoutSupport() can be called to determine if the
1561bf215546Sopenharmony_ci       * layout is within D3D12 descriptor heap bounds.
1562bf215546Sopenharmony_ci       */
1563bf215546Sopenharmony_ci      .maxPerSetDescriptors                  = 1024,
1564bf215546Sopenharmony_ci      /* According to the spec, the maximum D3D12 resource size is
1565bf215546Sopenharmony_ci       * min(max(128MB, 0.25f * (amount of dedicated VRAM)), 2GB),
1566bf215546Sopenharmony_ci       * but the limit actually depends on the max(system_ram, VRAM) not
1567bf215546Sopenharmony_ci       * just the VRAM.
1568bf215546Sopenharmony_ci       */
1569bf215546Sopenharmony_ci      .maxMemoryAllocationSize               =
1570bf215546Sopenharmony_ci         CLAMP(MAX2(pdevice->desc.dedicated_video_memory,
1571bf215546Sopenharmony_ci                    pdevice->desc.dedicated_system_memory +
1572bf215546Sopenharmony_ci                    pdevice->desc.shared_system_memory) / 4,
1573bf215546Sopenharmony_ci               128ull * 1024 * 1024, 2ull * 1024 * 1024 * 1024),
1574bf215546Sopenharmony_ci   };
1575bf215546Sopenharmony_ci   memcpy(core_1_1.driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
1576bf215546Sopenharmony_ci   memcpy(core_1_1.deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
1577bf215546Sopenharmony_ci   memcpy(core_1_1.deviceLUID, &pdevice->desc.adapter_luid, VK_LUID_SIZE);
1578bf215546Sopenharmony_ci
1579bf215546Sopenharmony_ci   STATIC_ASSERT(sizeof(pdevice->desc.adapter_luid) == sizeof(core_1_1.deviceLUID));
1580bf215546Sopenharmony_ci
1581bf215546Sopenharmony_ci   VkPhysicalDeviceVulkan12Properties core_1_2 = {
1582bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES,
1583bf215546Sopenharmony_ci      .driverID = VK_DRIVER_ID_MESA_DOZEN,
1584bf215546Sopenharmony_ci      .conformanceVersion = (VkConformanceVersion){
1585bf215546Sopenharmony_ci         .major = 0,
1586bf215546Sopenharmony_ci         .minor = 0,
1587bf215546Sopenharmony_ci         .subminor = 0,
1588bf215546Sopenharmony_ci         .patch = 0,
1589bf215546Sopenharmony_ci      },
1590bf215546Sopenharmony_ci      .denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL,
1591bf215546Sopenharmony_ci      .roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL,
1592bf215546Sopenharmony_ci      .shaderSignedZeroInfNanPreserveFloat16 = false,
1593bf215546Sopenharmony_ci      .shaderSignedZeroInfNanPreserveFloat32 = false,
1594bf215546Sopenharmony_ci      .shaderSignedZeroInfNanPreserveFloat64 = false,
1595bf215546Sopenharmony_ci      .shaderDenormPreserveFloat16 = true,
1596bf215546Sopenharmony_ci      .shaderDenormPreserveFloat32 = false,
1597bf215546Sopenharmony_ci      .shaderDenormPreserveFloat64 = true,
1598bf215546Sopenharmony_ci      .shaderDenormFlushToZeroFloat16 = false,
1599bf215546Sopenharmony_ci      .shaderDenormFlushToZeroFloat32 = true,
1600bf215546Sopenharmony_ci      .shaderDenormFlushToZeroFloat64 = false,
1601bf215546Sopenharmony_ci      .shaderRoundingModeRTEFloat16 = true,
1602bf215546Sopenharmony_ci      .shaderRoundingModeRTEFloat32 = true,
1603bf215546Sopenharmony_ci      .shaderRoundingModeRTEFloat64 = true,
1604bf215546Sopenharmony_ci      .shaderRoundingModeRTZFloat16 = false,
1605bf215546Sopenharmony_ci      .shaderRoundingModeRTZFloat32 = false,
1606bf215546Sopenharmony_ci      .shaderRoundingModeRTZFloat64 = false,
1607bf215546Sopenharmony_ci      .shaderUniformBufferArrayNonUniformIndexingNative = true,
1608bf215546Sopenharmony_ci      .shaderSampledImageArrayNonUniformIndexingNative = true,
1609bf215546Sopenharmony_ci      .shaderStorageBufferArrayNonUniformIndexingNative = true,
1610bf215546Sopenharmony_ci      .shaderStorageImageArrayNonUniformIndexingNative = true,
1611bf215546Sopenharmony_ci      .shaderInputAttachmentArrayNonUniformIndexingNative = true,
1612bf215546Sopenharmony_ci      .robustBufferAccessUpdateAfterBind = true,
1613bf215546Sopenharmony_ci      .quadDivergentImplicitLod = false,
1614bf215546Sopenharmony_ci      .maxPerStageDescriptorUpdateAfterBindSamplers = 0,
1615bf215546Sopenharmony_ci      .maxPerStageDescriptorUpdateAfterBindUniformBuffers = 0,
1616bf215546Sopenharmony_ci      .maxPerStageDescriptorUpdateAfterBindStorageBuffers = 0,
1617bf215546Sopenharmony_ci      .maxPerStageDescriptorUpdateAfterBindSampledImages = 0,
1618bf215546Sopenharmony_ci      .maxPerStageDescriptorUpdateAfterBindStorageImages = 0,
1619bf215546Sopenharmony_ci      .maxPerStageDescriptorUpdateAfterBindInputAttachments = 0,
1620bf215546Sopenharmony_ci      .maxPerStageUpdateAfterBindResources = 0,
1621bf215546Sopenharmony_ci      .maxDescriptorSetUpdateAfterBindSamplers = 0,
1622bf215546Sopenharmony_ci      .maxDescriptorSetUpdateAfterBindUniformBuffers = 0,
1623bf215546Sopenharmony_ci      .maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = 0,
1624bf215546Sopenharmony_ci      .maxDescriptorSetUpdateAfterBindStorageBuffers = 0,
1625bf215546Sopenharmony_ci      .maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = 0,
1626bf215546Sopenharmony_ci      .maxDescriptorSetUpdateAfterBindSampledImages = 0,
1627bf215546Sopenharmony_ci      .maxDescriptorSetUpdateAfterBindStorageImages = 0,
1628bf215546Sopenharmony_ci      .maxDescriptorSetUpdateAfterBindInputAttachments = 0,
1629bf215546Sopenharmony_ci
1630bf215546Sopenharmony_ci      /* FIXME: add support for VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
1631bf215546Sopenharmony_ci       * which is required by the VK 1.2 spec.
1632bf215546Sopenharmony_ci       */
1633bf215546Sopenharmony_ci      .supportedDepthResolveModes = VK_RESOLVE_MODE_AVERAGE_BIT,
1634bf215546Sopenharmony_ci
1635bf215546Sopenharmony_ci      .supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
1636bf215546Sopenharmony_ci      .independentResolveNone = false,
1637bf215546Sopenharmony_ci      .independentResolve = false,
1638bf215546Sopenharmony_ci      .filterMinmaxSingleComponentFormats = false,
1639bf215546Sopenharmony_ci      .filterMinmaxImageComponentMapping = false,
1640bf215546Sopenharmony_ci      .maxTimelineSemaphoreValueDifference = UINT64_MAX,
1641bf215546Sopenharmony_ci      .framebufferIntegerColorSampleCounts = VK_SAMPLE_COUNT_1_BIT,
1642bf215546Sopenharmony_ci   };
1643bf215546Sopenharmony_ci
1644bf215546Sopenharmony_ci   snprintf(core_1_2.driverName, VK_MAX_DRIVER_NAME_SIZE, "Dozen");
1645bf215546Sopenharmony_ci   snprintf(core_1_2.driverInfo, VK_MAX_DRIVER_INFO_SIZE, "Mesa " PACKAGE_VERSION MESA_GIT_SHA1);
1646bf215546Sopenharmony_ci
1647bf215546Sopenharmony_ci   const VkPhysicalDeviceVulkan13Properties core_1_3 = {
1648bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES,
1649bf215546Sopenharmony_ci   };
1650bf215546Sopenharmony_ci
1651bf215546Sopenharmony_ci   vk_foreach_struct(ext, pProperties->pNext) {
1652bf215546Sopenharmony_ci      if (vk_get_physical_device_core_1_1_property_ext(ext, &core_1_1) ||
1653bf215546Sopenharmony_ci          vk_get_physical_device_core_1_2_property_ext(ext, &core_1_2) ||
1654bf215546Sopenharmony_ci          vk_get_physical_device_core_1_3_property_ext(ext, &core_1_3))
1655bf215546Sopenharmony_ci         continue;
1656bf215546Sopenharmony_ci
1657bf215546Sopenharmony_ci      switch (ext->sType) {
1658bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
1659bf215546Sopenharmony_ci         VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *attr_div =
1660bf215546Sopenharmony_ci            (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext;
1661bf215546Sopenharmony_ci         attr_div->maxVertexAttribDivisor = UINT32_MAX;
1662bf215546Sopenharmony_ci         break;
1663bf215546Sopenharmony_ci      }
1664bf215546Sopenharmony_ci      default:
1665bf215546Sopenharmony_ci         dzn_debug_ignored_stype(ext->sType);
1666bf215546Sopenharmony_ci         break;
1667bf215546Sopenharmony_ci      }
1668bf215546Sopenharmony_ci   }
1669bf215546Sopenharmony_ci}
1670bf215546Sopenharmony_ci
1671bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1672bf215546Sopenharmony_cidzn_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
1673bf215546Sopenharmony_ci                                            uint32_t *pQueueFamilyPropertyCount,
1674bf215546Sopenharmony_ci                                            VkQueueFamilyProperties2 *pQueueFamilyProperties)
1675bf215546Sopenharmony_ci{
1676bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice);
1677bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties2, out,
1678bf215546Sopenharmony_ci                          pQueueFamilyProperties, pQueueFamilyPropertyCount);
1679bf215546Sopenharmony_ci
1680bf215546Sopenharmony_ci   (void)dzn_physical_device_get_d3d12_dev(pdev);
1681bf215546Sopenharmony_ci
1682bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pdev->queue_family_count; i++) {
1683bf215546Sopenharmony_ci      vk_outarray_append_typed(VkQueueFamilyProperties2, &out, p) {
1684bf215546Sopenharmony_ci         p->queueFamilyProperties = pdev->queue_families[i].props;
1685bf215546Sopenharmony_ci
1686bf215546Sopenharmony_ci         vk_foreach_struct(ext, pQueueFamilyProperties->pNext) {
1687bf215546Sopenharmony_ci            dzn_debug_ignored_stype(ext->sType);
1688bf215546Sopenharmony_ci         }
1689bf215546Sopenharmony_ci      }
1690bf215546Sopenharmony_ci   }
1691bf215546Sopenharmony_ci}
1692bf215546Sopenharmony_ci
1693bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1694bf215546Sopenharmony_cidzn_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
1695bf215546Sopenharmony_ci                                      VkPhysicalDeviceMemoryProperties *pMemoryProperties)
1696bf215546Sopenharmony_ci{
1697bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice);
1698bf215546Sopenharmony_ci
1699bf215546Sopenharmony_ci   // Ensure memory caps are up-to-date
1700bf215546Sopenharmony_ci   (void)dzn_physical_device_get_d3d12_dev(pdev);
1701bf215546Sopenharmony_ci   *pMemoryProperties = pdev->memory;
1702bf215546Sopenharmony_ci}
1703bf215546Sopenharmony_ci
1704bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
1705bf215546Sopenharmony_cidzn_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,
1706bf215546Sopenharmony_ci                                       VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
1707bf215546Sopenharmony_ci{
1708bf215546Sopenharmony_ci   dzn_GetPhysicalDeviceMemoryProperties(physicalDevice,
1709bf215546Sopenharmony_ci                                         &pMemoryProperties->memoryProperties);
1710bf215546Sopenharmony_ci
1711bf215546Sopenharmony_ci   vk_foreach_struct(ext, pMemoryProperties->pNext) {
1712bf215546Sopenharmony_ci      dzn_debug_ignored_stype(ext->sType);
1713bf215546Sopenharmony_ci   }
1714bf215546Sopenharmony_ci}
1715bf215546Sopenharmony_ci
1716bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
1717bf215546Sopenharmony_cidzn_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
1718bf215546Sopenharmony_ci                                     VkLayerProperties *pProperties)
1719bf215546Sopenharmony_ci{
1720bf215546Sopenharmony_ci   if (pProperties == NULL) {
1721bf215546Sopenharmony_ci      *pPropertyCount = 0;
1722bf215546Sopenharmony_ci      return VK_SUCCESS;
1723bf215546Sopenharmony_ci   }
1724bf215546Sopenharmony_ci
1725bf215546Sopenharmony_ci   return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1726bf215546Sopenharmony_ci}
1727bf215546Sopenharmony_ci
1728bf215546Sopenharmony_cistatic VkResult
1729bf215546Sopenharmony_cidzn_queue_sync_wait(struct dzn_queue *queue, const struct vk_sync_wait *wait)
1730bf215546Sopenharmony_ci{
1731bf215546Sopenharmony_ci   if (wait->sync->type == &vk_sync_dummy_type)
1732bf215546Sopenharmony_ci      return VK_SUCCESS;
1733bf215546Sopenharmony_ci
1734bf215546Sopenharmony_ci   struct dzn_device *device = container_of(queue->vk.base.device, struct dzn_device, vk);
1735bf215546Sopenharmony_ci   assert(wait->sync->type == &dzn_sync_type);
1736bf215546Sopenharmony_ci   struct dzn_sync *sync = container_of(wait->sync, struct dzn_sync, vk);
1737bf215546Sopenharmony_ci   uint64_t value =
1738bf215546Sopenharmony_ci      (sync->vk.flags & VK_SYNC_IS_TIMELINE) ? wait->wait_value : 1;
1739bf215546Sopenharmony_ci
1740bf215546Sopenharmony_ci   assert(sync->fence != NULL);
1741bf215546Sopenharmony_ci
1742bf215546Sopenharmony_ci   if (value > 0 && FAILED(ID3D12CommandQueue_Wait(queue->cmdqueue, sync->fence, value)))
1743bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_UNKNOWN);
1744bf215546Sopenharmony_ci
1745bf215546Sopenharmony_ci   return VK_SUCCESS;
1746bf215546Sopenharmony_ci}
1747bf215546Sopenharmony_ci
1748bf215546Sopenharmony_cistatic VkResult
1749bf215546Sopenharmony_cidzn_queue_sync_signal(struct dzn_queue *queue, const struct vk_sync_signal *signal)
1750bf215546Sopenharmony_ci{
1751bf215546Sopenharmony_ci   if (signal->sync->type == &vk_sync_dummy_type)
1752bf215546Sopenharmony_ci      return VK_SUCCESS;
1753bf215546Sopenharmony_ci
1754bf215546Sopenharmony_ci   struct dzn_device *device = container_of(queue->vk.base.device, struct dzn_device, vk);
1755bf215546Sopenharmony_ci   assert(signal->sync->type == &dzn_sync_type);
1756bf215546Sopenharmony_ci   struct dzn_sync *sync = container_of(signal->sync, struct dzn_sync, vk);
1757bf215546Sopenharmony_ci   uint64_t value =
1758bf215546Sopenharmony_ci      (sync->vk.flags & VK_SYNC_IS_TIMELINE) ? signal->signal_value : 1;
1759bf215546Sopenharmony_ci   assert(value > 0);
1760bf215546Sopenharmony_ci
1761bf215546Sopenharmony_ci   assert(sync->fence != NULL);
1762bf215546Sopenharmony_ci
1763bf215546Sopenharmony_ci   if (FAILED(ID3D12CommandQueue_Signal(queue->cmdqueue, sync->fence, value)))
1764bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_UNKNOWN);
1765bf215546Sopenharmony_ci
1766bf215546Sopenharmony_ci   return VK_SUCCESS;
1767bf215546Sopenharmony_ci}
1768bf215546Sopenharmony_ci
1769bf215546Sopenharmony_cistatic VkResult
1770bf215546Sopenharmony_cidzn_queue_submit(struct vk_queue *q,
1771bf215546Sopenharmony_ci                 struct vk_queue_submit *info)
1772bf215546Sopenharmony_ci{
1773bf215546Sopenharmony_ci   struct dzn_queue *queue = container_of(q, struct dzn_queue, vk);
1774bf215546Sopenharmony_ci   struct dzn_device *device = container_of(q->base.device, struct dzn_device, vk);
1775bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
1776bf215546Sopenharmony_ci
1777bf215546Sopenharmony_ci   for (uint32_t i = 0; i < info->wait_count; i++) {
1778bf215546Sopenharmony_ci      result = dzn_queue_sync_wait(queue, &info->waits[i]);
1779bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1780bf215546Sopenharmony_ci         return result;
1781bf215546Sopenharmony_ci   }
1782bf215546Sopenharmony_ci
1783bf215546Sopenharmony_ci   for (uint32_t i = 0; i < info->command_buffer_count; i++) {
1784bf215546Sopenharmony_ci      struct dzn_cmd_buffer *cmd_buffer =
1785bf215546Sopenharmony_ci         container_of(info->command_buffers[i], struct dzn_cmd_buffer, vk);
1786bf215546Sopenharmony_ci
1787bf215546Sopenharmony_ci      ID3D12CommandList *cmdlists[] = { (ID3D12CommandList *)cmd_buffer->cmdlist };
1788bf215546Sopenharmony_ci
1789bf215546Sopenharmony_ci      util_dynarray_foreach(&cmd_buffer->events.wait, struct dzn_event *, evt) {
1790bf215546Sopenharmony_ci         if (FAILED(ID3D12CommandQueue_Wait(queue->cmdqueue, (*evt)->fence, 1)))
1791bf215546Sopenharmony_ci            return vk_error(device, VK_ERROR_UNKNOWN);
1792bf215546Sopenharmony_ci      }
1793bf215546Sopenharmony_ci
1794bf215546Sopenharmony_ci      util_dynarray_foreach(&cmd_buffer->queries.wait, struct dzn_cmd_buffer_query_range, range) {
1795bf215546Sopenharmony_ci         mtx_lock(&range->qpool->queries_lock);
1796bf215546Sopenharmony_ci         for (uint32_t q = range->start; q < range->start + range->count; q++) {
1797bf215546Sopenharmony_ci            struct dzn_query *query = &range->qpool->queries[q];
1798bf215546Sopenharmony_ci
1799bf215546Sopenharmony_ci            if (query->fence &&
1800bf215546Sopenharmony_ci                FAILED(ID3D12CommandQueue_Wait(queue->cmdqueue, query->fence, query->fence_value)))
1801bf215546Sopenharmony_ci               return vk_error(device, VK_ERROR_UNKNOWN);
1802bf215546Sopenharmony_ci         }
1803bf215546Sopenharmony_ci         mtx_unlock(&range->qpool->queries_lock);
1804bf215546Sopenharmony_ci      }
1805bf215546Sopenharmony_ci
1806bf215546Sopenharmony_ci      util_dynarray_foreach(&cmd_buffer->queries.reset, struct dzn_cmd_buffer_query_range, range) {
1807bf215546Sopenharmony_ci         mtx_lock(&range->qpool->queries_lock);
1808bf215546Sopenharmony_ci         for (uint32_t q = range->start; q < range->start + range->count; q++) {
1809bf215546Sopenharmony_ci            struct dzn_query *query = &range->qpool->queries[q];
1810bf215546Sopenharmony_ci            if (query->fence) {
1811bf215546Sopenharmony_ci               ID3D12Fence_Release(query->fence);
1812bf215546Sopenharmony_ci               query->fence = NULL;
1813bf215546Sopenharmony_ci            }
1814bf215546Sopenharmony_ci            query->fence_value = 0;
1815bf215546Sopenharmony_ci         }
1816bf215546Sopenharmony_ci         mtx_unlock(&range->qpool->queries_lock);
1817bf215546Sopenharmony_ci      }
1818bf215546Sopenharmony_ci
1819bf215546Sopenharmony_ci      ID3D12CommandQueue_ExecuteCommandLists(queue->cmdqueue, 1, cmdlists);
1820bf215546Sopenharmony_ci
1821bf215546Sopenharmony_ci      util_dynarray_foreach(&cmd_buffer->events.signal, struct dzn_cmd_event_signal, evt) {
1822bf215546Sopenharmony_ci         if (FAILED(ID3D12CommandQueue_Signal(queue->cmdqueue, evt->event->fence, evt->value ? 1 : 0)))
1823bf215546Sopenharmony_ci            return vk_error(device, VK_ERROR_UNKNOWN);
1824bf215546Sopenharmony_ci      }
1825bf215546Sopenharmony_ci
1826bf215546Sopenharmony_ci      util_dynarray_foreach(&cmd_buffer->queries.signal, struct dzn_cmd_buffer_query_range, range) {
1827bf215546Sopenharmony_ci         mtx_lock(&range->qpool->queries_lock);
1828bf215546Sopenharmony_ci         for (uint32_t q = range->start; q < range->start + range->count; q++) {
1829bf215546Sopenharmony_ci            struct dzn_query *query = &range->qpool->queries[q];
1830bf215546Sopenharmony_ci            query->fence_value = queue->fence_point + 1;
1831bf215546Sopenharmony_ci            query->fence = queue->fence;
1832bf215546Sopenharmony_ci            ID3D12Fence_AddRef(query->fence);
1833bf215546Sopenharmony_ci         }
1834bf215546Sopenharmony_ci         mtx_unlock(&range->qpool->queries_lock);
1835bf215546Sopenharmony_ci      }
1836bf215546Sopenharmony_ci   }
1837bf215546Sopenharmony_ci
1838bf215546Sopenharmony_ci   for (uint32_t i = 0; i < info->signal_count; i++) {
1839bf215546Sopenharmony_ci      result = dzn_queue_sync_signal(queue, &info->signals[i]);
1840bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1841bf215546Sopenharmony_ci         return vk_error(device, VK_ERROR_UNKNOWN);
1842bf215546Sopenharmony_ci   }
1843bf215546Sopenharmony_ci
1844bf215546Sopenharmony_ci   if (FAILED(ID3D12CommandQueue_Signal(queue->cmdqueue, queue->fence, ++queue->fence_point)))
1845bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_UNKNOWN);
1846bf215546Sopenharmony_ci
1847bf215546Sopenharmony_ci   return VK_SUCCESS;
1848bf215546Sopenharmony_ci}
1849bf215546Sopenharmony_ci
1850bf215546Sopenharmony_cistatic void
1851bf215546Sopenharmony_cidzn_queue_finish(struct dzn_queue *queue)
1852bf215546Sopenharmony_ci{
1853bf215546Sopenharmony_ci   if (queue->cmdqueue)
1854bf215546Sopenharmony_ci      ID3D12CommandQueue_Release(queue->cmdqueue);
1855bf215546Sopenharmony_ci
1856bf215546Sopenharmony_ci   if (queue->fence)
1857bf215546Sopenharmony_ci      ID3D12Fence_Release(queue->fence);
1858bf215546Sopenharmony_ci
1859bf215546Sopenharmony_ci   vk_queue_finish(&queue->vk);
1860bf215546Sopenharmony_ci}
1861bf215546Sopenharmony_ci
1862bf215546Sopenharmony_cistatic VkResult
1863bf215546Sopenharmony_cidzn_queue_init(struct dzn_queue *queue,
1864bf215546Sopenharmony_ci               struct dzn_device *device,
1865bf215546Sopenharmony_ci               const VkDeviceQueueCreateInfo *pCreateInfo,
1866bf215546Sopenharmony_ci               uint32_t index_in_family)
1867bf215546Sopenharmony_ci{
1868bf215546Sopenharmony_ci   struct dzn_physical_device *pdev = container_of(device->vk.physical, struct dzn_physical_device, vk);
1869bf215546Sopenharmony_ci
1870bf215546Sopenharmony_ci   VkResult result = vk_queue_init(&queue->vk, &device->vk, pCreateInfo, index_in_family);
1871bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1872bf215546Sopenharmony_ci      return result;
1873bf215546Sopenharmony_ci
1874bf215546Sopenharmony_ci   queue->vk.driver_submit = dzn_queue_submit;
1875bf215546Sopenharmony_ci
1876bf215546Sopenharmony_ci   assert(pCreateInfo->queueFamilyIndex < pdev->queue_family_count);
1877bf215546Sopenharmony_ci
1878bf215546Sopenharmony_ci   D3D12_COMMAND_QUEUE_DESC queue_desc =
1879bf215546Sopenharmony_ci      pdev->queue_families[pCreateInfo->queueFamilyIndex].desc;
1880bf215546Sopenharmony_ci
1881bf215546Sopenharmony_ci   float priority_in = pCreateInfo->pQueuePriorities[index_in_family];
1882bf215546Sopenharmony_ci   queue_desc.Priority =
1883bf215546Sopenharmony_ci      priority_in > 0.5f ? D3D12_COMMAND_QUEUE_PRIORITY_HIGH : D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
1884bf215546Sopenharmony_ci   queue_desc.NodeMask = 0;
1885bf215546Sopenharmony_ci
1886bf215546Sopenharmony_ci   if (FAILED(ID3D12Device1_CreateCommandQueue(device->dev, &queue_desc,
1887bf215546Sopenharmony_ci                                               &IID_ID3D12CommandQueue,
1888bf215546Sopenharmony_ci                                               (void **)&queue->cmdqueue))) {
1889bf215546Sopenharmony_ci      dzn_queue_finish(queue);
1890bf215546Sopenharmony_ci      return vk_error(device->vk.physical->instance, VK_ERROR_INITIALIZATION_FAILED);
1891bf215546Sopenharmony_ci   }
1892bf215546Sopenharmony_ci
1893bf215546Sopenharmony_ci   if (FAILED(ID3D12Device1_CreateFence(device->dev, 0, D3D12_FENCE_FLAG_NONE,
1894bf215546Sopenharmony_ci                                        &IID_ID3D12Fence,
1895bf215546Sopenharmony_ci                                        (void **)&queue->fence))) {
1896bf215546Sopenharmony_ci      dzn_queue_finish(queue);
1897bf215546Sopenharmony_ci      return vk_error(device->vk.physical->instance, VK_ERROR_INITIALIZATION_FAILED);
1898bf215546Sopenharmony_ci   }
1899bf215546Sopenharmony_ci
1900bf215546Sopenharmony_ci   return VK_SUCCESS;
1901bf215546Sopenharmony_ci}
1902bf215546Sopenharmony_ci
1903bf215546Sopenharmony_cistatic VkResult
1904bf215546Sopenharmony_cicheck_physical_device_features(VkPhysicalDevice physicalDevice,
1905bf215546Sopenharmony_ci                               const VkPhysicalDeviceFeatures *features)
1906bf215546Sopenharmony_ci{
1907bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_physical_device, pdev, physicalDevice);
1908bf215546Sopenharmony_ci
1909bf215546Sopenharmony_ci   VkPhysicalDeviceFeatures supported_features;
1910bf215546Sopenharmony_ci
1911bf215546Sopenharmony_ci   pdev->vk.dispatch_table.GetPhysicalDeviceFeatures(physicalDevice, &supported_features);
1912bf215546Sopenharmony_ci
1913bf215546Sopenharmony_ci   VkBool32 *supported_feature = (VkBool32 *)&supported_features;
1914bf215546Sopenharmony_ci   VkBool32 *enabled_feature = (VkBool32 *)features;
1915bf215546Sopenharmony_ci   unsigned num_features = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
1916bf215546Sopenharmony_ci   for (uint32_t i = 0; i < num_features; i++) {
1917bf215546Sopenharmony_ci      if (enabled_feature[i] && !supported_feature[i])
1918bf215546Sopenharmony_ci         return VK_ERROR_FEATURE_NOT_PRESENT;
1919bf215546Sopenharmony_ci   }
1920bf215546Sopenharmony_ci
1921bf215546Sopenharmony_ci   return VK_SUCCESS;
1922bf215546Sopenharmony_ci}
1923bf215546Sopenharmony_ci
1924bf215546Sopenharmony_cistatic VkResult
1925bf215546Sopenharmony_cidzn_device_create_sync_for_memory(struct vk_device *device,
1926bf215546Sopenharmony_ci                                  VkDeviceMemory memory,
1927bf215546Sopenharmony_ci                                  bool signal_memory,
1928bf215546Sopenharmony_ci                                  struct vk_sync **sync_out)
1929bf215546Sopenharmony_ci{
1930bf215546Sopenharmony_ci   return vk_sync_create(device, &vk_sync_dummy_type,
1931bf215546Sopenharmony_ci                         0, 1, sync_out);
1932bf215546Sopenharmony_ci}
1933bf215546Sopenharmony_ci
1934bf215546Sopenharmony_cistatic VkResult
1935bf215546Sopenharmony_cidzn_device_query_init(struct dzn_device *device)
1936bf215546Sopenharmony_ci{
1937bf215546Sopenharmony_ci   /* FIXME: create the resource in the default heap */
1938bf215546Sopenharmony_ci   D3D12_HEAP_PROPERTIES hprops = dzn_ID3D12Device2_GetCustomHeapProperties(device->dev, 0, D3D12_HEAP_TYPE_UPLOAD);
1939bf215546Sopenharmony_ci   D3D12_RESOURCE_DESC rdesc = {
1940bf215546Sopenharmony_ci      .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
1941bf215546Sopenharmony_ci      .Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
1942bf215546Sopenharmony_ci      .Width = DZN_QUERY_REFS_RES_SIZE,
1943bf215546Sopenharmony_ci      .Height = 1,
1944bf215546Sopenharmony_ci      .DepthOrArraySize = 1,
1945bf215546Sopenharmony_ci      .MipLevels = 1,
1946bf215546Sopenharmony_ci      .Format = DXGI_FORMAT_UNKNOWN,
1947bf215546Sopenharmony_ci      .SampleDesc = { .Count = 1, .Quality = 0 },
1948bf215546Sopenharmony_ci      .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
1949bf215546Sopenharmony_ci      .Flags = D3D12_RESOURCE_FLAG_NONE,
1950bf215546Sopenharmony_ci   };
1951bf215546Sopenharmony_ci
1952bf215546Sopenharmony_ci   if (FAILED(ID3D12Device1_CreateCommittedResource(device->dev, &hprops,
1953bf215546Sopenharmony_ci                                                   D3D12_HEAP_FLAG_NONE,
1954bf215546Sopenharmony_ci                                                   &rdesc,
1955bf215546Sopenharmony_ci                                                   D3D12_RESOURCE_STATE_GENERIC_READ,
1956bf215546Sopenharmony_ci                                                   NULL,
1957bf215546Sopenharmony_ci                                                   &IID_ID3D12Resource,
1958bf215546Sopenharmony_ci                                                   (void **)&device->queries.refs)))
1959bf215546Sopenharmony_ci      return vk_error(device->vk.physical, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1960bf215546Sopenharmony_ci
1961bf215546Sopenharmony_ci   uint8_t *queries_ref;
1962bf215546Sopenharmony_ci   if (FAILED(ID3D12Resource_Map(device->queries.refs, 0, NULL, (void **)&queries_ref)))
1963bf215546Sopenharmony_ci      return vk_error(device->vk.physical, VK_ERROR_OUT_OF_HOST_MEMORY);
1964bf215546Sopenharmony_ci
1965bf215546Sopenharmony_ci   memset(queries_ref + DZN_QUERY_REFS_ALL_ONES_OFFSET, 0xff, DZN_QUERY_REFS_SECTION_SIZE);
1966bf215546Sopenharmony_ci   memset(queries_ref + DZN_QUERY_REFS_ALL_ZEROS_OFFSET, 0x0, DZN_QUERY_REFS_SECTION_SIZE);
1967bf215546Sopenharmony_ci   ID3D12Resource_Unmap(device->queries.refs, 0, NULL);
1968bf215546Sopenharmony_ci
1969bf215546Sopenharmony_ci   return VK_SUCCESS;
1970bf215546Sopenharmony_ci}
1971bf215546Sopenharmony_ci
1972bf215546Sopenharmony_cistatic void
1973bf215546Sopenharmony_cidzn_device_query_finish(struct dzn_device *device)
1974bf215546Sopenharmony_ci{
1975bf215546Sopenharmony_ci   if (device->queries.refs)
1976bf215546Sopenharmony_ci      ID3D12Resource_Release(device->queries.refs);
1977bf215546Sopenharmony_ci}
1978bf215546Sopenharmony_ci
1979bf215546Sopenharmony_cistatic void
1980bf215546Sopenharmony_cidzn_device_destroy(struct dzn_device *device, const VkAllocationCallbacks *pAllocator)
1981bf215546Sopenharmony_ci{
1982bf215546Sopenharmony_ci   if (!device)
1983bf215546Sopenharmony_ci      return;
1984bf215546Sopenharmony_ci
1985bf215546Sopenharmony_ci   struct dzn_instance *instance =
1986bf215546Sopenharmony_ci      container_of(device->vk.physical->instance, struct dzn_instance, vk);
1987bf215546Sopenharmony_ci
1988bf215546Sopenharmony_ci   vk_foreach_queue_safe(q, &device->vk) {
1989bf215546Sopenharmony_ci      struct dzn_queue *queue = container_of(q, struct dzn_queue, vk);
1990bf215546Sopenharmony_ci
1991bf215546Sopenharmony_ci      dzn_queue_finish(queue);
1992bf215546Sopenharmony_ci   }
1993bf215546Sopenharmony_ci
1994bf215546Sopenharmony_ci   dzn_device_query_finish(device);
1995bf215546Sopenharmony_ci   dzn_meta_finish(device);
1996bf215546Sopenharmony_ci
1997bf215546Sopenharmony_ci   if (device->dev)
1998bf215546Sopenharmony_ci      ID3D12Device1_Release(device->dev);
1999bf215546Sopenharmony_ci
2000bf215546Sopenharmony_ci   vk_device_finish(&device->vk);
2001bf215546Sopenharmony_ci   vk_free2(&instance->vk.alloc, pAllocator, device);
2002bf215546Sopenharmony_ci}
2003bf215546Sopenharmony_ci
2004bf215546Sopenharmony_cistatic VkResult
2005bf215546Sopenharmony_cidzn_device_check_status(struct vk_device *dev)
2006bf215546Sopenharmony_ci{
2007bf215546Sopenharmony_ci   struct dzn_device *device = container_of(dev, struct dzn_device, vk);
2008bf215546Sopenharmony_ci
2009bf215546Sopenharmony_ci   if (FAILED(ID3D12Device_GetDeviceRemovedReason(device->dev)))
2010bf215546Sopenharmony_ci      return vk_device_set_lost(&device->vk, "D3D12 device removed");
2011bf215546Sopenharmony_ci
2012bf215546Sopenharmony_ci   return VK_SUCCESS;
2013bf215546Sopenharmony_ci}
2014bf215546Sopenharmony_ci
2015bf215546Sopenharmony_cistatic VkResult
2016bf215546Sopenharmony_cidzn_device_create(struct dzn_physical_device *pdev,
2017bf215546Sopenharmony_ci                  const VkDeviceCreateInfo *pCreateInfo,
2018bf215546Sopenharmony_ci                  const VkAllocationCallbacks *pAllocator,
2019bf215546Sopenharmony_ci                  VkDevice *out)
2020bf215546Sopenharmony_ci{
2021bf215546Sopenharmony_ci   struct dzn_instance *instance = container_of(pdev->vk.instance, struct dzn_instance, vk);
2022bf215546Sopenharmony_ci
2023bf215546Sopenharmony_ci   uint32_t queue_count = 0;
2024bf215546Sopenharmony_ci   for (uint32_t qf = 0; qf < pCreateInfo->queueCreateInfoCount; qf++) {
2025bf215546Sopenharmony_ci      const VkDeviceQueueCreateInfo *qinfo = &pCreateInfo->pQueueCreateInfos[qf];
2026bf215546Sopenharmony_ci      queue_count += qinfo->queueCount;
2027bf215546Sopenharmony_ci   }
2028bf215546Sopenharmony_ci
2029bf215546Sopenharmony_ci   VK_MULTIALLOC(ma);
2030bf215546Sopenharmony_ci   VK_MULTIALLOC_DECL(&ma, struct dzn_device, device, 1);
2031bf215546Sopenharmony_ci   VK_MULTIALLOC_DECL(&ma, struct dzn_queue, queues, queue_count);
2032bf215546Sopenharmony_ci
2033bf215546Sopenharmony_ci   if (!vk_multialloc_zalloc2(&ma, &instance->vk.alloc, pAllocator,
2034bf215546Sopenharmony_ci                              VK_SYSTEM_ALLOCATION_SCOPE_DEVICE))
2035bf215546Sopenharmony_ci      return vk_error(pdev, VK_ERROR_OUT_OF_HOST_MEMORY);
2036bf215546Sopenharmony_ci
2037bf215546Sopenharmony_ci   struct vk_device_dispatch_table dispatch_table;
2038bf215546Sopenharmony_ci
2039bf215546Sopenharmony_ci   /* For secondary command buffer support, overwrite any command entrypoints
2040bf215546Sopenharmony_ci    * in the main device-level dispatch table with
2041bf215546Sopenharmony_ci    * vk_cmd_enqueue_unless_primary_Cmd*.
2042bf215546Sopenharmony_ci    */
2043bf215546Sopenharmony_ci   vk_device_dispatch_table_from_entrypoints(&dispatch_table,
2044bf215546Sopenharmony_ci      &vk_cmd_enqueue_unless_primary_device_entrypoints, true);
2045bf215546Sopenharmony_ci   vk_device_dispatch_table_from_entrypoints(&dispatch_table,
2046bf215546Sopenharmony_ci      &dzn_device_entrypoints, false);
2047bf215546Sopenharmony_ci   vk_device_dispatch_table_from_entrypoints(&dispatch_table,
2048bf215546Sopenharmony_ci      &wsi_device_entrypoints, false);
2049bf215546Sopenharmony_ci
2050bf215546Sopenharmony_ci   /* Populate our primary cmd_dispatch table. */
2051bf215546Sopenharmony_ci   vk_device_dispatch_table_from_entrypoints(&device->cmd_dispatch,
2052bf215546Sopenharmony_ci      &dzn_device_entrypoints, true);
2053bf215546Sopenharmony_ci   vk_device_dispatch_table_from_entrypoints(&device->cmd_dispatch,
2054bf215546Sopenharmony_ci                                             &vk_common_device_entrypoints,
2055bf215546Sopenharmony_ci                                             false);
2056bf215546Sopenharmony_ci
2057bf215546Sopenharmony_ci   VkResult result =
2058bf215546Sopenharmony_ci      vk_device_init(&device->vk, &pdev->vk, &dispatch_table, pCreateInfo, pAllocator);
2059bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
2060bf215546Sopenharmony_ci      vk_free2(&device->vk.alloc, pAllocator, device);
2061bf215546Sopenharmony_ci      return result;
2062bf215546Sopenharmony_ci   }
2063bf215546Sopenharmony_ci
2064bf215546Sopenharmony_ci   /* Must be done after vk_device_init() because this function memset(0) the
2065bf215546Sopenharmony_ci    * whole struct.
2066bf215546Sopenharmony_ci    */
2067bf215546Sopenharmony_ci   device->vk.command_dispatch_table = &device->cmd_dispatch;
2068bf215546Sopenharmony_ci   device->vk.create_sync_for_memory = dzn_device_create_sync_for_memory;
2069bf215546Sopenharmony_ci   device->vk.check_status = dzn_device_check_status;
2070bf215546Sopenharmony_ci
2071bf215546Sopenharmony_ci   device->dev = dzn_physical_device_get_d3d12_dev(pdev);
2072bf215546Sopenharmony_ci   if (!device->dev) {
2073bf215546Sopenharmony_ci      dzn_device_destroy(device, pAllocator);
2074bf215546Sopenharmony_ci      return vk_error(pdev, VK_ERROR_INITIALIZATION_FAILED);
2075bf215546Sopenharmony_ci   }
2076bf215546Sopenharmony_ci
2077bf215546Sopenharmony_ci   ID3D12Device1_AddRef(device->dev);
2078bf215546Sopenharmony_ci
2079bf215546Sopenharmony_ci   ID3D12InfoQueue *info_queue;
2080bf215546Sopenharmony_ci   if (SUCCEEDED(ID3D12Device1_QueryInterface(device->dev,
2081bf215546Sopenharmony_ci                                              &IID_ID3D12InfoQueue,
2082bf215546Sopenharmony_ci                                              (void **)&info_queue))) {
2083bf215546Sopenharmony_ci      D3D12_MESSAGE_SEVERITY severities[] = {
2084bf215546Sopenharmony_ci         D3D12_MESSAGE_SEVERITY_INFO,
2085bf215546Sopenharmony_ci         D3D12_MESSAGE_SEVERITY_WARNING,
2086bf215546Sopenharmony_ci      };
2087bf215546Sopenharmony_ci
2088bf215546Sopenharmony_ci      D3D12_MESSAGE_ID msg_ids[] = {
2089bf215546Sopenharmony_ci         D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE,
2090bf215546Sopenharmony_ci      };
2091bf215546Sopenharmony_ci
2092bf215546Sopenharmony_ci      D3D12_INFO_QUEUE_FILTER NewFilter = { 0 };
2093bf215546Sopenharmony_ci      NewFilter.DenyList.NumSeverities = ARRAY_SIZE(severities);
2094bf215546Sopenharmony_ci      NewFilter.DenyList.pSeverityList = severities;
2095bf215546Sopenharmony_ci      NewFilter.DenyList.NumIDs = ARRAY_SIZE(msg_ids);
2096bf215546Sopenharmony_ci      NewFilter.DenyList.pIDList = msg_ids;
2097bf215546Sopenharmony_ci
2098bf215546Sopenharmony_ci      ID3D12InfoQueue_PushStorageFilter(info_queue, &NewFilter);
2099bf215546Sopenharmony_ci   }
2100bf215546Sopenharmony_ci
2101bf215546Sopenharmony_ci   result = dzn_meta_init(device);
2102bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
2103bf215546Sopenharmony_ci      dzn_device_destroy(device, pAllocator);
2104bf215546Sopenharmony_ci      return result;
2105bf215546Sopenharmony_ci   }
2106bf215546Sopenharmony_ci
2107bf215546Sopenharmony_ci   result = dzn_device_query_init(device);
2108bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
2109bf215546Sopenharmony_ci      dzn_device_destroy(device, pAllocator);
2110bf215546Sopenharmony_ci      return result;
2111bf215546Sopenharmony_ci   }
2112bf215546Sopenharmony_ci
2113bf215546Sopenharmony_ci   uint32_t qindex = 0;
2114bf215546Sopenharmony_ci   for (uint32_t qf = 0; qf < pCreateInfo->queueCreateInfoCount; qf++) {
2115bf215546Sopenharmony_ci      const VkDeviceQueueCreateInfo *qinfo = &pCreateInfo->pQueueCreateInfos[qf];
2116bf215546Sopenharmony_ci
2117bf215546Sopenharmony_ci      for (uint32_t q = 0; q < qinfo->queueCount; q++) {
2118bf215546Sopenharmony_ci         result =
2119bf215546Sopenharmony_ci            dzn_queue_init(&queues[qindex++], device, qinfo, q);
2120bf215546Sopenharmony_ci         if (result != VK_SUCCESS) {
2121bf215546Sopenharmony_ci            dzn_device_destroy(device, pAllocator);
2122bf215546Sopenharmony_ci            return result;
2123bf215546Sopenharmony_ci         }
2124bf215546Sopenharmony_ci      }
2125bf215546Sopenharmony_ci   }
2126bf215546Sopenharmony_ci
2127bf215546Sopenharmony_ci   assert(queue_count == qindex);
2128bf215546Sopenharmony_ci   *out = dzn_device_to_handle(device);
2129bf215546Sopenharmony_ci   return VK_SUCCESS;
2130bf215546Sopenharmony_ci}
2131bf215546Sopenharmony_ci
2132bf215546Sopenharmony_ciID3D12RootSignature *
2133bf215546Sopenharmony_cidzn_device_create_root_sig(struct dzn_device *device,
2134bf215546Sopenharmony_ci                           const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc)
2135bf215546Sopenharmony_ci{
2136bf215546Sopenharmony_ci   struct dzn_instance *instance =
2137bf215546Sopenharmony_ci      container_of(device->vk.physical->instance, struct dzn_instance, vk);
2138bf215546Sopenharmony_ci   ID3D12RootSignature *root_sig = NULL;
2139bf215546Sopenharmony_ci   ID3DBlob *sig = NULL, *error = NULL;
2140bf215546Sopenharmony_ci
2141bf215546Sopenharmony_ci   if (FAILED(instance->d3d12.serialize_root_sig(desc,
2142bf215546Sopenharmony_ci                                                 &sig, &error))) {
2143bf215546Sopenharmony_ci      if (instance->debug_flags & DZN_DEBUG_SIG) {
2144bf215546Sopenharmony_ci         const char *error_msg = (const char *)ID3D10Blob_GetBufferPointer(error);
2145bf215546Sopenharmony_ci         fprintf(stderr,
2146bf215546Sopenharmony_ci                 "== SERIALIZE ROOT SIG ERROR =============================================\n"
2147bf215546Sopenharmony_ci                 "%s\n"
2148bf215546Sopenharmony_ci                 "== END ==========================================================\n",
2149bf215546Sopenharmony_ci                 error_msg);
2150bf215546Sopenharmony_ci      }
2151bf215546Sopenharmony_ci
2152bf215546Sopenharmony_ci      goto out;
2153bf215546Sopenharmony_ci   }
2154bf215546Sopenharmony_ci
2155bf215546Sopenharmony_ci   ID3D12Device1_CreateRootSignature(device->dev, 0,
2156bf215546Sopenharmony_ci                                     ID3D10Blob_GetBufferPointer(sig),
2157bf215546Sopenharmony_ci                                     ID3D10Blob_GetBufferSize(sig),
2158bf215546Sopenharmony_ci                                     &IID_ID3D12RootSignature,
2159bf215546Sopenharmony_ci                                     (void **)&root_sig);
2160bf215546Sopenharmony_ci
2161bf215546Sopenharmony_ciout:
2162bf215546Sopenharmony_ci   if (error)
2163bf215546Sopenharmony_ci      ID3D10Blob_Release(error);
2164bf215546Sopenharmony_ci
2165bf215546Sopenharmony_ci   if (sig)
2166bf215546Sopenharmony_ci      ID3D10Blob_Release(sig);
2167bf215546Sopenharmony_ci
2168bf215546Sopenharmony_ci   return root_sig;
2169bf215546Sopenharmony_ci}
2170bf215546Sopenharmony_ci
2171bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2172bf215546Sopenharmony_cidzn_CreateDevice(VkPhysicalDevice physicalDevice,
2173bf215546Sopenharmony_ci                 const VkDeviceCreateInfo *pCreateInfo,
2174bf215546Sopenharmony_ci                 const VkAllocationCallbacks *pAllocator,
2175bf215546Sopenharmony_ci                 VkDevice *pDevice)
2176bf215546Sopenharmony_ci{
2177bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_physical_device, physical_device, physicalDevice);
2178bf215546Sopenharmony_ci   VkResult result;
2179bf215546Sopenharmony_ci
2180bf215546Sopenharmony_ci   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
2181bf215546Sopenharmony_ci
2182bf215546Sopenharmony_ci   /* Check enabled features */
2183bf215546Sopenharmony_ci   if (pCreateInfo->pEnabledFeatures) {
2184bf215546Sopenharmony_ci      result = check_physical_device_features(physicalDevice,
2185bf215546Sopenharmony_ci                                              pCreateInfo->pEnabledFeatures);
2186bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
2187bf215546Sopenharmony_ci         return vk_error(physical_device, result);
2188bf215546Sopenharmony_ci   }
2189bf215546Sopenharmony_ci
2190bf215546Sopenharmony_ci   /* Check requested queues and fail if we are requested to create any
2191bf215546Sopenharmony_ci    * queues with flags we don't support.
2192bf215546Sopenharmony_ci    */
2193bf215546Sopenharmony_ci   assert(pCreateInfo->queueCreateInfoCount > 0);
2194bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
2195bf215546Sopenharmony_ci      if (pCreateInfo->pQueueCreateInfos[i].flags != 0)
2196bf215546Sopenharmony_ci         return vk_error(physical_device, VK_ERROR_INITIALIZATION_FAILED);
2197bf215546Sopenharmony_ci   }
2198bf215546Sopenharmony_ci
2199bf215546Sopenharmony_ci   return dzn_device_create(physical_device, pCreateInfo, pAllocator, pDevice);
2200bf215546Sopenharmony_ci}
2201bf215546Sopenharmony_ci
2202bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2203bf215546Sopenharmony_cidzn_DestroyDevice(VkDevice dev,
2204bf215546Sopenharmony_ci                  const VkAllocationCallbacks *pAllocator)
2205bf215546Sopenharmony_ci{
2206bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_device, device, dev);
2207bf215546Sopenharmony_ci
2208bf215546Sopenharmony_ci   device->vk.dispatch_table.DeviceWaitIdle(dev);
2209bf215546Sopenharmony_ci
2210bf215546Sopenharmony_ci   dzn_device_destroy(device, pAllocator);
2211bf215546Sopenharmony_ci}
2212bf215546Sopenharmony_ci
2213bf215546Sopenharmony_cistatic void
2214bf215546Sopenharmony_cidzn_device_memory_destroy(struct dzn_device_memory *mem,
2215bf215546Sopenharmony_ci                          const VkAllocationCallbacks *pAllocator)
2216bf215546Sopenharmony_ci{
2217bf215546Sopenharmony_ci   if (!mem)
2218bf215546Sopenharmony_ci      return;
2219bf215546Sopenharmony_ci
2220bf215546Sopenharmony_ci   struct dzn_device *device = container_of(mem->base.device, struct dzn_device, vk);
2221bf215546Sopenharmony_ci
2222bf215546Sopenharmony_ci   if (mem->map)
2223bf215546Sopenharmony_ci      ID3D12Resource_Unmap(mem->map_res, 0, NULL);
2224bf215546Sopenharmony_ci
2225bf215546Sopenharmony_ci   if (mem->map_res)
2226bf215546Sopenharmony_ci      ID3D12Resource_Release(mem->map_res);
2227bf215546Sopenharmony_ci
2228bf215546Sopenharmony_ci   if (mem->heap)
2229bf215546Sopenharmony_ci      ID3D12Heap_Release(mem->heap);
2230bf215546Sopenharmony_ci
2231bf215546Sopenharmony_ci   vk_object_base_finish(&mem->base);
2232bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, mem);
2233bf215546Sopenharmony_ci}
2234bf215546Sopenharmony_ci
2235bf215546Sopenharmony_cistatic VkResult
2236bf215546Sopenharmony_cidzn_device_memory_create(struct dzn_device *device,
2237bf215546Sopenharmony_ci                         const VkMemoryAllocateInfo *pAllocateInfo,
2238bf215546Sopenharmony_ci                         const VkAllocationCallbacks *pAllocator,
2239bf215546Sopenharmony_ci                         VkDeviceMemory *out)
2240bf215546Sopenharmony_ci{
2241bf215546Sopenharmony_ci   struct dzn_physical_device *pdevice =
2242bf215546Sopenharmony_ci      container_of(device->vk.physical, struct dzn_physical_device, vk);
2243bf215546Sopenharmony_ci
2244bf215546Sopenharmony_ci   struct dzn_device_memory *mem =
2245bf215546Sopenharmony_ci      vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*mem), 8,
2246bf215546Sopenharmony_ci                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2247bf215546Sopenharmony_ci   if (!mem)
2248bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2249bf215546Sopenharmony_ci
2250bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &mem->base, VK_OBJECT_TYPE_DEVICE_MEMORY);
2251bf215546Sopenharmony_ci
2252bf215546Sopenharmony_ci   /* The Vulkan 1.0.33 spec says "allocationSize must be greater than 0". */
2253bf215546Sopenharmony_ci   assert(pAllocateInfo->allocationSize > 0);
2254bf215546Sopenharmony_ci
2255bf215546Sopenharmony_ci   mem->size = pAllocateInfo->allocationSize;
2256bf215546Sopenharmony_ci
2257bf215546Sopenharmony_ci   const struct dzn_buffer *buffer = NULL;
2258bf215546Sopenharmony_ci   const struct dzn_image *image = NULL;
2259bf215546Sopenharmony_ci
2260bf215546Sopenharmony_ci   vk_foreach_struct_const(ext, pAllocateInfo->pNext) {
2261bf215546Sopenharmony_ci      switch (ext->sType) {
2262bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO: {
2263bf215546Sopenharmony_ci         UNUSED const VkExportMemoryAllocateInfo *exp =
2264bf215546Sopenharmony_ci            (const VkExportMemoryAllocateInfo *)ext;
2265bf215546Sopenharmony_ci
2266bf215546Sopenharmony_ci         // TODO: support export
2267bf215546Sopenharmony_ci         assert(exp->handleTypes == 0);
2268bf215546Sopenharmony_ci         break;
2269bf215546Sopenharmony_ci      }
2270bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO: {
2271bf215546Sopenharmony_ci         const VkMemoryDedicatedAllocateInfo *dedicated =
2272bf215546Sopenharmony_ci           (const VkMemoryDedicatedAllocateInfo *)ext;
2273bf215546Sopenharmony_ci
2274bf215546Sopenharmony_ci         buffer = dzn_buffer_from_handle(dedicated->buffer);
2275bf215546Sopenharmony_ci         image = dzn_image_from_handle(dedicated->image);
2276bf215546Sopenharmony_ci         assert(!buffer || !image);
2277bf215546Sopenharmony_ci         break;
2278bf215546Sopenharmony_ci      }
2279bf215546Sopenharmony_ci      default:
2280bf215546Sopenharmony_ci         dzn_debug_ignored_stype(ext->sType);
2281bf215546Sopenharmony_ci         break;
2282bf215546Sopenharmony_ci      }
2283bf215546Sopenharmony_ci   }
2284bf215546Sopenharmony_ci
2285bf215546Sopenharmony_ci   const VkMemoryType *mem_type =
2286bf215546Sopenharmony_ci      &pdevice->memory.memoryTypes[pAllocateInfo->memoryTypeIndex];
2287bf215546Sopenharmony_ci
2288bf215546Sopenharmony_ci   D3D12_HEAP_DESC heap_desc = { 0 };
2289bf215546Sopenharmony_ci
2290bf215546Sopenharmony_ci   heap_desc.SizeInBytes = pAllocateInfo->allocationSize;
2291bf215546Sopenharmony_ci   if (buffer) {
2292bf215546Sopenharmony_ci      heap_desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
2293bf215546Sopenharmony_ci   } else if (image) {
2294bf215546Sopenharmony_ci      heap_desc.Alignment =
2295bf215546Sopenharmony_ci         image->vk.samples > 1 ?
2296bf215546Sopenharmony_ci         D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT :
2297bf215546Sopenharmony_ci         D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
2298bf215546Sopenharmony_ci   } else {
2299bf215546Sopenharmony_ci      heap_desc.Alignment =
2300bf215546Sopenharmony_ci         heap_desc.SizeInBytes >= D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT ?
2301bf215546Sopenharmony_ci         D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT :
2302bf215546Sopenharmony_ci         D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
2303bf215546Sopenharmony_ci   }
2304bf215546Sopenharmony_ci
2305bf215546Sopenharmony_ci   heap_desc.Flags =
2306bf215546Sopenharmony_ci      dzn_physical_device_get_heap_flags_for_mem_type(pdevice,
2307bf215546Sopenharmony_ci                                                      pAllocateInfo->memoryTypeIndex);
2308bf215546Sopenharmony_ci
2309bf215546Sopenharmony_ci   /* TODO: Unsure about this logic??? */
2310bf215546Sopenharmony_ci   mem->initial_state = D3D12_RESOURCE_STATE_COMMON;
2311bf215546Sopenharmony_ci   heap_desc.Properties.Type = D3D12_HEAP_TYPE_CUSTOM;
2312bf215546Sopenharmony_ci   heap_desc.Properties.MemoryPoolPreference =
2313bf215546Sopenharmony_ci      ((mem_type->propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) &&
2314bf215546Sopenharmony_ci       !pdevice->architecture.UMA) ?
2315bf215546Sopenharmony_ci      D3D12_MEMORY_POOL_L1 : D3D12_MEMORY_POOL_L0;
2316bf215546Sopenharmony_ci   if (mem_type->propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
2317bf215546Sopenharmony_ci      heap_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_BACK;
2318bf215546Sopenharmony_ci   } else if (mem_type->propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
2319bf215546Sopenharmony_ci      heap_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE;
2320bf215546Sopenharmony_ci   } else {
2321bf215546Sopenharmony_ci      heap_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE;
2322bf215546Sopenharmony_ci   }
2323bf215546Sopenharmony_ci
2324bf215546Sopenharmony_ci   if (FAILED(ID3D12Device1_CreateHeap(device->dev, &heap_desc,
2325bf215546Sopenharmony_ci                                       &IID_ID3D12Heap,
2326bf215546Sopenharmony_ci                                       (void **)&mem->heap))) {
2327bf215546Sopenharmony_ci      dzn_device_memory_destroy(mem, pAllocator);
2328bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2329bf215546Sopenharmony_ci   }
2330bf215546Sopenharmony_ci
2331bf215546Sopenharmony_ci   if ((mem_type->propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) &&
2332bf215546Sopenharmony_ci       !(heap_desc.Flags & D3D12_HEAP_FLAG_DENY_BUFFERS)){
2333bf215546Sopenharmony_ci      D3D12_RESOURCE_DESC res_desc = { 0 };
2334bf215546Sopenharmony_ci      res_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
2335bf215546Sopenharmony_ci      res_desc.Format = DXGI_FORMAT_UNKNOWN;
2336bf215546Sopenharmony_ci      res_desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
2337bf215546Sopenharmony_ci      res_desc.Width = heap_desc.SizeInBytes;
2338bf215546Sopenharmony_ci      res_desc.Height = 1;
2339bf215546Sopenharmony_ci      res_desc.DepthOrArraySize = 1;
2340bf215546Sopenharmony_ci      res_desc.MipLevels = 1;
2341bf215546Sopenharmony_ci      res_desc.SampleDesc.Count = 1;
2342bf215546Sopenharmony_ci      res_desc.SampleDesc.Quality = 0;
2343bf215546Sopenharmony_ci      res_desc.Flags = D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
2344bf215546Sopenharmony_ci      res_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
2345bf215546Sopenharmony_ci      HRESULT hr = ID3D12Device1_CreatePlacedResource(device->dev, mem->heap, 0, &res_desc,
2346bf215546Sopenharmony_ci                                                      mem->initial_state,
2347bf215546Sopenharmony_ci                                                      NULL,
2348bf215546Sopenharmony_ci                                                      &IID_ID3D12Resource,
2349bf215546Sopenharmony_ci                                                      (void **)&mem->map_res);
2350bf215546Sopenharmony_ci      if (FAILED(hr)) {
2351bf215546Sopenharmony_ci         dzn_device_memory_destroy(mem, pAllocator);
2352bf215546Sopenharmony_ci         return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2353bf215546Sopenharmony_ci      }
2354bf215546Sopenharmony_ci   }
2355bf215546Sopenharmony_ci
2356bf215546Sopenharmony_ci   *out = dzn_device_memory_to_handle(mem);
2357bf215546Sopenharmony_ci   return VK_SUCCESS;
2358bf215546Sopenharmony_ci}
2359bf215546Sopenharmony_ci
2360bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2361bf215546Sopenharmony_cidzn_AllocateMemory(VkDevice device,
2362bf215546Sopenharmony_ci                   const VkMemoryAllocateInfo *pAllocateInfo,
2363bf215546Sopenharmony_ci                   const VkAllocationCallbacks *pAllocator,
2364bf215546Sopenharmony_ci                   VkDeviceMemory *pMem)
2365bf215546Sopenharmony_ci{
2366bf215546Sopenharmony_ci   return dzn_device_memory_create(dzn_device_from_handle(device),
2367bf215546Sopenharmony_ci                                   pAllocateInfo, pAllocator, pMem);
2368bf215546Sopenharmony_ci}
2369bf215546Sopenharmony_ci
2370bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2371bf215546Sopenharmony_cidzn_FreeMemory(VkDevice device,
2372bf215546Sopenharmony_ci               VkDeviceMemory mem,
2373bf215546Sopenharmony_ci               const VkAllocationCallbacks *pAllocator)
2374bf215546Sopenharmony_ci{
2375bf215546Sopenharmony_ci   dzn_device_memory_destroy(dzn_device_memory_from_handle(mem), pAllocator);
2376bf215546Sopenharmony_ci}
2377bf215546Sopenharmony_ci
2378bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2379bf215546Sopenharmony_cidzn_MapMemory(VkDevice _device,
2380bf215546Sopenharmony_ci              VkDeviceMemory _memory,
2381bf215546Sopenharmony_ci              VkDeviceSize offset,
2382bf215546Sopenharmony_ci              VkDeviceSize size,
2383bf215546Sopenharmony_ci              VkMemoryMapFlags flags,
2384bf215546Sopenharmony_ci              void **ppData)
2385bf215546Sopenharmony_ci{
2386bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_device, device, _device);
2387bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_device_memory, mem, _memory);
2388bf215546Sopenharmony_ci
2389bf215546Sopenharmony_ci   if (mem == NULL) {
2390bf215546Sopenharmony_ci      *ppData = NULL;
2391bf215546Sopenharmony_ci      return VK_SUCCESS;
2392bf215546Sopenharmony_ci   }
2393bf215546Sopenharmony_ci
2394bf215546Sopenharmony_ci   if (size == VK_WHOLE_SIZE)
2395bf215546Sopenharmony_ci      size = mem->size - offset;
2396bf215546Sopenharmony_ci
2397bf215546Sopenharmony_ci   /* From the Vulkan spec version 1.0.32 docs for MapMemory:
2398bf215546Sopenharmony_ci    *
2399bf215546Sopenharmony_ci    *  * If size is not equal to VK_WHOLE_SIZE, size must be greater than 0
2400bf215546Sopenharmony_ci    *    assert(size != 0);
2401bf215546Sopenharmony_ci    *  * If size is not equal to VK_WHOLE_SIZE, size must be less than or
2402bf215546Sopenharmony_ci    *    equal to the size of the memory minus offset
2403bf215546Sopenharmony_ci    */
2404bf215546Sopenharmony_ci   assert(size > 0);
2405bf215546Sopenharmony_ci   assert(offset + size <= mem->size);
2406bf215546Sopenharmony_ci
2407bf215546Sopenharmony_ci   assert(mem->map_res);
2408bf215546Sopenharmony_ci   D3D12_RANGE range = { 0 };
2409bf215546Sopenharmony_ci   range.Begin = offset;
2410bf215546Sopenharmony_ci   range.End = offset + size;
2411bf215546Sopenharmony_ci   void *map = NULL;
2412bf215546Sopenharmony_ci   if (FAILED(ID3D12Resource_Map(mem->map_res, 0, &range, &map)))
2413bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED);
2414bf215546Sopenharmony_ci
2415bf215546Sopenharmony_ci   mem->map = map;
2416bf215546Sopenharmony_ci   mem->map_size = size;
2417bf215546Sopenharmony_ci
2418bf215546Sopenharmony_ci   *ppData = ((uint8_t *) map) + offset;
2419bf215546Sopenharmony_ci
2420bf215546Sopenharmony_ci   return VK_SUCCESS;
2421bf215546Sopenharmony_ci}
2422bf215546Sopenharmony_ci
2423bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2424bf215546Sopenharmony_cidzn_UnmapMemory(VkDevice _device,
2425bf215546Sopenharmony_ci                VkDeviceMemory _memory)
2426bf215546Sopenharmony_ci{
2427bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_device_memory, mem, _memory);
2428bf215546Sopenharmony_ci
2429bf215546Sopenharmony_ci   if (mem == NULL)
2430bf215546Sopenharmony_ci      return;
2431bf215546Sopenharmony_ci
2432bf215546Sopenharmony_ci   assert(mem->map_res);
2433bf215546Sopenharmony_ci   ID3D12Resource_Unmap(mem->map_res, 0, NULL);
2434bf215546Sopenharmony_ci
2435bf215546Sopenharmony_ci   mem->map = NULL;
2436bf215546Sopenharmony_ci   mem->map_size = 0;
2437bf215546Sopenharmony_ci}
2438bf215546Sopenharmony_ci
2439bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2440bf215546Sopenharmony_cidzn_FlushMappedMemoryRanges(VkDevice _device,
2441bf215546Sopenharmony_ci                            uint32_t memoryRangeCount,
2442bf215546Sopenharmony_ci                            const VkMappedMemoryRange *pMemoryRanges)
2443bf215546Sopenharmony_ci{
2444bf215546Sopenharmony_ci   return VK_SUCCESS;
2445bf215546Sopenharmony_ci}
2446bf215546Sopenharmony_ci
2447bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2448bf215546Sopenharmony_cidzn_InvalidateMappedMemoryRanges(VkDevice _device,
2449bf215546Sopenharmony_ci                                 uint32_t memoryRangeCount,
2450bf215546Sopenharmony_ci                                 const VkMappedMemoryRange *pMemoryRanges)
2451bf215546Sopenharmony_ci{
2452bf215546Sopenharmony_ci   return VK_SUCCESS;
2453bf215546Sopenharmony_ci}
2454bf215546Sopenharmony_ci
2455bf215546Sopenharmony_cistatic void
2456bf215546Sopenharmony_cidzn_buffer_destroy(struct dzn_buffer *buf, const VkAllocationCallbacks *pAllocator)
2457bf215546Sopenharmony_ci{
2458bf215546Sopenharmony_ci   if (!buf)
2459bf215546Sopenharmony_ci      return;
2460bf215546Sopenharmony_ci
2461bf215546Sopenharmony_ci   struct dzn_device *device = container_of(buf->base.device, struct dzn_device, vk);
2462bf215546Sopenharmony_ci
2463bf215546Sopenharmony_ci   if (buf->res)
2464bf215546Sopenharmony_ci      ID3D12Resource_Release(buf->res);
2465bf215546Sopenharmony_ci
2466bf215546Sopenharmony_ci   vk_object_base_finish(&buf->base);
2467bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, buf);
2468bf215546Sopenharmony_ci}
2469bf215546Sopenharmony_ci
2470bf215546Sopenharmony_cistatic VkResult
2471bf215546Sopenharmony_cidzn_buffer_create(struct dzn_device *device,
2472bf215546Sopenharmony_ci                  const VkBufferCreateInfo *pCreateInfo,
2473bf215546Sopenharmony_ci                  const VkAllocationCallbacks *pAllocator,
2474bf215546Sopenharmony_ci                  VkBuffer *out)
2475bf215546Sopenharmony_ci{
2476bf215546Sopenharmony_ci   struct dzn_buffer *buf =
2477bf215546Sopenharmony_ci      vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*buf), 8,
2478bf215546Sopenharmony_ci                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2479bf215546Sopenharmony_ci   if (!buf)
2480bf215546Sopenharmony_ci     return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2481bf215546Sopenharmony_ci
2482bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &buf->base, VK_OBJECT_TYPE_BUFFER);
2483bf215546Sopenharmony_ci   buf->create_flags = pCreateInfo->flags;
2484bf215546Sopenharmony_ci   buf->size = pCreateInfo->size;
2485bf215546Sopenharmony_ci   buf->usage = pCreateInfo->usage;
2486bf215546Sopenharmony_ci
2487bf215546Sopenharmony_ci   if (buf->usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
2488bf215546Sopenharmony_ci      buf->size = ALIGN_POT(buf->size, 256);
2489bf215546Sopenharmony_ci
2490bf215546Sopenharmony_ci   buf->desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
2491bf215546Sopenharmony_ci   buf->desc.Format = DXGI_FORMAT_UNKNOWN;
2492bf215546Sopenharmony_ci   buf->desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
2493bf215546Sopenharmony_ci   buf->desc.Width = buf->size;
2494bf215546Sopenharmony_ci   buf->desc.Height = 1;
2495bf215546Sopenharmony_ci   buf->desc.DepthOrArraySize = 1;
2496bf215546Sopenharmony_ci   buf->desc.MipLevels = 1;
2497bf215546Sopenharmony_ci   buf->desc.SampleDesc.Count = 1;
2498bf215546Sopenharmony_ci   buf->desc.SampleDesc.Quality = 0;
2499bf215546Sopenharmony_ci   buf->desc.Flags = D3D12_RESOURCE_FLAG_NONE;
2500bf215546Sopenharmony_ci   buf->desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
2501bf215546Sopenharmony_ci
2502bf215546Sopenharmony_ci   if (buf->usage &
2503bf215546Sopenharmony_ci       (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
2504bf215546Sopenharmony_ci        VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
2505bf215546Sopenharmony_ci      buf->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
2506bf215546Sopenharmony_ci
2507bf215546Sopenharmony_ci   *out = dzn_buffer_to_handle(buf);
2508bf215546Sopenharmony_ci   return VK_SUCCESS;
2509bf215546Sopenharmony_ci}
2510bf215546Sopenharmony_ci
2511bf215546Sopenharmony_ciDXGI_FORMAT
2512bf215546Sopenharmony_cidzn_buffer_get_dxgi_format(VkFormat format)
2513bf215546Sopenharmony_ci{
2514bf215546Sopenharmony_ci   enum pipe_format pfmt = vk_format_to_pipe_format(format);
2515bf215546Sopenharmony_ci
2516bf215546Sopenharmony_ci   return dzn_pipe_to_dxgi_format(pfmt);
2517bf215546Sopenharmony_ci}
2518bf215546Sopenharmony_ci
2519bf215546Sopenharmony_ciD3D12_TEXTURE_COPY_LOCATION
2520bf215546Sopenharmony_cidzn_buffer_get_copy_loc(const struct dzn_buffer *buf,
2521bf215546Sopenharmony_ci                        VkFormat format,
2522bf215546Sopenharmony_ci                        const VkBufferImageCopy2 *region,
2523bf215546Sopenharmony_ci                        VkImageAspectFlagBits aspect,
2524bf215546Sopenharmony_ci                        uint32_t layer)
2525bf215546Sopenharmony_ci{
2526bf215546Sopenharmony_ci   const uint32_t buffer_row_length =
2527bf215546Sopenharmony_ci      region->bufferRowLength ? region->bufferRowLength : region->imageExtent.width;
2528bf215546Sopenharmony_ci
2529bf215546Sopenharmony_ci   VkFormat plane_format = dzn_image_get_plane_format(format, aspect);
2530bf215546Sopenharmony_ci
2531bf215546Sopenharmony_ci   enum pipe_format pfmt = vk_format_to_pipe_format(plane_format);
2532bf215546Sopenharmony_ci   uint32_t blksz = util_format_get_blocksize(pfmt);
2533bf215546Sopenharmony_ci   uint32_t blkw = util_format_get_blockwidth(pfmt);
2534bf215546Sopenharmony_ci   uint32_t blkh = util_format_get_blockheight(pfmt);
2535bf215546Sopenharmony_ci
2536bf215546Sopenharmony_ci   D3D12_TEXTURE_COPY_LOCATION loc = {
2537bf215546Sopenharmony_ci     .pResource = buf->res,
2538bf215546Sopenharmony_ci     .Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
2539bf215546Sopenharmony_ci     .PlacedFootprint = {
2540bf215546Sopenharmony_ci        .Footprint = {
2541bf215546Sopenharmony_ci           .Format =
2542bf215546Sopenharmony_ci              dzn_image_get_placed_footprint_format(format, aspect),
2543bf215546Sopenharmony_ci           .Width = region->imageExtent.width,
2544bf215546Sopenharmony_ci           .Height = region->imageExtent.height,
2545bf215546Sopenharmony_ci           .Depth = region->imageExtent.depth,
2546bf215546Sopenharmony_ci           .RowPitch = blksz * DIV_ROUND_UP(buffer_row_length, blkw),
2547bf215546Sopenharmony_ci        },
2548bf215546Sopenharmony_ci     },
2549bf215546Sopenharmony_ci   };
2550bf215546Sopenharmony_ci
2551bf215546Sopenharmony_ci   uint32_t buffer_layer_stride =
2552bf215546Sopenharmony_ci      loc.PlacedFootprint.Footprint.RowPitch *
2553bf215546Sopenharmony_ci      DIV_ROUND_UP(loc.PlacedFootprint.Footprint.Height, blkh);
2554bf215546Sopenharmony_ci
2555bf215546Sopenharmony_ci   loc.PlacedFootprint.Offset =
2556bf215546Sopenharmony_ci      region->bufferOffset + (layer * buffer_layer_stride);
2557bf215546Sopenharmony_ci
2558bf215546Sopenharmony_ci   return loc;
2559bf215546Sopenharmony_ci}
2560bf215546Sopenharmony_ci
2561bf215546Sopenharmony_ciD3D12_TEXTURE_COPY_LOCATION
2562bf215546Sopenharmony_cidzn_buffer_get_line_copy_loc(const struct dzn_buffer *buf, VkFormat format,
2563bf215546Sopenharmony_ci                             const VkBufferImageCopy2 *region,
2564bf215546Sopenharmony_ci                             const D3D12_TEXTURE_COPY_LOCATION *loc,
2565bf215546Sopenharmony_ci                             uint32_t y, uint32_t z, uint32_t *start_x)
2566bf215546Sopenharmony_ci{
2567bf215546Sopenharmony_ci   uint32_t buffer_row_length =
2568bf215546Sopenharmony_ci      region->bufferRowLength ? region->bufferRowLength : region->imageExtent.width;
2569bf215546Sopenharmony_ci   uint32_t buffer_image_height =
2570bf215546Sopenharmony_ci      region->bufferImageHeight ? region->bufferImageHeight : region->imageExtent.height;
2571bf215546Sopenharmony_ci
2572bf215546Sopenharmony_ci   format = dzn_image_get_plane_format(format, region->imageSubresource.aspectMask);
2573bf215546Sopenharmony_ci
2574bf215546Sopenharmony_ci   enum pipe_format pfmt = vk_format_to_pipe_format(format);
2575bf215546Sopenharmony_ci   uint32_t blksz = util_format_get_blocksize(pfmt);
2576bf215546Sopenharmony_ci   uint32_t blkw = util_format_get_blockwidth(pfmt);
2577bf215546Sopenharmony_ci   uint32_t blkh = util_format_get_blockheight(pfmt);
2578bf215546Sopenharmony_ci   uint32_t blkd = util_format_get_blockdepth(pfmt);
2579bf215546Sopenharmony_ci   D3D12_TEXTURE_COPY_LOCATION new_loc = *loc;
2580bf215546Sopenharmony_ci   uint32_t buffer_row_stride =
2581bf215546Sopenharmony_ci      DIV_ROUND_UP(buffer_row_length, blkw) * blksz;
2582bf215546Sopenharmony_ci   uint32_t buffer_layer_stride =
2583bf215546Sopenharmony_ci      buffer_row_stride *
2584bf215546Sopenharmony_ci      DIV_ROUND_UP(buffer_image_height, blkh);
2585bf215546Sopenharmony_ci
2586bf215546Sopenharmony_ci   uint64_t tex_offset =
2587bf215546Sopenharmony_ci      ((y / blkh) * buffer_row_stride) +
2588bf215546Sopenharmony_ci      ((z / blkd) * buffer_layer_stride);
2589bf215546Sopenharmony_ci   uint64_t offset = loc->PlacedFootprint.Offset + tex_offset;
2590bf215546Sopenharmony_ci   uint32_t offset_alignment = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
2591bf215546Sopenharmony_ci
2592bf215546Sopenharmony_ci   while (offset_alignment % blksz)
2593bf215546Sopenharmony_ci      offset_alignment += D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
2594bf215546Sopenharmony_ci
2595bf215546Sopenharmony_ci   new_loc.PlacedFootprint.Footprint.Height = blkh;
2596bf215546Sopenharmony_ci   new_loc.PlacedFootprint.Footprint.Depth = 1;
2597bf215546Sopenharmony_ci   new_loc.PlacedFootprint.Offset = (offset / offset_alignment) * offset_alignment;
2598bf215546Sopenharmony_ci   *start_x = ((offset % offset_alignment) / blksz) * blkw;
2599bf215546Sopenharmony_ci   new_loc.PlacedFootprint.Footprint.Width = *start_x + region->imageExtent.width;
2600bf215546Sopenharmony_ci   new_loc.PlacedFootprint.Footprint.RowPitch =
2601bf215546Sopenharmony_ci      ALIGN_POT(DIV_ROUND_UP(new_loc.PlacedFootprint.Footprint.Width, blkw) * blksz,
2602bf215546Sopenharmony_ci                D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
2603bf215546Sopenharmony_ci   return new_loc;
2604bf215546Sopenharmony_ci}
2605bf215546Sopenharmony_ci
2606bf215546Sopenharmony_cibool
2607bf215546Sopenharmony_cidzn_buffer_supports_region_copy(const D3D12_TEXTURE_COPY_LOCATION *loc)
2608bf215546Sopenharmony_ci{
2609bf215546Sopenharmony_ci   return !(loc->PlacedFootprint.Offset & (D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT - 1)) &&
2610bf215546Sopenharmony_ci          !(loc->PlacedFootprint.Footprint.RowPitch & (D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1));
2611bf215546Sopenharmony_ci}
2612bf215546Sopenharmony_ci
2613bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2614bf215546Sopenharmony_cidzn_CreateBuffer(VkDevice device,
2615bf215546Sopenharmony_ci                 const VkBufferCreateInfo *pCreateInfo,
2616bf215546Sopenharmony_ci                 const VkAllocationCallbacks *pAllocator,
2617bf215546Sopenharmony_ci                 VkBuffer *pBuffer)
2618bf215546Sopenharmony_ci{
2619bf215546Sopenharmony_ci   return dzn_buffer_create(dzn_device_from_handle(device),
2620bf215546Sopenharmony_ci                            pCreateInfo, pAllocator, pBuffer);
2621bf215546Sopenharmony_ci}
2622bf215546Sopenharmony_ci
2623bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2624bf215546Sopenharmony_cidzn_DestroyBuffer(VkDevice device,
2625bf215546Sopenharmony_ci                  VkBuffer buffer,
2626bf215546Sopenharmony_ci                  const VkAllocationCallbacks *pAllocator)
2627bf215546Sopenharmony_ci{
2628bf215546Sopenharmony_ci   dzn_buffer_destroy(dzn_buffer_from_handle(buffer), pAllocator);
2629bf215546Sopenharmony_ci}
2630bf215546Sopenharmony_ci
2631bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2632bf215546Sopenharmony_cidzn_GetBufferMemoryRequirements2(VkDevice dev,
2633bf215546Sopenharmony_ci                                 const VkBufferMemoryRequirementsInfo2 *pInfo,
2634bf215546Sopenharmony_ci                                 VkMemoryRequirements2 *pMemoryRequirements)
2635bf215546Sopenharmony_ci{
2636bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_device, device, dev);
2637bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_buffer, buffer, pInfo->buffer);
2638bf215546Sopenharmony_ci   struct dzn_physical_device *pdev =
2639bf215546Sopenharmony_ci      container_of(device->vk.physical, struct dzn_physical_device, vk);
2640bf215546Sopenharmony_ci
2641bf215546Sopenharmony_ci   /* uh, this is grossly over-estimating things */
2642bf215546Sopenharmony_ci   uint32_t alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
2643bf215546Sopenharmony_ci   VkDeviceSize size = buffer->size;
2644bf215546Sopenharmony_ci
2645bf215546Sopenharmony_ci   if (buffer->usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) {
2646bf215546Sopenharmony_ci      alignment = MAX2(alignment, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
2647bf215546Sopenharmony_ci      size = ALIGN_POT(size, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT);
2648bf215546Sopenharmony_ci   }
2649bf215546Sopenharmony_ci
2650bf215546Sopenharmony_ci   pMemoryRequirements->memoryRequirements.size = size;
2651bf215546Sopenharmony_ci   pMemoryRequirements->memoryRequirements.alignment = alignment;
2652bf215546Sopenharmony_ci   pMemoryRequirements->memoryRequirements.memoryTypeBits =
2653bf215546Sopenharmony_ci      dzn_physical_device_get_mem_type_mask_for_resource(pdev, &buffer->desc);
2654bf215546Sopenharmony_ci
2655bf215546Sopenharmony_ci   vk_foreach_struct(ext, pMemoryRequirements->pNext) {
2656bf215546Sopenharmony_ci      switch (ext->sType) {
2657bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
2658bf215546Sopenharmony_ci         VkMemoryDedicatedRequirements *requirements =
2659bf215546Sopenharmony_ci            (VkMemoryDedicatedRequirements *)ext;
2660bf215546Sopenharmony_ci         /* TODO: figure out dedicated allocations */
2661bf215546Sopenharmony_ci         requirements->prefersDedicatedAllocation = false;
2662bf215546Sopenharmony_ci         requirements->requiresDedicatedAllocation = false;
2663bf215546Sopenharmony_ci         break;
2664bf215546Sopenharmony_ci      }
2665bf215546Sopenharmony_ci
2666bf215546Sopenharmony_ci      default:
2667bf215546Sopenharmony_ci         dzn_debug_ignored_stype(ext->sType);
2668bf215546Sopenharmony_ci         break;
2669bf215546Sopenharmony_ci      }
2670bf215546Sopenharmony_ci   }
2671bf215546Sopenharmony_ci
2672bf215546Sopenharmony_ci#if 0
2673bf215546Sopenharmony_ci   D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfo(
2674bf215546Sopenharmony_ci      UINT                      visibleMask,
2675bf215546Sopenharmony_ci      UINT                      numResourceDescs,
2676bf215546Sopenharmony_ci      const D3D12_RESOURCE_DESC *pResourceDescs);
2677bf215546Sopenharmony_ci#endif
2678bf215546Sopenharmony_ci}
2679bf215546Sopenharmony_ci
2680bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2681bf215546Sopenharmony_cidzn_BindBufferMemory2(VkDevice _device,
2682bf215546Sopenharmony_ci                      uint32_t bindInfoCount,
2683bf215546Sopenharmony_ci                      const VkBindBufferMemoryInfo *pBindInfos)
2684bf215546Sopenharmony_ci{
2685bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_device, device, _device);
2686bf215546Sopenharmony_ci
2687bf215546Sopenharmony_ci   for (uint32_t i = 0; i < bindInfoCount; i++) {
2688bf215546Sopenharmony_ci      assert(pBindInfos[i].sType == VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO);
2689bf215546Sopenharmony_ci
2690bf215546Sopenharmony_ci      VK_FROM_HANDLE(dzn_device_memory, mem, pBindInfos[i].memory);
2691bf215546Sopenharmony_ci      VK_FROM_HANDLE(dzn_buffer, buffer, pBindInfos[i].buffer);
2692bf215546Sopenharmony_ci
2693bf215546Sopenharmony_ci      if (FAILED(ID3D12Device1_CreatePlacedResource(device->dev, mem->heap,
2694bf215546Sopenharmony_ci                                                   pBindInfos[i].memoryOffset,
2695bf215546Sopenharmony_ci                                                   &buffer->desc,
2696bf215546Sopenharmony_ci                                                   mem->initial_state,
2697bf215546Sopenharmony_ci                                                   NULL,
2698bf215546Sopenharmony_ci                                                   &IID_ID3D12Resource,
2699bf215546Sopenharmony_ci                                                   (void **)&buffer->res)))
2700bf215546Sopenharmony_ci         return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2701bf215546Sopenharmony_ci   }
2702bf215546Sopenharmony_ci
2703bf215546Sopenharmony_ci   return VK_SUCCESS;
2704bf215546Sopenharmony_ci}
2705bf215546Sopenharmony_ci
2706bf215546Sopenharmony_cistatic void
2707bf215546Sopenharmony_cidzn_event_destroy(struct dzn_event *event,
2708bf215546Sopenharmony_ci                  const VkAllocationCallbacks *pAllocator)
2709bf215546Sopenharmony_ci{
2710bf215546Sopenharmony_ci   if (!event)
2711bf215546Sopenharmony_ci      return;
2712bf215546Sopenharmony_ci
2713bf215546Sopenharmony_ci   struct dzn_device *device =
2714bf215546Sopenharmony_ci      container_of(event->base.device, struct dzn_device, vk);
2715bf215546Sopenharmony_ci
2716bf215546Sopenharmony_ci   if (event->fence)
2717bf215546Sopenharmony_ci      ID3D12Fence_Release(event->fence);
2718bf215546Sopenharmony_ci
2719bf215546Sopenharmony_ci   vk_object_base_finish(&event->base);
2720bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, event);
2721bf215546Sopenharmony_ci}
2722bf215546Sopenharmony_ci
2723bf215546Sopenharmony_cistatic VkResult
2724bf215546Sopenharmony_cidzn_event_create(struct dzn_device *device,
2725bf215546Sopenharmony_ci                 const VkEventCreateInfo *pCreateInfo,
2726bf215546Sopenharmony_ci                 const VkAllocationCallbacks *pAllocator,
2727bf215546Sopenharmony_ci                 VkEvent *out)
2728bf215546Sopenharmony_ci{
2729bf215546Sopenharmony_ci   struct dzn_event *event =
2730bf215546Sopenharmony_ci      vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*event), 8,
2731bf215546Sopenharmony_ci                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2732bf215546Sopenharmony_ci   if (!event)
2733bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2734bf215546Sopenharmony_ci
2735bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &event->base, VK_OBJECT_TYPE_EVENT);
2736bf215546Sopenharmony_ci
2737bf215546Sopenharmony_ci   if (FAILED(ID3D12Device1_CreateFence(device->dev, 0, D3D12_FENCE_FLAG_NONE,
2738bf215546Sopenharmony_ci                                        &IID_ID3D12Fence,
2739bf215546Sopenharmony_ci                                        (void **)&event->fence))) {
2740bf215546Sopenharmony_ci      dzn_event_destroy(event, pAllocator);
2741bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2742bf215546Sopenharmony_ci   }
2743bf215546Sopenharmony_ci
2744bf215546Sopenharmony_ci   *out = dzn_event_to_handle(event);
2745bf215546Sopenharmony_ci   return VK_SUCCESS;
2746bf215546Sopenharmony_ci}
2747bf215546Sopenharmony_ci
2748bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2749bf215546Sopenharmony_cidzn_CreateEvent(VkDevice device,
2750bf215546Sopenharmony_ci                const VkEventCreateInfo *pCreateInfo,
2751bf215546Sopenharmony_ci                const VkAllocationCallbacks *pAllocator,
2752bf215546Sopenharmony_ci                VkEvent *pEvent)
2753bf215546Sopenharmony_ci{
2754bf215546Sopenharmony_ci   return dzn_event_create(dzn_device_from_handle(device),
2755bf215546Sopenharmony_ci                           pCreateInfo, pAllocator, pEvent);
2756bf215546Sopenharmony_ci}
2757bf215546Sopenharmony_ci
2758bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2759bf215546Sopenharmony_cidzn_DestroyEvent(VkDevice device,
2760bf215546Sopenharmony_ci                 VkEvent event,
2761bf215546Sopenharmony_ci                 const VkAllocationCallbacks *pAllocator)
2762bf215546Sopenharmony_ci{
2763bf215546Sopenharmony_ci   dzn_event_destroy(dzn_event_from_handle(event), pAllocator);
2764bf215546Sopenharmony_ci}
2765bf215546Sopenharmony_ci
2766bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2767bf215546Sopenharmony_cidzn_ResetEvent(VkDevice dev,
2768bf215546Sopenharmony_ci               VkEvent evt)
2769bf215546Sopenharmony_ci{
2770bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_device, device, dev);
2771bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_event, event, evt);
2772bf215546Sopenharmony_ci
2773bf215546Sopenharmony_ci   if (FAILED(ID3D12Fence_Signal(event->fence, 0)))
2774bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2775bf215546Sopenharmony_ci
2776bf215546Sopenharmony_ci   return VK_SUCCESS;
2777bf215546Sopenharmony_ci}
2778bf215546Sopenharmony_ci
2779bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2780bf215546Sopenharmony_cidzn_SetEvent(VkDevice dev,
2781bf215546Sopenharmony_ci             VkEvent evt)
2782bf215546Sopenharmony_ci{
2783bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_device, device, dev);
2784bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_event, event, evt);
2785bf215546Sopenharmony_ci
2786bf215546Sopenharmony_ci   if (FAILED(ID3D12Fence_Signal(event->fence, 1)))
2787bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2788bf215546Sopenharmony_ci
2789bf215546Sopenharmony_ci   return VK_SUCCESS;
2790bf215546Sopenharmony_ci}
2791bf215546Sopenharmony_ci
2792bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2793bf215546Sopenharmony_cidzn_GetEventStatus(VkDevice device,
2794bf215546Sopenharmony_ci                   VkEvent evt)
2795bf215546Sopenharmony_ci{
2796bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_event, event, evt);
2797bf215546Sopenharmony_ci
2798bf215546Sopenharmony_ci   return ID3D12Fence_GetCompletedValue(event->fence) == 0 ?
2799bf215546Sopenharmony_ci          VK_EVENT_RESET : VK_EVENT_SET;
2800bf215546Sopenharmony_ci}
2801bf215546Sopenharmony_ci
2802bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2803bf215546Sopenharmony_cidzn_GetDeviceMemoryCommitment(VkDevice device,
2804bf215546Sopenharmony_ci                              VkDeviceMemory memory,
2805bf215546Sopenharmony_ci                              VkDeviceSize *pCommittedMemoryInBytes)
2806bf215546Sopenharmony_ci{
2807bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_device_memory, mem, memory);
2808bf215546Sopenharmony_ci
2809bf215546Sopenharmony_ci   // TODO: find if there's a way to query/track actual heap residency
2810bf215546Sopenharmony_ci   *pCommittedMemoryInBytes = mem->size;
2811bf215546Sopenharmony_ci}
2812bf215546Sopenharmony_ci
2813bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2814bf215546Sopenharmony_cidzn_QueueBindSparse(VkQueue queue,
2815bf215546Sopenharmony_ci                    uint32_t bindInfoCount,
2816bf215546Sopenharmony_ci                    const VkBindSparseInfo *pBindInfo,
2817bf215546Sopenharmony_ci                    VkFence fence)
2818bf215546Sopenharmony_ci{
2819bf215546Sopenharmony_ci   // FIXME: add proper implem
2820bf215546Sopenharmony_ci   dzn_stub();
2821bf215546Sopenharmony_ci   return VK_SUCCESS;
2822bf215546Sopenharmony_ci}
2823bf215546Sopenharmony_ci
2824bf215546Sopenharmony_cistatic D3D12_TEXTURE_ADDRESS_MODE
2825bf215546Sopenharmony_cidzn_sampler_translate_addr_mode(VkSamplerAddressMode in)
2826bf215546Sopenharmony_ci{
2827bf215546Sopenharmony_ci   switch (in) {
2828bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
2829bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
2830bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
2831bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return D3D12_TEXTURE_ADDRESS_MODE_BORDER;
2832bf215546Sopenharmony_ci   default: unreachable("Invalid address mode");
2833bf215546Sopenharmony_ci   }
2834bf215546Sopenharmony_ci}
2835bf215546Sopenharmony_ci
2836bf215546Sopenharmony_cistatic void
2837bf215546Sopenharmony_cidzn_sampler_destroy(struct dzn_sampler *sampler,
2838bf215546Sopenharmony_ci                    const VkAllocationCallbacks *pAllocator)
2839bf215546Sopenharmony_ci{
2840bf215546Sopenharmony_ci   if (!sampler)
2841bf215546Sopenharmony_ci      return;
2842bf215546Sopenharmony_ci
2843bf215546Sopenharmony_ci   struct dzn_device *device =
2844bf215546Sopenharmony_ci      container_of(sampler->base.device, struct dzn_device, vk);
2845bf215546Sopenharmony_ci
2846bf215546Sopenharmony_ci   vk_object_base_finish(&sampler->base);
2847bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, pAllocator, sampler);
2848bf215546Sopenharmony_ci}
2849bf215546Sopenharmony_ci
2850bf215546Sopenharmony_cistatic VkResult
2851bf215546Sopenharmony_cidzn_sampler_create(struct dzn_device *device,
2852bf215546Sopenharmony_ci                   const VkSamplerCreateInfo *pCreateInfo,
2853bf215546Sopenharmony_ci                   const VkAllocationCallbacks *pAllocator,
2854bf215546Sopenharmony_ci                   VkSampler *out)
2855bf215546Sopenharmony_ci{
2856bf215546Sopenharmony_ci   struct dzn_sampler *sampler =
2857bf215546Sopenharmony_ci      vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*sampler), 8,
2858bf215546Sopenharmony_ci                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2859bf215546Sopenharmony_ci   if (!sampler)
2860bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2861bf215546Sopenharmony_ci
2862bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &sampler->base, VK_OBJECT_TYPE_SAMPLER);
2863bf215546Sopenharmony_ci
2864bf215546Sopenharmony_ci   const VkSamplerCustomBorderColorCreateInfoEXT *pBorderColor = (const VkSamplerCustomBorderColorCreateInfoEXT *)
2865bf215546Sopenharmony_ci      vk_find_struct_const(pCreateInfo->pNext, SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT);
2866bf215546Sopenharmony_ci
2867bf215546Sopenharmony_ci   /* TODO: have a sampler pool to allocate shader-invisible descs which we
2868bf215546Sopenharmony_ci    * can copy to the desc_set when UpdateDescriptorSets() is called.
2869bf215546Sopenharmony_ci    */
2870bf215546Sopenharmony_ci   sampler->desc.Filter = dzn_translate_sampler_filter(pCreateInfo);
2871bf215546Sopenharmony_ci   sampler->desc.AddressU = dzn_sampler_translate_addr_mode(pCreateInfo->addressModeU);
2872bf215546Sopenharmony_ci   sampler->desc.AddressV = dzn_sampler_translate_addr_mode(pCreateInfo->addressModeV);
2873bf215546Sopenharmony_ci   sampler->desc.AddressW = dzn_sampler_translate_addr_mode(pCreateInfo->addressModeW);
2874bf215546Sopenharmony_ci   sampler->desc.MipLODBias = pCreateInfo->mipLodBias;
2875bf215546Sopenharmony_ci   sampler->desc.MaxAnisotropy = pCreateInfo->maxAnisotropy;
2876bf215546Sopenharmony_ci   sampler->desc.MinLOD = pCreateInfo->minLod;
2877bf215546Sopenharmony_ci   sampler->desc.MaxLOD = pCreateInfo->maxLod;
2878bf215546Sopenharmony_ci
2879bf215546Sopenharmony_ci   if (pCreateInfo->compareEnable)
2880bf215546Sopenharmony_ci      sampler->desc.ComparisonFunc = dzn_translate_compare_op(pCreateInfo->compareOp);
2881bf215546Sopenharmony_ci
2882bf215546Sopenharmony_ci   bool reads_border_color =
2883bf215546Sopenharmony_ci      pCreateInfo->addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
2884bf215546Sopenharmony_ci      pCreateInfo->addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
2885bf215546Sopenharmony_ci      pCreateInfo->addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
2886bf215546Sopenharmony_ci
2887bf215546Sopenharmony_ci   if (reads_border_color) {
2888bf215546Sopenharmony_ci      switch (pCreateInfo->borderColor) {
2889bf215546Sopenharmony_ci      case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
2890bf215546Sopenharmony_ci      case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
2891bf215546Sopenharmony_ci         sampler->desc.BorderColor[0] = 0.0f;
2892bf215546Sopenharmony_ci         sampler->desc.BorderColor[1] = 0.0f;
2893bf215546Sopenharmony_ci         sampler->desc.BorderColor[2] = 0.0f;
2894bf215546Sopenharmony_ci         sampler->desc.BorderColor[3] =
2895bf215546Sopenharmony_ci            pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK ? 0.0f : 1.0f;
2896bf215546Sopenharmony_ci         sampler->static_border_color =
2897bf215546Sopenharmony_ci            pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK ?
2898bf215546Sopenharmony_ci            D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK :
2899bf215546Sopenharmony_ci            D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
2900bf215546Sopenharmony_ci         break;
2901bf215546Sopenharmony_ci      case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
2902bf215546Sopenharmony_ci         sampler->desc.BorderColor[0] = sampler->desc.BorderColor[1] = 1.0f;
2903bf215546Sopenharmony_ci         sampler->desc.BorderColor[2] = sampler->desc.BorderColor[3] = 1.0f;
2904bf215546Sopenharmony_ci         sampler->static_border_color = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;
2905bf215546Sopenharmony_ci         break;
2906bf215546Sopenharmony_ci      case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT:
2907bf215546Sopenharmony_ci         sampler->static_border_color = (D3D12_STATIC_BORDER_COLOR)-1;
2908bf215546Sopenharmony_ci         for (unsigned i = 0; i < ARRAY_SIZE(sampler->desc.BorderColor); i++)
2909bf215546Sopenharmony_ci            sampler->desc.BorderColor[i] = pBorderColor->customBorderColor.float32[i];
2910bf215546Sopenharmony_ci         break;
2911bf215546Sopenharmony_ci      case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
2912bf215546Sopenharmony_ci      case VK_BORDER_COLOR_INT_OPAQUE_BLACK:
2913bf215546Sopenharmony_ci      case VK_BORDER_COLOR_INT_OPAQUE_WHITE:
2914bf215546Sopenharmony_ci      case VK_BORDER_COLOR_INT_CUSTOM_EXT:
2915bf215546Sopenharmony_ci         /* FIXME: sampling from integer textures is not supported yet. */
2916bf215546Sopenharmony_ci         sampler->static_border_color = (D3D12_STATIC_BORDER_COLOR)-1;
2917bf215546Sopenharmony_ci         break;
2918bf215546Sopenharmony_ci      default:
2919bf215546Sopenharmony_ci         unreachable("Unsupported border color");
2920bf215546Sopenharmony_ci      }
2921bf215546Sopenharmony_ci   }
2922bf215546Sopenharmony_ci
2923bf215546Sopenharmony_ci   *out = dzn_sampler_to_handle(sampler);
2924bf215546Sopenharmony_ci   return VK_SUCCESS;
2925bf215546Sopenharmony_ci}
2926bf215546Sopenharmony_ci
2927bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2928bf215546Sopenharmony_cidzn_CreateSampler(VkDevice device,
2929bf215546Sopenharmony_ci                  const VkSamplerCreateInfo *pCreateInfo,
2930bf215546Sopenharmony_ci                  const VkAllocationCallbacks *pAllocator,
2931bf215546Sopenharmony_ci                  VkSampler *pSampler)
2932bf215546Sopenharmony_ci{
2933bf215546Sopenharmony_ci   return dzn_sampler_create(dzn_device_from_handle(device),
2934bf215546Sopenharmony_ci                             pCreateInfo, pAllocator, pSampler);
2935bf215546Sopenharmony_ci}
2936bf215546Sopenharmony_ci
2937bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2938bf215546Sopenharmony_cidzn_DestroySampler(VkDevice device,
2939bf215546Sopenharmony_ci                   VkSampler sampler,
2940bf215546Sopenharmony_ci                   const VkAllocationCallbacks *pAllocator)
2941bf215546Sopenharmony_ci{
2942bf215546Sopenharmony_ci   dzn_sampler_destroy(dzn_sampler_from_handle(sampler), pAllocator);
2943bf215546Sopenharmony_ci}
2944bf215546Sopenharmony_ci
2945bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2946bf215546Sopenharmony_cidzn_GetDeviceGroupPeerMemoryFeatures(VkDevice device,
2947bf215546Sopenharmony_ci                                     uint32_t heapIndex,
2948bf215546Sopenharmony_ci                                     uint32_t localDeviceIndex,
2949bf215546Sopenharmony_ci                                     uint32_t remoteDeviceIndex,
2950bf215546Sopenharmony_ci                                     VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
2951bf215546Sopenharmony_ci{
2952bf215546Sopenharmony_ci   *pPeerMemoryFeatures = 0;
2953bf215546Sopenharmony_ci}
2954bf215546Sopenharmony_ci
2955bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2956bf215546Sopenharmony_cidzn_GetImageSparseMemoryRequirements2(VkDevice device,
2957bf215546Sopenharmony_ci                                      const VkImageSparseMemoryRequirementsInfo2* pInfo,
2958bf215546Sopenharmony_ci                                      uint32_t *pSparseMemoryRequirementCount,
2959bf215546Sopenharmony_ci                                      VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
2960bf215546Sopenharmony_ci{
2961bf215546Sopenharmony_ci   *pSparseMemoryRequirementCount = 0;
2962bf215546Sopenharmony_ci}
2963bf215546Sopenharmony_ci
2964bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
2965bf215546Sopenharmony_cidzn_CreateSamplerYcbcrConversion(VkDevice device,
2966bf215546Sopenharmony_ci                                 const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
2967bf215546Sopenharmony_ci                                 const VkAllocationCallbacks *pAllocator,
2968bf215546Sopenharmony_ci                                 VkSamplerYcbcrConversion *pYcbcrConversion)
2969bf215546Sopenharmony_ci{
2970bf215546Sopenharmony_ci   unreachable("Ycbcr sampler conversion is not supported");
2971bf215546Sopenharmony_ci   return VK_SUCCESS;
2972bf215546Sopenharmony_ci}
2973bf215546Sopenharmony_ci
2974bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
2975bf215546Sopenharmony_cidzn_DestroySamplerYcbcrConversion(VkDevice device,
2976bf215546Sopenharmony_ci                                  VkSamplerYcbcrConversion YcbcrConversion,
2977bf215546Sopenharmony_ci                                  const VkAllocationCallbacks *pAllocator)
2978bf215546Sopenharmony_ci{
2979bf215546Sopenharmony_ci   unreachable("Ycbcr sampler conversion is not supported");
2980bf215546Sopenharmony_ci}
2981