| /* | |
| * Copyright 2016 Józef Kucia for CodeWeavers | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API | |
| #include "vkd3d_private.h" | |
| #include <errno.h> | |
| #define VKD3D_MAX_DXGI_FORMAT DXGI_FORMAT_A4B4G4R4_UNORM | |
| #define COLOR (VK_IMAGE_ASPECT_COLOR_BIT) | |
| #define DEPTH (VK_IMAGE_ASPECT_DEPTH_BIT) | |
| #define STENCIL (VK_IMAGE_ASPECT_STENCIL_BIT) | |
| #define DEPTH_STENCIL (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) | |
| #define PLANAR (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT) | |
| #define TYPELESS VKD3D_FORMAT_TYPE_TYPELESS | |
| #define SINT VKD3D_FORMAT_TYPE_SINT | |
| #define UINT VKD3D_FORMAT_TYPE_UINT | |
| static const struct vkd3d_format_footprint nv12_copy_footprints[] = | |
| { | |
| { DXGI_FORMAT_R8_TYPELESS, 1, 1, 1, 0, 0 }, | |
| { DXGI_FORMAT_R8G8_TYPELESS, 1, 1, 2, 1, 1 }, | |
| }; | |
| static const struct vkd3d_format_footprint p016_copy_footprints[] = | |
| { | |
| { DXGI_FORMAT_R16_TYPELESS, 1, 1, 2, 0, 0 }, | |
| { DXGI_FORMAT_R16G16_TYPELESS, 1, 1, 4, 1, 1 }, | |
| }; | |
| static const struct vkd3d_format vkd3d_formats[] = | |
| { | |
| {DXGI_FORMAT_R32G32B32A32_TYPELESS, VK_FORMAT_R32G32B32A32_SFLOAT, 16, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_R32G32B32A32_FLOAT, VK_FORMAT_R32G32B32A32_SFLOAT, 16, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R32G32B32A32_UINT, VK_FORMAT_R32G32B32A32_UINT, 16, 1, 1, 1, COLOR, 1, UINT}, | |
| {DXGI_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32G32B32A32_SINT, 16, 1, 1, 1, COLOR, 1, SINT}, | |
| {DXGI_FORMAT_R32G32B32_TYPELESS, VK_FORMAT_R32G32B32_SFLOAT, 12, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_R32G32B32_FLOAT, VK_FORMAT_R32G32B32_SFLOAT, 12, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R32G32B32_UINT, VK_FORMAT_R32G32B32_UINT, 12, 1, 1, 1, COLOR, 1, UINT}, | |
| {DXGI_FORMAT_R32G32B32_SINT, VK_FORMAT_R32G32B32_SINT, 12, 1, 1, 1, COLOR, 1, SINT}, | |
| {DXGI_FORMAT_R16G16B16A16_TYPELESS, VK_FORMAT_R16G16B16A16_SFLOAT, 8, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_R16G16B16A16_FLOAT, VK_FORMAT_R16G16B16A16_SFLOAT, 8, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_R16G16B16A16_UNORM, 8, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R16G16B16A16_UINT, VK_FORMAT_R16G16B16A16_UINT, 8, 1, 1, 1, COLOR, 1, UINT}, | |
| {DXGI_FORMAT_R16G16B16A16_SNORM, VK_FORMAT_R16G16B16A16_SNORM, 8, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R16G16B16A16_SINT, VK_FORMAT_R16G16B16A16_SINT, 8, 1, 1, 1, COLOR, 1, SINT}, | |
| {DXGI_FORMAT_R32G32_TYPELESS, VK_FORMAT_R32G32_SFLOAT, 8, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_R32G32_FLOAT, VK_FORMAT_R32G32_SFLOAT, 8, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R32G32_UINT, VK_FORMAT_R32G32_UINT, 8, 1, 1, 1, COLOR, 1, UINT}, | |
| {DXGI_FORMAT_R32G32_SINT, VK_FORMAT_R32G32_SINT, 8, 1, 1, 1, COLOR, 1, SINT}, | |
| {DXGI_FORMAT_R10G10B10A2_TYPELESS, VK_FORMAT_A2B10G10R10_UNORM_PACK32, 4, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_R10G10B10A2_UNORM, VK_FORMAT_A2B10G10R10_UNORM_PACK32, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R10G10B10A2_UINT, VK_FORMAT_A2B10G10R10_UINT_PACK32, 4, 1, 1, 1, COLOR, 1, UINT}, | |
| {DXGI_FORMAT_R11G11B10_FLOAT, VK_FORMAT_B10G11R11_UFLOAT_PACK32, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R8G8_TYPELESS, VK_FORMAT_R8G8_UNORM, 2, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8_UNORM, 2, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R8G8_UINT, VK_FORMAT_R8G8_UINT, 2, 1, 1, 1, COLOR, 1, UINT}, | |
| {DXGI_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8_SNORM, 2, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R8G8_SINT, VK_FORMAT_R8G8_SINT, 2, 1, 1, 1, COLOR, 1, SINT}, | |
| {DXGI_FORMAT_R8G8B8A8_TYPELESS, VK_FORMAT_R8G8B8A8_UNORM, 4, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, VK_FORMAT_R8G8B8A8_SRGB, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_UINT, 4, 1, 1, 1, COLOR, 1, UINT}, | |
| {DXGI_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_R8G8B8A8_SNORM, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R8G8B8A8_SINT, VK_FORMAT_R8G8B8A8_SINT, 4, 1, 1, 1, COLOR, 1, SINT}, | |
| {DXGI_FORMAT_R16G16_TYPELESS, VK_FORMAT_R16G16_SFLOAT, 4, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_R16G16_FLOAT, VK_FORMAT_R16G16_SFLOAT, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R16G16_UNORM, VK_FORMAT_R16G16_UNORM, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R16G16_UINT, VK_FORMAT_R16G16_UINT, 4, 1, 1, 1, COLOR, 1, UINT}, | |
| {DXGI_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16_SNORM, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R16G16_SINT, VK_FORMAT_R16G16_SINT, 4, 1, 1, 1, COLOR, 1, SINT}, | |
| {DXGI_FORMAT_R32_TYPELESS, VK_FORMAT_R32_UINT, 4, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_D32_FLOAT, VK_FORMAT_D32_SFLOAT, 4, 1, 1, 1, DEPTH, 1}, | |
| {DXGI_FORMAT_R32_FLOAT, VK_FORMAT_R32_SFLOAT, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R32_UINT, VK_FORMAT_R32_UINT, 4, 1, 1, 1, COLOR, 1, UINT}, | |
| {DXGI_FORMAT_R32_SINT, VK_FORMAT_R32_SINT, 4, 1, 1, 1, COLOR, 1, SINT}, | |
| {DXGI_FORMAT_R16_TYPELESS, VK_FORMAT_R16_UINT, 2, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_R16_FLOAT, VK_FORMAT_R16_SFLOAT, 2, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_D16_UNORM, VK_FORMAT_D16_UNORM, 2, 1, 1, 1, DEPTH, 1}, | |
| {DXGI_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, 2, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R16_UINT, VK_FORMAT_R16_UINT, 2, 1, 1, 1, COLOR, 1, UINT}, | |
| {DXGI_FORMAT_R16_SNORM, VK_FORMAT_R16_SNORM, 2, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R16_SINT, VK_FORMAT_R16_SINT, 2, 1, 1, 1, COLOR, 1, SINT}, | |
| {DXGI_FORMAT_R8_TYPELESS, VK_FORMAT_R8_UNORM, 1, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, 1, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R8_UINT, VK_FORMAT_R8_UINT, 1, 1, 1, 1, COLOR, 1, UINT}, | |
| {DXGI_FORMAT_R8_SNORM, VK_FORMAT_R8_SNORM, 1, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R8_SINT, VK_FORMAT_R8_SINT, 1, 1, 1, 1, COLOR, 1, SINT}, | |
| {DXGI_FORMAT_A8_UNORM, VK_FORMAT_A8_UNORM_KHR, 1, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_B8G8R8X8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_B8G8R8A8_TYPELESS, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, VK_FORMAT_B8G8R8A8_SRGB, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_B8G8R8X8_TYPELESS, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, VK_FORMAT_B8G8R8A8_SRGB, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_R9G9B9E5_SHAREDEXP, VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 4, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_B5G6R5_UNORM, VK_FORMAT_R5G6B5_UNORM_PACK16, 2, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_B5G5R5A1_UNORM, VK_FORMAT_A1R5G5B5_UNORM_PACK16, 2, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_BC1_TYPELESS, VK_FORMAT_BC1_RGBA_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_BC1_UNORM, VK_FORMAT_BC1_RGBA_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1}, | |
| {DXGI_FORMAT_BC1_UNORM_SRGB, VK_FORMAT_BC1_RGBA_SRGB_BLOCK, 1, 4, 4, 8, COLOR, 1}, | |
| {DXGI_FORMAT_BC2_TYPELESS, VK_FORMAT_BC2_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_BC2_UNORM, VK_FORMAT_BC2_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1}, | |
| {DXGI_FORMAT_BC2_UNORM_SRGB, VK_FORMAT_BC2_SRGB_BLOCK, 1, 4, 4, 16, COLOR, 1}, | |
| {DXGI_FORMAT_BC3_TYPELESS, VK_FORMAT_BC3_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_BC3_UNORM, VK_FORMAT_BC3_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1}, | |
| {DXGI_FORMAT_BC3_UNORM_SRGB, VK_FORMAT_BC3_SRGB_BLOCK, 1, 4, 4, 16, COLOR, 1}, | |
| {DXGI_FORMAT_BC4_TYPELESS, VK_FORMAT_BC4_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_BC4_UNORM, VK_FORMAT_BC4_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1}, | |
| {DXGI_FORMAT_BC4_SNORM, VK_FORMAT_BC4_SNORM_BLOCK, 1, 4, 4, 8, COLOR, 1}, | |
| {DXGI_FORMAT_BC5_TYPELESS, VK_FORMAT_BC5_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_BC5_UNORM, VK_FORMAT_BC5_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1}, | |
| {DXGI_FORMAT_BC5_SNORM, VK_FORMAT_BC5_SNORM_BLOCK, 1, 4, 4, 16, COLOR, 1}, | |
| {DXGI_FORMAT_BC6H_TYPELESS, VK_FORMAT_BC6H_UFLOAT_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_BC6H_UF16, VK_FORMAT_BC6H_UFLOAT_BLOCK, 1, 4, 4, 16, COLOR, 1}, | |
| {DXGI_FORMAT_BC6H_SF16, VK_FORMAT_BC6H_SFLOAT_BLOCK, 1, 4, 4, 16, COLOR, 1}, | |
| {DXGI_FORMAT_BC7_TYPELESS, VK_FORMAT_BC7_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS}, | |
| {DXGI_FORMAT_BC7_UNORM, VK_FORMAT_BC7_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1}, | |
| {DXGI_FORMAT_BC7_UNORM_SRGB, VK_FORMAT_BC7_SRGB_BLOCK, 1, 4, 4, 16, COLOR, 1}, | |
| {DXGI_FORMAT_B4G4R4A4_UNORM, VK_FORMAT_A4R4G4B4_UNORM_PACK16, 2, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_A4B4G4R4_UNORM, VK_FORMAT_R4G4B4A4_UNORM_PACK16, 2, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_NV12, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, 0, 1, 1, 1, PLANAR, 2, TYPELESS, false, nv12_copy_footprints}, | |
| /* P010 and P016 are functionally equivalent, there is no way to interpret data as R10X6 in D3D. */ | |
| {DXGI_FORMAT_P010, VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, 0, 1, 1, 1, PLANAR, 2, TYPELESS, false, p016_copy_footprints}, | |
| {DXGI_FORMAT_P016, VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, 0, 1, 1, 1, PLANAR, 2, TYPELESS, false, p016_copy_footprints}, | |
| {DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE, VK_FORMAT_R32G32_UINT, 8, 1, 1, 1, COLOR, 1}, | |
| {DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE, VK_FORMAT_R32G32_UINT, 8, 1, 1, 1, COLOR, 1}, | |
| }; | |
| static const struct vkd3d_format_footprint depth_stencil_copy_footprints[] = | |
| { | |
| { DXGI_FORMAT_R32_TYPELESS, 1, 1, 4, 0, 0 }, | |
| { DXGI_FORMAT_R8_TYPELESS, 1, 1, 1, 0, 0 }, | |
| }; | |
| /* Each depth/stencil format is only compatible with itself in Vulkan. */ | |
| static const struct vkd3d_format vkd3d_depth_stencil_formats[] = | |
| { | |
| {DXGI_FORMAT_R32G8X24_TYPELESS, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, DEPTH_STENCIL, 2, TYPELESS, false, depth_stencil_copy_footprints}, | |
| {DXGI_FORMAT_D32_FLOAT_S8X24_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, DEPTH_STENCIL, 2, 0, false, depth_stencil_copy_footprints}, | |
| {DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, DEPTH, 2}, | |
| {DXGI_FORMAT_X32_TYPELESS_G8X24_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, STENCIL, 2}, | |
| {DXGI_FORMAT_R32_TYPELESS, VK_FORMAT_D32_SFLOAT, 4, 1, 1, 1, DEPTH, 1, TYPELESS}, | |
| {DXGI_FORMAT_R32_FLOAT, VK_FORMAT_D32_SFLOAT, 4, 1, 1, 1, DEPTH, 1}, | |
| {DXGI_FORMAT_R24G8_TYPELESS, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, DEPTH_STENCIL, 2, TYPELESS, false, depth_stencil_copy_footprints}, | |
| {DXGI_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, DEPTH_STENCIL, 2, 0, false, depth_stencil_copy_footprints}, | |
| {DXGI_FORMAT_R24_UNORM_X8_TYPELESS, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, DEPTH, 2}, | |
| {DXGI_FORMAT_X24_TYPELESS_G8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, STENCIL, 2}, | |
| {DXGI_FORMAT_R16_TYPELESS, VK_FORMAT_D16_UNORM, 2, 1, 1, 1, DEPTH, 1, TYPELESS}, | |
| {DXGI_FORMAT_R16_UNORM, VK_FORMAT_D16_UNORM, 2, 1, 1, 1, DEPTH, 1}, | |
| }; | |
| #undef COLOR | |
| #undef DEPTH | |
| #undef STENCIL | |
| #undef DEPTH_STENCIL | |
| #undef TYPELESS | |
| #undef SINT | |
| #undef UINT | |
| static const struct dxgi_format_compatibility_list | |
| { | |
| DXGI_FORMAT image_format; | |
| DXGI_FORMAT view_formats[VKD3D_MAX_COMPATIBLE_FORMAT_COUNT]; | |
| DXGI_FORMAT uint_format; /* for ClearUAVUint */ | |
| DXGI_FORMAT typeless_format; | |
| } | |
| dxgi_format_compatibility_list[] = | |
| { | |
| {DXGI_FORMAT_R32G32B32A32_TYPELESS, | |
| {DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_SINT}, | |
| DXGI_FORMAT_R32G32B32A32_UINT, | |
| DXGI_FORMAT_R32G32B32A32_TYPELESS}, | |
| {DXGI_FORMAT_R32G32B32A32_FLOAT, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_R32G32B32A32_UINT, | |
| DXGI_FORMAT_R32G32B32A32_TYPELESS}, | |
| {DXGI_FORMAT_R32G32B32A32_UINT, | |
| {DXGI_FORMAT_R32G32B32A32_SINT}, | |
| DXGI_FORMAT_R32G32B32A32_UINT, | |
| DXGI_FORMAT_R32G32B32A32_TYPELESS}, | |
| {DXGI_FORMAT_R32G32B32A32_SINT, | |
| {DXGI_FORMAT_R32G32B32A32_UINT}, | |
| DXGI_FORMAT_R32G32B32A32_UINT, | |
| DXGI_FORMAT_R32G32B32A32_TYPELESS}, | |
| {DXGI_FORMAT_R32G32B32_TYPELESS, | |
| {DXGI_FORMAT_R32G32B32_FLOAT, DXGI_FORMAT_R32G32B32_UINT, DXGI_FORMAT_R32G32B32_SINT}, | |
| DXGI_FORMAT_R32G32B32_UINT, | |
| DXGI_FORMAT_R32G32B32_TYPELESS}, | |
| {DXGI_FORMAT_R32G32B32_FLOAT, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_R32G32B32_UINT, | |
| DXGI_FORMAT_R32G32B32_TYPELESS}, | |
| {DXGI_FORMAT_R32G32B32_UINT, | |
| {DXGI_FORMAT_R32G32B32_SINT}, | |
| DXGI_FORMAT_R32G32B32_UINT, | |
| DXGI_FORMAT_R32G32B32_TYPELESS}, | |
| {DXGI_FORMAT_R32G32B32_SINT, | |
| {DXGI_FORMAT_R32G32B32_UINT}, | |
| DXGI_FORMAT_R32G32B32_UINT, | |
| DXGI_FORMAT_R32G32B32_TYPELESS}, | |
| {DXGI_FORMAT_R16G16B16A16_TYPELESS, | |
| {DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_SINT}, | |
| DXGI_FORMAT_R16G16B16A16_UINT, | |
| DXGI_FORMAT_R16G16B16A16_TYPELESS}, | |
| {DXGI_FORMAT_R16G16B16A16_FLOAT, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_R16G16B16A16_UINT, | |
| DXGI_FORMAT_R16G16B16A16_TYPELESS}, | |
| {DXGI_FORMAT_R16G16B16A16_UINT, | |
| {DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_SNORM}, | |
| DXGI_FORMAT_R16G16B16A16_UINT, | |
| DXGI_FORMAT_R16G16B16A16_TYPELESS}, | |
| {DXGI_FORMAT_R16G16B16A16_SINT, | |
| {DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_SNORM}, | |
| DXGI_FORMAT_R16G16B16A16_UINT, | |
| DXGI_FORMAT_R16G16B16A16_TYPELESS}, | |
| {DXGI_FORMAT_R16G16B16A16_UNORM, | |
| {DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_SINT}, | |
| DXGI_FORMAT_R16G16B16A16_UINT, | |
| DXGI_FORMAT_R16G16B16A16_TYPELESS}, | |
| {DXGI_FORMAT_R16G16B16A16_SNORM, | |
| {DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_SINT}, | |
| DXGI_FORMAT_R16G16B16A16_UINT, | |
| DXGI_FORMAT_R16G16B16A16_TYPELESS}, | |
| {DXGI_FORMAT_R32G32_TYPELESS, | |
| {DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_SINT}, | |
| DXGI_FORMAT_R32G32_UINT, | |
| DXGI_FORMAT_R32G32_TYPELESS}, | |
| {DXGI_FORMAT_R32G32_FLOAT, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_R32G32_UINT, | |
| DXGI_FORMAT_R32G32_TYPELESS}, | |
| {DXGI_FORMAT_R32G32_UINT, | |
| {DXGI_FORMAT_R32G32_SINT}, | |
| DXGI_FORMAT_R32G32_UINT, | |
| DXGI_FORMAT_R32G32_TYPELESS}, | |
| {DXGI_FORMAT_R32G32_SINT, | |
| {DXGI_FORMAT_R32G32_UINT}, | |
| DXGI_FORMAT_R32G32_UINT, | |
| DXGI_FORMAT_R32G32_TYPELESS}, | |
| {DXGI_FORMAT_R32G8X24_TYPELESS, | |
| {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_R32G8X24_TYPELESS}, | |
| {DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, | |
| {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_R32G8X24_TYPELESS}, | |
| {DXGI_FORMAT_X32_TYPELESS_G8X24_UINT, | |
| {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_R32G8X24_TYPELESS}, | |
| {DXGI_FORMAT_D32_FLOAT_S8X24_UINT, | |
| {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_R32G8X24_TYPELESS}, | |
| {DXGI_FORMAT_R10G10B10A2_TYPELESS, | |
| {DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UINT}, | |
| DXGI_FORMAT_R10G10B10A2_UINT, | |
| DXGI_FORMAT_R10G10B10A2_TYPELESS}, | |
| {DXGI_FORMAT_R10G10B10A2_UINT, | |
| {DXGI_FORMAT_R10G10B10A2_UNORM}, | |
| DXGI_FORMAT_R10G10B10A2_UINT, | |
| DXGI_FORMAT_R10G10B10A2_TYPELESS}, | |
| {DXGI_FORMAT_R10G10B10A2_UNORM, | |
| {DXGI_FORMAT_R10G10B10A2_UINT}, | |
| DXGI_FORMAT_R10G10B10A2_UINT, | |
| DXGI_FORMAT_R10G10B10A2_TYPELESS}, | |
| {DXGI_FORMAT_R11G11B10_FLOAT, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_R32_UINT}, | |
| {DXGI_FORMAT_R9G9B9E5_SHAREDEXP, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_R32_UINT}, | |
| {DXGI_FORMAT_R8G8_TYPELESS, | |
| {DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_SNORM}, | |
| DXGI_FORMAT_R8G8_UINT, | |
| DXGI_FORMAT_R8G8_TYPELESS}, | |
| {DXGI_FORMAT_R8G8_UINT, | |
| {DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_SNORM}, | |
| DXGI_FORMAT_R8G8_UINT, | |
| DXGI_FORMAT_R8G8_TYPELESS}, | |
| {DXGI_FORMAT_R8G8_SINT, | |
| {DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_SNORM}, | |
| DXGI_FORMAT_R8G8_UINT, | |
| DXGI_FORMAT_R8G8_TYPELESS}, | |
| {DXGI_FORMAT_R8G8_UNORM, | |
| {DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_SINT}, | |
| DXGI_FORMAT_R8G8_UINT, | |
| DXGI_FORMAT_R8G8_TYPELESS}, | |
| {DXGI_FORMAT_R8G8_SNORM, | |
| {DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_SINT}, | |
| DXGI_FORMAT_R8G8_UINT, | |
| DXGI_FORMAT_R8G8_TYPELESS}, | |
| {DXGI_FORMAT_R8G8B8A8_TYPELESS, | |
| {DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_SNORM}, | |
| DXGI_FORMAT_R8G8B8A8_UINT, | |
| DXGI_FORMAT_R8G8B8A8_TYPELESS}, | |
| {DXGI_FORMAT_R8G8B8A8_UINT, | |
| {DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_SNORM}, | |
| DXGI_FORMAT_R8G8B8A8_UINT, | |
| DXGI_FORMAT_R8G8B8A8_TYPELESS}, | |
| {DXGI_FORMAT_R8G8B8A8_SINT, | |
| {DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_SNORM}, | |
| DXGI_FORMAT_R8G8B8A8_UINT, | |
| DXGI_FORMAT_R8G8B8A8_TYPELESS}, | |
| {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, | |
| {DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_UNORM}, | |
| DXGI_FORMAT_R8G8B8A8_UINT, | |
| DXGI_FORMAT_R8G8B8A8_TYPELESS}, | |
| {DXGI_FORMAT_R8G8B8A8_UNORM, | |
| {DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB}, | |
| DXGI_FORMAT_R8G8B8A8_UINT, | |
| DXGI_FORMAT_R8G8B8A8_TYPELESS}, | |
| {DXGI_FORMAT_R8G8B8A8_SNORM, | |
| {DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_SINT}, | |
| DXGI_FORMAT_R8G8B8A8_UINT, | |
| DXGI_FORMAT_R8G8B8A8_TYPELESS}, | |
| {DXGI_FORMAT_R16G16_TYPELESS, | |
| {DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16_SNORM}, | |
| DXGI_FORMAT_R16G16_UINT, | |
| DXGI_FORMAT_R16G16_TYPELESS}, | |
| {DXGI_FORMAT_R16G16_FLOAT, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_R16G16_UINT, | |
| DXGI_FORMAT_R16G16_TYPELESS}, | |
| {DXGI_FORMAT_R16G16_UINT, | |
| {DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16_SNORM}, | |
| DXGI_FORMAT_R16G16_UINT, | |
| DXGI_FORMAT_R16G16_TYPELESS}, | |
| {DXGI_FORMAT_R16G16_SINT, | |
| {DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16_SNORM}, | |
| DXGI_FORMAT_R16G16_UINT, | |
| DXGI_FORMAT_R16G16_TYPELESS}, | |
| {DXGI_FORMAT_R16G16_UNORM, | |
| {DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_SINT}, | |
| DXGI_FORMAT_R16G16_UINT, | |
| DXGI_FORMAT_R16G16_TYPELESS}, | |
| {DXGI_FORMAT_R16G16_SNORM, | |
| {DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_SINT}, | |
| DXGI_FORMAT_R16G16_UINT, | |
| DXGI_FORMAT_R16G16_TYPELESS}, | |
| {DXGI_FORMAT_R32_TYPELESS, | |
| {DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_SINT}, | |
| DXGI_FORMAT_R32_UINT, | |
| DXGI_FORMAT_R32_TYPELESS}, | |
| {DXGI_FORMAT_R32_FLOAT, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_R32_UINT, | |
| DXGI_FORMAT_R32_TYPELESS}, | |
| {DXGI_FORMAT_R32_UINT, | |
| {DXGI_FORMAT_R32_SINT}, | |
| DXGI_FORMAT_R32_UINT, | |
| DXGI_FORMAT_R32_TYPELESS}, | |
| {DXGI_FORMAT_R32_SINT, | |
| {DXGI_FORMAT_R32_UINT}, | |
| DXGI_FORMAT_R32_UINT, | |
| DXGI_FORMAT_R32_TYPELESS}, | |
| {DXGI_FORMAT_D32_FLOAT, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_R32_TYPELESS}, | |
| {DXGI_FORMAT_R24G8_TYPELESS, | |
| {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_R24G8_TYPELESS}, | |
| {DXGI_FORMAT_R24_UNORM_X8_TYPELESS, | |
| {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_R24G8_TYPELESS}, | |
| {DXGI_FORMAT_X24_TYPELESS_G8_UINT, | |
| {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_R24G8_TYPELESS}, | |
| {DXGI_FORMAT_D24_UNORM_S8_UINT, | |
| {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_R24G8_TYPELESS}, | |
| {DXGI_FORMAT_R16_TYPELESS, | |
| {DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_SNORM}, | |
| DXGI_FORMAT_R16_UINT, | |
| DXGI_FORMAT_R16_TYPELESS}, | |
| {DXGI_FORMAT_R16_FLOAT, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_R16_UINT, | |
| DXGI_FORMAT_R16_TYPELESS}, | |
| {DXGI_FORMAT_R16_UINT, | |
| {DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_SNORM}, | |
| DXGI_FORMAT_R16_UINT, | |
| DXGI_FORMAT_R16_TYPELESS}, | |
| {DXGI_FORMAT_R16_SINT, | |
| {DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_SNORM}, | |
| DXGI_FORMAT_R16_UINT, | |
| DXGI_FORMAT_R16_TYPELESS}, | |
| {DXGI_FORMAT_R16_UNORM, | |
| {DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_SINT}, | |
| DXGI_FORMAT_R16_UINT, | |
| DXGI_FORMAT_R16_TYPELESS}, | |
| {DXGI_FORMAT_R16_SNORM, | |
| {DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_SINT}, | |
| DXGI_FORMAT_R16_UINT, | |
| DXGI_FORMAT_R16_TYPELESS}, | |
| {DXGI_FORMAT_D16_UNORM, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_R16_TYPELESS}, | |
| {DXGI_FORMAT_R8_TYPELESS, | |
| {DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_SNORM}, | |
| DXGI_FORMAT_R8_UINT, | |
| DXGI_FORMAT_R8_TYPELESS}, | |
| {DXGI_FORMAT_R8_UINT, | |
| {DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_SNORM}, | |
| DXGI_FORMAT_R8_UINT, | |
| DXGI_FORMAT_R8_TYPELESS}, | |
| {DXGI_FORMAT_R8_SINT, | |
| {DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_SNORM}, | |
| DXGI_FORMAT_R8_UINT, | |
| DXGI_FORMAT_R8_TYPELESS}, | |
| {DXGI_FORMAT_R8_UNORM, | |
| {DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_SINT}, | |
| DXGI_FORMAT_R8_UINT, | |
| DXGI_FORMAT_R8_TYPELESS}, | |
| {DXGI_FORMAT_R8_SNORM, | |
| {DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_SINT}, | |
| DXGI_FORMAT_R8_UINT, | |
| DXGI_FORMAT_R8_TYPELESS}, | |
| /* A8 has no corresponding UINT format */ | |
| {DXGI_FORMAT_A8_UNORM, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_A8_UNORM}, | |
| /* There's no BGRA8_UINT either, so use UNORM directly */ | |
| {DXGI_FORMAT_B8G8R8A8_TYPELESS, | |
| {DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB}, | |
| DXGI_FORMAT_B8G8R8A8_UNORM, | |
| DXGI_FORMAT_B8G8R8A8_TYPELESS}, | |
| {DXGI_FORMAT_B8G8R8A8_UNORM, | |
| {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB}, | |
| DXGI_FORMAT_B8G8R8A8_UNORM, | |
| DXGI_FORMAT_B8G8R8A8_TYPELESS}, | |
| {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, | |
| {DXGI_FORMAT_B8G8R8A8_UNORM}, | |
| DXGI_FORMAT_B8G8R8A8_UNORM, | |
| DXGI_FORMAT_B8G8R8A8_TYPELESS}, | |
| {DXGI_FORMAT_B8G8R8X8_TYPELESS, | |
| {DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8X8_UNORM_SRGB}, | |
| DXGI_FORMAT_B8G8R8X8_UNORM, | |
| DXGI_FORMAT_B8G8R8X8_TYPELESS}, | |
| {DXGI_FORMAT_B8G8R8X8_UNORM, | |
| {DXGI_FORMAT_B8G8R8X8_UNORM_SRGB}, | |
| DXGI_FORMAT_B8G8R8X8_UNORM, | |
| DXGI_FORMAT_B8G8R8X8_TYPELESS}, | |
| {DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, | |
| {DXGI_FORMAT_B8G8R8X8_UNORM}, | |
| DXGI_FORMAT_B8G8R8X8_UNORM, | |
| DXGI_FORMAT_B8G8R8X8_TYPELESS}, | |
| {DXGI_FORMAT_BC1_TYPELESS, | |
| {DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM_SRGB}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC1_TYPELESS}, | |
| {DXGI_FORMAT_BC1_UNORM, | |
| {DXGI_FORMAT_BC1_UNORM_SRGB}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC1_TYPELESS}, | |
| {DXGI_FORMAT_BC1_UNORM_SRGB, | |
| {DXGI_FORMAT_BC1_UNORM}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC1_TYPELESS}, | |
| {DXGI_FORMAT_BC2_TYPELESS, | |
| {DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM_SRGB}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC2_TYPELESS}, | |
| {DXGI_FORMAT_BC2_UNORM, | |
| {DXGI_FORMAT_BC2_UNORM_SRGB}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC2_TYPELESS}, | |
| {DXGI_FORMAT_BC2_UNORM_SRGB, | |
| {DXGI_FORMAT_BC2_UNORM}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC2_TYPELESS}, | |
| {DXGI_FORMAT_BC3_TYPELESS, | |
| {DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM_SRGB}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC3_TYPELESS}, | |
| {DXGI_FORMAT_BC3_UNORM, | |
| {DXGI_FORMAT_BC3_UNORM_SRGB}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC3_TYPELESS}, | |
| {DXGI_FORMAT_BC3_UNORM_SRGB, | |
| {DXGI_FORMAT_BC3_UNORM}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC3_TYPELESS}, | |
| {DXGI_FORMAT_BC4_TYPELESS, | |
| {DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_SNORM}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC4_TYPELESS}, | |
| {DXGI_FORMAT_BC4_UNORM, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC4_TYPELESS}, | |
| {DXGI_FORMAT_BC4_SNORM, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC4_TYPELESS}, | |
| {DXGI_FORMAT_BC5_TYPELESS, | |
| {DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_SNORM}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC5_TYPELESS}, | |
| {DXGI_FORMAT_BC5_UNORM, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC5_TYPELESS}, | |
| {DXGI_FORMAT_BC5_SNORM, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC5_TYPELESS}, | |
| {DXGI_FORMAT_BC6H_TYPELESS, | |
| {DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_SF16}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC6H_TYPELESS}, | |
| {DXGI_FORMAT_BC6H_UF16, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC6H_TYPELESS}, | |
| {DXGI_FORMAT_BC6H_SF16, {DXGI_FORMAT_UNKNOWN}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC6H_TYPELESS}, | |
| {DXGI_FORMAT_BC7_TYPELESS, | |
| {DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM_SRGB}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC7_TYPELESS}, | |
| {DXGI_FORMAT_BC7_UNORM, | |
| {DXGI_FORMAT_BC7_UNORM_SRGB}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC7_TYPELESS}, | |
| {DXGI_FORMAT_BC7_UNORM_SRGB, | |
| {DXGI_FORMAT_BC7_UNORM}, | |
| DXGI_FORMAT_UNKNOWN, | |
| DXGI_FORMAT_BC7_TYPELESS}, | |
| {DXGI_FORMAT_NV12, | |
| {DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UINT}}, | |
| {DXGI_FORMAT_P010, | |
| {DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16_UINT}}, | |
| {DXGI_FORMAT_P016, | |
| {DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16_UINT}}, | |
| /* Internal implementation detail. We desire 64-bit atomics and R32G32 UAV will trigger that compat | |
| * similar to other 64-bit images. */ | |
| {DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE, | |
| {DXGI_FORMAT_R32G32_UINT}}, | |
| {DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE, | |
| {DXGI_FORMAT_R32G32_UINT}}, | |
| }; | |
| void vkd3d_format_compatibility_list_add_format(struct vkd3d_format_compatibility_list *list, VkFormat vk_format) | |
| { | |
| unsigned int i; | |
| bool found = false; | |
| for (i = 0; i < list->format_count && !found; i++) | |
| found = list->vk_formats[i] == vk_format; | |
| if (!found) | |
| { | |
| if (list->format_count < ARRAY_SIZE(list->vk_formats)) | |
| list->vk_formats[list->format_count++] = vk_format; | |
| else | |
| WARN("Format compatiblity list overflowed.\n"); | |
| } | |
| } | |
| static HRESULT vkd3d_init_format_compatibility_lists(struct d3d12_device *device) | |
| { | |
| struct vkd3d_format_compatibility_list *lists, *dst; | |
| const struct dxgi_format_compatibility_list *src; | |
| unsigned int count; | |
| unsigned int i, j; | |
| device->format_compatibility_list_count = 0; | |
| device->format_compatibility_lists = NULL; | |
| count = 0; | |
| for (i = 0; i < ARRAY_SIZE(dxgi_format_compatibility_list); ++i) | |
| count = max(count, dxgi_format_compatibility_list[i].image_format + 1); | |
| if (!(lists = vkd3d_calloc(count, sizeof(*lists)))) | |
| return E_OUTOFMEMORY; | |
| for (i = 0; i < ARRAY_SIZE(dxgi_format_compatibility_list); ++i) | |
| { | |
| src = &dxgi_format_compatibility_list[i]; | |
| dst = &lists[src->image_format]; | |
| dst->uint_format = src->uint_format; | |
| dst->typeless_format = src->typeless_format; | |
| vkd3d_format_compatibility_list_add_format(dst, vkd3d_get_vk_format(src->image_format)); | |
| for (j = 0; j < ARRAY_SIZE(src->view_formats) && src->view_formats[j]; j++) | |
| vkd3d_format_compatibility_list_add_format(dst, vkd3d_get_vk_format(src->view_formats[j])); | |
| } | |
| device->format_compatibility_list_count = count; | |
| device->format_compatibility_lists = lists; | |
| return S_OK; | |
| } | |
| static void vkd3d_cleanup_format_compatibility_lists(struct d3d12_device *device) | |
| { | |
| vkd3d_free((void *)device->format_compatibility_lists); | |
| device->format_compatibility_lists = NULL; | |
| device->format_compatibility_list_count = 0; | |
| } | |
| static void vkd3d_get_vk_format_properties(struct d3d12_device *device, VkFormat vk_format, VkFormatProperties3 *properties3) | |
| { | |
| const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; | |
| VkFormatProperties2 properties; | |
| memset(properties3, 0, sizeof(*properties3)); | |
| properties3->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3; | |
| memset(&properties, 0, sizeof(properties)); | |
| properties.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; | |
| properties.pNext = properties3; | |
| VK_CALL(vkGetPhysicalDeviceFormatProperties2(device->vk_physical_device, vk_format, &properties)); | |
| } | |
| static void vkd3d_init_format_sample_counts(struct d3d12_device *device, struct vkd3d_format *format) | |
| { | |
| const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; | |
| VkPhysicalDeviceSparseImageFormatInfo2 sparse_info; | |
| VkPhysicalDeviceImageFormatInfo2 info; | |
| VkSampleCountFlagBits sample_count; | |
| VkImageFormatProperties2 props; | |
| uint32_t info_count; | |
| format->supported_sample_counts = 0; | |
| format->supported_sparse_sample_counts = 0; | |
| memset(&props, 0, sizeof(props)); | |
| props.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2; | |
| memset(&info, 0, sizeof(info)); | |
| info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2; | |
| info.format = format->vk_format; | |
| info.type = VK_IMAGE_TYPE_2D; | |
| info.tiling = format->vk_image_tiling; | |
| info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; | |
| if (VK_CALL(vkGetPhysicalDeviceImageFormatProperties2(device->vk_physical_device, &info, &props))) | |
| return; | |
| format->supported_sample_counts = props.imageFormatProperties.sampleCounts; | |
| /* Planar and depth-stencil formats do not support sparse in D3D12 */ | |
| if (format->plane_count > 1 || !device->device_info.features2.features.sparseResidencyImage2D) | |
| return; | |
| info.flags |= VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | | |
| VK_IMAGE_CREATE_SPARSE_ALIASED_BIT | | |
| VK_IMAGE_CREATE_SPARSE_BINDING_BIT; | |
| if (VK_CALL(vkGetPhysicalDeviceImageFormatProperties2(device->vk_physical_device, &info, &props))) | |
| return; | |
| while (props.imageFormatProperties.sampleCounts) | |
| { | |
| /* VUID 01094. Samples must be marked as supported by ImageFormatProperties. */ | |
| sample_count = 1u << vkd3d_bitmask_iter32(&props.imageFormatProperties.sampleCounts); | |
| memset(&sparse_info, 0, sizeof(sparse_info)); | |
| sparse_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2; | |
| sparse_info.format = info.format; | |
| sparse_info.type = info.type; | |
| sparse_info.samples = sample_count; | |
| sparse_info.usage = info.usage; | |
| sparse_info.tiling = info.tiling; | |
| VK_CALL(vkGetPhysicalDeviceSparseImageFormatProperties2( | |
| device->vk_physical_device, &sparse_info, &info_count, NULL)); | |
| if (info_count > 0) | |
| format->supported_sparse_sample_counts |= sample_count; | |
| } | |
| } | |
| static HRESULT vkd3d_init_depth_stencil_formats(struct d3d12_device *device) | |
| { | |
| struct vkd3d_format *formats, *format; | |
| VkFormatProperties3 d24s8_properties; | |
| VkFormatProperties3 properties; | |
| unsigned int i; | |
| if (!(formats = vkd3d_calloc(VKD3D_MAX_DXGI_FORMAT + 1, sizeof(*formats)))) | |
| return E_OUTOFMEMORY; | |
| vkd3d_get_vk_format_properties(device, VK_FORMAT_D24_UNORM_S8_UINT, &d24s8_properties); | |
| if (!(d24s8_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) | |
| { | |
| /* AMD doesn't support VK_FORMAT_D24_UNORM_S8_UINT. */ | |
| WARN("Mapping VK_FORMAT_D24_UNORM_S8_UINT to VK_FORMAT_D32_SFLOAT_S8_UINT.\n"); | |
| } | |
| for (i = 0; i < ARRAY_SIZE(vkd3d_depth_stencil_formats); ++i) | |
| { | |
| assert(vkd3d_depth_stencil_formats[i].dxgi_format <= VKD3D_MAX_DXGI_FORMAT); | |
| format = &formats[vkd3d_depth_stencil_formats[i].dxgi_format]; | |
| *format = vkd3d_depth_stencil_formats[i]; | |
| if (format->vk_format == VK_FORMAT_D24_UNORM_S8_UINT && | |
| !(d24s8_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) | |
| { | |
| format->vk_format = VK_FORMAT_D32_SFLOAT_S8_UINT; | |
| format->is_emulated = true; | |
| } | |
| vkd3d_get_vk_format_properties(device, format->vk_format, &properties); | |
| /* We cannot cast depth stencil formats in Vulkan, so features == castable. */ | |
| format->vk_image_tiling = VK_IMAGE_TILING_OPTIMAL; | |
| format->vk_format_features = properties.optimalTilingFeatures; | |
| format->vk_format_features_castable = properties.optimalTilingFeatures; | |
| format->vk_format_features_buffer = 0; | |
| vkd3d_init_format_sample_counts(device, format); | |
| } | |
| device->depth_stencil_formats = formats; | |
| return S_OK; | |
| } | |
| static void vkd3d_cleanup_depth_stencil_formats(struct d3d12_device *device) | |
| { | |
| vkd3d_free((void *)device->depth_stencil_formats); | |
| device->depth_stencil_formats = NULL; | |
| } | |
| static HRESULT vkd3d_init_formats(struct d3d12_device *device) | |
| { | |
| const struct vkd3d_format_compatibility_list *list; | |
| struct vkd3d_format *formats, *format; | |
| VkFormatProperties3 properties; | |
| DXGI_FORMAT dxgi_format; | |
| unsigned int i, j; | |
| bool emulate_a8; | |
| static const VkFormatFeatureFlags2 feature_mask = | |
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | | |
| VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | | |
| VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | | |
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | | |
| VK_FORMAT_FEATURE_TRANSFER_DST_BIT; | |
| if (!(formats = vkd3d_calloc(VKD3D_MAX_DXGI_FORMAT + 1, sizeof(*formats)))) | |
| return E_OUTOFMEMORY; | |
| if (device->device_info.maintenance_5_features.maintenance5) | |
| { | |
| const VkFormatFeatureFlags a8_required_features = | |
| VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | | |
| VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | | |
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | | |
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | | |
| VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | | |
| VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | | |
| VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT; | |
| VkFormatProperties3 a8_properties, r8_properties; | |
| VkFormatFeatureFlags r8_unique_features; | |
| vkd3d_get_vk_format_properties(device, VK_FORMAT_A8_UNORM_KHR, &a8_properties); | |
| vkd3d_get_vk_format_properties(device, VK_FORMAT_R8_UNORM, &r8_properties); | |
| /* Only use the native A8_UNORM format if support is at least as good | |
| * as for the R8_UNORM fallback format for relevant features. */ | |
| r8_unique_features = (r8_properties.optimalTilingFeatures | r8_properties.bufferFeatures) & | |
| ~(a8_properties.optimalTilingFeatures | a8_properties.bufferFeatures); | |
| emulate_a8 = (r8_unique_features & a8_required_features) != 0; | |
| } | |
| else | |
| emulate_a8 = true; | |
| if (emulate_a8) | |
| WARN("Mapping VK_FORMAT_A8_UNORM_KHR to VK_FORMAT_R8_UNORM.\n"); | |
| for (i = 0; i < ARRAY_SIZE(vkd3d_formats); ++i) | |
| { | |
| assert(vkd3d_formats[i].dxgi_format <= VKD3D_MAX_DXGI_FORMAT); | |
| dxgi_format = vkd3d_formats[i].dxgi_format; | |
| format = &formats[dxgi_format]; | |
| *format = vkd3d_formats[i]; | |
| if (format->vk_format == VK_FORMAT_A8_UNORM_KHR && emulate_a8) | |
| { | |
| format->vk_format = VK_FORMAT_R8_UNORM; | |
| format->is_emulated = true; | |
| } | |
| vkd3d_get_vk_format_properties(device, format->vk_format, &properties); | |
| if ((properties.optimalTilingFeatures & feature_mask) || !(properties.linearTilingFeatures & feature_mask)) | |
| { | |
| format->vk_image_tiling = VK_IMAGE_TILING_OPTIMAL; | |
| format->vk_format_features = properties.optimalTilingFeatures; | |
| format->vk_format_features_castable = properties.optimalTilingFeatures; | |
| } | |
| else | |
| { | |
| format->vk_image_tiling = VK_IMAGE_TILING_LINEAR; | |
| format->vk_format_features = properties.linearTilingFeatures; | |
| format->vk_format_features_castable = properties.linearTilingFeatures; | |
| } | |
| format->vk_format_features_buffer = properties.bufferFeatures; | |
| if (dxgi_format < device->format_compatibility_list_count) | |
| { | |
| list = &device->format_compatibility_lists[dxgi_format]; | |
| for (j = 0; j < list->format_count; j++) | |
| { | |
| vkd3d_get_vk_format_properties(device, list->vk_formats[j], &properties); | |
| format->vk_format_features_castable |= format->vk_image_tiling == VK_IMAGE_TILING_OPTIMAL | |
| ? properties.optimalTilingFeatures | |
| : properties.linearTilingFeatures; | |
| } | |
| } | |
| vkd3d_init_format_sample_counts(device, format); | |
| } | |
| device->formats = formats; | |
| return S_OK; | |
| } | |
| static void vkd3d_cleanup_formats(struct d3d12_device *device) | |
| { | |
| vkd3d_free((void *)device->formats); | |
| device->formats = NULL; | |
| } | |
| HRESULT vkd3d_init_format_info(struct d3d12_device *device) | |
| { | |
| HRESULT hr; | |
| if (FAILED(hr = vkd3d_init_depth_stencil_formats(device))) | |
| return hr; | |
| if (FAILED(hr = vkd3d_init_format_compatibility_lists(device))) | |
| { | |
| vkd3d_cleanup_depth_stencil_formats(device); | |
| return hr; | |
| } | |
| if (FAILED(hr = vkd3d_init_formats(device))) | |
| { | |
| vkd3d_cleanup_depth_stencil_formats(device); | |
| vkd3d_cleanup_format_compatibility_lists(device); | |
| } | |
| return hr; | |
| } | |
| void vkd3d_cleanup_format_info(struct d3d12_device *device) | |
| { | |
| vkd3d_cleanup_depth_stencil_formats(device); | |
| vkd3d_cleanup_format_compatibility_lists(device); | |
| vkd3d_cleanup_formats(device); | |
| } | |
| /* We use overrides for depth/stencil formats. This is required in order to | |
| * properly support typeless formats because depth/stencil formats are only | |
| * compatible with themselves in Vulkan. | |
| */ | |
| static const struct vkd3d_format *vkd3d_get_depth_stencil_format(const struct d3d12_device *device, | |
| DXGI_FORMAT dxgi_format) | |
| { | |
| const struct vkd3d_format *format; | |
| assert(device); | |
| format = &device->depth_stencil_formats[dxgi_format]; | |
| return format->dxgi_format ? format : NULL; | |
| } | |
| const struct vkd3d_format *vkd3d_get_format(const struct d3d12_device *device, | |
| DXGI_FORMAT dxgi_format, bool depth_stencil) | |
| { | |
| const struct vkd3d_format *format; | |
| if (!is_valid_format(dxgi_format)) | |
| { | |
| ERR("Invalid format %d.\n", dxgi_format); | |
| return NULL; | |
| } | |
| /* If we request a depth-stencil format (or typeless variant) that is planar, | |
| * there cannot be any ambiguity which format to select, we must choose a depth-stencil format. | |
| * For single aspect formats, | |
| * there are cases where we need to choose either COLOR or DEPTH aspect variants based on depth_stencil argument, | |
| * but there cannot be any such issue for DEPTH_STENCIL types. | |
| * This fixes issues where e.g. R24_UNORM_X8_TYPELESS format is used without ALLOW_DEPTH_STENCIL. */ | |
| format = vkd3d_get_depth_stencil_format(device, dxgi_format); | |
| if (format && (depth_stencil || format->plane_count > 1)) | |
| return format; | |
| format = &device->formats[dxgi_format]; | |
| return format->dxgi_format ? format : NULL; | |
| } | |
| struct vkd3d_format_footprint vkd3d_format_footprint_for_plane(const struct vkd3d_format *format, unsigned int plane_idx) | |
| { | |
| if (format->plane_footprints) | |
| { | |
| return format->plane_footprints[plane_idx]; | |
| } | |
| else | |
| { | |
| struct vkd3d_format_footprint footprint; | |
| footprint.dxgi_format = format->dxgi_format; | |
| footprint.block_width = format->block_width; | |
| footprint.block_height = format->block_height; | |
| footprint.subsample_x_log2 = 0; | |
| footprint.subsample_y_log2 = 0; | |
| footprint.block_byte_count = format->byte_count * format->block_byte_count; | |
| return footprint; | |
| } | |
| } | |
| VkFormat vkd3d_internal_get_vk_format(const struct d3d12_device *device, DXGI_FORMAT dxgi_format) | |
| { | |
| const struct vkd3d_format *format; | |
| if ((format = vkd3d_get_format(device, dxgi_format, false))) | |
| return format->vk_format; | |
| return VK_FORMAT_UNDEFINED; | |
| } | |
| void vkd3d_format_copy_data(const struct vkd3d_format *format, const uint8_t *src, | |
| unsigned int src_row_pitch, unsigned int src_slice_pitch, uint8_t *dst, unsigned int dst_row_pitch, | |
| unsigned int dst_slice_pitch, unsigned int w, unsigned int h, unsigned int d) | |
| { | |
| unsigned int row_block_count, row_count, row_size, slice, row; | |
| unsigned int slice_count = d; | |
| const uint8_t *src_row; | |
| uint8_t *dst_row; | |
| row_block_count = (w + format->block_width - 1) / format->block_width; | |
| row_count = (h + format->block_height - 1) / format->block_height; | |
| row_size = row_block_count * format->byte_count * format->block_byte_count; | |
| for (slice = 0; slice < slice_count; ++slice) | |
| { | |
| for (row = 0; row < row_count; ++row) | |
| { | |
| src_row = &src[slice * src_slice_pitch + row * src_row_pitch]; | |
| dst_row = &dst[slice * dst_slice_pitch + row * dst_row_pitch]; | |
| memcpy(dst_row, src_row, row_size); | |
| } | |
| } | |
| } | |
| VkFormat vkd3d_get_vk_format(DXGI_FORMAT format) | |
| { | |
| unsigned int i; | |
| for (i = 0; i < ARRAY_SIZE(vkd3d_formats); ++i) | |
| { | |
| if (vkd3d_formats[i].dxgi_format == format) | |
| return vkd3d_formats[i].vk_format; | |
| } | |
| return VK_FORMAT_UNDEFINED; | |
| } | |
| /* Get some size-based low bits for memory prioritization in the same | |
| way as d3d12; d3d12 bumps certain resource priorities to | |
| D3D12_RESIDENCY_PRIORITY_HIGH + size-based bits (10MB resolution) | |
| see: https://learn.microsoft.com/en-us/windows/win32/direct3d12/residency#default-priority-algorithm */ | |
| uint32_t vkd3d_get_priority_adjust(VkDeviceSize size) | |
| { | |
| return min((size / (10 * 1048576)), 0xffffUL); | |
| } | |
| static float vkd3d_lerp_u32_to_float(uint32_t uval, uint32_t ustart, uint32_t uend, float fstart, float fend) | |
| { | |
| float a; | |
| if (uval <= ustart) return fstart; | |
| else if (uval >= uend) return fend; | |
| a = (float)(uval - ustart) / (float)(uend - ustart); | |
| return fstart * (1.0f - a) + (fend * a); | |
| } | |
| /* map from 32-bit d3d prio to float (0..1) vk prio. */ | |
| float vkd3d_convert_to_vk_prio(D3D12_RESIDENCY_PRIORITY d3d12prio) | |
| { | |
| float result; | |
| /* align D3D12_RESIDENCY_PRIORITY_NORMAL (the default d3d12 prio) with | |
| 0.5 (the default vk prio) so neither kind wins without explicit prio */ | |
| if (d3d12prio <= D3D12_RESIDENCY_PRIORITY_NORMAL) | |
| { | |
| result = vkd3d_lerp_u32_to_float(d3d12prio, | |
| 0, D3D12_RESIDENCY_PRIORITY_NORMAL, | |
| 0.001f, 0.500f); | |
| } | |
| else if (d3d12prio <= D3D12_RESIDENCY_PRIORITY_HIGH) | |
| { | |
| result = vkd3d_lerp_u32_to_float(d3d12prio, | |
| D3D12_RESIDENCY_PRIORITY_NORMAL, D3D12_RESIDENCY_PRIORITY_HIGH, | |
| 0.500f, 0.700f); | |
| } | |
| else if (d3d12prio <= D3D12_RESIDENCY_PRIORITY_HIGH+0xffff) | |
| { | |
| result = vkd3d_lerp_u32_to_float(d3d12prio, | |
| D3D12_RESIDENCY_PRIORITY_HIGH, D3D12_RESIDENCY_PRIORITY_HIGH+0xffff, | |
| 0.700f, 0.800f); | |
| } | |
| else | |
| { | |
| result = vkd3d_lerp_u32_to_float(d3d12prio, | |
| D3D12_RESIDENCY_PRIORITY_HIGH+0xffff, UINT32_MAX, | |
| 0.800f, 1.000f); | |
| } | |
| /* Note: A naive conversion from a UINT32 d3d priority to a float32 vk priority | |
| loses around 9 of the 16 lower-order bits which encode size-based subranking | |
| in the D3D12_RESIDENCY_PRIORITY_HIGH to HIGH+0xffff domain. The above expansion | |
| of that domain into a proportionally wider range works around this. */ | |
| /* 0.0f is reserved for explicitly evicted resources */ | |
| return max(min(result, 1.f), 0.001f); | |
| } | |
| DXGI_FORMAT vkd3d_get_dxgi_format(VkFormat format) | |
| { | |
| DXGI_FORMAT dxgi_format; | |
| VkFormat vk_format; | |
| unsigned int i; | |
| for (i = 0; i < ARRAY_SIZE(vkd3d_formats); ++i) | |
| { | |
| vk_format = vkd3d_formats[i].vk_format; | |
| dxgi_format = vkd3d_formats[i].dxgi_format; | |
| if (vk_format == format && vkd3d_formats[i].type != VKD3D_FORMAT_TYPE_TYPELESS) | |
| return dxgi_format; | |
| } | |
| FIXME("Unhandled Vulkan format %#x.\n", format); | |
| return DXGI_FORMAT_UNKNOWN; | |
| } | |
| bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) | |
| { | |
| static const D3D_FEATURE_LEVEL valid_feature_levels[] = | |
| { | |
| D3D_FEATURE_LEVEL_12_2, | |
| D3D_FEATURE_LEVEL_12_1, | |
| D3D_FEATURE_LEVEL_12_0, | |
| D3D_FEATURE_LEVEL_11_1, | |
| D3D_FEATURE_LEVEL_11_0, | |
| D3D_FEATURE_LEVEL_10_1, | |
| D3D_FEATURE_LEVEL_10_0, | |
| D3D_FEATURE_LEVEL_9_3, | |
| D3D_FEATURE_LEVEL_9_2, | |
| D3D_FEATURE_LEVEL_9_1, | |
| }; | |
| unsigned int i; | |
| for (i = 0; i < ARRAY_SIZE(valid_feature_levels); ++i) | |
| { | |
| if (valid_feature_levels[i] == feature_level) | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool is_write_resource_state(D3D12_RESOURCE_STATES state) | |
| { | |
| return state & (D3D12_RESOURCE_STATE_RENDER_TARGET | |
| | D3D12_RESOURCE_STATE_UNORDERED_ACCESS | |
| | D3D12_RESOURCE_STATE_DEPTH_WRITE | |
| | D3D12_RESOURCE_STATE_STREAM_OUT | |
| | D3D12_RESOURCE_STATE_COPY_DEST | |
| | D3D12_RESOURCE_STATE_RESOLVE_DEST); | |
| } | |
| bool is_valid_resource_state(D3D12_RESOURCE_STATES state) | |
| { | |
| const D3D12_RESOURCE_STATES valid_states = | |
| D3D12_RESOURCE_STATE_COMMON | | |
| D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER | | |
| D3D12_RESOURCE_STATE_INDEX_BUFFER | | |
| D3D12_RESOURCE_STATE_RENDER_TARGET | | |
| D3D12_RESOURCE_STATE_UNORDERED_ACCESS | | |
| D3D12_RESOURCE_STATE_DEPTH_WRITE | | |
| D3D12_RESOURCE_STATE_DEPTH_READ | | |
| D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | | |
| D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | | |
| D3D12_RESOURCE_STATE_STREAM_OUT | | |
| D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT | | |
| D3D12_RESOURCE_STATE_COPY_DEST | | |
| D3D12_RESOURCE_STATE_COPY_SOURCE | | |
| D3D12_RESOURCE_STATE_RESOLVE_DEST | | |
| D3D12_RESOURCE_STATE_RESOLVE_SOURCE | | |
| D3D12_RESOURCE_STATE_GENERIC_READ | | |
| D3D12_RESOURCE_STATE_PRESENT | | |
| D3D12_RESOURCE_STATE_PREDICATION | | |
| D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE | | |
| D3D12_RESOURCE_STATE_SHADING_RATE_SOURCE; | |
| if (state & ~valid_states) | |
| { | |
| WARN("Invalid resource states %#x.\n", state & ~valid_states); | |
| return false; | |
| } | |
| /* Exactly one bit must be set for write states. */ | |
| if (is_write_resource_state(state) && !is_power_of_two(state)) | |
| { | |
| WARN("Write state cannot be mixed with other states: %#x.\n", state); | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool is_valid_format(DXGI_FORMAT dxgi_format) | |
| { | |
| if (dxgi_format >= DXGI_FORMAT_UNKNOWN && dxgi_format <= DXGI_FORMAT_B4G4R4A4_UNORM) | |
| return true; | |
| if (dxgi_format >= DXGI_FORMAT_P208 && dxgi_format <= DXGI_FORMAT_A4B4G4R4_UNORM) | |
| return true; | |
| return false; | |
| } | |
| HRESULT return_interface(void *iface, REFIID iface_iid, | |
| REFIID requested_iid, void **object) | |
| { | |
| IUnknown *unknown = iface; | |
| HRESULT hr; | |
| /* Don't check IID here, we always have to return S_FALSE. */ | |
| if (!object) | |
| { | |
| IUnknown_Release(unknown); | |
| return S_FALSE; | |
| } | |
| if (IsEqualGUID(iface_iid, requested_iid)) | |
| { | |
| *object = unknown; | |
| return S_OK; | |
| } | |
| hr = IUnknown_QueryInterface(unknown, requested_iid, object); | |
| IUnknown_Release(unknown); | |
| return hr; | |
| } | |
| const char *debug_dxgi_format(DXGI_FORMAT format) | |
| { | |
| #define ENUM_NAME(x) \ | |
| case x: return #x; | |
| switch(format) | |
| { | |
| ENUM_NAME(DXGI_FORMAT_UNKNOWN) | |
| ENUM_NAME(DXGI_FORMAT_R32G32B32A32_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_R32G32B32A32_FLOAT) | |
| ENUM_NAME(DXGI_FORMAT_R32G32B32A32_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R32G32B32A32_SINT) | |
| ENUM_NAME(DXGI_FORMAT_R32G32B32_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_R32G32B32_FLOAT) | |
| ENUM_NAME(DXGI_FORMAT_R32G32B32_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R32G32B32_SINT) | |
| ENUM_NAME(DXGI_FORMAT_R16G16B16A16_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_R16G16B16A16_FLOAT) | |
| ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SNORM) | |
| ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SINT) | |
| ENUM_NAME(DXGI_FORMAT_R32G32_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_R32G32_FLOAT) | |
| ENUM_NAME(DXGI_FORMAT_R32G32_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R32G32_SINT) | |
| ENUM_NAME(DXGI_FORMAT_R32G8X24_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_D32_FLOAT_S8X24_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_X32_TYPELESS_G8X24_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R10G10B10A2_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R11G11B10_FLOAT) | |
| ENUM_NAME(DXGI_FORMAT_R8G8B8A8_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) | |
| ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SNORM) | |
| ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SINT) | |
| ENUM_NAME(DXGI_FORMAT_R16G16_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_R16G16_FLOAT) | |
| ENUM_NAME(DXGI_FORMAT_R16G16_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_R16G16_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R16G16_SNORM) | |
| ENUM_NAME(DXGI_FORMAT_R16G16_SINT) | |
| ENUM_NAME(DXGI_FORMAT_R32_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_D32_FLOAT) | |
| ENUM_NAME(DXGI_FORMAT_R32_FLOAT) | |
| ENUM_NAME(DXGI_FORMAT_R32_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R32_SINT) | |
| ENUM_NAME(DXGI_FORMAT_R24G8_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_D24_UNORM_S8_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R24_UNORM_X8_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_X24_TYPELESS_G8_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R8G8_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_R8G8_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_R8G8_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R8G8_SNORM) | |
| ENUM_NAME(DXGI_FORMAT_R8G8_SINT) | |
| ENUM_NAME(DXGI_FORMAT_R16_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_R16_FLOAT) | |
| ENUM_NAME(DXGI_FORMAT_D16_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_R16_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_R16_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R16_SNORM) | |
| ENUM_NAME(DXGI_FORMAT_R16_SINT) | |
| ENUM_NAME(DXGI_FORMAT_R8_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_R8_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_R8_UINT) | |
| ENUM_NAME(DXGI_FORMAT_R8_SNORM) | |
| ENUM_NAME(DXGI_FORMAT_R8_SINT) | |
| ENUM_NAME(DXGI_FORMAT_A8_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_R1_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_R9G9B9E5_SHAREDEXP) | |
| ENUM_NAME(DXGI_FORMAT_R8G8_B8G8_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_G8R8_G8B8_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_BC1_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_BC1_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_BC1_UNORM_SRGB) | |
| ENUM_NAME(DXGI_FORMAT_BC2_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_BC2_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_BC2_UNORM_SRGB) | |
| ENUM_NAME(DXGI_FORMAT_BC3_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_BC3_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_BC3_UNORM_SRGB) | |
| ENUM_NAME(DXGI_FORMAT_BC4_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_BC4_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_BC4_SNORM) | |
| ENUM_NAME(DXGI_FORMAT_BC5_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_BC5_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_BC5_SNORM) | |
| ENUM_NAME(DXGI_FORMAT_B5G6R5_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_B5G5R5A1_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_B8G8R8A8_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB) | |
| ENUM_NAME(DXGI_FORMAT_B8G8R8X8_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM_SRGB) | |
| ENUM_NAME(DXGI_FORMAT_BC6H_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_BC6H_UF16) | |
| ENUM_NAME(DXGI_FORMAT_BC6H_SF16) | |
| ENUM_NAME(DXGI_FORMAT_BC7_TYPELESS) | |
| ENUM_NAME(DXGI_FORMAT_BC7_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_BC7_UNORM_SRGB) | |
| ENUM_NAME(DXGI_FORMAT_AYUV) | |
| ENUM_NAME(DXGI_FORMAT_Y410) | |
| ENUM_NAME(DXGI_FORMAT_Y416) | |
| ENUM_NAME(DXGI_FORMAT_NV12) | |
| ENUM_NAME(DXGI_FORMAT_P010) | |
| ENUM_NAME(DXGI_FORMAT_P016) | |
| ENUM_NAME(DXGI_FORMAT_420_OPAQUE) | |
| ENUM_NAME(DXGI_FORMAT_YUY2) | |
| ENUM_NAME(DXGI_FORMAT_Y210) | |
| ENUM_NAME(DXGI_FORMAT_Y216) | |
| ENUM_NAME(DXGI_FORMAT_NV11) | |
| ENUM_NAME(DXGI_FORMAT_AI44) | |
| ENUM_NAME(DXGI_FORMAT_IA44) | |
| ENUM_NAME(DXGI_FORMAT_P8) | |
| ENUM_NAME(DXGI_FORMAT_A8P8) | |
| ENUM_NAME(DXGI_FORMAT_B4G4R4A4_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_P208) | |
| ENUM_NAME(DXGI_FORMAT_V208) | |
| ENUM_NAME(DXGI_FORMAT_V408) | |
| ENUM_NAME(DXGI_FORMAT_UNDOCUMENTED_ASTC_FIRST) | |
| ENUM_NAME(DXGI_FORMAT_UNDOCUMENTED_ASTC_LAST) | |
| ENUM_NAME(DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE) | |
| ENUM_NAME(DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE) | |
| ENUM_NAME(DXGI_FORMAT_A4B4G4R4_UNORM) | |
| ENUM_NAME(DXGI_FORMAT_FORCE_UINT) | |
| } | |
| #undef ENUM_NAME | |
| return vkd3d_dbg_sprintf("Unknown DXGI_FORMAT (%u)", | |
| (uint32_t) format); | |
| } | |
| const char *debug_d3d12_box(const D3D12_BOX *box) | |
| { | |
| if (!box) | |
| return "(null)"; | |
| return vkd3d_dbg_sprintf("(%u, %u, %u)-(%u, %u, %u)", | |
| box->left, box->top, box->front, | |
| box->right, box->bottom, box->back); | |
| } | |
| static const char *debug_d3d12_shader_component(D3D12_SHADER_COMPONENT_MAPPING component) | |
| { | |
| switch (component) | |
| { | |
| case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0: | |
| return "r"; | |
| case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1: | |
| return "g"; | |
| case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2: | |
| return "b"; | |
| case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3: | |
| return "a"; | |
| case D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0: | |
| return "0"; | |
| case D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1: | |
| return "1"; | |
| } | |
| FIXME("Invalid component mapping %#x.\n", component); | |
| return "invalid"; | |
| } | |
| const char *debug_d3d12_shader_component_mapping(unsigned int mapping) | |
| { | |
| return vkd3d_dbg_sprintf("{%s, %s, %s, %s}", | |
| debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(0, mapping)), | |
| debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(1, mapping)), | |
| debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(2, mapping)), | |
| debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(3, mapping))); | |
| } | |
| const char *debug_vk_extent_3d(VkExtent3D extent) | |
| { | |
| return vkd3d_dbg_sprintf("(%u, %u, %u)", | |
| (unsigned int)extent.width, | |
| (unsigned int)extent.height, | |
| (unsigned int)extent.depth); | |
| } | |
| const char *debug_vk_queue_flags(VkQueueFlags flags, char buffer[VKD3D_DEBUG_FLAGS_BUFFER_SIZE]) | |
| { | |
| buffer[0] = '\0'; | |
| #define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; } | |
| FLAG_TO_STR(VK_QUEUE_GRAPHICS_BIT) | |
| FLAG_TO_STR(VK_QUEUE_COMPUTE_BIT) | |
| FLAG_TO_STR(VK_QUEUE_TRANSFER_BIT) | |
| FLAG_TO_STR(VK_QUEUE_SPARSE_BINDING_BIT) | |
| FLAG_TO_STR(VK_QUEUE_PROTECTED_BIT) | |
| FLAG_TO_STR(VK_QUEUE_OPTICAL_FLOW_BIT_NV) | |
| #undef FLAG_TO_STR | |
| if (flags) | |
| FIXME("Unrecognized flag(s) %#x.\n", flags); | |
| if (!buffer[0]) | |
| return "0"; | |
| return vkd3d_dbg_sprintf("%s", &buffer[3]); | |
| } | |
| const char *debug_vk_memory_heap_flags(VkMemoryHeapFlags flags, char buffer[VKD3D_DEBUG_FLAGS_BUFFER_SIZE]) | |
| { | |
| buffer[0] = '\0'; | |
| #define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; } | |
| FLAG_TO_STR(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) | |
| FLAG_TO_STR(VK_MEMORY_HEAP_MULTI_INSTANCE_BIT) | |
| #undef FLAG_TO_STR | |
| if (flags) | |
| FIXME("Unrecognized flag(s) %#x.\n", flags); | |
| if (!buffer[0]) | |
| return "0"; | |
| return vkd3d_dbg_sprintf("%s", &buffer[3]); | |
| } | |
| const char *debug_vk_memory_property_flags(VkMemoryPropertyFlags flags, char buffer[VKD3D_DEBUG_FLAGS_BUFFER_SIZE]) | |
| { | |
| buffer[0] = '\0'; | |
| #define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; } | |
| FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) | |
| FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) | |
| FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) | |
| FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_CACHED_BIT) | |
| FLAG_TO_STR(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) | |
| FLAG_TO_STR(VK_MEMORY_PROPERTY_PROTECTED_BIT) | |
| FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD) | |
| FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD) | |
| #undef FLAG_TO_STR | |
| if (flags) | |
| FIXME("Unrecognized flag(s) %#x.\n", flags); | |
| if (!buffer[0]) | |
| return "0"; | |
| return vkd3d_dbg_sprintf("%s", &buffer[3]); | |
| } | |
| HRESULT hresult_from_errno(int rc) | |
| { | |
| switch (rc) | |
| { | |
| case 0: | |
| return S_OK; | |
| case ENOMEM: | |
| return E_OUTOFMEMORY; | |
| case EINVAL: | |
| return E_INVALIDARG; | |
| default: | |
| FIXME("Unhandled errno %d.\n", rc); | |
| return E_FAIL; | |
| } | |
| } | |
| HRESULT hresult_from_vk_result(VkResult vr) | |
| { | |
| /* Wine tends to dispatch Vulkan calls to their own syscall stack. | |
| * Crashes are captured and return this magic VkResult. | |
| * Report it explicitly here so it's easier to debug when it happens. */ | |
| if (vr == -1073741819) | |
| { | |
| ERR("Detected segfault in Wine syscall handler.\n"); | |
| /* HACK: For ad-hoc debugging can also trigger backtrace printing here. */ | |
| return E_POINTER; | |
| } | |
| switch (vr) | |
| { | |
| case VK_SUCCESS: | |
| return S_OK; | |
| case VK_ERROR_OUT_OF_DEVICE_MEMORY: | |
| WARN("Out of device memory.\n"); | |
| /* fall-through */ | |
| case VK_ERROR_OUT_OF_HOST_MEMORY: | |
| return E_OUTOFMEMORY; | |
| case VK_ERROR_VALIDATION_FAILED_EXT: | |
| /* NV driver sometimes returns this on invalid API usage. */ | |
| return E_INVALIDARG; | |
| default: | |
| FIXME("Unhandled VkResult %d.\n", vr); | |
| /* fall-through */ | |
| case VK_ERROR_DEVICE_LOST: | |
| case VK_ERROR_EXTENSION_NOT_PRESENT: | |
| return E_FAIL; | |
| } | |
| } | |
| HRESULT hresult_from_vkd3d_result(int vkd3d_result) | |
| { | |
| switch (vkd3d_result) | |
| { | |
| case VKD3D_OK: | |
| return S_OK; | |
| case VKD3D_ERROR_INVALID_SHADER: | |
| WARN("Invalid shader bytecode.\n"); | |
| /* fall-through */ | |
| case VKD3D_ERROR: | |
| return E_FAIL; | |
| case VKD3D_ERROR_OUT_OF_MEMORY: | |
| return E_OUTOFMEMORY; | |
| case VKD3D_ERROR_INVALID_ARGUMENT: | |
| return E_INVALIDARG; | |
| case VKD3D_ERROR_NOT_IMPLEMENTED: | |
| return E_NOTIMPL; | |
| default: | |
| FIXME("Unhandled vkd3d result %d.\n", vkd3d_result); | |
| return E_FAIL; | |
| } | |
| } | |
| #define LOAD_GLOBAL_PFN(name) \ | |
| if (!(procs->name = (void *)vkGetInstanceProcAddr(NULL, #name))) \ | |
| { \ | |
| ERR("Could not get global proc addr for '" #name "'.\n"); \ | |
| return E_FAIL; \ | |
| } | |
| #define MAYBE_LOAD_GLOBAL_PFN(name) \ | |
| procs->name = (void *)vkGetInstanceProcAddr(NULL, #name); | |
| HRESULT vkd3d_load_vk_global_procs(struct vkd3d_vk_global_procs *procs, | |
| PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr) | |
| { | |
| memset(procs, 0, sizeof(*procs)); | |
| procs->vkGetInstanceProcAddr = vkGetInstanceProcAddr; | |
| LOAD_GLOBAL_PFN(vkCreateInstance) | |
| LOAD_GLOBAL_PFN(vkEnumerateInstanceExtensionProperties) | |
| LOAD_GLOBAL_PFN(vkEnumerateInstanceLayerProperties) | |
| MAYBE_LOAD_GLOBAL_PFN(vkEnumerateInstanceVersion) | |
| TRACE("Loaded global Vulkan procs.\n"); | |
| return S_OK; | |
| } | |
| #define LOAD_INSTANCE_PFN(name) \ | |
| if (!(procs->name = (void *)global_procs->vkGetInstanceProcAddr(instance, #name))) \ | |
| { \ | |
| ERR("Could not get instance proc addr for '" #name "'.\n"); \ | |
| return E_FAIL; \ | |
| } | |
| #define LOAD_INSTANCE_OPTIONAL_PFN(name) \ | |
| procs->name = (void *)global_procs->vkGetInstanceProcAddr(instance, #name); | |
| HRESULT vkd3d_load_vk_instance_procs(struct vkd3d_vk_instance_procs *procs, | |
| const struct vkd3d_vk_global_procs *global_procs, VkInstance instance) | |
| { | |
| memset(procs, 0, sizeof(*procs)); | |
| #define VK_INSTANCE_PFN LOAD_INSTANCE_PFN | |
| #define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPTIONAL_PFN | |
| #include "vulkan_procs.h" | |
| TRACE("Loaded procs for VkInstance %p.\n", instance); | |
| return S_OK; | |
| } | |
| #define COPY_PARENT_PFN(name) procs->name = parent_procs->name; | |
| #define LOAD_DEVICE_PFN(name) \ | |
| if (!(procs->name = (void *)procs->vkGetDeviceProcAddr(device, #name))) \ | |
| { \ | |
| ERR("Could not get device proc addr for '" #name "'.\n"); \ | |
| return E_FAIL; \ | |
| } | |
| #define LOAD_DEVICE_OPTIONAL_PFN(name) \ | |
| procs->name = (void *)procs->vkGetDeviceProcAddr(device, #name); | |
| HRESULT vkd3d_load_vk_device_procs(struct vkd3d_vk_device_procs *procs, | |
| const struct vkd3d_vk_instance_procs *parent_procs, VkDevice device) | |
| { | |
| memset(procs, 0, sizeof(*procs)); | |
| #define VK_INSTANCE_PFN COPY_PARENT_PFN | |
| #define VK_INSTANCE_EXT_PFN COPY_PARENT_PFN | |
| #define VK_DEVICE_PFN LOAD_DEVICE_PFN | |
| #define VK_DEVICE_EXT_PFN LOAD_DEVICE_OPTIONAL_PFN | |
| #include "vulkan_procs.h" | |
| TRACE("Loaded procs for VkDevice %p.\n", device); | |
| return S_OK; | |
| } | |
| static struct vkd3d_private_data *vkd3d_private_store_get_private_data( | |
| const struct vkd3d_private_store *store, const GUID *tag) | |
| { | |
| struct vkd3d_private_data *data; | |
| LIST_FOR_EACH_ENTRY(data, &store->content, struct vkd3d_private_data, entry) | |
| { | |
| if (IsEqualGUID(&data->tag, tag)) | |
| return data; | |
| } | |
| return NULL; | |
| } | |
| HRESULT vkd3d_private_store_set_private_data(struct vkd3d_private_store *store, | |
| const GUID *tag, const void *data, unsigned int data_size, bool is_object) | |
| { | |
| struct vkd3d_private_data *d, *old_data; | |
| const void *ptr = data; | |
| if (!data) | |
| { | |
| if ((d = vkd3d_private_store_get_private_data(store, tag))) | |
| { | |
| vkd3d_private_data_destroy(d); | |
| return S_OK; | |
| } | |
| return S_FALSE; | |
| } | |
| if (is_object) | |
| { | |
| if (data_size != sizeof(IUnknown *)) | |
| return E_INVALIDARG; | |
| ptr = &data; | |
| } | |
| if (!(d = vkd3d_malloc(offsetof(struct vkd3d_private_data, data[data_size])))) | |
| return E_OUTOFMEMORY; | |
| d->tag = *tag; | |
| d->size = data_size; | |
| d->is_object = is_object; | |
| memcpy(d->data, ptr, data_size); | |
| if (is_object) | |
| IUnknown_AddRef(d->object); | |
| if ((old_data = vkd3d_private_store_get_private_data(store, tag))) | |
| vkd3d_private_data_destroy(old_data); | |
| list_add_tail(&store->content, &d->entry); | |
| return S_OK; | |
| } | |
| HRESULT vkd3d_get_private_data(struct vkd3d_private_store *store, | |
| const GUID *tag, unsigned int *out_size, void *out) | |
| { | |
| const struct vkd3d_private_data *data; | |
| unsigned int size; | |
| HRESULT hr; | |
| if (!out_size) | |
| return E_INVALIDARG; | |
| if (FAILED(hr = vkd3d_private_data_lock(store))) | |
| return hr; | |
| if (!(data = vkd3d_private_store_get_private_data(store, tag))) | |
| { | |
| *out_size = 0; | |
| hr = DXGI_ERROR_NOT_FOUND; | |
| goto done; | |
| } | |
| size = *out_size; | |
| *out_size = data->size; | |
| if (!out) | |
| goto done; | |
| if (size < data->size) | |
| { | |
| hr = DXGI_ERROR_MORE_DATA; | |
| goto done; | |
| } | |
| if (data->is_object) | |
| IUnknown_AddRef(data->object); | |
| memcpy(out, data->data, data->size); | |
| done: | |
| vkd3d_private_data_unlock(store); | |
| return hr; | |
| } | |
| HRESULT STDMETHODCALLTYPE d3d12_object_SetName(ID3D12Object *iface, const WCHAR *name) | |
| { | |
| size_t size = 0; | |
| TRACE("iface %p, name %s.\n", iface, debugstr_w(name)); | |
| if (name) | |
| size = sizeof(WCHAR) * (vkd3d_wcslen(name) + 1); | |
| return ID3D12Object_SetPrivateData(iface, &WKPDID_D3DDebugObjectNameW, size, name); | |
| } | |
| HRESULT vkd3d_set_vk_object_name(struct d3d12_device *device, uint64_t vk_object, | |
| VkObjectType vk_object_type, const char *name) | |
| { | |
| const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; | |
| VkDebugUtilsObjectNameInfoEXT info; | |
| VkResult vr; | |
| if (!device->vk_info.EXT_debug_utils) | |
| return VK_SUCCESS; | |
| info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; | |
| info.pNext = NULL; | |
| info.objectType = vk_object_type; | |
| info.objectHandle = vk_object; | |
| info.pObjectName = name; | |
| vr = VK_CALL(vkSetDebugUtilsObjectNameEXT(device->vk_device, &info)); | |
| return hresult_from_vk_result(vr); | |
| } | |
| static struct d3d_blob *impl_from_ID3DBlob(ID3DBlob *iface) | |
| { | |
| return CONTAINING_RECORD(iface, struct d3d_blob, ID3DBlob_iface); | |
| } | |
| static HRESULT STDMETHODCALLTYPE d3d_blob_QueryInterface(ID3DBlob *iface, REFIID riid, void **object) | |
| { | |
| TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); | |
| if (IsEqualGUID(riid, &IID_ID3DBlob) | |
| || IsEqualGUID(riid, &IID_IUnknown)) | |
| { | |
| ID3D10Blob_AddRef(iface); | |
| *object = iface; | |
| return S_OK; | |
| } | |
| WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); | |
| *object = NULL; | |
| return E_NOINTERFACE; | |
| } | |
| static ULONG STDMETHODCALLTYPE d3d_blob_AddRef(ID3DBlob *iface) | |
| { | |
| struct d3d_blob *blob = impl_from_ID3DBlob(iface); | |
| ULONG refcount = InterlockedIncrement(&blob->refcount); | |
| TRACE("%p increasing refcount to %u.\n", blob, refcount); | |
| return refcount; | |
| } | |
| static ULONG STDMETHODCALLTYPE d3d_blob_Release(ID3DBlob *iface) | |
| { | |
| struct d3d_blob *blob = impl_from_ID3DBlob(iface); | |
| ULONG refcount = InterlockedDecrement(&blob->refcount); | |
| TRACE("%p decreasing refcount to %u.\n", blob, refcount); | |
| if (!refcount) | |
| { | |
| vkd3d_free(blob->buffer); | |
| vkd3d_free(blob); | |
| } | |
| return refcount; | |
| } | |
| static void * STDMETHODCALLTYPE d3d_blob_GetBufferPointer(ID3DBlob *iface) | |
| { | |
| struct d3d_blob *blob = impl_from_ID3DBlob(iface); | |
| TRACE("iface %p.\n", iface); | |
| return blob->buffer; | |
| } | |
| static SIZE_T STDMETHODCALLTYPE d3d_blob_GetBufferSize(ID3DBlob *iface) | |
| { | |
| struct d3d_blob *blob = impl_from_ID3DBlob(iface); | |
| TRACE("iface %p.\n", iface); | |
| return blob->size; | |
| } | |
| static CONST_VTBL struct ID3D10BlobVtbl d3d_blob_vtbl = | |
| { | |
| /* IUnknown methods */ | |
| d3d_blob_QueryInterface, | |
| d3d_blob_AddRef, | |
| d3d_blob_Release, | |
| /* ID3DBlob methods */ | |
| d3d_blob_GetBufferPointer, | |
| d3d_blob_GetBufferSize | |
| }; | |
| static void d3d_blob_init(struct d3d_blob *blob, void *buffer, SIZE_T size) | |
| { | |
| blob->ID3DBlob_iface.lpVtbl = &d3d_blob_vtbl; | |
| blob->refcount = 1; | |
| blob->buffer = buffer; | |
| blob->size = size; | |
| } | |
| HRESULT d3d_blob_create(void *buffer, SIZE_T size, struct d3d_blob **blob) | |
| { | |
| struct d3d_blob *object; | |
| if (!(object = vkd3d_malloc(sizeof(*object)))) | |
| return E_OUTOFMEMORY; | |
| d3d_blob_init(object, buffer, size); | |
| TRACE("Created blob object %p.\n", object); | |
| *blob = object; | |
| return S_OK; | |
| } | |
| static struct d3d_destruction_notifier *impl_from_ID3DDestructionNotifier(ID3DDestructionNotifier *iface) | |
| { | |
| return CONTAINING_RECORD(iface, struct d3d_destruction_notifier, ID3DDestructionNotifier_iface); | |
| } | |
| static HRESULT STDMETHODCALLTYPE d3d_destruction_notifier_QueryInterface(ID3DDestructionNotifier *iface, REFIID riid, void **object) | |
| { | |
| struct d3d_destruction_notifier *notifier = impl_from_ID3DDestructionNotifier(iface); | |
| TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); | |
| return IUnknown_QueryInterface(notifier->parent, riid, object); | |
| } | |
| static ULONG STDMETHODCALLTYPE d3d_destruction_notifier_AddRef(ID3DDestructionNotifier *iface) | |
| { | |
| struct d3d_destruction_notifier *notifier = impl_from_ID3DDestructionNotifier(iface); | |
| ULONG refcount = IUnknown_AddRef(notifier->parent); | |
| TRACE("%p increasing refcount to %u.\n", notifier, refcount); | |
| return refcount; | |
| } | |
| static ULONG STDMETHODCALLTYPE d3d_destruction_notifier_Release(ID3DDestructionNotifier *iface) | |
| { | |
| struct d3d_destruction_notifier *notifier = impl_from_ID3DDestructionNotifier(iface); | |
| ULONG refcount = IUnknown_Release(notifier->parent); | |
| TRACE("%p decreasing refcount to %u.\n", notifier, refcount); | |
| return refcount; | |
| } | |
| static HRESULT STDMETHODCALLTYPE d3d_destruction_notifier_RegisterDestructionCallback( | |
| ID3DDestructionNotifier *iface, PFN_DESTRUCTION_CALLBACK callback, void *data, | |
| UINT *callback_id) | |
| { | |
| struct d3d_destruction_notifier *notifier = impl_from_ID3DDestructionNotifier(iface); | |
| struct d3d_destruction_callback_entry *entry; | |
| TRACE("iface %p, callback %p, data %p, callback_id %p.\n", iface, (void*)callback, data, callback_id); | |
| if (!callback) | |
| return DXGI_ERROR_INVALID_CALL; | |
| pthread_mutex_lock(¬ifier->mutex); | |
| if (!vkd3d_array_reserve((void**)¬ifier->callbacks, ¬ifier->callback_size, | |
| notifier->callback_count + 1, sizeof(*notifier->callbacks))) | |
| { | |
| ERR("Failed to allocate callback array.\n"); | |
| pthread_mutex_unlock(¬ifier->mutex); | |
| return E_OUTOFMEMORY; | |
| } | |
| entry = ¬ifier->callbacks[notifier->callback_count++]; | |
| entry->callback = callback; | |
| entry->userdata = data; | |
| entry->callback_id = 0; | |
| if (callback_id) | |
| { | |
| entry->callback_id = ++notifier->next_callback_id; | |
| *callback_id = entry->callback_id; | |
| } | |
| pthread_mutex_unlock(¬ifier->mutex); | |
| return S_OK; | |
| } | |
| static HRESULT STDMETHODCALLTYPE d3d_destruction_notifier_UnregisterDestructionCallback( | |
| ID3DDestructionNotifier *iface, UINT callback_id) | |
| { | |
| struct d3d_destruction_notifier *notifier = impl_from_ID3DDestructionNotifier(iface); | |
| unsigned int i, entry_index; | |
| TRACE("iface %p, callback_id %u.\n", iface, callback_id); | |
| if (!callback_id) | |
| return DXGI_ERROR_NOT_FOUND; | |
| pthread_mutex_lock(¬ifier->mutex); | |
| entry_index = -1u; | |
| for (i = 0; i < notifier->callback_count; i++) | |
| { | |
| if (notifier->callbacks[i].callback_id == callback_id) | |
| { | |
| entry_index = i; | |
| break; | |
| } | |
| } | |
| if (entry_index == -1u) | |
| { | |
| pthread_mutex_unlock(¬ifier->mutex); | |
| return DXGI_ERROR_NOT_FOUND; | |
| } | |
| notifier->callbacks[entry_index] = notifier->callbacks[--notifier->callback_count]; | |
| pthread_mutex_unlock(¬ifier->mutex); | |
| return S_OK; | |
| } | |
| static CONST_VTBL struct ID3DDestructionNotifierVtbl d3d_destruction_notifier_vtbl = | |
| { | |
| /* IUnknown methods */ | |
| d3d_destruction_notifier_QueryInterface, | |
| d3d_destruction_notifier_AddRef, | |
| d3d_destruction_notifier_Release, | |
| /* ID3DDestructionNotifier methods */ | |
| d3d_destruction_notifier_RegisterDestructionCallback, | |
| d3d_destruction_notifier_UnregisterDestructionCallback | |
| }; | |
| void d3d_destruction_notifier_init(struct d3d_destruction_notifier *notifier, IUnknown *parent) | |
| { | |
| memset(notifier, 0, sizeof(*notifier)); | |
| notifier->ID3DDestructionNotifier_iface.lpVtbl = &d3d_destruction_notifier_vtbl; | |
| notifier->parent = parent; | |
| pthread_mutex_init(¬ifier->mutex, NULL); | |
| } | |
| void d3d_destruction_notifier_free(struct d3d_destruction_notifier *notifier) | |
| { | |
| d3d_destruction_notifier_notify(notifier); | |
| pthread_mutex_destroy(¬ifier->mutex); | |
| } | |
| void d3d_destruction_notifier_notify(struct d3d_destruction_notifier *notifier) | |
| { | |
| size_t i; | |
| for (i = 0; i < notifier->callback_count; i++) | |
| { | |
| const struct d3d_destruction_callback_entry *entry = ¬ifier->callbacks[i]; | |
| entry->callback(entry->userdata); | |
| } | |
| vkd3d_free(notifier->callbacks); | |
| notifier->callbacks = NULL; | |
| notifier->callback_count = 0u; | |
| notifier->callback_size = 0u; | |
| } | |