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