• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_image *image =
72       vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*image), 8,
73                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
74    struct dzn_physical_device *pdev =
75       container_of(device->vk.physical, struct dzn_physical_device, vk);
76 
77    if (!image)
78       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
79 
80 #if 0
81     VkExternalMemoryHandleTypeFlags supported =
82         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT |
83         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT |
84         VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT |
85         VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT |
86         VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT |
87         VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT;
88 
89    if (create_info && (create_info->handleTypes & supported))
90       return dzn_image_from_external(device, pCreateInfo, create_info,
91                                      pAllocator, pImage);
92 #endif
93 
94 #if 0
95    const VkImageSwapchainCreateInfoKHR *swapchain_info = (const VkImageSwapchainCreateInfoKHR *)
96       vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
97    if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE)
98       return dzn_image_from_swapchain(device, pCreateInfo, swapchain_info,
99                                       pAllocator, pImage);
100 #endif
101 
102    vk_image_init(&device->vk, &image->vk, pCreateInfo);
103    enum pipe_format pfmt = vk_format_to_pipe_format(image->vk.format);
104 
105    if (image->vk.tiling == VK_IMAGE_TILING_LINEAR) {
106       /* Treat linear images as buffers: they should only be used as copy
107        * src/dest, and CopyTextureResource() can manipulate buffers.
108        * We only support linear tiling on things strictly required by the spec:
109        * "Images created with tiling equal to VK_IMAGE_TILING_LINEAR have
110        * further restrictions on their limits and capabilities compared to
111        * images created with tiling equal to VK_IMAGE_TILING_OPTIMAL. Creation
112        * of images with tiling VK_IMAGE_TILING_LINEAR may not be supported
113        * unless other parameters meet all of the constraints:
114        * - imageType is VK_IMAGE_TYPE_2D
115        * - format is not a depth/stencil format
116        * - mipLevels is 1
117        * - arrayLayers is 1
118        * - samples is VK_SAMPLE_COUNT_1_BIT
119        * - usage only includes VK_IMAGE_USAGE_TRANSFER_SRC_BIT and/or VK_IMAGE_USAGE_TRANSFER_DST_BIT
120        * "
121        */
122       assert(!vk_format_is_depth_or_stencil(pCreateInfo->format));
123       assert(pCreateInfo->mipLevels == 1);
124       assert(pCreateInfo->arrayLayers == 1);
125       assert(pCreateInfo->samples == 1);
126       assert(pCreateInfo->imageType != VK_IMAGE_TYPE_3D);
127       assert(!(pCreateInfo->usage & ~(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)));
128       D3D12_RESOURCE_DESC tmp_desc = {
129          .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
130          .Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
131          .Width = ALIGN(image->vk.extent.width, util_format_get_blockwidth(pfmt)),
132          .Height = (UINT)ALIGN(image->vk.extent.height, util_format_get_blockheight(pfmt)),
133          .DepthOrArraySize = 1,
134          .MipLevels = 1,
135          .Format =
136             dzn_image_get_dxgi_format(pCreateInfo->format, pCreateInfo->usage, 0),
137          .SampleDesc = { .Count = 1, .Quality = 0 },
138          .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
139          .Flags = D3D12_RESOURCE_FLAG_NONE
140       };
141       D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
142       uint64_t size = 0;
143       ID3D12Device1_GetCopyableFootprints(device->dev, &tmp_desc, 0, 1, 0, &footprint, NULL, NULL, &size);
144 
145       image->linear.row_stride = footprint.Footprint.RowPitch;
146       image->linear.size = size;
147       size *= pCreateInfo->arrayLayers;
148       image->desc.Format = DXGI_FORMAT_UNKNOWN;
149       image->desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
150       image->desc.Width = size;
151       image->desc.Height = 1;
152       image->desc.DepthOrArraySize = 1;
153       image->desc.MipLevels = 1;
154       image->desc.SampleDesc.Count = 1;
155       image->desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
156    } else {
157       image->desc.Format =
158          dzn_image_get_dxgi_format(pCreateInfo->format,
159                                    pCreateInfo->usage & ~VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
160                                    0),
161       image->desc.Dimension = (D3D12_RESOURCE_DIMENSION)(D3D12_RESOURCE_DIMENSION_TEXTURE1D + pCreateInfo->imageType);
162       image->desc.Width = image->vk.extent.width;
163       image->desc.Height = image->vk.extent.height;
164       image->desc.DepthOrArraySize = pCreateInfo->imageType == VK_IMAGE_TYPE_3D ?
165                                      image->vk.extent.depth :
166                                      pCreateInfo->arrayLayers;
167       image->desc.MipLevels = pCreateInfo->mipLevels;
168       image->desc.SampleDesc.Count = pCreateInfo->samples;
169       image->desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
170    }
171 
172    if (image->vk.create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)
173       image->desc.Format = dzn_get_typeless_dxgi_format(image->desc.Format);
174 
175    if (image->desc.SampleDesc.Count > 1)
176       image->desc.Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT;
177    else
178       image->desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
179 
180    image->desc.SampleDesc.Quality = 0;
181 
182    image->desc.Flags = D3D12_RESOURCE_FLAG_NONE;
183 
184    if (image->vk.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
185       image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
186 
187    if (image->vk.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
188       image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
189 
190       if (!(image->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
191                                VK_IMAGE_USAGE_STORAGE_BIT |
192                                VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
193                                VK_IMAGE_USAGE_TRANSFER_SRC_BIT)))
194          image->desc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
195    }
196 
197    /* Images with TRANSFER_DST can be cleared or passed as a blit/resolve
198     * destination. Both operations require the RT or DS cap flags.
199     */
200    if ((image->vk.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) &&
201        image->vk.tiling == VK_IMAGE_TILING_OPTIMAL) {
202 
203       D3D12_FEATURE_DATA_FORMAT_SUPPORT dfmt_info =
204          dzn_physical_device_get_format_support(pdev, pCreateInfo->format);
205       if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET) {
206          image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
207       } else if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL) {
208          image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
209       } else if (dfmt_info.Support1 & D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW) {
210          image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
211       }
212    }
213 
214    if (image->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT)
215       image->desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
216 
217    *out = dzn_image_to_handle(image);
218    return VK_SUCCESS;
219 }
220 
221 DXGI_FORMAT
dzn_image_get_dxgi_format(VkFormat format,VkImageUsageFlags usage,VkImageAspectFlags aspects)222 dzn_image_get_dxgi_format(VkFormat format,
223                           VkImageUsageFlags usage,
224                           VkImageAspectFlags aspects)
225 {
226    enum pipe_format pfmt = vk_format_to_pipe_format(format);
227 
228    if (!vk_format_is_depth_or_stencil(format))
229       return dzn_pipe_to_dxgi_format(pfmt);
230 
231    switch (pfmt) {
232    case PIPE_FORMAT_Z16_UNORM:
233       return usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ?
234              DXGI_FORMAT_D16_UNORM : DXGI_FORMAT_R16_UNORM;
235 
236    case PIPE_FORMAT_Z32_FLOAT:
237       return usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ?
238              DXGI_FORMAT_D32_FLOAT : DXGI_FORMAT_R32_FLOAT;
239 
240    case PIPE_FORMAT_Z24X8_UNORM:
241       return usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ?
242              DXGI_FORMAT_D24_UNORM_S8_UINT : DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
243 
244    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
245       if (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
246          return DXGI_FORMAT_D24_UNORM_S8_UINT;
247 
248       if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
249          return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
250       else
251          return DXGI_FORMAT_X24_TYPELESS_G8_UINT;
252 
253    case PIPE_FORMAT_X24S8_UINT:
254       return usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ?
255              DXGI_FORMAT_D24_UNORM_S8_UINT : DXGI_FORMAT_X24_TYPELESS_G8_UINT;
256 
257    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
258       if (usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
259          return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
260 
261       if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
262          return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
263       else if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
264          return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
265       else
266          return DXGI_FORMAT_R32G8X24_TYPELESS;
267 
268    default:
269       return dzn_pipe_to_dxgi_format(pfmt);
270    }
271 }
272 
273 DXGI_FORMAT
dzn_image_get_placed_footprint_format(VkFormat format,VkImageAspectFlags aspect)274 dzn_image_get_placed_footprint_format(VkFormat format,
275                                       VkImageAspectFlags aspect)
276 {
277    DXGI_FORMAT out =
278       dzn_image_get_dxgi_format(format,
279                                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
280                                 VK_IMAGE_USAGE_TRANSFER_DST_BIT,
281                                 aspect);
282 
283    switch (out) {
284    case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
285    case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
286       return DXGI_FORMAT_R32_TYPELESS;
287    case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
288    case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
289       return DXGI_FORMAT_R8_TYPELESS;
290    default:
291       return out;
292    }
293 }
294 
295 VkFormat
dzn_image_get_plane_format(VkFormat format,VkImageAspectFlags aspectMask)296 dzn_image_get_plane_format(VkFormat format,
297                            VkImageAspectFlags aspectMask)
298 {
299    if (aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
300       return vk_format_stencil_only(format);
301    else if (aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT)
302       return vk_format_depth_only(format);
303    else
304       return format;
305 }
306 
307 uint32_t
dzn_image_layers_get_subresource_index(const struct dzn_image * image,const VkImageSubresourceLayers * subres,VkImageAspectFlagBits aspect,uint32_t layer)308 dzn_image_layers_get_subresource_index(const struct dzn_image *image,
309                                        const VkImageSubresourceLayers *subres,
310                                        VkImageAspectFlagBits aspect,
311                                        uint32_t layer)
312 {
313    int planeSlice =
314       aspect == VK_IMAGE_ASPECT_STENCIL_BIT ? 1 : 0;
315 
316    return subres->mipLevel +
317           ((subres->baseArrayLayer + layer) * image->desc.MipLevels) +
318           (planeSlice * image->desc.MipLevels * image->desc.DepthOrArraySize);
319 }
320 
321 uint32_t
dzn_image_range_get_subresource_index(const struct dzn_image * image,const VkImageSubresourceRange * subres,VkImageAspectFlagBits aspect,uint32_t level,uint32_t layer)322 dzn_image_range_get_subresource_index(const struct dzn_image *image,
323                                       const VkImageSubresourceRange *subres,
324                                       VkImageAspectFlagBits aspect,
325                                       uint32_t level, uint32_t layer)
326 {
327    int planeSlice =
328       aspect == VK_IMAGE_ASPECT_STENCIL_BIT ? 1 : 0;
329 
330    return subres->baseMipLevel + level +
331           ((subres->baseArrayLayer + layer) * image->desc.MipLevels) +
332           (planeSlice * image->desc.MipLevels * image->desc.DepthOrArraySize);
333 }
334 
335 static uint32_t
dzn_image_get_subresource_index(const struct dzn_image * image,const VkImageSubresource * subres,VkImageAspectFlagBits aspect)336 dzn_image_get_subresource_index(const struct dzn_image *image,
337                                 const VkImageSubresource *subres,
338                                 VkImageAspectFlagBits aspect)
339 {
340    int planeSlice =
341       aspect == VK_IMAGE_ASPECT_STENCIL_BIT ? 1 : 0;
342 
343    return subres->mipLevel +
344           (subres->arrayLayer * image->desc.MipLevels) +
345           (planeSlice * image->desc.MipLevels * image->desc.DepthOrArraySize);
346 }
347 
348 D3D12_TEXTURE_COPY_LOCATION
dzn_image_get_copy_loc(const struct dzn_image * image,const VkImageSubresourceLayers * subres,VkImageAspectFlagBits aspect,uint32_t layer)349 dzn_image_get_copy_loc(const struct dzn_image *image,
350                        const VkImageSubresourceLayers *subres,
351                        VkImageAspectFlagBits aspect,
352                        uint32_t layer)
353 {
354    D3D12_TEXTURE_COPY_LOCATION loc = {
355       .pResource = image->res,
356    };
357 
358    assert((subres->aspectMask & aspect) != 0);
359 
360    if (image->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) {
361       assert((subres->baseArrayLayer + layer) == 0);
362       assert(subres->mipLevel == 0);
363       loc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
364       loc.PlacedFootprint.Offset = 0;
365       loc.PlacedFootprint.Footprint.Format =
366          dzn_image_get_placed_footprint_format(image->vk.format, aspect);
367       loc.PlacedFootprint.Footprint.Width = image->vk.extent.width;
368       loc.PlacedFootprint.Footprint.Height = image->vk.extent.height;
369       loc.PlacedFootprint.Footprint.Depth = image->vk.extent.depth;
370       loc.PlacedFootprint.Footprint.RowPitch = image->linear.row_stride;
371    } else {
372       loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
373       loc.SubresourceIndex = dzn_image_layers_get_subresource_index(image, subres, aspect, layer);
374    }
375 
376    return loc;
377 }
378 
379 D3D12_DEPTH_STENCIL_VIEW_DESC
dzn_image_get_dsv_desc(const struct dzn_image * image,const VkImageSubresourceRange * range,uint32_t level)380 dzn_image_get_dsv_desc(const struct dzn_image *image,
381                        const VkImageSubresourceRange *range,
382                        uint32_t level)
383 {
384    uint32_t layer_count = dzn_get_layer_count(image, range);
385    D3D12_DEPTH_STENCIL_VIEW_DESC dsv_desc = {
386       .Format =
387          dzn_image_get_dxgi_format(image->vk.format,
388                                    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
389                                    range->aspectMask),
390    };
391 
392    switch (image->vk.image_type) {
393    case VK_IMAGE_TYPE_1D:
394       dsv_desc.ViewDimension =
395          image->vk.array_layers > 1 ?
396          D3D12_DSV_DIMENSION_TEXTURE1DARRAY :
397          D3D12_DSV_DIMENSION_TEXTURE1D;
398       break;
399    case VK_IMAGE_TYPE_2D:
400       if (image->vk.array_layers > 1) {
401          dsv_desc.ViewDimension =
402             image->vk.samples > 1 ?
403             D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY :
404             D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
405       } else {
406          dsv_desc.ViewDimension =
407             image->vk.samples > 1 ?
408             D3D12_DSV_DIMENSION_TEXTURE2DMS :
409             D3D12_DSV_DIMENSION_TEXTURE2D;
410       }
411       break;
412    default:
413       unreachable("Invalid image type");
414    }
415 
416    switch (dsv_desc.ViewDimension) {
417    case D3D12_DSV_DIMENSION_TEXTURE1D:
418       dsv_desc.Texture1D.MipSlice = range->baseMipLevel + level;
419       break;
420    case D3D12_DSV_DIMENSION_TEXTURE1DARRAY:
421       dsv_desc.Texture1DArray.MipSlice = range->baseMipLevel + level;
422       dsv_desc.Texture1DArray.FirstArraySlice = range->baseArrayLayer;
423       dsv_desc.Texture1DArray.ArraySize = layer_count;
424       break;
425    case D3D12_DSV_DIMENSION_TEXTURE2D:
426       dsv_desc.Texture2D.MipSlice = range->baseMipLevel + level;
427       break;
428    case D3D12_DSV_DIMENSION_TEXTURE2DMS:
429       break;
430    case D3D12_DSV_DIMENSION_TEXTURE2DARRAY:
431       dsv_desc.Texture2DArray.MipSlice = range->baseMipLevel + level;
432       dsv_desc.Texture2DArray.FirstArraySlice = range->baseArrayLayer;
433       dsv_desc.Texture2DArray.ArraySize = layer_count;
434       break;
435    case D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY:
436       dsv_desc.Texture2DMSArray.FirstArraySlice = range->baseArrayLayer;
437       dsv_desc.Texture2DMSArray.ArraySize = layer_count;
438       break;
439    default:
440       unreachable("Invalid view dimension");
441    }
442 
443    return dsv_desc;
444 }
445 
446 D3D12_RENDER_TARGET_VIEW_DESC
dzn_image_get_rtv_desc(const struct dzn_image * image,const VkImageSubresourceRange * range,uint32_t level)447 dzn_image_get_rtv_desc(const struct dzn_image *image,
448                        const VkImageSubresourceRange *range,
449                        uint32_t level)
450 {
451    uint32_t layer_count = dzn_get_layer_count(image, range);
452    D3D12_RENDER_TARGET_VIEW_DESC rtv_desc = {
453       .Format =
454          dzn_image_get_dxgi_format(image->vk.format,
455                                    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
456                                    VK_IMAGE_ASPECT_COLOR_BIT),
457    };
458 
459    switch (image->vk.image_type) {
460    case VK_IMAGE_TYPE_1D:
461       rtv_desc.ViewDimension =
462          image->vk.array_layers > 1 ?
463          D3D12_RTV_DIMENSION_TEXTURE1DARRAY : D3D12_RTV_DIMENSION_TEXTURE1D;
464       break;
465    case VK_IMAGE_TYPE_2D:
466       if (image->vk.array_layers > 1) {
467          rtv_desc.ViewDimension =
468             image->vk.samples > 1 ?
469             D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY :
470             D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
471       } else {
472          rtv_desc.ViewDimension =
473             image->vk.samples > 1 ?
474             D3D12_RTV_DIMENSION_TEXTURE2DMS :
475             D3D12_RTV_DIMENSION_TEXTURE2D;
476       }
477       break;
478    case VK_IMAGE_TYPE_3D:
479       rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
480       break;
481    default: unreachable("Invalid image type\n");
482    }
483 
484    switch (rtv_desc.ViewDimension) {
485    case D3D12_RTV_DIMENSION_TEXTURE1D:
486       rtv_desc.Texture1D.MipSlice = range->baseMipLevel + level;
487       break;
488    case D3D12_RTV_DIMENSION_TEXTURE1DARRAY:
489       rtv_desc.Texture1DArray.MipSlice = range->baseMipLevel + level;
490       rtv_desc.Texture1DArray.FirstArraySlice = range->baseArrayLayer;
491       rtv_desc.Texture1DArray.ArraySize = layer_count;
492       break;
493    case D3D12_RTV_DIMENSION_TEXTURE2D:
494       rtv_desc.Texture2D.MipSlice = range->baseMipLevel + level;
495       if (range->aspectMask & VK_IMAGE_ASPECT_PLANE_1_BIT)
496          rtv_desc.Texture2D.PlaneSlice = 1;
497       else if (range->aspectMask & VK_IMAGE_ASPECT_PLANE_2_BIT)
498          rtv_desc.Texture2D.PlaneSlice = 2;
499       else
500          rtv_desc.Texture2D.PlaneSlice = 0;
501       break;
502    case D3D12_RTV_DIMENSION_TEXTURE2DMS:
503       break;
504    case D3D12_RTV_DIMENSION_TEXTURE2DARRAY:
505       rtv_desc.Texture2DArray.MipSlice = range->baseMipLevel + level;
506       rtv_desc.Texture2DArray.FirstArraySlice = range->baseArrayLayer;
507       rtv_desc.Texture2DArray.ArraySize = layer_count;
508       if (range->aspectMask & VK_IMAGE_ASPECT_PLANE_1_BIT)
509          rtv_desc.Texture2DArray.PlaneSlice = 1;
510       else if (range->aspectMask & VK_IMAGE_ASPECT_PLANE_2_BIT)
511          rtv_desc.Texture2DArray.PlaneSlice = 2;
512       else
513          rtv_desc.Texture2DArray.PlaneSlice = 0;
514       break;
515    case D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY:
516       rtv_desc.Texture2DMSArray.FirstArraySlice = range->baseArrayLayer;
517       rtv_desc.Texture2DMSArray.ArraySize = layer_count;
518       break;
519    case D3D12_RTV_DIMENSION_TEXTURE3D:
520       rtv_desc.Texture3D.MipSlice = range->baseMipLevel + level;
521       rtv_desc.Texture3D.FirstWSlice = range->baseArrayLayer;
522       rtv_desc.Texture3D.WSize =
523          range->layerCount == VK_REMAINING_ARRAY_LAYERS ? -1 : layer_count;
524       break;
525    default:
526       unreachable("Invalid ViewDimension");
527    }
528 
529    return rtv_desc;
530 }
531 
532 D3D12_RESOURCE_STATES
dzn_image_layout_to_state(const struct dzn_image * image,VkImageLayout layout,VkImageAspectFlagBits aspect)533 dzn_image_layout_to_state(const struct dzn_image *image,
534                           VkImageLayout layout,
535                           VkImageAspectFlagBits aspect)
536 {
537    /* Handle VK_IMAGE_LAYOUT_SUBPASS_SELF_DEPENDENCY_MESA separately to
538     * silence -Wswitch warnings (VK_IMAGE_LAYOUT_SUBPASS_SELF_DEPENDENCY_MESA is
539     * not part of the official VkImageLayout enum, it's a define in
540     * vk_render_pass.h)
541     */
542    if (layout == VK_IMAGE_LAYOUT_SUBPASS_SELF_DEPENDENCY_MESA)
543       return D3D12_RESOURCE_STATE_COMMON;
544 
545    D3D12_RESOURCE_STATES shaders_access =
546       (image->desc.Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE) ?
547       0 : D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
548 
549    switch (layout) {
550    case VK_IMAGE_LAYOUT_PREINITIALIZED:
551    case VK_IMAGE_LAYOUT_UNDEFINED:
552    case VK_IMAGE_LAYOUT_GENERAL:
553       /* YOLO! */
554    case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
555       return D3D12_RESOURCE_STATE_COMMON;
556 
557    case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
558       return D3D12_RESOURCE_STATE_COPY_DEST;
559 
560    case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
561       return D3D12_RESOURCE_STATE_COPY_SOURCE;
562 
563    case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
564       return D3D12_RESOURCE_STATE_RENDER_TARGET;
565 
566    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
567    case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
568    case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
569       return D3D12_RESOURCE_STATE_DEPTH_WRITE;
570 
571    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
572    case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
573       return D3D12_RESOURCE_STATE_DEPTH_READ | shaders_access;
574 
575    case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
576       return aspect == VK_IMAGE_ASPECT_STENCIL_BIT ?
577              D3D12_RESOURCE_STATE_DEPTH_WRITE :
578              (D3D12_RESOURCE_STATE_DEPTH_READ | shaders_access);
579 
580    case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
581       return aspect == VK_IMAGE_ASPECT_STENCIL_BIT ?
582              (D3D12_RESOURCE_STATE_DEPTH_READ | shaders_access) :
583              D3D12_RESOURCE_STATE_DEPTH_WRITE;
584 
585    case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
586       return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
587 
588    default:
589       unreachable("not implemented");
590    }
591 }
592 
593 bool
dzn_image_formats_are_compatible(const struct dzn_device * device,VkFormat orig_fmt,VkFormat new_fmt,VkImageUsageFlags usage,VkImageAspectFlagBits aspect)594 dzn_image_formats_are_compatible(const struct dzn_device *device,
595                                  VkFormat orig_fmt, VkFormat new_fmt,
596                                  VkImageUsageFlags usage,
597                                  VkImageAspectFlagBits aspect)
598 {
599    const struct dzn_physical_device *pdev =
600       container_of(device->vk.physical, struct dzn_physical_device, vk);
601    DXGI_FORMAT orig_dxgi = dzn_image_get_dxgi_format(orig_fmt, usage, aspect);
602    DXGI_FORMAT new_dxgi = dzn_image_get_dxgi_format(new_fmt, usage, aspect);
603 
604    if (orig_dxgi == new_dxgi)
605       return true;
606 
607    DXGI_FORMAT typeless_orig = dzn_get_typeless_dxgi_format(orig_dxgi);
608    DXGI_FORMAT typeless_new = dzn_get_typeless_dxgi_format(new_dxgi);
609 
610    if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT))
611       return typeless_orig == typeless_new;
612 
613    if (pdev->options3.CastingFullyTypedFormatSupported) {
614       enum pipe_format orig_pfmt = vk_format_to_pipe_format(orig_fmt);
615       enum pipe_format new_pfmt = vk_format_to_pipe_format(new_fmt);
616 
617       /* Types don't belong to the same group, they're incompatible. */
618       if (typeless_orig != typeless_new)
619          return false;
620 
621       /* FLOAT <-> non-FLOAT casting is disallowed. */
622       if (util_format_is_float(orig_pfmt) != util_format_is_float(new_pfmt))
623          return false;
624 
625       /* UNORM <-> SNORM casting is disallowed. */
626       bool orig_is_norm =
627          util_format_is_unorm(orig_pfmt) || util_format_is_snorm(orig_pfmt);
628       bool new_is_norm =
629          util_format_is_unorm(new_pfmt) || util_format_is_snorm(new_pfmt);
630       if (orig_is_norm && new_is_norm &&
631           util_format_is_unorm(orig_pfmt) != util_format_is_unorm(new_pfmt))
632          return false;
633 
634       return true;
635    }
636 
637    return false;
638 }
639 
640 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateImage(VkDevice device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)641 dzn_CreateImage(VkDevice device,
642                 const VkImageCreateInfo *pCreateInfo,
643                 const VkAllocationCallbacks *pAllocator,
644                 VkImage *pImage)
645 {
646    return dzn_image_create(dzn_device_from_handle(device),
647                            pCreateInfo, pAllocator, pImage);
648 }
649 
650 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyImage(VkDevice device,VkImage image,const VkAllocationCallbacks * pAllocator)651 dzn_DestroyImage(VkDevice device, VkImage image,
652                  const VkAllocationCallbacks *pAllocator)
653 {
654    dzn_image_destroy(dzn_image_from_handle(image), pAllocator);
655 }
656 
657 static struct dzn_image *
dzn_swapchain_get_image(struct dzn_device * device,VkSwapchainKHR swapchain,uint32_t index)658 dzn_swapchain_get_image(struct dzn_device *device,
659                         VkSwapchainKHR swapchain,
660                         uint32_t index)
661 {
662    uint32_t n_images = index + 1;
663    STACK_ARRAY(VkImage, images, n_images);
664    struct dzn_image *image = NULL;
665 
666    VkResult result = wsi_common_get_images(swapchain, &n_images, images);
667 
668    if (result == VK_SUCCESS || result == VK_INCOMPLETE)
669       image = dzn_image_from_handle(images[index]);
670 
671    STACK_ARRAY_FINISH(images);
672    return image;
673 }
674 
675 VKAPI_ATTR VkResult VKAPI_CALL
dzn_BindImageMemory2(VkDevice dev,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)676 dzn_BindImageMemory2(VkDevice dev,
677                      uint32_t bindInfoCount,
678                      const VkBindImageMemoryInfo *pBindInfos)
679 {
680    VK_FROM_HANDLE(dzn_device, device, dev);
681 
682    for (uint32_t i = 0; i < bindInfoCount; i++) {
683       const VkBindImageMemoryInfo *bind_info = &pBindInfos[i];
684       VK_FROM_HANDLE(dzn_device_memory, mem, bind_info->memory);
685       VK_FROM_HANDLE(dzn_image, image, bind_info->image);
686       bool did_bind = false;
687 
688       vk_foreach_struct_const(s, bind_info->pNext) {
689          switch (s->sType) {
690          case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: {
691             const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
692                (const VkBindImageMemorySwapchainInfoKHR *) s;
693             ASSERTED struct dzn_image *swapchain_image =
694                dzn_swapchain_get_image(device,
695                                        swapchain_info->swapchain,
696                                        swapchain_info->imageIndex);
697             assert(swapchain_image);
698             assert(image->vk.aspects == swapchain_image->vk.aspects);
699             assert(mem == NULL);
700 
701             /* TODO: something something binding the image memory */
702             assert(false);
703 
704             did_bind = true;
705             break;
706          }
707          default:
708             dzn_debug_ignored_stype(s->sType);
709             break;
710          }
711       }
712 
713       if (!did_bind) {
714          image->mem = mem;
715          image->mem_offset = bind_info->memoryOffset;
716          if (FAILED(ID3D12Device1_CreatePlacedResource(device->dev, mem->heap,
717                                                       bind_info->memoryOffset,
718                                                       &image->desc,
719                                                       mem->initial_state,
720                                                       NULL,
721                                                       &IID_ID3D12Resource,
722                                                       (void **)&image->res)))
723             return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
724          did_bind = true;
725       }
726    }
727 
728    return VK_SUCCESS;
729 }
730 
731 VKAPI_ATTR void VKAPI_CALL
dzn_GetImageMemoryRequirements2(VkDevice _device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)732 dzn_GetImageMemoryRequirements2(VkDevice _device,
733                                 const VkImageMemoryRequirementsInfo2 *pInfo,
734                                 VkMemoryRequirements2 *pMemoryRequirements)
735 {
736    VK_FROM_HANDLE(dzn_device, device, _device);
737    VK_FROM_HANDLE(dzn_image, image, pInfo->image);
738    struct dzn_physical_device *pdev =
739       container_of(device->vk.physical, struct dzn_physical_device, vk);
740 
741    vk_foreach_struct_const(ext, pInfo->pNext) {
742       dzn_debug_ignored_stype(ext->sType);
743    }
744 
745    vk_foreach_struct(ext, pMemoryRequirements->pNext) {
746       switch (ext->sType) {
747       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
748          VkMemoryDedicatedRequirements *requirements =
749             (VkMemoryDedicatedRequirements *)ext;
750          /* TODO: figure out dedicated allocations */
751          requirements->prefersDedicatedAllocation = false;
752          requirements->requiresDedicatedAllocation = false;
753          break;
754       }
755 
756       default:
757          dzn_debug_ignored_stype(ext->sType);
758          break;
759       }
760    }
761 
762    D3D12_RESOURCE_ALLOCATION_INFO info = dzn_ID3D12Device2_GetResourceAllocationInfo(device->dev, 0, 1, &image->desc);
763 
764    pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
765       .size = info.SizeInBytes,
766       .alignment = info.Alignment,
767       .memoryTypeBits =
768          dzn_physical_device_get_mem_type_mask_for_resource(pdev, &image->desc),
769    };
770 
771    /*
772     * MSAA images need memory to be aligned on
773     * D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT (4MB), but the memory
774     * allocation function doesn't know what the memory will be used for,
775     * and forcing all allocations to be 4MB-aligned has a cost, so let's
776     * force MSAA resources to be at least 4MB, such that the allocation
777     * logic can consider sub-4MB allocations to not require this 4MB alignment.
778     */
779    if (image->vk.samples > 1 &&
780        pMemoryRequirements->memoryRequirements.size < D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT)
781       pMemoryRequirements->memoryRequirements.size = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT;
782 }
783 
784 VKAPI_ATTR void VKAPI_CALL
dzn_GetImageSubresourceLayout(VkDevice _device,VkImage _image,const VkImageSubresource * subresource,VkSubresourceLayout * layout)785 dzn_GetImageSubresourceLayout(VkDevice _device,
786                               VkImage _image,
787                               const VkImageSubresource *subresource,
788                               VkSubresourceLayout *layout)
789 {
790    VK_FROM_HANDLE(dzn_device, device, _device);
791    VK_FROM_HANDLE(dzn_image, image, _image);
792 
793    if (image->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) {
794       assert(subresource->arrayLayer == 0);
795       assert(subresource->mipLevel == 0);
796       layout->offset = 0;
797       layout->rowPitch = image->linear.row_stride;
798       layout->depthPitch = 0;
799       layout->arrayPitch = 0;
800       layout->size = image->linear.size;
801    } else {
802       UINT subres_index =
803          dzn_image_get_subresource_index(image, subresource,
804                                          (VkImageAspectFlagBits)subresource->aspectMask);
805       D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
806       UINT num_rows;
807       UINT64 row_size, total_size;
808       ID3D12Device1_GetCopyableFootprints(device->dev, &image->desc,
809                                          subres_index, 1,
810                                          0, // base-offset?
811                                          &footprint,
812                                          &num_rows, &row_size,
813                                          &total_size);
814 
815       layout->offset = footprint.Offset;
816       layout->rowPitch = footprint.Footprint.RowPitch;
817       layout->depthPitch = layout->rowPitch * footprint.Footprint.Height;
818       layout->arrayPitch = layout->depthPitch; // uuuh... why is this even here?
819       layout->size = total_size;
820    }
821 }
822 
823 static D3D12_SHADER_COMPONENT_MAPPING
translate_swizzle(VkComponentSwizzle in,uint32_t comp)824 translate_swizzle(VkComponentSwizzle in, uint32_t comp)
825 {
826    switch (in) {
827    case VK_COMPONENT_SWIZZLE_IDENTITY:
828       return (D3D12_SHADER_COMPONENT_MAPPING)
829              (comp + D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0);
830    case VK_COMPONENT_SWIZZLE_ZERO:
831       return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0;
832    case VK_COMPONENT_SWIZZLE_ONE:
833       return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1;
834    case VK_COMPONENT_SWIZZLE_R:
835       return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0;
836    case VK_COMPONENT_SWIZZLE_G:
837       return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1;
838    case VK_COMPONENT_SWIZZLE_B:
839       return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2;
840    case VK_COMPONENT_SWIZZLE_A:
841       return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3;
842    default: unreachable("Invalid swizzle");
843    }
844 }
845 
846 static void
dzn_image_view_prepare_srv_desc(struct dzn_image_view * iview)847 dzn_image_view_prepare_srv_desc(struct dzn_image_view *iview)
848 {
849    uint32_t plane_slice = (iview->vk.aspects & VK_IMAGE_ASPECT_STENCIL_BIT) ? 1 : 0;
850    bool ms = iview->vk.image->samples > 1;
851    uint32_t layers_per_elem =
852       (iview->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE ||
853        iview->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
854       6 : 1;
855    bool use_array = (iview->vk.base_array_layer / layers_per_elem) > 0 ||
856                     (iview->vk.layer_count / layers_per_elem) > 1;
857 
858    iview->srv_desc = (D3D12_SHADER_RESOURCE_VIEW_DESC) {
859       .Format =
860          dzn_image_get_dxgi_format(iview->vk.format,
861                                    iview->vk.image->usage & ~VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
862                                    iview->vk.aspects),
863    };
864 
865    D3D12_SHADER_COMPONENT_MAPPING swz[] = {
866       translate_swizzle(iview->vk.swizzle.r, 0),
867       translate_swizzle(iview->vk.swizzle.g, 1),
868       translate_swizzle(iview->vk.swizzle.b, 2),
869       translate_swizzle(iview->vk.swizzle.a, 3),
870    };
871 
872    /* Swap components to fake B4G4R4A4 support. */
873    if (iview->vk.format == VK_FORMAT_B4G4R4A4_UNORM_PACK16) {
874       static const D3D12_SHADER_COMPONENT_MAPPING bgra4_remap[] = {
875          D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
876          D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
877          D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3,
878          D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2,
879          D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
880          D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1,
881       };
882 
883       for (uint32_t i = 0; i < ARRAY_SIZE(swz); i++)
884          swz[i] = bgra4_remap[swz[i]];
885    }
886 
887    iview->srv_desc.Shader4ComponentMapping =
888       D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(swz[0], swz[1], swz[2], swz[3]);
889 
890    switch (iview->vk.view_type) {
891    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
892    case VK_IMAGE_VIEW_TYPE_1D:
893       if (use_array) {
894          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
895          iview->srv_desc.Texture1DArray.MostDetailedMip = iview->vk.base_mip_level;
896          iview->srv_desc.Texture1DArray.MipLevels = iview->vk.level_count;
897          iview->srv_desc.Texture1DArray.FirstArraySlice = iview->vk.base_array_layer;
898          iview->srv_desc.Texture1DArray.ArraySize = iview->vk.layer_count;
899       } else {
900          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
901          iview->srv_desc.Texture1D.MostDetailedMip = iview->vk.base_mip_level;
902          iview->srv_desc.Texture1D.MipLevels = iview->vk.level_count;
903       }
904       break;
905 
906    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
907    case VK_IMAGE_VIEW_TYPE_2D:
908       if (use_array && ms) {
909          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;
910          iview->srv_desc.Texture2DMSArray.FirstArraySlice = iview->vk.base_array_layer;
911          iview->srv_desc.Texture2DMSArray.ArraySize = iview->vk.layer_count;
912       } else if (use_array && !ms) {
913          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
914          iview->srv_desc.Texture2DArray.MostDetailedMip = iview->vk.base_mip_level;
915          iview->srv_desc.Texture2DArray.MipLevels = iview->vk.level_count;
916          iview->srv_desc.Texture2DArray.FirstArraySlice = iview->vk.base_array_layer;
917          iview->srv_desc.Texture2DArray.ArraySize = iview->vk.layer_count;
918          iview->srv_desc.Texture2DArray.PlaneSlice = plane_slice;
919       } else if (!use_array && ms) {
920          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;
921       } else {
922          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
923          iview->srv_desc.Texture2D.MostDetailedMip = iview->vk.base_mip_level;
924          iview->srv_desc.Texture2D.MipLevels = iview->vk.level_count;
925          iview->srv_desc.Texture2D.PlaneSlice = plane_slice;
926       }
927       break;
928 
929    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
930    case VK_IMAGE_VIEW_TYPE_CUBE:
931       if (use_array) {
932          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
933          iview->srv_desc.TextureCubeArray.MostDetailedMip = iview->vk.base_mip_level;
934          iview->srv_desc.TextureCubeArray.MipLevels = iview->vk.level_count;
935          iview->srv_desc.TextureCubeArray.First2DArrayFace = iview->vk.base_array_layer;
936          iview->srv_desc.TextureCubeArray.NumCubes = iview->vk.layer_count / 6;
937       } else {
938          iview->srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
939          iview->srv_desc.TextureCube.MostDetailedMip = iview->vk.base_mip_level;
940          iview->srv_desc.TextureCube.MipLevels = iview->vk.level_count;
941       }
942       break;
943 
944    case VK_IMAGE_VIEW_TYPE_3D:
945       iview->srv_desc.ViewDimension =  D3D12_SRV_DIMENSION_TEXTURE3D;
946       iview->srv_desc.Texture3D.MostDetailedMip = iview->vk.base_mip_level;
947       iview->srv_desc.Texture3D.MipLevels = iview->vk.level_count;
948       break;
949 
950    default: unreachable("Invalid view type");
951    }
952 }
953 
954 static void
dzn_image_view_prepare_uav_desc(struct dzn_image_view * iview)955 dzn_image_view_prepare_uav_desc(struct dzn_image_view *iview)
956 {
957    bool use_array = iview->vk.base_array_layer > 0 || iview->vk.layer_count > 1;
958 
959    assert(iview->vk.image->samples == 1);
960 
961    iview->uav_desc = (D3D12_UNORDERED_ACCESS_VIEW_DESC) {
962       .Format =
963          dzn_image_get_dxgi_format(iview->vk.format,
964                                    VK_IMAGE_USAGE_STORAGE_BIT,
965                                    iview->vk.aspects),
966    };
967 
968    switch (iview->vk.view_type) {
969    case VK_IMAGE_VIEW_TYPE_1D:
970    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
971       if (use_array) {
972          iview->uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY;
973          iview->uav_desc.Texture1DArray.MipSlice = iview->vk.base_mip_level;
974          iview->uav_desc.Texture1DArray.FirstArraySlice = iview->vk.base_array_layer;
975          iview->uav_desc.Texture1DArray.ArraySize = iview->vk.layer_count;
976       } else {
977          iview->uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D;
978          iview->uav_desc.Texture1D.MipSlice = iview->vk.base_mip_level;
979       }
980       break;
981 
982    case VK_IMAGE_VIEW_TYPE_2D:
983    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
984    case VK_IMAGE_VIEW_TYPE_CUBE:
985    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
986       if (use_array) {
987          iview->uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
988          iview->uav_desc.Texture2DArray.PlaneSlice = 0;
989          iview->uav_desc.Texture2DArray.MipSlice = iview->vk.base_mip_level;
990          iview->uav_desc.Texture2DArray.FirstArraySlice = iview->vk.base_array_layer;
991          iview->uav_desc.Texture2DArray.ArraySize = iview->vk.layer_count;
992       } else {
993          iview->uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
994          iview->uav_desc.Texture2D.MipSlice = iview->vk.base_mip_level;
995          iview->uav_desc.Texture2D.PlaneSlice = 0;
996       }
997       break;
998    case VK_IMAGE_VIEW_TYPE_3D:
999       iview->uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
1000       iview->uav_desc.Texture3D.MipSlice = iview->vk.base_mip_level;
1001       iview->uav_desc.Texture3D.FirstWSlice = 0;
1002       iview->uav_desc.Texture3D.WSize = iview->vk.extent.depth;
1003       break;
1004    default: unreachable("Invalid type");
1005    }
1006 }
1007 
1008 static void
dzn_image_view_prepare_rtv_desc(struct dzn_image_view * iview)1009 dzn_image_view_prepare_rtv_desc(struct dzn_image_view *iview)
1010 {
1011    bool use_array = iview->vk.base_array_layer > 0 || iview->vk.layer_count > 1;
1012    bool from_3d_image = iview->vk.image->image_type == VK_IMAGE_TYPE_3D;
1013    bool ms = iview->vk.image->samples > 1;
1014    uint32_t plane_slice =
1015       (iview->vk.aspects & VK_IMAGE_ASPECT_PLANE_2_BIT) ? 2 :
1016       (iview->vk.aspects & VK_IMAGE_ASPECT_PLANE_1_BIT) ? 1 : 0;
1017 
1018    assert(iview->vk.level_count == 1);
1019 
1020    iview->rtv_desc = (D3D12_RENDER_TARGET_VIEW_DESC) {
1021       .Format =
1022          dzn_image_get_dxgi_format(iview->vk.format,
1023                                    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
1024                                    iview->vk.aspects),
1025    };
1026 
1027    switch (iview->vk.view_type) {
1028    case VK_IMAGE_VIEW_TYPE_1D:
1029    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1030       if (use_array) {
1031          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE1DARRAY;
1032          iview->rtv_desc.Texture1DArray.MipSlice = iview->vk.base_mip_level;
1033          iview->rtv_desc.Texture1DArray.FirstArraySlice = iview->vk.base_array_layer;
1034          iview->rtv_desc.Texture1DArray.ArraySize = iview->vk.layer_count;
1035       } else {
1036          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE1D;
1037          iview->rtv_desc.Texture1D.MipSlice = iview->vk.base_mip_level;
1038       }
1039       break;
1040 
1041    case VK_IMAGE_VIEW_TYPE_2D:
1042    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1043    case VK_IMAGE_VIEW_TYPE_CUBE:
1044    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1045       if (from_3d_image) {
1046          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
1047          iview->rtv_desc.Texture3D.MipSlice = iview->vk.base_mip_level;
1048          iview->rtv_desc.Texture3D.FirstWSlice = iview->vk.base_array_layer;
1049          iview->rtv_desc.Texture3D.WSize = iview->vk.layer_count;
1050       } else if (use_array && ms) {
1051          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
1052          iview->rtv_desc.Texture2DMSArray.FirstArraySlice = iview->vk.base_array_layer;
1053          iview->rtv_desc.Texture2DMSArray.ArraySize = iview->vk.layer_count;
1054       } else if (use_array && !ms) {
1055          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
1056          iview->rtv_desc.Texture2DArray.MipSlice = iview->vk.base_mip_level;
1057          iview->rtv_desc.Texture2DArray.FirstArraySlice = iview->vk.base_array_layer;
1058          iview->rtv_desc.Texture2DArray.ArraySize = iview->vk.layer_count;
1059          iview->rtv_desc.Texture2DArray.PlaneSlice = plane_slice;
1060       } else if (!use_array && ms) {
1061          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
1062       } else {
1063          iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
1064          iview->rtv_desc.Texture2D.MipSlice = iview->vk.base_mip_level;
1065          iview->rtv_desc.Texture2D.PlaneSlice = plane_slice;
1066       }
1067       break;
1068 
1069    case VK_IMAGE_VIEW_TYPE_3D:
1070       iview->rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
1071       iview->rtv_desc.Texture3D.MipSlice = iview->vk.base_mip_level;
1072       iview->rtv_desc.Texture3D.FirstWSlice = 0;
1073       iview->rtv_desc.Texture3D.WSize = iview->vk.extent.depth;
1074       break;
1075 
1076    default: unreachable("Invalid view type");
1077    }
1078 }
1079 
1080 static void
dzn_image_view_prepare_dsv_desc(struct dzn_image_view * iview)1081 dzn_image_view_prepare_dsv_desc(struct dzn_image_view *iview)
1082 {
1083    bool use_array = iview->vk.base_array_layer > 0 || iview->vk.layer_count > 1;
1084    bool ms = iview->vk.image->samples > 1;
1085 
1086    iview->dsv_desc = (D3D12_DEPTH_STENCIL_VIEW_DESC) {
1087       .Format =
1088          dzn_image_get_dxgi_format(iview->vk.format,
1089                                    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
1090                                    iview->vk.aspects),
1091    };
1092 
1093    switch (iview->vk.view_type) {
1094    case VK_IMAGE_VIEW_TYPE_1D:
1095    case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1096       if (use_array) {
1097          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE1DARRAY;
1098          iview->dsv_desc.Texture1DArray.MipSlice = iview->vk.base_mip_level;
1099          iview->dsv_desc.Texture1DArray.FirstArraySlice = iview->vk.base_array_layer;
1100          iview->dsv_desc.Texture1DArray.ArraySize = iview->vk.layer_count;
1101       } else {
1102          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE1D;
1103          iview->dsv_desc.Texture1D.MipSlice = iview->vk.base_mip_level;
1104       }
1105       break;
1106 
1107    case VK_IMAGE_VIEW_TYPE_2D:
1108    case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1109    case VK_IMAGE_VIEW_TYPE_CUBE:
1110    case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1111       if (use_array && ms) {
1112          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY;
1113          iview->dsv_desc.Texture2DMSArray.FirstArraySlice = iview->vk.base_array_layer;
1114          iview->dsv_desc.Texture2DMSArray.ArraySize = iview->vk.layer_count;
1115       } else if (use_array && !ms) {
1116          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
1117          iview->dsv_desc.Texture2DArray.MipSlice = iview->vk.base_mip_level;
1118          iview->dsv_desc.Texture2DArray.FirstArraySlice = iview->vk.base_array_layer;
1119          iview->dsv_desc.Texture2DArray.ArraySize = iview->vk.layer_count;
1120       } else if (!use_array && ms) {
1121          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMS;
1122       } else {
1123          iview->dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
1124          iview->dsv_desc.Texture2D.MipSlice = iview->vk.base_mip_level;
1125       }
1126       break;
1127 
1128    default: unreachable("Invalid view type");
1129    }
1130 }
1131 
1132 void
dzn_image_view_finish(struct dzn_image_view * iview)1133 dzn_image_view_finish(struct dzn_image_view *iview)
1134 {
1135    vk_image_view_finish(&iview->vk);
1136 }
1137 
1138 void
dzn_image_view_init(struct dzn_device * device,struct dzn_image_view * iview,const VkImageViewCreateInfo * pCreateInfo)1139 dzn_image_view_init(struct dzn_device *device,
1140                     struct dzn_image_view *iview,
1141                     const VkImageViewCreateInfo *pCreateInfo)
1142 {
1143    VK_FROM_HANDLE(dzn_image, image, pCreateInfo->image);
1144 
1145    const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
1146    ASSERTED uint32_t layer_count = dzn_get_layer_count(image, range);
1147 
1148    vk_image_view_init(&device->vk, &iview->vk, false, pCreateInfo);
1149 
1150    assert(layer_count > 0);
1151    assert(range->baseMipLevel < image->vk.mip_levels);
1152 
1153    /* View usage should be a subset of image usage */
1154    assert(iview->vk.usage & (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1155                              VK_IMAGE_USAGE_SAMPLED_BIT |
1156                              VK_IMAGE_USAGE_STORAGE_BIT |
1157                              VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1158                              VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
1159                              VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
1160 
1161    switch (image->vk.image_type) {
1162    default:
1163       unreachable("bad VkImageType");
1164    case VK_IMAGE_TYPE_1D:
1165    case VK_IMAGE_TYPE_2D:
1166       assert(range->baseArrayLayer + dzn_get_layer_count(image, range) - 1 <= image->vk.array_layers);
1167       break;
1168    case VK_IMAGE_TYPE_3D:
1169       assert(range->baseArrayLayer + dzn_get_layer_count(image, range) - 1
1170              <= u_minify(image->vk.extent.depth, range->baseMipLevel));
1171       break;
1172    }
1173 
1174    dzn_image_view_prepare_srv_desc(iview);
1175 
1176    if (iview->vk.usage & VK_IMAGE_USAGE_STORAGE_BIT)
1177       dzn_image_view_prepare_uav_desc(iview);
1178 
1179    if (iview->vk.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
1180       dzn_image_view_prepare_rtv_desc(iview);
1181 
1182    if (iview->vk.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
1183       dzn_image_view_prepare_dsv_desc(iview);
1184 }
1185 
1186 static void
dzn_image_view_destroy(struct dzn_image_view * iview,const VkAllocationCallbacks * pAllocator)1187 dzn_image_view_destroy(struct dzn_image_view *iview,
1188                       const VkAllocationCallbacks *pAllocator)
1189 {
1190    if (!iview)
1191       return;
1192 
1193    struct dzn_device *device = container_of(iview->vk.base.device, struct dzn_device, vk);
1194 
1195    vk_image_view_finish(&iview->vk);
1196    vk_free2(&device->vk.alloc, pAllocator, iview);
1197 }
1198 
1199 static VkResult
dzn_image_view_create(struct dzn_device * device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * out)1200 dzn_image_view_create(struct dzn_device *device,
1201                       const VkImageViewCreateInfo *pCreateInfo,
1202                       const VkAllocationCallbacks *pAllocator,
1203                       VkImageView *out)
1204 {
1205    struct dzn_image_view *iview =
1206       vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*iview), 8,
1207                  VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1208    if (!iview)
1209       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1210 
1211    dzn_image_view_init(device, iview, pCreateInfo);
1212 
1213    *out = dzn_image_view_to_handle(iview);
1214    return VK_SUCCESS;
1215 }
1216 
1217 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateImageView(VkDevice device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)1218 dzn_CreateImageView(VkDevice device,
1219                     const VkImageViewCreateInfo *pCreateInfo,
1220                     const VkAllocationCallbacks *pAllocator,
1221                     VkImageView *pView)
1222 {
1223    return dzn_image_view_create(dzn_device_from_handle(device), pCreateInfo,
1224                                 pAllocator, pView);
1225 }
1226 
1227 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyImageView(VkDevice device,VkImageView imageView,const VkAllocationCallbacks * pAllocator)1228 dzn_DestroyImageView(VkDevice device,
1229                      VkImageView imageView,
1230                      const VkAllocationCallbacks *pAllocator)
1231 {
1232    dzn_image_view_destroy(dzn_image_view_from_handle(imageView), pAllocator);
1233 }
1234 
1235 static void
dzn_buffer_view_destroy(struct dzn_buffer_view * bview,const VkAllocationCallbacks * pAllocator)1236 dzn_buffer_view_destroy(struct dzn_buffer_view *bview,
1237                         const VkAllocationCallbacks *pAllocator)
1238 {
1239    if (!bview)
1240       return;
1241 
1242    struct dzn_device *device = container_of(bview->base.device, struct dzn_device, vk);
1243 
1244    vk_object_base_finish(&bview->base);
1245    vk_free2(&device->vk.alloc, pAllocator, bview);
1246 }
1247 
1248 static VkResult
dzn_buffer_view_create(struct dzn_device * device,const VkBufferViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBufferView * out)1249 dzn_buffer_view_create(struct dzn_device *device,
1250                        const VkBufferViewCreateInfo *pCreateInfo,
1251                        const VkAllocationCallbacks *pAllocator,
1252                        VkBufferView *out)
1253 {
1254    VK_FROM_HANDLE(dzn_buffer, buf, pCreateInfo->buffer);
1255 
1256    struct dzn_buffer_view *bview =
1257       vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*bview), 8,
1258                  VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1259    if (!bview)
1260       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1261 
1262    vk_object_base_init(&device->vk, &bview->base, VK_OBJECT_TYPE_BUFFER_VIEW);
1263 
1264    enum pipe_format pfmt = vk_format_to_pipe_format(pCreateInfo->format);
1265    unsigned blksz = util_format_get_blocksize(pfmt);
1266    VkDeviceSize size =
1267       pCreateInfo->range == VK_WHOLE_SIZE ?
1268       buf->size - pCreateInfo->offset : pCreateInfo->range;
1269 
1270    bview->buffer = buf;
1271    if (buf->usage &
1272        (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
1273         VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
1274       bview->srv_desc = (D3D12_SHADER_RESOURCE_VIEW_DESC) {
1275          .Format = dzn_buffer_get_dxgi_format(pCreateInfo->format),
1276          .ViewDimension = D3D12_SRV_DIMENSION_BUFFER,
1277          .Shader4ComponentMapping =
1278             D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
1279          .Buffer = {
1280             .FirstElement = pCreateInfo->offset / blksz,
1281             .NumElements = (UINT)(size / blksz),
1282             .Flags = D3D12_BUFFER_SRV_FLAG_NONE,
1283          },
1284       };
1285    }
1286 
1287    if (buf->usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) {
1288       bview->uav_desc = (D3D12_UNORDERED_ACCESS_VIEW_DESC) {
1289          .Format = dzn_buffer_get_dxgi_format(pCreateInfo->format),
1290          .ViewDimension = D3D12_UAV_DIMENSION_BUFFER,
1291          .Buffer = {
1292             .FirstElement = pCreateInfo->offset / blksz,
1293             .NumElements = (UINT)(size / blksz),
1294             .Flags = D3D12_BUFFER_UAV_FLAG_NONE,
1295          },
1296       };
1297    }
1298 
1299    *out = dzn_buffer_view_to_handle(bview);
1300    return VK_SUCCESS;
1301 }
1302 
1303 VKAPI_ATTR VkResult VKAPI_CALL
dzn_CreateBufferView(VkDevice device,const VkBufferViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBufferView * pView)1304 dzn_CreateBufferView(VkDevice device,
1305                      const VkBufferViewCreateInfo *pCreateInfo,
1306                      const VkAllocationCallbacks *pAllocator,
1307                      VkBufferView *pView)
1308 {
1309    return dzn_buffer_view_create(dzn_device_from_handle(device),
1310                                  pCreateInfo, pAllocator, pView);
1311 }
1312 
1313 VKAPI_ATTR void VKAPI_CALL
dzn_DestroyBufferView(VkDevice device,VkBufferView bufferView,const VkAllocationCallbacks * pAllocator)1314 dzn_DestroyBufferView(VkDevice device,
1315                       VkBufferView bufferView,
1316                       const VkAllocationCallbacks *pAllocator)
1317 {
1318    dzn_buffer_view_destroy(dzn_buffer_view_from_handle(bufferView), pAllocator);
1319 }
1320