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