xref: /aosp_15_r20/external/mesa3d/src/microsoft/vulkan/dzn_image.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © Microsoft Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "dzn_private.h"
25 
26 #include "vk_alloc.h"
27 #include "vk_debug_report.h"
28 #include "vk_format.h"
29 #include "vk_util.h"
30 
31 void
dzn_image_align_extent(const struct dzn_image * image,VkExtent3D * extent)32 dzn_image_align_extent(const struct dzn_image *image,
33                        VkExtent3D *extent)
34 {
35    enum pipe_format pfmt = vk_format_to_pipe_format(image->vk.format);
36    uint32_t blkw = util_format_get_blockwidth(pfmt);
37    uint32_t blkh = util_format_get_blockheight(pfmt);
38    uint32_t blkd = util_format_get_blockdepth(pfmt);
39 
40    assert(util_is_power_of_two_nonzero(blkw) &&
41           util_is_power_of_two_nonzero(blkh) &&
42           util_is_power_of_two_nonzero(blkh));
43 
44    extent->width = ALIGN_POT(extent->width, blkw);
45    extent->height = ALIGN_POT(extent->height, blkh);
46    extent->depth = ALIGN_POT(extent->depth, blkd);
47 }
48 
49 static void
dzn_image_destroy(struct dzn_image * image,const VkAllocationCallbacks * pAllocator)50 dzn_image_destroy(struct dzn_image *image,
51                   const VkAllocationCallbacks *pAllocator)
52 {
53    if (!image)
54       return;
55 
56    struct dzn_device *device = container_of(image->vk.base.device, struct dzn_device, vk);
57 
58    if (image->res)
59       ID3D12Resource_Release(image->res);
60 
61    vk_image_finish(&image->vk);
62    vk_free2(&device->vk.alloc, pAllocator, image);
63 }
64 
65 static VkResult
dzn_image_create(struct dzn_device * device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * out)66 dzn_image_create(struct dzn_device *device,
67                  const VkImageCreateInfo *pCreateInfo,
68                  const VkAllocationCallbacks *pAllocator,
69                  VkImage *out)
70 {
71    struct dzn_physical_device *pdev =
72       container_of(device->vk.physical, struct dzn_physical_device, vk);
73    VkFormat *compat_formats = NULL;
74    uint32_t compat_format_count = 0;
75 
76    if (pdev->options12.RelaxedFormatCastingSupported) {
77       VkResult ret =
78          vk_image_create_get_format_list(&device->vk, pCreateInfo, pAllocator,
79                                          &compat_formats, &compat_format_count);
80       if (ret != VK_SUCCESS)
81          return ret;
82    }
83 
84    VK_MULTIALLOC(ma);
85    VK_MULTIALLOC_DECL(&ma, struct dzn_image, image, 1);
86    VK_MULTIALLOC_DECL(&ma, DXGI_FORMAT, castable_formats, compat_format_count);
87 
88    if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, pAllocator, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)) {
89       vk_free2(&device->vk.alloc, pAllocator, compat_formats);
90       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
91    }
92 
93 #if 0
94     VkExternalMemoryHandleTypeFlags supported =
95         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT |
96         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT |
97         VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT |
98         VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT |
99         VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT |
100         VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT;
101 
102    if (create_info && (create_info->handleTypes & supported))
103       return dzn_image_from_external(device, pCreateInfo, create_info,
104                                      pAllocator, pImage);
105 #endif
106 
107 #if 0
108    const VkImageSwapchainCreateInfoKHR *swapchain_info = (const VkImageSwapchainCreateInfoKHR *)
109       vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
110    if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE)
111       return dzn_image_from_swapchain(device, pCreateInfo, swapchain_info,
112                                       pAllocator, pImage);
113 #endif
114 
115    vk_image_init(&device->vk, &image->vk, pCreateInfo);
116    enum pipe_format pfmt = vk_format_to_pipe_format(image->vk.format);
117 
118    VkImageUsageFlags usage = image->vk.usage | image->vk.stencil_usage;
119 
120    image->castable_formats = castable_formats;
121    image->castable_format_count = 0;
122    for (uint32_t i = 0; i < compat_format_count; i++) {
123       castable_formats[image->castable_format_count] =
124          dzn_image_get_dxgi_format(pdev, compat_formats[i], usage, 0);
125 
126       if (castable_formats[image->castable_format_count] != DXGI_FORMAT_UNKNOWN)
127          image->castable_format_count++;
128    }
129 
130    vk_free2(&device->vk.alloc, pAllocator, compat_formats);
131 
132    image->valid_access = D3D12_BARRIER_ACCESS_COPY_SOURCE | D3D12_BARRIER_ACCESS_COPY_DEST;
133 
134    if (image->vk.tiling == VK_IMAGE_TILING_LINEAR) {
135       /* Treat linear images as buffers: they should only be used as copy
136        * src/dest, and CopyTextureResource() can manipulate buffers.
137        * We only support linear tiling on things strictly required by the spec:
138        * "Images created with tiling equal to VK_IMAGE_TILING_LINEAR have
139        * further restrictions on their limits and capabilities compared to
140        * images created with tiling equal to VK_IMAGE_TILING_OPTIMAL. Creation
141        * of images with tiling VK_IMAGE_TILING_LINEAR may not be supported
142        * unless other parameters meet all of the constraints:
143        * - imageType is VK_IMAGE_TYPE_2D
144        * - format is not a depth/stencil format
145        * - mipLevels is 1
146        * - arrayLayers is 1
147        * - samples is VK_SAMPLE_COUNT_1_BIT
148        * - usage only includes VK_IMAGE_USAGE_TRANSFER_SRC_BIT and/or VK_IMAGE_USAGE_TRANSFER_DST_BIT
149        * "
150        */
151       assert(!vk_format_is_depth_or_stencil(pCreateInfo->format));
152       assert(pCreateInfo->mipLevels == 1);
153       assert(pCreateInfo->arrayLayers == 1);
154       assert(pCreateInfo->samples == 1);
155       assert(pCreateInfo->imageType != VK_IMAGE_TYPE_3D);
156       assert(!(usage & ~(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)));
157       D3D12_RESOURCE_DESC tmp_desc = {
158          .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
159          .Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
160          .Width = ALIGN_POT(image->vk.extent.width, util_format_get_blockwidth(pfmt)),
161          .Height = (UINT)ALIGN_POT(image->vk.extent.height, util_format_get_blockheight(pfmt)),
162          .DepthOrArraySize = 1,
163          .MipLevels = 1,
164          .Format =
165             dzn_image_get_dxgi_format(pdev, pCreateInfo->format, usage, 0),
166          .SampleDesc = { .Count = 1, .Quality = 0 },
167          .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
168          .Flags = D3D12_RESOURCE_FLAG_NONE
169       };
170       D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
171       uint64_t size = 0;
172       ID3D12Device1_GetCopyableFootprints(device->dev, &tmp_desc, 0, 1, 0, &footprint, NULL, NULL, &size);
173 
174       image->linear.row_stride = footprint.Footprint.RowPitch;
175       image->linear.size = size;
176       size *= pCreateInfo->arrayLayers;
177       image->desc.Format = DXGI_FORMAT_UNKNOWN;
178       image->desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
179       image->desc.Width = size;
180       image->desc.Height = 1;
181       image->desc.DepthOrArraySize = 1;
182       image->desc.MipLevels = 1;
183       image->desc.SampleDesc.Count = 1;
184       image->desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
185       image->castable_formats = NULL;
186       image->castable_format_count = 0;
187    } else {
188       image->desc.Format =
189          dzn_image_get_dxgi_format(pdev, pCreateInfo->format,
190                                    usage & ~VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
191                                    0),
192       image->desc.Dimension = (D3D12_RESOURCE_DIMENSION)(D3D12_RESOURCE_DIMENSION_TEXTURE1D + pCreateInfo->imageType);
193       image->desc.Width = image->vk.extent.width;
194       image->desc.Height = image->vk.extent.height;
195       image->desc.DepthOrArraySize = pCreateInfo->imageType == VK_IMAGE_TYPE_3D ?
196                                      image->vk.extent.depth :
197                                      pCreateInfo->arrayLayers;
198       image->desc.MipLevels = pCreateInfo->mipLevels;
199       image->desc.SampleDesc.Count = pCreateInfo->samples;
200       image->desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
201       image->valid_access |= D3D12_BARRIER_ACCESS_RESOLVE_DEST |
202          D3D12_BARRIER_ACCESS_SHADER_RESOURCE |
203          (pCreateInfo->samples > 1 ? D3D12_BARRIER_ACCESS_RESOLVE_SOURCE : 0);
204    }
205 
206    if ((image->vk.create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
207        !pdev->options12.RelaxedFormatCastingSupported)
208       image->desc.Format = dzn_get_typeless_dxgi_format(image->desc.Format);
209 
210    if (image->desc.SampleDesc.Count > 1)
211       image->desc.Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT;
212    else
213       image->desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
214 
215    image->desc.SampleDesc.Quality = 0;
216 
217    image->desc.Flags = D3D12_RESOURCE_FLAG_NONE;
218 
219    if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
220       image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
221       image->valid_access |= D3D12_BARRIER_ACCESS_RENDER_TARGET;
222    }
223 
224    if (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
225       image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
226       image->valid_access |= D3D12_BARRIER_ACCESS_DEPTH_STENCIL_READ |
227                              D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE;
228 
229       if (!(usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
230                                VK_IMAGE_USAGE_STORAGE_BIT |
231                                VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
232                                VK_IMAGE_USAGE_TRANSFER_SRC_BIT))) {
233          image->desc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
234          image->valid_access &= ~D3D12_BARRIER_ACCESS_SHADER_RESOURCE;
235       }
236    } else if (usage & VK_IMAGE_USAGE_STORAGE_BIT) {
237       image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
238       image->valid_access |= D3D12_BARRIER_ACCESS_UNORDERED_ACCESS;
239    }
240 
241    /* Images with TRANSFER_DST can be cleared or passed as a blit/resolve
242     * destination. Both operations require the RT or DS cap flags.
243     */
244    if ((usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) &&
245        image->vk.tiling == VK_IMAGE_TILING_OPTIMAL) {
246 
247       D3D12_FEATURE_DATA_FORMAT_SUPPORT dfmt_info =
248          dzn_physical_device_get_format_support(pdev, pCreateInfo->format, pCreateInfo->flags);
249       if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET) {
250          image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
251          image->valid_access |= D3D12_BARRIER_ACCESS_RENDER_TARGET;
252       } else if ((dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL) &&
253                  (image->desc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET |
254                                        D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)) == D3D12_RESOURCE_FLAG_NONE) {
255          image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
256          image->valid_access |= D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE;
257       } else if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW) {
258          image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
259          image->valid_access |= D3D12_BARRIER_ACCESS_UNORDERED_ACCESS;
260       }
261    }
262 
263    if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT &&
264        !(image->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) &&
265        image->desc.SampleDesc.Count == 1)
266       image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS;
267 
268    *out = dzn_image_to_handle(image);
269    return VK_SUCCESS;
270 }
271 
272 DXGI_FORMAT
dzn_image_get_dxgi_format(const struct dzn_physical_device * pdev,VkFormat format,VkImageUsageFlags usage,VkImageAspectFlags aspects)273 dzn_image_get_dxgi_format(const struct dzn_physical_device *pdev,
274                           VkFormat format,
275                           VkImageUsageFlags usage,
276                           VkImageAspectFlags aspects)
277 {
278    enum pipe_format pfmt = vk_format_to_pipe_format(format);
279 
280    if (pdev && !pdev->support_a4b4g4r4) {
281       if (pfmt == PIPE_FORMAT_A4R4G4B4_UNORM)
282          return DXGI_FORMAT_B4G4R4A4_UNORM;
283       if (pfmt == PIPE_FORMAT_A4B4G4R4_UNORM)
284          return DXGI_FORMAT_UNKNOWN;
285    }
286 
287    if (!vk_format_is_depth_or_stencil(format))
288       return dzn_pipe_to_dxgi_format(pfmt);
289 
290    switch (pfmt) {
291    case PIPE_FORMAT_Z16_UNORM:
292       return usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ?
293              DXGI_FORMAT_D16_UNORM : DXGI_FORMAT_R16_UNORM;
294 
295    case PIPE_FORMAT_Z32_FLOAT:
296       return usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ?
297              DXGI_FORMAT_D32_FLOAT : DXGI_FORMAT_R32_FLOAT;
298 
299    case PIPE_FORMAT_Z24X8_UNORM:
300       if (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
301          return DXGI_FORMAT_D24_UNORM_S8_UINT;
302       if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
303          return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
304       return DXGI_FORMAT_R24G8_TYPELESS;
305 
306    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
307       if (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
308          return DXGI_FORMAT_D24_UNORM_S8_UINT;
309 
310       if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
311          return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
312       else if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
313          return DXGI_FORMAT_X24_TYPELESS_G8_UINT;
314       else
315          return DXGI_FORMAT_R24G8_TYPELESS;
316 
317    case PIPE_FORMAT_X24S8_UINT:
318       if (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
319          return DXGI_FORMAT_D24_UNORM_S8_UINT;
320       if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
321          return DXGI_FORMAT_X24_TYPELESS_G8_UINT;
322       return DXGI_FORMAT_R24G8_TYPELESS;
323 
324    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
325       if (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
326          return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
327 
328       if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
329          return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
330       else if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
331          return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
332       else
333          return DXGI_FORMAT_R32G8X24_TYPELESS;
334 
335    default:
336       return dzn_pipe_to_dxgi_format(pfmt);
337    }
338 }
339 
340 DXGI_FORMAT
dzn_image_get_placed_footprint_format(const struct dzn_physical_device * pdev,VkFormat format,VkImageAspectFlags aspect)341 dzn_image_get_placed_footprint_format(const struct dzn_physical_device *pdev,
342                                       VkFormat format,
343                                       VkImageAspectFlags aspect)
344 {
345    DXGI_FORMAT out =
346       dzn_image_get_dxgi_format(pdev, format,
347                                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
348                                 VK_IMAGE_USAGE_TRANSFER_DST_BIT,
349                                 aspect);
350 
351    switch (out) {
352    case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
353    case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
354       return DXGI_FORMAT_R32_TYPELESS;
355    case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
356    case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
357       return DXGI_FORMAT_R8_TYPELESS;
358    default:
359       return out;
360    }
361 }
362 
363 VkFormat
dzn_image_get_plane_format(VkFormat format,VkImageAspectFlags aspectMask)364 dzn_image_get_plane_format(VkFormat format,
365                            VkImageAspectFlags aspectMask)
366 {
367    if (aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
368       return vk_format_stencil_only(format);
369    else if (aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT)
370       return vk_format_depth_only(format);
371    else
372       return format;
373 }
374 
375 uint32_t
dzn_image_layers_get_subresource_index(const struct dzn_image * image,const VkImageSubresourceLayers * subres,VkImageAspectFlagBits aspect,uint32_t layer)376 dzn_image_layers_get_subresource_index(const struct dzn_image *image,
377                                        const VkImageSubresourceLayers *subres,
378                                        VkImageAspectFlagBits aspect,
379                                        uint32_t layer)
380 {
381    int planeSlice =
382       aspect == VK_IMAGE_ASPECT_STENCIL_BIT ? 1 : 0;
383 
384    return subres->mipLevel +
385           ((subres->baseArrayLayer + layer) * image->desc.MipLevels) +
386           (planeSlice * image->desc.MipLevels * image->desc.DepthOrArraySize);
387 }
388 
389 uint32_t
dzn_image_range_get_subresource_index(const struct dzn_image * image,const VkImageSubresourceRange * subres,VkImageAspectFlagBits aspect,uint32_t level,uint32_t layer)390 dzn_image_range_get_subresource_index(const struct dzn_image *image,
391                                       const VkImageSubresourceRange *subres,
392                                       VkImageAspectFlagBits aspect,
393                                       uint32_t level, uint32_t layer)
394 {
395    int planeSlice =
396       aspect == VK_IMAGE_ASPECT_STENCIL_BIT ? 1 : 0;
397 
398    return subres->baseMipLevel + level +
399           ((subres->baseArrayLayer + layer) * image->desc.MipLevels) +
400           (planeSlice * image->desc.MipLevels * image->desc.DepthOrArraySize);
401 }
402 
403 static uint32_t
dzn_image_get_subresource_index(const struct dzn_image * image,const VkImageSubresource * subres,VkImageAspectFlagBits aspect)404 dzn_image_get_subresource_index(const struct dzn_image *image,
405                                 const VkImageSubresource *subres,
406                                 VkImageAspectFlagBits aspect)
407 {
408    int planeSlice =
409       aspect == VK_IMAGE_ASPECT_STENCIL_BIT ? 1 : 0;
410 
411    return subres->mipLevel +
412           (subres->arrayLayer * image->desc.MipLevels) +
413           (planeSlice * image->desc.MipLevels * image->desc.DepthOrArraySize);
414 }
415 
416 D3D12_TEXTURE_COPY_LOCATION
dzn_image_get_copy_loc(const struct dzn_image * image,const VkImageSubresourceLayers * subres,VkImageAspectFlagBits aspect,uint32_t layer)417 dzn_image_get_copy_loc(const struct dzn_image *image,
418                        const VkImageSubresourceLayers *subres,
419                        VkImageAspectFlagBits aspect,
420                        uint32_t layer)
421 {
422    struct dzn_physical_device *pdev =
423       container_of(image->vk.base.device->physical, struct dzn_physical_device, vk);
424    D3D12_TEXTURE_COPY_LOCATION loc = {
425       .pResource = image->res,
426    };
427 
428    assert((subres->aspectMask & aspect) != 0);
429 
430    if (image->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) {
431       assert((subres->baseArrayLayer + layer) == 0);
432       assert(subres->mipLevel == 0);
433       enum pipe_format pfmt = vk_format_to_pipe_format(image->vk.format);
434       uint32_t blkw = util_format_get_blockwidth(pfmt);
435       uint32_t blkh = util_format_get_blockheight(pfmt);
436       uint32_t blkd = util_format_get_blockdepth(pfmt);
437       loc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
438       loc.PlacedFootprint.Offset = 0;
439       loc.PlacedFootprint.Footprint.Format =
440          dzn_image_get_placed_footprint_format(pdev, image->vk.format, aspect);
441       loc.PlacedFootprint.Footprint.Width = ALIGN_POT(image->vk.extent.width, blkw);
442       loc.PlacedFootprint.Footprint.Height = ALIGN_POT(image->vk.extent.height, blkh);
443       loc.PlacedFootprint.Footprint.Depth = ALIGN_POT(image->vk.extent.depth, blkd);
444       loc.PlacedFootprint.Footprint.RowPitch = image->linear.row_stride;
445    } else {
446       loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
447       loc.SubresourceIndex = dzn_image_layers_get_subresource_index(image, subres, aspect, layer);
448    }
449 
450    return loc;
451 }
452 
453 D3D12_DEPTH_STENCIL_VIEW_DESC
dzn_image_get_dsv_desc(const struct dzn_image * image,const VkImageSubresourceRange * range,uint32_t level)454 dzn_image_get_dsv_desc(const struct dzn_image *image,
455                        const VkImageSubresourceRange *range,
456                        uint32_t level)
457 {
458    struct dzn_physical_device *pdev =
459       container_of(image->vk.base.device->physical, struct dzn_physical_device, vk);
460    uint32_t layer_count = dzn_get_layer_count(image, range);
461    D3D12_DEPTH_STENCIL_VIEW_DESC dsv_desc = {
462       .Format =
463          dzn_image_get_dxgi_format(pdev, image->vk.format,
464                                    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
465                                    range->aspectMask),
466    };
467 
468    switch (image->vk.image_type) {
469    case VK_IMAGE_TYPE_1D:
470       dsv_desc.ViewDimension =
471          image->vk.array_layers > 1 ?
472          D3D12_DSV_DIMENSION_TEXTURE1DARRAY :
473          D3D12_DSV_DIMENSION_TEXTURE1D;
474       break;
475    case VK_IMAGE_TYPE_2D:
476       if (image->vk.array_layers > 1) {
477          dsv_desc.ViewDimension =
478             image->vk.samples > 1 ?
479             D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY :
480             D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
481       } else {
482          dsv_desc.ViewDimension =
483             image->vk.samples > 1 ?
484             D3D12_DSV_DIMENSION_TEXTURE2DMS :
485             D3D12_DSV_DIMENSION_TEXTURE2D;
486       }
487       break;
488    default:
489       unreachable("Invalid image type");
490    }
491 
492    switch (dsv_desc.ViewDimension) {
493    case D3D12_DSV_DIMENSION_TEXTURE1D:
494       dsv_desc.Texture1D.MipSlice = range->baseMipLevel + level;
495       break;
496    case D3D12_DSV_DIMENSION_TEXTURE1DARRAY:
497       dsv_desc.Texture1DArray.MipSlice = range->baseMipLevel + level;
498       dsv_desc.Texture1DArray.FirstArraySlice = range->baseArrayLayer;
499       dsv_desc.Texture1DArray.ArraySize = layer_count;
500       break;
501    case D3D12_DSV_DIMENSION_TEXTURE2D:
502       dsv_desc.Texture2D.MipSlice = range->baseMipLevel + level;
503       break;
504    case D3D12_DSV_DIMENSION_TEXTURE2DMS:
505       break;
506    case D3D12_DSV_DIMENSION_TEXTURE2DARRAY:
507       dsv_desc.Texture2DArray.MipSlice = range->baseMipLevel + level;
508       dsv_desc.Texture2DArray.FirstArraySlice = range->baseArrayLayer;
509       dsv_desc.Texture2DArray.ArraySize = layer_count;
510       break;
511    case D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY:
512       dsv_desc.Texture2DMSArray.FirstArraySlice = range->baseArrayLayer;
513       dsv_desc.Texture2DMSArray.ArraySize = layer_count;
514       break;
515    default:
516       unreachable("Invalid view dimension");
517    }
518 
519    return dsv_desc;
520 }
521 
522 D3D12_RENDER_TARGET_VIEW_DESC
dzn_image_get_rtv_desc(const struct dzn_image * image,const VkImageSubresourceRange * range,uint32_t level)523 dzn_image_get_rtv_desc(const struct dzn_image *image,
524                        const VkImageSubresourceRange *range,
525                        uint32_t level)
526 {
527    struct dzn_physical_device *pdev =
528       container_of(image->vk.base.device->physical, struct dzn_physical_device, vk);
529    uint32_t layer_count = dzn_get_layer_count(image, range);
530    D3D12_RENDER_TARGET_VIEW_DESC rtv_desc = {
531       .Format =
532          dzn_image_get_dxgi_format(pdev, image->vk.format,
533                                    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
534                                    VK_IMAGE_ASPECT_COLOR_BIT),
535    };
536 
537    switch (image->vk.image_type) {
538    case VK_IMAGE_TYPE_1D:
539       rtv_desc.ViewDimension =
540          image->vk.array_layers > 1 ?
541          D3D12_RTV_DIMENSION_TEXTURE1DARRAY : D3D12_RTV_DIMENSION_TEXTURE1D;
542       break;
543    case VK_IMAGE_TYPE_2D:
544       if (image->vk.array_layers > 1) {
545          rtv_desc.ViewDimension =
546             image->vk.samples > 1 ?
547             D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY :
548             D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
549       } else {
550          rtv_desc.ViewDimension =
551             image->vk.samples > 1 ?
552             D3D12_RTV_DIMENSION_TEXTURE2DMS :
553             D3D12_RTV_DIMENSION_TEXTURE2D;
554       }
555       break;
556    case VK_IMAGE_TYPE_3D:
557       rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
558       break;
559    default: unreachable("Invalid image type\n");
560    }
561 
562    switch (rtv_desc.ViewDimension) {
563    case D3D12_RTV_DIMENSION_TEXTURE1D:
564       rtv_desc.Texture1D.MipSlice = range->baseMipLevel + level;
565       break;
566    case D3D12_RTV_DIMENSION_TEXTURE1DARRAY:
567       rtv_desc.Texture1DArray.MipSlice = range->baseMipLevel + level;
568       rtv_desc.Texture1DArray.FirstArraySlice = range->baseArrayLayer;
569       rtv_desc.Texture1DArray.ArraySize = layer_count;
570       break;
571    case D3D12_RTV_DIMENSION_TEXTURE2D:
572       rtv_desc.Texture2D.MipSlice = range->baseMipLevel + level;
573       if (range->aspectMask & VK_IMAGE_ASPECT_PLANE_1_BIT)
574          rtv_desc.Texture2D.PlaneSlice = 1;
575       else if (range->aspectMask & VK_IMAGE_ASPECT_PLANE_2_BIT)
576          rtv_desc.Texture2D.PlaneSlice = 2;
577       else
578          rtv_desc.Texture2D.PlaneSlice = 0;
579       break;
580    case D3D12_RTV_DIMENSION_TEXTURE2DMS:
581       break;
582    case D3D12_RTV_DIMENSION_TEXTURE2DARRAY:
583       rtv_desc.Texture2DArray.MipSlice = range->baseMipLevel + level;
584       rtv_desc.Texture2DArray.FirstArraySlice = range->baseArrayLayer;
585       rtv_desc.Texture2DArray.ArraySize = layer_count;
586       if (range->aspectMask & VK_IMAGE_ASPECT_PLANE_1_BIT)
587          rtv_desc.Texture2DArray.PlaneSlice = 1;
588       else if (range->aspectMask & VK_IMAGE_ASPECT_PLANE_2_BIT)
589          rtv_desc.Texture2DArray.PlaneSlice = 2;
590       else
591          rtv_desc.Texture2DArray.PlaneSlice = 0;
592       break;
593    case D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY:
594       rtv_desc.Texture2DMSArray.FirstArraySlice = range->baseArrayLayer;
595       rtv_desc.Texture2DMSArray.ArraySize = layer_count;
596       break;
597    case D3D12_RTV_DIMENSION_TEXTURE3D:
598       rtv_desc.Texture3D.MipSlice = range->baseMipLevel + level;
599       rtv_desc.Texture3D.FirstWSlice = range->baseArrayLayer;
600       rtv_desc.Texture3D.WSize =
601          range->layerCount == VK_REMAINING_ARRAY_LAYERS ? -1 : layer_count;
602       break;
603    default:
604       unreachable("Invalid ViewDimension");
605    }
606 
607    return rtv_desc;
608 }
609 
610 D3D12_RESOURCE_STATES
dzn_image_layout_to_state(const struct dzn_image * image,VkImageLayout layout,VkImageAspectFlagBits aspect,D3D12_COMMAND_LIST_TYPE type)611 dzn_image_layout_to_state(const struct dzn_image *image,
612                           VkImageLayout layout,
613                           VkImageAspectFlagBits aspect,
614                           D3D12_COMMAND_LIST_TYPE type)
615 {
616    D3D12_RESOURCE_STATES shaders_access =
617       (image->desc.Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE) ?
618       0 : (type == D3D12_COMMAND_LIST_TYPE_DIRECT ?
619            D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE :
620            D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
621 
622    switch (layout) {
623    case VK_IMAGE_LAYOUT_PREINITIALIZED:
624    case VK_IMAGE_LAYOUT_UNDEFINED:
625    case VK_IMAGE_LAYOUT_GENERAL:
626       /* YOLO! */
627    case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
628       return D3D12_RESOURCE_STATE_COMMON;
629 
630    case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
631       return D3D12_RESOURCE_STATE_COPY_DEST;
632 
633    case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
634       return D3D12_RESOURCE_STATE_COPY_SOURCE;
635 
636    case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
637       return type == D3D12_COMMAND_LIST_TYPE_DIRECT ?
638          D3D12_RESOURCE_STATE_RENDER_TARGET : D3D12_RESOURCE_STATE_COMMON;
639 
640    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
641    case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
642    case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
643       return D3D12_RESOURCE_STATE_DEPTH_WRITE;
644 
645    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
646    case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
647       return D3D12_RESOURCE_STATE_DEPTH_READ | shaders_access;
648 
649    case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
650       return aspect == VK_IMAGE_ASPECT_STENCIL_BIT ?
651              D3D12_RESOURCE_STATE_DEPTH_WRITE :
652              (D3D12_RESOURCE_STATE_DEPTH_READ | shaders_access);
653 
654    case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
655       return aspect == VK_IMAGE_ASPECT_STENCIL_BIT ?
656              (D3D12_RESOURCE_STATE_DEPTH_READ | shaders_access) :
657              D3D12_RESOURCE_STATE_DEPTH_WRITE;
658 
659    case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
660       return shaders_access;
661 
662    case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT:
663       return D3D12_RESOURCE_STATE_COMMON;
664 
665    default:
666       unreachable("not implemented");
667    }
668 }
669 
670 D3D12_BARRIER_LAYOUT
dzn_vk_layout_to_d3d_layout(VkImageLayout layout,D3D12_COMMAND_LIST_TYPE type,VkImageAspectFlags aspect)671 dzn_vk_layout_to_d3d_layout(VkImageLayout layout,
672                             D3D12_COMMAND_LIST_TYPE type,
673                             VkImageAspectFlags aspect)
674 {
675    if (type == D3D12_COMMAND_LIST_TYPE_COPY)
676       return D3D12_BARRIER_LAYOUT_COMMON;
677 
678    switch (layout) {
679    case VK_IMAGE_LAYOUT_UNDEFINED:
680       return D3D12_BARRIER_LAYOUT_UNDEFINED;
681    case VK_IMAGE_LAYOUT_PREINITIALIZED:
682       return D3D12_BARRIER_LAYOUT_COMMON;
683    case VK_IMAGE_LAYOUT_GENERAL:
684    case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
685    case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT:
686       switch (type) {
687       case D3D12_COMMAND_LIST_TYPE_DIRECT: return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON;
688       case D3D12_COMMAND_LIST_TYPE_COMPUTE: return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COMMON;
689       default: return D3D12_BARRIER_LAYOUT_COMMON;
690       }
691    case VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL:
692    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
693    case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
694    case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
695    case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
696    case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
697       switch (type) {
698       case D3D12_COMMAND_LIST_TYPE_DIRECT: return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ;
699       case D3D12_COMMAND_LIST_TYPE_COMPUTE: return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_GENERIC_READ;
700       default: return D3D12_BARRIER_LAYOUT_GENERIC_READ;
701       }
702    case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
703       return D3D12_BARRIER_LAYOUT_RENDER_TARGET;
704    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
705    case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
706    case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
707       return D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE;
708    case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
709       return aspect == VK_IMAGE_ASPECT_DEPTH_BIT ?
710          dzn_vk_layout_to_d3d_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, type, aspect) :
711          D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE;
712    case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
713       return aspect == VK_IMAGE_ASPECT_DEPTH_BIT ?
714          D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE :
715          dzn_vk_layout_to_d3d_layout(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, type, aspect);
716    case VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL:
717       return aspect == VK_IMAGE_ASPECT_COLOR_BIT ?
718          D3D12_BARRIER_LAYOUT_RENDER_TARGET : D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE;
719    case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
720    case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
721       return D3D12_BARRIER_LAYOUT_PRESENT;
722    case VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR:
723       return D3D12_BARRIER_LAYOUT_SHADING_RATE_SOURCE;
724    default:
725       assert(!"Unexpected layout");
726       return D3D12_BARRIER_LAYOUT_COMMON;
727    }
728 }
729 
730 bool
dzn_image_formats_are_compatible(const struct dzn_device * device,VkFormat orig_fmt,VkFormat new_fmt,VkImageUsageFlags usage,VkImageAspectFlagBits aspect)731 dzn_image_formats_are_compatible(const struct dzn_device *device,
732                                  VkFormat orig_fmt, VkFormat new_fmt,
733                                  VkImageUsageFlags usage,
734                                  VkImageAspectFlagBits aspect)
735 {
736    const struct dzn_physical_device *pdev =
737       container_of(device->vk.physical, struct dzn_physical_device, vk);
738    DXGI_FORMAT orig_dxgi = dzn_image_get_dxgi_format(pdev, orig_fmt, usage, aspect);
739    DXGI_FORMAT new_dxgi = dzn_image_get_dxgi_format(pdev, new_fmt, usage, aspect);
740 
741    if (orig_dxgi == new_dxgi)
742       return true;
743 
744    DXGI_FORMAT typeless_orig = dzn_get_typeless_dxgi_format(orig_dxgi);
745    DXGI_FORMAT typeless_new = dzn_get_typeless_dxgi_format(new_dxgi);
746 
747    if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT))
748       return typeless_orig == typeless_new;
749 
750    if (pdev->options3.CastingFullyTypedFormatSupported) {
751       enum pipe_format orig_pfmt = vk_format_to_pipe_format(orig_fmt);
752       enum pipe_format new_pfmt = vk_format_to_pipe_format(new_fmt);
753 
754       /* Types don't belong to the same group, they're incompatible. */
755       if (typeless_orig != typeless_new)
756          return false;
757 
758       /* FLOAT <-> non-FLOAT casting is disallowed. */
759       if (util_format_is_float(orig_pfmt) != util_format_is_float(new_pfmt))
760          return false;
761 
762       /* UNORM <-> SNORM casting is disallowed. */
763       bool orig_is_norm =
764          util_format_is_unorm(orig_pfmt) || util_format_is_snorm(orig_pfmt);
765       bool new_is_norm =
766          util_format_is_unorm(new_pfmt) || util_format_is_snorm(new_pfmt);
767       if (orig_is_norm && new_is_norm &&
768           util_format_is_unorm(orig_pfmt) != util_format_is_unorm(new_pfmt))
769          return false;
770 
771       return true;
772    }
773 
774    return false;
775 }
776 
777 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateImage(VkDevice device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)778 dzn_CreateImage(VkDevice device,
779                 const VkImageCreateInfo *pCreateInfo,
780                 const VkAllocationCallbacks *pAllocator,
781                 VkImage *pImage)
782 {
783    return dzn_image_create(dzn_device_from_handle(device),
784                            pCreateInfo, pAllocator, pImage);
785 }
786 
787 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyImage(VkDevice device,VkImage image,const VkAllocationCallbacks * pAllocator)788 dzn_DestroyImage(VkDevice device, VkImage image,
789                  const VkAllocationCallbacks *pAllocator)
790 {
791    dzn_image_destroy(dzn_image_from_handle(image), pAllocator);
792 }
793 
794 static struct dzn_image *
dzn_swapchain_get_image(struct dzn_device * device,VkSwapchainKHR swapchain,uint32_t index)795 dzn_swapchain_get_image(struct dzn_device *device,
796                         VkSwapchainKHR swapchain,
797                         uint32_t index)
798 {
799    uint32_t n_images = index + 1;
800    STACK_ARRAY(VkImage, images, n_images);
801    struct dzn_image *image = NULL;
802 
803    VkResult result = wsi_common_get_images(swapchain, &n_images, images);
804 
805    if (result == VK_SUCCESS || result == VK_INCOMPLETE)
806       image = dzn_image_from_handle(images[index]);
807 
808    STACK_ARRAY_FINISH(images);
809    return image;
810 }
811 
812 VKAPI_ATTR VkResult VKAPI_CALL
dzn_BindImageMemory2(VkDevice dev,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)813 dzn_BindImageMemory2(VkDevice dev,
814                      uint32_t bindInfoCount,
815                      const VkBindImageMemoryInfo *pBindInfos)
816 {
817    VK_FROM_HANDLE(dzn_device, device, dev);
818 
819    for (uint32_t i = 0; i < bindInfoCount; i++) {
820       const VkBindImageMemoryInfo *bind_info = &pBindInfos[i];
821       VK_FROM_HANDLE(dzn_device_memory, mem, bind_info->memory);
822       VK_FROM_HANDLE(dzn_image, image, bind_info->image);
823 
824 #ifdef DZN_USE_WSI_PLATFORM
825       const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
826          vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
827 
828       if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE) {
829          struct dzn_image *swapchain_img =
830             dzn_image_from_handle(wsi_common_get_image(swapchain_info->swapchain, swapchain_info->imageIndex));
831 
832          mem = swapchain_img->mem;
833       }
834 #endif
835 
836       image->mem = mem;
837 
838       HRESULT hres = S_OK;
839 
840       if (mem->dedicated_res) {
841          assert(pBindInfos[i].memoryOffset == 0);
842          image->res = mem->dedicated_res;
843          ID3D12Resource_AddRef(image->res);
844       } else if (device->dev10 && image->castable_format_count > 0) {
845          D3D12_RESOURCE_DESC1 desc = {
846             .Dimension = image->desc.Dimension,
847             .Alignment = image->desc.Alignment,
848             .Width = image->desc.Width,
849             .Height = image->desc.Height,
850             .DepthOrArraySize = image->desc.DepthOrArraySize,
851             .MipLevels = image->desc.MipLevels,
852             .Format = image->desc.Format,
853             .SampleDesc = image->desc.SampleDesc,
854             .Layout = image->desc.Layout,
855             .Flags = image->desc.Flags | mem->res_flags,
856          };
857 
858          hres = ID3D12Device10_CreatePlacedResource2(device->dev10, mem->heap,
859                                                      bind_info->memoryOffset,
860                                                      &desc,
861                                                      D3D12_BARRIER_LAYOUT_COMMON,
862                                                      NULL,
863                                                      image->castable_format_count,
864                                                      image->castable_formats,
865                                                      &IID_ID3D12Resource,
866                                                      (void **)&image->res);
867       } else {
868          D3D12_RESOURCE_DESC desc = image->desc;
869          desc.Flags |= mem->res_flags;
870          hres = ID3D12Device1_CreatePlacedResource(device->dev, mem->heap,
871                                                    bind_info->memoryOffset,
872                                                    &desc,
873                                                    D3D12_RESOURCE_STATE_COMMON,
874                                                    NULL,
875                                                    &IID_ID3D12Resource,
876                                                    (void **)&image->res);
877       }
878       if (FAILED(hres))
879          return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
880    }
881 
882    return VK_SUCCESS;
883 }
884 
885 VKAPI_ATTR void VKAPI_CALL
dzn_GetImageMemoryRequirements2(VkDevice _device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)886 dzn_GetImageMemoryRequirements2(VkDevice _device,
887                                 const VkImageMemoryRequirementsInfo2 *pInfo,
888                                 VkMemoryRequirements2 *pMemoryRequirements)
889 {
890    VK_FROM_HANDLE(dzn_device, device, _device);
891    VK_FROM_HANDLE(dzn_image, image, pInfo->image);
892    struct dzn_physical_device *pdev =
893       container_of(device->vk.physical, struct dzn_physical_device, vk);
894 
895    vk_foreach_struct_const(ext, pInfo->pNext) {
896       vk_debug_ignored_stype(ext->sType);
897    }
898 
899    vk_foreach_struct(ext, pMemoryRequirements->pNext) {
900       switch (ext->sType) {
901       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
902          VkMemoryDedicatedRequirements *requirements =
903             (VkMemoryDedicatedRequirements *)ext;
904          requirements->requiresDedicatedAllocation = image->vk.external_handle_types != 0;
905          requirements->prefersDedicatedAllocation = requirements->requiresDedicatedAllocation ||
906             image->vk.tiling == VK_IMAGE_TILING_OPTIMAL;
907          break;
908       }
909 
910       default:
911          vk_debug_ignored_stype(ext->sType);
912          break;
913       }
914    }
915 
916    D3D12_RESOURCE_ALLOCATION_INFO info;
917    if (device->dev12 && image->castable_format_count > 0) {
918       D3D12_RESOURCE_DESC1 desc1;
919       memcpy(&desc1, &image->desc, sizeof(image->desc));
920       memset(&desc1.SamplerFeedbackMipRegion, 0, sizeof(desc1.SamplerFeedbackMipRegion));
921       info = dzn_ID3D12Device12_GetResourceAllocationInfo3(device->dev12, 0, 1, &desc1,
922                                                            &image->castable_format_count,
923                                                            (const DXGI_FORMAT *const *) &image->castable_formats,
924                                                            NULL);
925    } else {
926       info = dzn_ID3D12Device4_GetResourceAllocationInfo(device->dev, 0, 1, &image->desc);
927    }
928 
929    pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
930       .size = info.SizeInBytes,
931       .alignment = info.Alignment,
932       .memoryTypeBits =
933          dzn_physical_device_get_mem_type_mask_for_resource(pdev, &image->desc,
934                                                             image->vk.external_handle_types != 0),
935    };
936 
937    /*
938     * MSAA images need memory to be aligned on
939     * D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT (4MB), but the memory
940     * allocation function doesn't know what the memory will be used for,
941     * and forcing all allocations to be 4MB-aligned has a cost, so let's
942     * force MSAA resources to be at least 4MB, such that the allocation
943     * logic can consider sub-4MB allocations to not require this 4MB alignment.
944     */
945    if (image->vk.samples > 1 &&
946        pMemoryRequirements->memoryRequirements.size < D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT)
947       pMemoryRequirements->memoryRequirements.size = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT;
948 }
949 
950 VKAPI_ATTR void VKAPI_CALL
dzn_GetImageSubresourceLayout(VkDevice _device,VkImage _image,const VkImageSubresource * subresource,VkSubresourceLayout * layout)951 dzn_GetImageSubresourceLayout(VkDevice _device,
952                               VkImage _image,
953                               const VkImageSubresource *subresource,
954                               VkSubresourceLayout *layout)
955 {
956    VK_FROM_HANDLE(dzn_device, device, _device);
957    VK_FROM_HANDLE(dzn_image, image, _image);
958 
959    if (image->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) {
960       assert(subresource->arrayLayer == 0);
961       assert(subresource->mipLevel == 0);
962       layout->offset = 0;
963       layout->rowPitch = image->linear.row_stride;
964       layout->depthPitch = 0;
965       layout->arrayPitch = 0;
966       layout->size = image->linear.size;
967    } else {
968       UINT subres_index =
969          dzn_image_get_subresource_index(image, subresource,
970                                          (VkImageAspectFlagBits)subresource->aspectMask);
971       D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
972       UINT num_rows;
973       UINT64 row_size, total_size;
974       ID3D12Device1_GetCopyableFootprints(device->dev, &image->desc,
975                                          subres_index, 1,
976                                          0, // base-offset?
977                                          &footprint,
978                                          &num_rows, &row_size,
979                                          &total_size);
980 
981       layout->offset = footprint.Offset;
982       layout->rowPitch = footprint.Footprint.RowPitch;
983       layout->depthPitch = layout->rowPitch * footprint.Footprint.Height;
984       layout->arrayPitch = layout->depthPitch; // uuuh... why is this even here?
985       layout->size = total_size;
986    }
987 }
988 
989 static D3D12_SHADER_COMPONENT_MAPPING
translate_swizzle(VkComponentSwizzle in,uint32_t comp)990 translate_swizzle(VkComponentSwizzle in, uint32_t comp)
991 {
992    switch (in) {
993    case VK_COMPONENT_SWIZZLE_IDENTITY:
994       return (D3D12_SHADER_COMPONENT_MAPPING)
995              (comp + D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0);
996    case VK_COMPONENT_SWIZZLE_ZERO:
997       return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0;
998    case VK_COMPONENT_SWIZZLE_ONE:
999       return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1;
1000    case VK_COMPONENT_SWIZZLE_R:
1001       return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0;
1002    case VK_COMPONENT_SWIZZLE_G:
1003       return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1;
1004    case VK_COMPONENT_SWIZZLE_B:
1005       return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2;
1006    case VK_COMPONENT_SWIZZLE_A:
1007       return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3;
1008    default: unreachable("Invalid swizzle");
1009    }
1010 }
1011 
1012 static void
dzn_image_view_prepare_srv_desc(struct dzn_image_view * iview)1013 dzn_image_view_prepare_srv_desc(struct dzn_image_view *iview)
1014 {
1015    struct dzn_physical_device *pdev =
1016       container_of(iview->vk.base.device->physical, struct dzn_physical_device, vk);
1017    uint32_t plane_slice = (iview->vk.aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) ==
1018       VK_IMAGE_ASPECT_STENCIL_BIT ? 1 : 0;
1019    bool ms = iview->vk.image->samples > 1;
1020    uint32_t layers_per_elem =
1021       (iview->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE ||
1022        iview->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
1023       6 : 1;
1024    bool from_3d_image = iview->vk.image->image_type == VK_IMAGE_TYPE_3D;
1025    bool use_array = iview->vk.base_array_layer > 0 ||
1026                     (iview->vk.layer_count / layers_per_elem) > 1;
1027 
1028    iview->srv_desc = (D3D12_SHADER_RESOURCE_VIEW_DESC) {
1029       .Format =
1030          dzn_image_get_dxgi_format(pdev, iview->vk.format,
1031                                    iview->vk.usage & ~VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
1032                                    iview->vk.aspects),
1033    };
1034 
1035    D3D12_SHADER_COMPONENT_MAPPING swz[] = {
1036       translate_swizzle(iview->vk.swizzle.r, 0),
1037       translate_swizzle(iview->vk.swizzle.g, 1),
1038       translate_swizzle(iview->vk.swizzle.b, 2),
1039       translate_swizzle(iview->vk.swizzle.a, 3),
1040    };
1041 
1042    /* Swap components to fake B4G4R4A4 support. */
1043    if (iview->vk.format == VK_FORMAT_B4G4R4A4_UNORM_PACK16) {
1044       if (pdev->support_a4b4g4r4) {
1045          static const D3D12_SHADER_COMPONENT_MAPPING bgra4_remap[] = {
1046             D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2,
1047             D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
1048             D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
1049             D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3,
1050             D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
1051             D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1,
1052          };
1053 
1054          for (uint32_t i = 0; i < ARRAY_SIZE(swz); i++)
1055             swz[i] = bgra4_remap[swz[i]];
1056       } else {
1057          static const D3D12_SHADER_COMPONENT_MAPPING bgra4_remap[] = {
1058             D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
1059             D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
1060             D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3,
1061             D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2,
1062             D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
1063             D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1,
1064          };
1065 
1066          for (uint32_t i = 0; i < ARRAY_SIZE(swz); i++)
1067             swz[i] = bgra4_remap[swz[i]];
1068       }
1069    } else if (iview->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
1070       /* D3D puts stencil in G, not R. Requests for R should be routed to G and vice versa. */
1071       for (uint32_t i = 0; i < ARRAY_SIZE(swz); i++) {
1072          if (swz[i] == D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0)
1073             swz[i] = D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1;
1074          else if (swz[i] == D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1)
1075             swz[i] = D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0;
1076       }
1077    } else if (iview->vk.view_format == VK_FORMAT_BC1_RGB_SRGB_BLOCK ||
1078               iview->vk.view_format == VK_FORMAT_BC1_RGB_UNORM_BLOCK) {
1079       /* D3D has no opaque version of these; force alpha to 1 */
1080       for (uint32_t i = 0; i < ARRAY_SIZE(swz); i++) {
1081          if (swz[i] == D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3)
1082             swz[i] = D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1;
1083       }
1084    }
1085 
1086    iview->srv_desc.Shader4ComponentMapping =
1087       D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(swz[0], swz[1], swz[2], swz[3]);
1088 
1089    switch (iview->vk.view_type) {
1090    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1091    case VK_IMAGE_VIEW_TYPE_1D:
1092       if (use_array) {
1093          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
1094          iview->srv_desc.Texture1DArray.MostDetailedMip = iview->vk.base_mip_level;
1095          iview->srv_desc.Texture1DArray.MipLevels = iview->vk.level_count;
1096          iview->srv_desc.Texture1DArray.FirstArraySlice = iview->vk.base_array_layer;
1097          iview->srv_desc.Texture1DArray.ArraySize = iview->vk.layer_count;
1098          iview->srv_desc.Texture1DArray.ResourceMinLODClamp = 0.0f;
1099       } else {
1100          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
1101          iview->srv_desc.Texture1D.MostDetailedMip = iview->vk.base_mip_level;
1102          iview->srv_desc.Texture1D.MipLevels = iview->vk.level_count;
1103          iview->srv_desc.Texture1D.ResourceMinLODClamp = 0.0f;
1104       }
1105       break;
1106 
1107    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1108    case VK_IMAGE_VIEW_TYPE_2D:
1109       if (from_3d_image) {
1110          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
1111          iview->srv_desc.Texture3D.MostDetailedMip = iview->vk.base_mip_level;
1112          iview->srv_desc.Texture3D.MipLevels = iview->vk.level_count;
1113          iview->srv_desc.Texture3D.ResourceMinLODClamp = 0.0f;
1114       } else if (use_array && ms) {
1115          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;
1116          iview->srv_desc.Texture2DMSArray.FirstArraySlice = iview->vk.base_array_layer;
1117          iview->srv_desc.Texture2DMSArray.ArraySize = iview->vk.layer_count;
1118       } else if (use_array && !ms) {
1119          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
1120          iview->srv_desc.Texture2DArray.MostDetailedMip = iview->vk.base_mip_level;
1121          iview->srv_desc.Texture2DArray.MipLevels = iview->vk.level_count;
1122          iview->srv_desc.Texture2DArray.FirstArraySlice = iview->vk.base_array_layer;
1123          iview->srv_desc.Texture2DArray.ArraySize = iview->vk.layer_count;
1124          iview->srv_desc.Texture2DArray.PlaneSlice = plane_slice;
1125          iview->srv_desc.Texture2DArray.ResourceMinLODClamp = 0.0f;
1126       } else if (!use_array && ms) {
1127          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;
1128       } else {
1129          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
1130          iview->srv_desc.Texture2D.MostDetailedMip = iview->vk.base_mip_level;
1131          iview->srv_desc.Texture2D.MipLevels = iview->vk.level_count;
1132          iview->srv_desc.Texture2D.PlaneSlice = plane_slice;
1133          iview->srv_desc.Texture2D.ResourceMinLODClamp = 0.0f;
1134       }
1135       break;
1136 
1137    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1138    case VK_IMAGE_VIEW_TYPE_CUBE:
1139       if (use_array) {
1140          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
1141          iview->srv_desc.TextureCubeArray.MostDetailedMip = iview->vk.base_mip_level;
1142          iview->srv_desc.TextureCubeArray.MipLevels = iview->vk.level_count;
1143          iview->srv_desc.TextureCubeArray.First2DArrayFace = iview->vk.base_array_layer;
1144          iview->srv_desc.TextureCubeArray.NumCubes = iview->vk.layer_count / 6;
1145          iview->srv_desc.TextureCubeArray.ResourceMinLODClamp = 0.0f;
1146       } else {
1147          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
1148          iview->srv_desc.TextureCube.MostDetailedMip = iview->vk.base_mip_level;
1149          iview->srv_desc.TextureCube.MipLevels = iview->vk.level_count;
1150          iview->srv_desc.TextureCube.ResourceMinLODClamp = 0.0f;
1151       }
1152       break;
1153 
1154    case VK_IMAGE_VIEW_TYPE_3D:
1155       iview->srv_desc.ViewDimension =  D3D12_SRV_DIMENSION_TEXTURE3D;
1156       iview->srv_desc.Texture3D.MostDetailedMip = iview->vk.base_mip_level;
1157       iview->srv_desc.Texture3D.MipLevels = iview->vk.level_count;
1158       iview->srv_desc.Texture3D.ResourceMinLODClamp = 0.0f;
1159       break;
1160 
1161    default: unreachable("Invalid view type");
1162    }
1163 }
1164 
1165 static void
dzn_image_view_prepare_uav_desc(struct dzn_image_view * iview)1166 dzn_image_view_prepare_uav_desc(struct dzn_image_view *iview)
1167 {
1168    struct dzn_physical_device *pdev =
1169       container_of(iview->vk.base.device->physical, struct dzn_physical_device, vk);
1170    bool use_array = iview->vk.base_array_layer > 0 || iview->vk.layer_count > 1;
1171 
1172    assert(iview->vk.image->samples == 1);
1173 
1174    iview->uav_desc = (D3D12_UNORDERED_ACCESS_VIEW_DESC) {
1175       .Format =
1176          dzn_image_get_dxgi_format(pdev, iview->vk.format,
1177                                    VK_IMAGE_USAGE_STORAGE_BIT,
1178                                    iview->vk.aspects),
1179    };
1180 
1181    switch (iview->vk.view_type) {
1182    case VK_IMAGE_VIEW_TYPE_1D:
1183    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1184       if (use_array) {
1185          iview->uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY;
1186          iview->uav_desc.Texture1DArray.MipSlice = iview->vk.base_mip_level;
1187          iview->uav_desc.Texture1DArray.FirstArraySlice = iview->vk.base_array_layer;
1188          iview->uav_desc.Texture1DArray.ArraySize = iview->vk.layer_count;
1189       } else {
1190          iview->uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D;
1191          iview->uav_desc.Texture1D.MipSlice = iview->vk.base_mip_level;
1192       }
1193       break;
1194 
1195    case VK_IMAGE_VIEW_TYPE_2D:
1196    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1197    case VK_IMAGE_VIEW_TYPE_CUBE:
1198    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1199       if (use_array) {
1200          iview->uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
1201          iview->uav_desc.Texture2DArray.PlaneSlice = 0;
1202          iview->uav_desc.Texture2DArray.MipSlice = iview->vk.base_mip_level;
1203          iview->uav_desc.Texture2DArray.FirstArraySlice = iview->vk.base_array_layer;
1204          iview->uav_desc.Texture2DArray.ArraySize = iview->vk.layer_count;
1205       } else {
1206          iview->uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
1207          iview->uav_desc.Texture2D.MipSlice = iview->vk.base_mip_level;
1208          iview->uav_desc.Texture2D.PlaneSlice = 0;
1209       }
1210       break;
1211    case VK_IMAGE_VIEW_TYPE_3D:
1212       iview->uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
1213       iview->uav_desc.Texture3D.MipSlice = iview->vk.base_mip_level;
1214       iview->uav_desc.Texture3D.FirstWSlice = 0;
1215       iview->uav_desc.Texture3D.WSize = iview->vk.extent.depth;
1216       break;
1217    default: unreachable("Invalid type");
1218    }
1219 }
1220 
1221 static void
dzn_image_view_prepare_rtv_desc(struct dzn_image_view * iview)1222 dzn_image_view_prepare_rtv_desc(struct dzn_image_view *iview)
1223 {
1224    struct dzn_physical_device *pdev =
1225       container_of(iview->vk.base.device->physical, struct dzn_physical_device, vk);
1226    bool use_array = iview->vk.base_array_layer > 0 || iview->vk.layer_count > 1;
1227    bool from_3d_image = iview->vk.image->image_type == VK_IMAGE_TYPE_3D;
1228    bool ms = iview->vk.image->samples > 1;
1229    uint32_t plane_slice =
1230       (iview->vk.aspects & VK_IMAGE_ASPECT_PLANE_2_BIT) ? 2 :
1231       (iview->vk.aspects & VK_IMAGE_ASPECT_PLANE_1_BIT) ? 1 : 0;
1232 
1233    iview->rtv_desc = (D3D12_RENDER_TARGET_VIEW_DESC) {
1234       .Format =
1235          dzn_image_get_dxgi_format(pdev, iview->vk.format,
1236                                    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
1237                                    iview->vk.aspects),
1238    };
1239 
1240    switch (iview->vk.view_type) {
1241    case VK_IMAGE_VIEW_TYPE_1D:
1242    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1243       if (use_array) {
1244          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE1DARRAY;
1245          iview->rtv_desc.Texture1DArray.MipSlice = iview->vk.base_mip_level;
1246          iview->rtv_desc.Texture1DArray.FirstArraySlice = iview->vk.base_array_layer;
1247          iview->rtv_desc.Texture1DArray.ArraySize = iview->vk.layer_count;
1248       } else {
1249          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE1D;
1250          iview->rtv_desc.Texture1D.MipSlice = iview->vk.base_mip_level;
1251       }
1252       break;
1253 
1254    case VK_IMAGE_VIEW_TYPE_2D:
1255    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1256    case VK_IMAGE_VIEW_TYPE_CUBE:
1257    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1258       if (from_3d_image) {
1259          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
1260          iview->rtv_desc.Texture3D.MipSlice = iview->vk.base_mip_level;
1261          iview->rtv_desc.Texture3D.FirstWSlice = iview->vk.base_array_layer;
1262          iview->rtv_desc.Texture3D.WSize = iview->vk.layer_count;
1263       } else if (use_array && ms) {
1264          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
1265          iview->rtv_desc.Texture2DMSArray.FirstArraySlice = iview->vk.base_array_layer;
1266          iview->rtv_desc.Texture2DMSArray.ArraySize = iview->vk.layer_count;
1267       } else if (use_array && !ms) {
1268          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
1269          iview->rtv_desc.Texture2DArray.MipSlice = iview->vk.base_mip_level;
1270          iview->rtv_desc.Texture2DArray.FirstArraySlice = iview->vk.base_array_layer;
1271          iview->rtv_desc.Texture2DArray.ArraySize = iview->vk.layer_count;
1272          iview->rtv_desc.Texture2DArray.PlaneSlice = plane_slice;
1273       } else if (!use_array && ms) {
1274          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
1275       } else {
1276          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
1277          iview->rtv_desc.Texture2D.MipSlice = iview->vk.base_mip_level;
1278          iview->rtv_desc.Texture2D.PlaneSlice = plane_slice;
1279       }
1280       break;
1281 
1282    case VK_IMAGE_VIEW_TYPE_3D:
1283       iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
1284       iview->rtv_desc.Texture3D.MipSlice = iview->vk.base_mip_level;
1285       iview->rtv_desc.Texture3D.FirstWSlice = 0;
1286       iview->rtv_desc.Texture3D.WSize = iview->vk.extent.depth;
1287       break;
1288 
1289    default: unreachable("Invalid view type");
1290    }
1291 }
1292 
1293 static void
dzn_image_view_prepare_dsv_desc(struct dzn_image_view * iview)1294 dzn_image_view_prepare_dsv_desc(struct dzn_image_view *iview)
1295 {
1296    struct dzn_physical_device *pdev =
1297       container_of(iview->vk.base.device->physical, struct dzn_physical_device, vk);
1298    bool use_array = iview->vk.base_array_layer > 0 || iview->vk.layer_count > 1;
1299    bool ms = iview->vk.image->samples > 1;
1300 
1301    iview->dsv_desc = (D3D12_DEPTH_STENCIL_VIEW_DESC) {
1302       .Format =
1303          dzn_image_get_dxgi_format(pdev, iview->vk.format,
1304                                    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
1305                                    iview->vk.aspects),
1306    };
1307 
1308    switch (iview->vk.view_type) {
1309    case VK_IMAGE_VIEW_TYPE_1D:
1310    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1311       if (use_array) {
1312          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE1DARRAY;
1313          iview->dsv_desc.Texture1DArray.MipSlice = iview->vk.base_mip_level;
1314          iview->dsv_desc.Texture1DArray.FirstArraySlice = iview->vk.base_array_layer;
1315          iview->dsv_desc.Texture1DArray.ArraySize = iview->vk.layer_count;
1316       } else {
1317          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE1D;
1318          iview->dsv_desc.Texture1D.MipSlice = iview->vk.base_mip_level;
1319       }
1320       break;
1321 
1322    case VK_IMAGE_VIEW_TYPE_2D:
1323    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1324    case VK_IMAGE_VIEW_TYPE_CUBE:
1325    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1326       if (use_array && ms) {
1327          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY;
1328          iview->dsv_desc.Texture2DMSArray.FirstArraySlice = iview->vk.base_array_layer;
1329          iview->dsv_desc.Texture2DMSArray.ArraySize = iview->vk.layer_count;
1330       } else if (use_array && !ms) {
1331          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
1332          iview->dsv_desc.Texture2DArray.MipSlice = iview->vk.base_mip_level;
1333          iview->dsv_desc.Texture2DArray.FirstArraySlice = iview->vk.base_array_layer;
1334          iview->dsv_desc.Texture2DArray.ArraySize = iview->vk.layer_count;
1335       } else if (!use_array && ms) {
1336          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMS;
1337       } else {
1338          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
1339          iview->dsv_desc.Texture2D.MipSlice = iview->vk.base_mip_level;
1340       }
1341       break;
1342 
1343    default: unreachable("Invalid view type");
1344    }
1345 }
1346 
1347 void
dzn_image_view_finish(struct dzn_image_view * iview)1348 dzn_image_view_finish(struct dzn_image_view *iview)
1349 {
1350    vk_image_view_finish(&iview->vk);
1351 }
1352 
1353 void
dzn_image_view_init(struct dzn_device * device,struct dzn_image_view * iview,const VkImageViewCreateInfo * pCreateInfo)1354 dzn_image_view_init(struct dzn_device *device,
1355                     struct dzn_image_view *iview,
1356                     const VkImageViewCreateInfo *pCreateInfo)
1357 {
1358    VK_FROM_HANDLE(dzn_image, image, pCreateInfo->image);
1359 
1360    const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
1361    ASSERTED uint32_t layer_count = dzn_get_layer_count(image, range);
1362 
1363    vk_image_view_init(&device->vk, &iview->vk, false, pCreateInfo);
1364 
1365    assert(layer_count > 0);
1366    assert(range->baseMipLevel < image->vk.mip_levels);
1367 
1368    /* View usage should be a subset of image usage */
1369    assert(iview->vk.usage & (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1370                              VK_IMAGE_USAGE_SAMPLED_BIT |
1371                              VK_IMAGE_USAGE_STORAGE_BIT |
1372                              VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1373                              VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
1374                              VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
1375 
1376    /* We remove this bit on depth textures, so skip creating a UAV for those */
1377    if ((iview->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
1378        !(image->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS))
1379       iview->vk.usage &= ~VK_IMAGE_USAGE_STORAGE_BIT;
1380 
1381    switch (image->vk.image_type) {
1382    default:
1383       unreachable("bad VkImageType");
1384    case VK_IMAGE_TYPE_1D:
1385    case VK_IMAGE_TYPE_2D:
1386       assert(range->baseArrayLayer + dzn_get_layer_count(image, range) - 1 <= image->vk.array_layers);
1387       break;
1388    case VK_IMAGE_TYPE_3D:
1389       assert(range->baseArrayLayer + dzn_get_layer_count(image, range) - 1
1390              <= u_minify(image->vk.extent.depth, range->baseMipLevel));
1391       break;
1392    }
1393 
1394    dzn_image_view_prepare_srv_desc(iview);
1395 
1396    if (iview->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT)
1397       dzn_image_view_prepare_uav_desc(iview);
1398 
1399    if (iview->vk.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
1400       dzn_image_view_prepare_rtv_desc(iview);
1401 
1402    if (iview->vk.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
1403       dzn_image_view_prepare_dsv_desc(iview);
1404 }
1405 
1406 static void
dzn_image_view_destroy(struct dzn_image_view * iview,const VkAllocationCallbacks * pAllocator)1407 dzn_image_view_destroy(struct dzn_image_view *iview,
1408                       const VkAllocationCallbacks *pAllocator)
1409 {
1410    if (!iview)
1411       return;
1412 
1413    struct dzn_device *device = container_of(iview->vk.base.device, struct dzn_device, vk);
1414 
1415    dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, iview->srv_bindless_slot);
1416    dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, iview->uav_bindless_slot);
1417 
1418    vk_image_view_finish(&iview->vk);
1419    vk_free2(&device->vk.alloc, pAllocator, iview);
1420 }
1421 
1422 static VkResult
dzn_image_view_create(struct dzn_device * device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * out)1423 dzn_image_view_create(struct dzn_device *device,
1424                       const VkImageViewCreateInfo *pCreateInfo,
1425                       const VkAllocationCallbacks *pAllocator,
1426                       VkImageView *out)
1427 {
1428    VK_FROM_HANDLE(dzn_image, image, pCreateInfo->image);
1429    struct dzn_image_view *iview =
1430       vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*iview), 8,
1431                  VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1432    if (!iview)
1433       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1434 
1435    dzn_image_view_init(device, iview, pCreateInfo);
1436 
1437    iview->srv_bindless_slot = iview->uav_bindless_slot = -1;
1438    if (device->bindless) {
1439       if (!(image->desc.Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE)) {
1440          iview->srv_bindless_slot = dzn_device_descriptor_heap_alloc_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
1441          if (iview->srv_bindless_slot < 0) {
1442             dzn_image_view_destroy(iview, pAllocator);
1443             return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1444          }
1445 
1446          dzn_descriptor_heap_write_image_view_desc(device,
1447                                                    &device->device_heaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heap,
1448                                                    iview->srv_bindless_slot,
1449                                                    false, false,
1450                                                    iview);
1451       }
1452       if (iview->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
1453          iview->uav_bindless_slot = dzn_device_descriptor_heap_alloc_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
1454          if (iview->uav_bindless_slot < 0) {
1455             dzn_image_view_destroy(iview, pAllocator);
1456             return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1457          }
1458 
1459          dzn_descriptor_heap_write_image_view_desc(device,
1460                                                    &device->device_heaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heap,
1461                                                    iview->uav_bindless_slot,
1462                                                    true, true,
1463                                                    iview);
1464       }
1465    }
1466 
1467    *out = dzn_image_view_to_handle(iview);
1468    return VK_SUCCESS;
1469 }
1470 
1471 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateImageView(VkDevice device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)1472 dzn_CreateImageView(VkDevice device,
1473                     const VkImageViewCreateInfo *pCreateInfo,
1474                     const VkAllocationCallbacks *pAllocator,
1475                     VkImageView *pView)
1476 {
1477    return dzn_image_view_create(dzn_device_from_handle(device), pCreateInfo,
1478                                 pAllocator, pView);
1479 }
1480 
1481 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyImageView(VkDevice device,VkImageView imageView,const VkAllocationCallbacks * pAllocator)1482 dzn_DestroyImageView(VkDevice device,
1483                      VkImageView imageView,
1484                      const VkAllocationCallbacks *pAllocator)
1485 {
1486    dzn_image_view_destroy(dzn_image_view_from_handle(imageView), pAllocator);
1487 }
1488 
1489 static void
dzn_buffer_view_destroy(struct dzn_buffer_view * bview,const VkAllocationCallbacks * pAllocator)1490 dzn_buffer_view_destroy(struct dzn_buffer_view *bview,
1491                         const VkAllocationCallbacks *pAllocator)
1492 {
1493    if (!bview)
1494       return;
1495 
1496    struct dzn_device *device = container_of(bview->base.device, struct dzn_device, vk);
1497 
1498    dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, bview->srv_bindless_slot);
1499    dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, bview->uav_bindless_slot);
1500 
1501    vk_object_base_finish(&bview->base);
1502    vk_free2(&device->vk.alloc, pAllocator, bview);
1503 }
1504 
1505 static VkResult
dzn_buffer_view_create(struct dzn_device * device,const VkBufferViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBufferView * out)1506 dzn_buffer_view_create(struct dzn_device *device,
1507                        const VkBufferViewCreateInfo *pCreateInfo,
1508                        const VkAllocationCallbacks *pAllocator,
1509                        VkBufferView *out)
1510 {
1511    VK_FROM_HANDLE(dzn_buffer, buf, pCreateInfo->buffer);
1512 
1513    struct dzn_buffer_view *bview =
1514       vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*bview), 8,
1515                  VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1516    if (!bview)
1517       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1518 
1519    vk_object_base_init(&device->vk, &bview->base, VK_OBJECT_TYPE_BUFFER_VIEW);
1520 
1521    enum pipe_format pfmt = vk_format_to_pipe_format(pCreateInfo->format);
1522    unsigned blksz = util_format_get_blocksize(pfmt);
1523    VkDeviceSize size =
1524       pCreateInfo->range == VK_WHOLE_SIZE ?
1525       buf->size - pCreateInfo->offset : pCreateInfo->range;
1526 
1527    bview->buffer = buf;
1528    bview->srv_bindless_slot = bview->uav_bindless_slot = -1;
1529    if (buf->usage &
1530        (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
1531         VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
1532       bview->srv_desc = (D3D12_SHADER_RESOURCE_VIEW_DESC) {
1533          .Format = dzn_buffer_get_dxgi_format(pCreateInfo->format),
1534          .ViewDimension = D3D12_SRV_DIMENSION_BUFFER,
1535          .Shader4ComponentMapping =
1536             D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
1537          .Buffer = {
1538             .FirstElement = pCreateInfo->offset / blksz,
1539             .NumElements = (UINT)(size / blksz),
1540             .Flags = D3D12_BUFFER_SRV_FLAG_NONE,
1541          },
1542       };
1543 
1544       if (device->bindless) {
1545          bview->srv_bindless_slot = dzn_device_descriptor_heap_alloc_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
1546          if (bview->srv_bindless_slot < 0) {
1547             dzn_buffer_view_destroy(bview, pAllocator);
1548             return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1549          }
1550          dzn_descriptor_heap_write_buffer_view_desc(device, &device->device_heaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heap,
1551                                                     bview->srv_bindless_slot, false, bview);
1552       }
1553    }
1554 
1555    if (buf->usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) {
1556       bview->uav_desc = (D3D12_UNORDERED_ACCESS_VIEW_DESC) {
1557          .Format = dzn_buffer_get_dxgi_format(pCreateInfo->format),
1558          .ViewDimension = D3D12_UAV_DIMENSION_BUFFER,
1559          .Buffer = {
1560             .FirstElement = pCreateInfo->offset / blksz,
1561             .NumElements = (UINT)(size / blksz),
1562             .Flags = D3D12_BUFFER_UAV_FLAG_NONE,
1563          },
1564       };
1565 
1566       if (device->bindless) {
1567          bview->uav_bindless_slot = dzn_device_descriptor_heap_alloc_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
1568          if (bview->uav_bindless_slot < 0) {
1569             dzn_buffer_view_destroy(bview, pAllocator);
1570             return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1571          }
1572          dzn_descriptor_heap_write_buffer_view_desc(device, &device->device_heaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heap,
1573                                                     bview->uav_bindless_slot, true, bview);
1574       }
1575    }
1576 
1577    *out = dzn_buffer_view_to_handle(bview);
1578    return VK_SUCCESS;
1579 }
1580 
1581 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateBufferView(VkDevice device,const VkBufferViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBufferView * pView)1582 dzn_CreateBufferView(VkDevice device,
1583                      const VkBufferViewCreateInfo *pCreateInfo,
1584                      const VkAllocationCallbacks *pAllocator,
1585                      VkBufferView *pView)
1586 {
1587    return dzn_buffer_view_create(dzn_device_from_handle(device),
1588                                  pCreateInfo, pAllocator, pView);
1589 }
1590 
1591 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyBufferView(VkDevice device,VkBufferView bufferView,const VkAllocationCallbacks * pAllocator)1592 dzn_DestroyBufferView(VkDevice device,
1593                       VkBufferView bufferView,
1594                       const VkAllocationCallbacks *pAllocator)
1595 {
1596    dzn_buffer_view_destroy(dzn_buffer_view_from_handle(bufferView), pAllocator);
1597 }
1598