1 /*
2 * Copyright 2016 Józef Kucia for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #include "vkd3d_private.h"
20
21 #include <errno.h>
22
23 #define COLOR (VK_IMAGE_ASPECT_COLOR_BIT)
24 #define DEPTH (VK_IMAGE_ASPECT_DEPTH_BIT)
25 #define STENCIL (VK_IMAGE_ASPECT_STENCIL_BIT)
26 #define DEPTH_STENCIL (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)
27 #define TYPELESS VKD3D_FORMAT_TYPE_TYPELESS
28 #define SINT VKD3D_FORMAT_TYPE_SINT
29 #define UINT VKD3D_FORMAT_TYPE_UINT
30 static const struct vkd3d_format vkd3d_formats[] =
31 {
32 {DXGI_FORMAT_R32G32B32A32_TYPELESS, VK_FORMAT_R32G32B32A32_SFLOAT, 16, 1, 1, 1, COLOR, 1, TYPELESS},
33 {DXGI_FORMAT_R32G32B32A32_FLOAT, VK_FORMAT_R32G32B32A32_SFLOAT, 16, 1, 1, 1, COLOR, 1},
34 {DXGI_FORMAT_R32G32B32A32_UINT, VK_FORMAT_R32G32B32A32_UINT, 16, 1, 1, 1, COLOR, 1, UINT},
35 {DXGI_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32G32B32A32_SINT, 16, 1, 1, 1, COLOR, 1, SINT},
36 {DXGI_FORMAT_R32G32B32_TYPELESS, VK_FORMAT_R32G32B32_SFLOAT, 12, 1, 1, 1, COLOR, 1, TYPELESS},
37 {DXGI_FORMAT_R32G32B32_FLOAT, VK_FORMAT_R32G32B32_SFLOAT, 12, 1, 1, 1, COLOR, 1},
38 {DXGI_FORMAT_R32G32B32_UINT, VK_FORMAT_R32G32B32_UINT, 12, 1, 1, 1, COLOR, 1, UINT},
39 {DXGI_FORMAT_R32G32B32_SINT, VK_FORMAT_R32G32B32_SINT, 12, 1, 1, 1, COLOR, 1, SINT},
40 {DXGI_FORMAT_R16G16B16A16_TYPELESS, VK_FORMAT_R16G16B16A16_SFLOAT, 8, 1, 1, 1, COLOR, 1, TYPELESS},
41 {DXGI_FORMAT_R16G16B16A16_FLOAT, VK_FORMAT_R16G16B16A16_SFLOAT, 8, 1, 1, 1, COLOR, 1},
42 {DXGI_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_R16G16B16A16_UNORM, 8, 1, 1, 1, COLOR, 1},
43 {DXGI_FORMAT_R16G16B16A16_UINT, VK_FORMAT_R16G16B16A16_UINT, 8, 1, 1, 1, COLOR, 1, UINT},
44 {DXGI_FORMAT_R16G16B16A16_SNORM, VK_FORMAT_R16G16B16A16_SNORM, 8, 1, 1, 1, COLOR, 1},
45 {DXGI_FORMAT_R16G16B16A16_SINT, VK_FORMAT_R16G16B16A16_SINT, 8, 1, 1, 1, COLOR, 1, SINT},
46 {DXGI_FORMAT_R32G32_TYPELESS, VK_FORMAT_R32G32_SFLOAT, 8, 1, 1, 1, COLOR, 1, TYPELESS},
47 {DXGI_FORMAT_R32G32_FLOAT, VK_FORMAT_R32G32_SFLOAT, 8, 1, 1, 1, COLOR, 1},
48 {DXGI_FORMAT_R32G32_UINT, VK_FORMAT_R32G32_UINT, 8, 1, 1, 1, COLOR, 1, UINT},
49 {DXGI_FORMAT_R32G32_SINT, VK_FORMAT_R32G32_SINT, 8, 1, 1, 1, COLOR, 1, SINT},
50 {DXGI_FORMAT_R10G10B10A2_TYPELESS, VK_FORMAT_A2B10G10R10_UNORM_PACK32, 4, 1, 1, 1, COLOR, 1, TYPELESS},
51 {DXGI_FORMAT_R10G10B10A2_UNORM, VK_FORMAT_A2B10G10R10_UNORM_PACK32, 4, 1, 1, 1, COLOR, 1},
52 {DXGI_FORMAT_R10G10B10A2_UINT, VK_FORMAT_A2B10G10R10_UINT_PACK32, 4, 1, 1, 1, COLOR, 1, UINT},
53 {DXGI_FORMAT_R11G11B10_FLOAT, VK_FORMAT_B10G11R11_UFLOAT_PACK32, 4, 1, 1, 1, COLOR, 1},
54 {DXGI_FORMAT_R8G8_TYPELESS, VK_FORMAT_R8G8_UNORM, 2, 1, 1, 1, COLOR, 1, TYPELESS},
55 {DXGI_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8_UNORM, 2, 1, 1, 1, COLOR, 1},
56 {DXGI_FORMAT_R8G8_UINT, VK_FORMAT_R8G8_UINT, 2, 1, 1, 1, COLOR, 1, UINT},
57 {DXGI_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8_SNORM, 2, 1, 1, 1, COLOR, 1},
58 {DXGI_FORMAT_R8G8_SINT, VK_FORMAT_R8G8_SINT, 2, 1, 1, 1, COLOR, 1, SINT},
59 {DXGI_FORMAT_R8G8B8A8_TYPELESS, VK_FORMAT_R8G8B8A8_UNORM, 4, 1, 1, 1, COLOR, 1, TYPELESS},
60 {DXGI_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, 4, 1, 1, 1, COLOR, 1},
61 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, VK_FORMAT_R8G8B8A8_SRGB, 4, 1, 1, 1, COLOR, 1},
62 {DXGI_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_UINT, 4, 1, 1, 1, COLOR, 1, UINT},
63 {DXGI_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_R8G8B8A8_SNORM, 4, 1, 1, 1, COLOR, 1},
64 {DXGI_FORMAT_R8G8B8A8_SINT, VK_FORMAT_R8G8B8A8_SINT, 4, 1, 1, 1, COLOR, 1, SINT},
65 {DXGI_FORMAT_R16G16_TYPELESS, VK_FORMAT_R16G16_SFLOAT, 4, 1, 1, 1, COLOR, 1, TYPELESS},
66 {DXGI_FORMAT_R16G16_FLOAT, VK_FORMAT_R16G16_SFLOAT, 4, 1, 1, 1, COLOR, 1},
67 {DXGI_FORMAT_R16G16_UNORM, VK_FORMAT_R16G16_UNORM, 4, 1, 1, 1, COLOR, 1},
68 {DXGI_FORMAT_R16G16_UINT, VK_FORMAT_R16G16_UINT, 4, 1, 1, 1, COLOR, 1, UINT},
69 {DXGI_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16_SNORM, 4, 1, 1, 1, COLOR, 1},
70 {DXGI_FORMAT_R16G16_SINT, VK_FORMAT_R16G16_SINT, 4, 1, 1, 1, COLOR, 1, SINT},
71 {DXGI_FORMAT_R32_TYPELESS, VK_FORMAT_R32_UINT, 4, 1, 1, 1, COLOR, 1, TYPELESS},
72 {DXGI_FORMAT_D32_FLOAT, VK_FORMAT_D32_SFLOAT, 4, 1, 1, 1, DEPTH, 1},
73 {DXGI_FORMAT_R32_FLOAT, VK_FORMAT_R32_SFLOAT, 4, 1, 1, 1, COLOR, 1},
74 {DXGI_FORMAT_R32_UINT, VK_FORMAT_R32_UINT, 4, 1, 1, 1, COLOR, 1, UINT},
75 {DXGI_FORMAT_R32_SINT, VK_FORMAT_R32_SINT, 4, 1, 1, 1, COLOR, 1, SINT},
76 {DXGI_FORMAT_R16_TYPELESS, VK_FORMAT_R16_UINT, 2, 1, 1, 1, COLOR, 1, TYPELESS},
77 {DXGI_FORMAT_R16_FLOAT, VK_FORMAT_R16_SFLOAT, 2, 1, 1, 1, COLOR, 1},
78 {DXGI_FORMAT_D16_UNORM, VK_FORMAT_D16_UNORM, 2, 1, 1, 1, DEPTH, 1},
79 {DXGI_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, 2, 1, 1, 1, COLOR, 1},
80 {DXGI_FORMAT_R16_UINT, VK_FORMAT_R16_UINT, 2, 1, 1, 1, COLOR, 1, UINT},
81 {DXGI_FORMAT_R16_SNORM, VK_FORMAT_R16_SNORM, 2, 1, 1, 1, COLOR, 1},
82 {DXGI_FORMAT_R16_SINT, VK_FORMAT_R16_SINT, 2, 1, 1, 1, COLOR, 1, SINT},
83 {DXGI_FORMAT_R8_TYPELESS, VK_FORMAT_R8_UNORM, 1, 1, 1, 1, COLOR, 1, TYPELESS},
84 {DXGI_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, 1, 1, 1, 1, COLOR, 1},
85 {DXGI_FORMAT_R8_UINT, VK_FORMAT_R8_UINT, 1, 1, 1, 1, COLOR, 1, UINT},
86 {DXGI_FORMAT_R8_SNORM, VK_FORMAT_R8_SNORM, 1, 1, 1, 1, COLOR, 1},
87 {DXGI_FORMAT_R8_SINT, VK_FORMAT_R8_SINT, 1, 1, 1, 1, COLOR, 1, SINT},
88 {DXGI_FORMAT_A8_UNORM, VK_FORMAT_R8_UNORM, 1, 1, 1, 1, COLOR, 1},
89 {DXGI_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1},
90 {DXGI_FORMAT_B8G8R8X8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1},
91 {DXGI_FORMAT_B8G8R8A8_TYPELESS, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1, TYPELESS},
92 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, VK_FORMAT_B8G8R8A8_SRGB, 4, 1, 1, 1, COLOR, 1},
93 {DXGI_FORMAT_B8G8R8X8_TYPELESS, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1},
94 {DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, VK_FORMAT_B8G8R8A8_SRGB, 4, 1, 1, 1, COLOR, 1},
95 {DXGI_FORMAT_BC1_TYPELESS, VK_FORMAT_BC1_RGBA_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1, TYPELESS},
96 {DXGI_FORMAT_BC1_UNORM, VK_FORMAT_BC1_RGBA_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1},
97 {DXGI_FORMAT_BC1_UNORM_SRGB, VK_FORMAT_BC1_RGBA_SRGB_BLOCK, 1, 4, 4, 8, COLOR, 1},
98 {DXGI_FORMAT_BC2_TYPELESS, VK_FORMAT_BC2_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS},
99 {DXGI_FORMAT_BC2_UNORM, VK_FORMAT_BC2_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1},
100 {DXGI_FORMAT_BC2_UNORM_SRGB, VK_FORMAT_BC2_SRGB_BLOCK, 1, 4, 4, 16, COLOR, 1},
101 {DXGI_FORMAT_BC3_TYPELESS, VK_FORMAT_BC3_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS},
102 {DXGI_FORMAT_BC3_UNORM, VK_FORMAT_BC3_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1},
103 {DXGI_FORMAT_BC3_UNORM_SRGB, VK_FORMAT_BC3_SRGB_BLOCK, 1, 4, 4, 16, COLOR, 1},
104 {DXGI_FORMAT_BC4_TYPELESS, VK_FORMAT_BC4_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1, TYPELESS},
105 {DXGI_FORMAT_BC4_UNORM, VK_FORMAT_BC4_UNORM_BLOCK, 1, 4, 4, 8, COLOR, 1},
106 {DXGI_FORMAT_BC4_SNORM, VK_FORMAT_BC4_SNORM_BLOCK, 1, 4, 4, 8, COLOR, 1},
107 {DXGI_FORMAT_BC5_TYPELESS, VK_FORMAT_BC5_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS},
108 {DXGI_FORMAT_BC5_UNORM, VK_FORMAT_BC5_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1},
109 {DXGI_FORMAT_BC5_SNORM, VK_FORMAT_BC5_SNORM_BLOCK, 1, 4, 4, 16, COLOR, 1},
110 {DXGI_FORMAT_BC6H_TYPELESS, VK_FORMAT_BC6H_UFLOAT_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS},
111 {DXGI_FORMAT_BC6H_UF16, VK_FORMAT_BC6H_UFLOAT_BLOCK, 1, 4, 4, 16, COLOR, 1},
112 {DXGI_FORMAT_BC6H_SF16, VK_FORMAT_BC6H_SFLOAT_BLOCK, 1, 4, 4, 16, COLOR, 1},
113 {DXGI_FORMAT_BC7_TYPELESS, VK_FORMAT_BC7_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1, TYPELESS},
114 {DXGI_FORMAT_BC7_UNORM, VK_FORMAT_BC7_UNORM_BLOCK, 1, 4, 4, 16, COLOR, 1},
115 {DXGI_FORMAT_BC7_UNORM_SRGB, VK_FORMAT_BC7_SRGB_BLOCK, 1, 4, 4, 16, COLOR, 1},
116 };
117
118 /* Each depth/stencil format is only compatible with itself in Vulkan. */
119 static const struct vkd3d_format vkd3d_depth_stencil_formats[] =
120 {
121 {DXGI_FORMAT_R32G8X24_TYPELESS, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, DEPTH_STENCIL, 2, TYPELESS},
122 {DXGI_FORMAT_D32_FLOAT_S8X24_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, DEPTH_STENCIL, 2},
123 {DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, DEPTH, 2},
124 {DXGI_FORMAT_X32_TYPELESS_G8X24_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, 8, 1, 1, 1, STENCIL, 2},
125 {DXGI_FORMAT_R32_TYPELESS, VK_FORMAT_D32_SFLOAT, 4, 1, 1, 1, DEPTH, 1, TYPELESS},
126 {DXGI_FORMAT_R32_FLOAT, VK_FORMAT_D32_SFLOAT, 4, 1, 1, 1, DEPTH, 1},
127 {DXGI_FORMAT_R24G8_TYPELESS, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, DEPTH_STENCIL, 2, TYPELESS},
128 {DXGI_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, DEPTH_STENCIL, 2},
129 {DXGI_FORMAT_R24_UNORM_X8_TYPELESS, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, DEPTH, 2},
130 {DXGI_FORMAT_X24_TYPELESS_G8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, 4, 1, 1, 1, STENCIL, 2},
131 {DXGI_FORMAT_R16_TYPELESS, VK_FORMAT_D16_UNORM, 2, 1, 1, 1, DEPTH, 1, TYPELESS},
132 {DXGI_FORMAT_R16_UNORM, VK_FORMAT_D16_UNORM, 2, 1, 1, 1, DEPTH, 1},
133 };
134 #undef COLOR
135 #undef DEPTH
136 #undef STENCIL
137 #undef DEPTH_STENCIL
138 #undef TYPELESS
139 #undef SINT
140 #undef UINT
141
142 static const struct vkd3d_format_compatibility_info
143 {
144 DXGI_FORMAT format;
145 DXGI_FORMAT typeless_format;
146 }
147 vkd3d_format_compatibility_info[] =
148 {
149 /* DXGI_FORMAT_R32G32B32A32_TYPELESS */
150 {DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_TYPELESS},
151 {DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_TYPELESS},
152 {DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_TYPELESS},
153 /* DXGI_FORMAT_R32G32B32_TYPELESS */
154 {DXGI_FORMAT_R32G32B32_UINT, DXGI_FORMAT_R32G32B32_TYPELESS},
155 {DXGI_FORMAT_R32G32B32_SINT, DXGI_FORMAT_R32G32B32_TYPELESS},
156 {DXGI_FORMAT_R32G32B32_FLOAT, DXGI_FORMAT_R32G32B32_TYPELESS},
157 /* DXGI_FORMAT_R16G16B16A16_TYPELESS */
158 {DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_TYPELESS},
159 {DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_TYPELESS},
160 {DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_TYPELESS},
161 {DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_TYPELESS},
162 {DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_TYPELESS},
163 /* DXGI_FORMAT_R32G32_TYPELESS */
164 {DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_TYPELESS},
165 {DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_TYPELESS},
166 {DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_TYPELESS},
167 /* DXGI_FORMAT_R32G8X24_TYPELESS */
168 {DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_R32G8X24_TYPELESS},
169 {DXGI_FORMAT_X32_TYPELESS_G8X24_UINT, DXGI_FORMAT_R32G8X24_TYPELESS},
170 {DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32G8X24_TYPELESS},
171 /* DXGI_FORMAT_R10G10B10A2_TYPELESS */
172 {DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_TYPELESS},
173 {DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_TYPELESS},
174 /* DXGI_FORMAT_R8G8B8A8_TYPELESS */
175 {DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_TYPELESS},
176 {DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_TYPELESS},
177 {DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS},
178 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_TYPELESS},
179 {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS},
180 /* DXGI_FORMAT_R16G16_TYPELESS */
181 {DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16_TYPELESS},
182 {DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16_TYPELESS},
183 {DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_TYPELESS},
184 {DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_TYPELESS},
185 {DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_TYPELESS},
186 /* DXGI_FORMAT_R32_TYPELESS */
187 {DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_TYPELESS},
188 {DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS},
189 {DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_TYPELESS},
190 {DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_TYPELESS},
191 /* DXGI_FORMAT_R24G8_TYPELESS */
192 {DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_R24G8_TYPELESS},
193 {DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_R24G8_TYPELESS},
194 {DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_R24G8_TYPELESS},
195 /* DXGI_FORMAT_R8G8_TYPELESS */
196 {DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_TYPELESS},
197 {DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_TYPELESS},
198 {DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_TYPELESS},
199 {DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_TYPELESS},
200 /* DXGI_FORMAT_R16_TYPELESS */
201 {DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_R16_TYPELESS},
202 {DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_TYPELESS},
203 {DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16_TYPELESS},
204 {DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_TYPELESS},
205 {DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_TYPELESS},
206 {DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_TYPELESS},
207 /* DXGI_FORMAT_R8_TYPELESS */
208 {DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_TYPELESS},
209 {DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_TYPELESS},
210 {DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_TYPELESS},
211 {DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_TYPELESS},
212 /* DXGI_FORMAT_BC1_TYPELESS */
213 {DXGI_FORMAT_BC1_UNORM_SRGB, DXGI_FORMAT_BC1_TYPELESS},
214 {DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_TYPELESS},
215 /* DXGI_FORMAT_BC2_TYPELESS */
216 {DXGI_FORMAT_BC2_UNORM_SRGB, DXGI_FORMAT_BC2_TYPELESS},
217 {DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_TYPELESS},
218 /* DXGI_FORMAT_BC3_TYPELESS */
219 {DXGI_FORMAT_BC3_UNORM_SRGB, DXGI_FORMAT_BC3_TYPELESS},
220 {DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_TYPELESS},
221 /* DXGI_FORMAT_BC4_TYPELESS */
222 {DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_TYPELESS},
223 {DXGI_FORMAT_BC4_SNORM, DXGI_FORMAT_BC4_TYPELESS},
224 /* DXGI_FORMAT_BC5_TYPELESS */
225 {DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_TYPELESS},
226 {DXGI_FORMAT_BC5_SNORM, DXGI_FORMAT_BC5_TYPELESS},
227 /* DXGI_FORMAT_BC6H_TYPELESS */
228 {DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_TYPELESS},
229 {DXGI_FORMAT_BC6H_SF16, DXGI_FORMAT_BC6H_TYPELESS},
230 /* DXGI_FORMAT_BC7_TYPELESS */
231 {DXGI_FORMAT_BC7_UNORM_SRGB, DXGI_FORMAT_BC7_TYPELESS},
232 {DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_TYPELESS},
233 /* DXGI_FORMAT_B8G8R8A8_TYPELESS */
234 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_B8G8R8A8_TYPELESS},
235 {DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_TYPELESS},
236 /* DXGI_FORMAT_B8G8R8X8_TYPELESS */
237 {DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, DXGI_FORMAT_B8G8R8X8_TYPELESS},
238 {DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8X8_TYPELESS},
239 };
240
dxgi_format_is_depth_stencil(DXGI_FORMAT dxgi_format)241 static bool dxgi_format_is_depth_stencil(DXGI_FORMAT dxgi_format)
242 {
243 unsigned int i;
244
245 for (i = 0; i < ARRAY_SIZE(vkd3d_formats); ++i)
246 {
247 const struct vkd3d_format *current = &vkd3d_formats[i];
248
249 if (current->dxgi_format == dxgi_format)
250 return current->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
251 }
252
253 for (i = 0; i < ARRAY_SIZE(vkd3d_depth_stencil_formats); ++i)
254 {
255 if (vkd3d_depth_stencil_formats[i].dxgi_format == dxgi_format)
256 return true;
257 }
258
259 return false;
260 }
261
262 /* FIXME: This table should be generated at compile-time. */
vkd3d_init_format_compatibility_lists(struct d3d12_device * device)263 static HRESULT vkd3d_init_format_compatibility_lists(struct d3d12_device *device)
264 {
265 struct vkd3d_format_compatibility_list *lists, *current_list;
266 const struct vkd3d_format_compatibility_info *current;
267 DXGI_FORMAT dxgi_format;
268 VkFormat vk_format;
269 unsigned int count;
270 unsigned int i, j;
271
272 device->format_compatibility_list_count = 0;
273 device->format_compatibility_lists = NULL;
274
275 if (!device->vk_info.KHR_image_format_list)
276 return S_OK;
277
278 count = 1;
279 dxgi_format = vkd3d_format_compatibility_info[0].typeless_format;
280 for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i)
281 {
282 DXGI_FORMAT typeless_format = vkd3d_format_compatibility_info[i].typeless_format;
283
284 if (dxgi_format != typeless_format)
285 {
286 ++count;
287 dxgi_format = typeless_format;
288 }
289 }
290
291 if (!(lists = vkd3d_calloc(count, sizeof(*lists))))
292 return E_OUTOFMEMORY;
293
294 count = 0;
295 current_list = lists;
296 current_list->typeless_format = vkd3d_format_compatibility_info[0].typeless_format;
297 for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i)
298 {
299 current = &vkd3d_format_compatibility_info[i];
300
301 if (current_list->typeless_format != current->typeless_format)
302 {
303 /* Avoid empty format lists. */
304 if (current_list->format_count)
305 {
306 ++current_list;
307 ++count;
308 }
309
310 current_list->typeless_format = current->typeless_format;
311 }
312
313 /* In Vulkan, each depth-stencil format is only compatible with itself. */
314 if (dxgi_format_is_depth_stencil(current->format))
315 continue;
316
317 if (!(vk_format = vkd3d_get_vk_format(current->format)))
318 continue;
319
320 for (j = 0; j < current_list->format_count; ++j)
321 {
322 if (current_list->vk_formats[j] == vk_format)
323 break;
324 }
325
326 if (j >= current_list->format_count)
327 {
328 assert(current_list->format_count < VKD3D_MAX_COMPATIBLE_FORMAT_COUNT);
329 current_list->vk_formats[current_list->format_count++] = vk_format;
330 }
331 }
332 if (current_list->format_count)
333 ++count;
334
335 device->format_compatibility_list_count = count;
336 device->format_compatibility_lists = lists;
337 return S_OK;
338 }
339
vkd3d_cleanup_format_compatibility_lists(struct d3d12_device * device)340 static void vkd3d_cleanup_format_compatibility_lists(struct d3d12_device *device)
341 {
342 vkd3d_free((void *)device->format_compatibility_lists);
343
344 device->format_compatibility_lists = NULL;
345 device->format_compatibility_list_count = 0;
346 }
347
vkd3d_init_depth_stencil_formats(struct d3d12_device * device)348 static HRESULT vkd3d_init_depth_stencil_formats(struct d3d12_device *device)
349 {
350 const unsigned int count = ARRAY_SIZE(vkd3d_depth_stencil_formats);
351 const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
352 VkFormatProperties properties;
353 struct vkd3d_format *formats;
354 unsigned int i;
355
356 VK_CALL(vkGetPhysicalDeviceFormatProperties(device->vk_physical_device,
357 VK_FORMAT_D24_UNORM_S8_UINT, &properties));
358
359 if (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
360 {
361 device->depth_stencil_formats = vkd3d_depth_stencil_formats;
362 }
363 else
364 {
365 /* AMD doesn't support VK_FORMAT_D24_UNORM_S8_UINT. */
366 WARN("Mapping VK_FORMAT_D24_UNORM_S8_UINT to VK_FORMAT_D32_SFLOAT_S8_UINT.\n");
367
368 if (!(formats = vkd3d_calloc(count, sizeof(*formats))))
369 return E_OUTOFMEMORY;
370
371 memcpy(formats, vkd3d_depth_stencil_formats, sizeof(vkd3d_depth_stencil_formats));
372 for (i = 0; i < count; ++i)
373 {
374 if (formats[i].vk_format == VK_FORMAT_D24_UNORM_S8_UINT)
375 {
376 formats[i].vk_format = VK_FORMAT_D32_SFLOAT_S8_UINT;
377 formats[i].is_emulated = true;
378 }
379 }
380
381 device->depth_stencil_formats = formats;
382 }
383
384 return S_OK;
385 }
386
vkd3d_cleanup_depth_stencil_formats(struct d3d12_device * device)387 static void vkd3d_cleanup_depth_stencil_formats(struct d3d12_device *device)
388 {
389 if (vkd3d_depth_stencil_formats != device->depth_stencil_formats)
390 vkd3d_free((void *)device->depth_stencil_formats);
391
392 device->depth_stencil_formats = NULL;
393 }
394
vkd3d_init_format_info(struct d3d12_device * device)395 HRESULT vkd3d_init_format_info(struct d3d12_device *device)
396 {
397 HRESULT hr;
398
399 if (FAILED(hr = vkd3d_init_depth_stencil_formats(device)))
400 return hr;
401
402 if FAILED(hr = vkd3d_init_format_compatibility_lists(device))
403 vkd3d_cleanup_depth_stencil_formats(device);
404
405 return hr;
406 }
407
vkd3d_cleanup_format_info(struct d3d12_device * device)408 void vkd3d_cleanup_format_info(struct d3d12_device *device)
409 {
410 vkd3d_cleanup_depth_stencil_formats(device);
411 vkd3d_cleanup_format_compatibility_lists(device);
412 }
413
414 /* We use overrides for depth/stencil formats. This is required in order to
415 * properly support typeless formats because depth/stencil formats are only
416 * compatible with themselves in Vulkan.
417 */
vkd3d_get_depth_stencil_format(const struct d3d12_device * device,DXGI_FORMAT dxgi_format)418 static const struct vkd3d_format *vkd3d_get_depth_stencil_format(const struct d3d12_device *device,
419 DXGI_FORMAT dxgi_format)
420 {
421 const struct vkd3d_format *formats;
422 unsigned int i;
423
424 assert(device);
425 formats = device->depth_stencil_formats;
426
427 for (i = 0; i < ARRAY_SIZE(vkd3d_depth_stencil_formats); ++i)
428 {
429 if (formats[i].dxgi_format == dxgi_format)
430 return &formats[i];
431 }
432
433 return NULL;
434 }
435
vkd3d_get_format(const struct d3d12_device * device,DXGI_FORMAT dxgi_format,bool depth_stencil)436 const struct vkd3d_format *vkd3d_get_format(const struct d3d12_device *device,
437 DXGI_FORMAT dxgi_format, bool depth_stencil)
438 {
439 const struct vkd3d_format *format;
440 unsigned int i;
441
442 if (depth_stencil && (format = vkd3d_get_depth_stencil_format(device, dxgi_format)))
443 return format;
444
445 for (i = 0; i < ARRAY_SIZE(vkd3d_formats); ++i)
446 {
447 if (vkd3d_formats[i].dxgi_format == dxgi_format)
448 return &vkd3d_formats[i];
449 }
450
451 return NULL;
452 }
453
vkd3d_find_uint_format(const struct d3d12_device * device,DXGI_FORMAT dxgi_format)454 const struct vkd3d_format *vkd3d_find_uint_format(const struct d3d12_device *device, DXGI_FORMAT dxgi_format)
455 {
456 DXGI_FORMAT typeless_format = DXGI_FORMAT_UNKNOWN;
457 const struct vkd3d_format *vkd3d_format;
458 unsigned int i;
459
460 for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i)
461 {
462 if (vkd3d_format_compatibility_info[i].format == dxgi_format)
463 {
464 typeless_format = vkd3d_format_compatibility_info[i].typeless_format;
465 break;
466 }
467 }
468
469 if (!typeless_format)
470 return NULL;
471
472 for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i)
473 {
474 if (vkd3d_format_compatibility_info[i].typeless_format != typeless_format)
475 continue;
476
477 vkd3d_format = vkd3d_get_format(device, vkd3d_format_compatibility_info[i].format, false);
478 if (vkd3d_format->type == VKD3D_FORMAT_TYPE_UINT)
479 return vkd3d_format;
480 }
481
482 return NULL;
483 }
484
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)485 void vkd3d_format_copy_data(const struct vkd3d_format *format, const uint8_t *src,
486 unsigned int src_row_pitch, unsigned int src_slice_pitch, uint8_t *dst, unsigned int dst_row_pitch,
487 unsigned int dst_slice_pitch, unsigned int w, unsigned int h, unsigned int d)
488 {
489 unsigned int row_block_count, row_count, row_size, slice, row;
490 unsigned int slice_count = d;
491 const uint8_t *src_row;
492 uint8_t *dst_row;
493
494 row_block_count = (w + format->block_width - 1) / format->block_width;
495 row_count = (h + format->block_height - 1) / format->block_height;
496 row_size = row_block_count * format->byte_count * format->block_byte_count;
497
498 for (slice = 0; slice < slice_count; ++slice)
499 {
500 for (row = 0; row < row_count; ++row)
501 {
502 src_row = &src[slice * src_slice_pitch + row * src_row_pitch];
503 dst_row = &dst[slice * dst_slice_pitch + row * dst_row_pitch];
504 memcpy(dst_row, src_row, row_size);
505 }
506 }
507 }
508
vkd3d_get_vk_format(DXGI_FORMAT format)509 VkFormat vkd3d_get_vk_format(DXGI_FORMAT format)
510 {
511 const struct vkd3d_format *vkd3d_format;
512
513 if (!(vkd3d_format = vkd3d_get_format(NULL, format, false)))
514 return VK_FORMAT_UNDEFINED;
515
516 return vkd3d_format->vk_format;
517 }
518
vkd3d_get_dxgi_format(VkFormat format)519 DXGI_FORMAT vkd3d_get_dxgi_format(VkFormat format)
520 {
521 DXGI_FORMAT dxgi_format;
522 VkFormat vk_format;
523 unsigned int i;
524
525 for (i = 0; i < ARRAY_SIZE(vkd3d_formats); ++i)
526 {
527 vk_format = vkd3d_formats[i].vk_format;
528 dxgi_format = vkd3d_formats[i].dxgi_format;
529 if (vk_format == format && vkd3d_formats[i].type != VKD3D_FORMAT_TYPE_TYPELESS)
530 return dxgi_format;
531 }
532
533 FIXME("Unhandled Vulkan format %#x.\n", format);
534 return DXGI_FORMAT_UNKNOWN;
535 }
536
is_valid_feature_level(D3D_FEATURE_LEVEL feature_level)537 bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level)
538 {
539 static const D3D_FEATURE_LEVEL valid_feature_levels[] =
540 {
541 D3D_FEATURE_LEVEL_12_1,
542 D3D_FEATURE_LEVEL_12_0,
543 D3D_FEATURE_LEVEL_11_1,
544 D3D_FEATURE_LEVEL_11_0,
545 D3D_FEATURE_LEVEL_10_1,
546 D3D_FEATURE_LEVEL_10_0,
547 D3D_FEATURE_LEVEL_9_3,
548 D3D_FEATURE_LEVEL_9_2,
549 D3D_FEATURE_LEVEL_9_1,
550 };
551 unsigned int i;
552
553 for (i = 0; i < ARRAY_SIZE(valid_feature_levels); ++i)
554 {
555 if (valid_feature_levels[i] == feature_level)
556 return true;
557 }
558
559 return false;
560 }
561
is_write_resource_state(D3D12_RESOURCE_STATES state)562 bool is_write_resource_state(D3D12_RESOURCE_STATES state)
563 {
564 return state & (D3D12_RESOURCE_STATE_RENDER_TARGET
565 | D3D12_RESOURCE_STATE_UNORDERED_ACCESS
566 | D3D12_RESOURCE_STATE_DEPTH_WRITE
567 | D3D12_RESOURCE_STATE_STREAM_OUT
568 | D3D12_RESOURCE_STATE_COPY_DEST
569 | D3D12_RESOURCE_STATE_RESOLVE_DEST);
570 }
571
is_power_of_two(unsigned int x)572 static bool is_power_of_two(unsigned int x)
573 {
574 return x && !(x & (x -1));
575 }
576
is_valid_resource_state(D3D12_RESOURCE_STATES state)577 bool is_valid_resource_state(D3D12_RESOURCE_STATES state)
578 {
579 const D3D12_RESOURCE_STATES valid_states =
580 D3D12_RESOURCE_STATE_COMMON |
581 D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER |
582 D3D12_RESOURCE_STATE_INDEX_BUFFER |
583 D3D12_RESOURCE_STATE_RENDER_TARGET |
584 D3D12_RESOURCE_STATE_UNORDERED_ACCESS |
585 D3D12_RESOURCE_STATE_DEPTH_WRITE |
586 D3D12_RESOURCE_STATE_DEPTH_READ |
587 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE |
588 D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE |
589 D3D12_RESOURCE_STATE_STREAM_OUT |
590 D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT |
591 D3D12_RESOURCE_STATE_COPY_DEST |
592 D3D12_RESOURCE_STATE_COPY_SOURCE |
593 D3D12_RESOURCE_STATE_RESOLVE_DEST |
594 D3D12_RESOURCE_STATE_RESOLVE_SOURCE |
595 D3D12_RESOURCE_STATE_GENERIC_READ |
596 D3D12_RESOURCE_STATE_PRESENT |
597 D3D12_RESOURCE_STATE_PREDICATION;
598
599 if (state & ~valid_states)
600 {
601 WARN("Invalid resource states %#x.\n", state & ~valid_states);
602 return false;
603 }
604
605 /* Exactly one bit must be set for write states. */
606 if (is_write_resource_state(state) && !is_power_of_two(state))
607 {
608 WARN("Write state cannot be mixed with other states: %#x.\n", state);
609 return false;
610 }
611
612 return true;
613 }
614
return_interface(void * iface,REFIID iface_iid,REFIID requested_iid,void ** object)615 HRESULT return_interface(void *iface, REFIID iface_iid,
616 REFIID requested_iid, void **object)
617 {
618 IUnknown *unknown = iface;
619 HRESULT hr;
620
621 if (IsEqualGUID(iface_iid, requested_iid))
622 {
623 *object = unknown;
624 return S_OK;
625 }
626
627 hr = IUnknown_QueryInterface(unknown, requested_iid, object);
628 IUnknown_Release(unknown);
629 return hr;
630 }
631
debug_d3d12_box(const D3D12_BOX * box)632 const char *debug_d3d12_box(const D3D12_BOX *box)
633 {
634 if (!box)
635 return "(null)";
636
637 return vkd3d_dbg_sprintf("(%u, %u, %u)-(%u, %u, %u)",
638 box->left, box->top, box->front,
639 box->right, box->bottom, box->back);
640 }
641
debug_d3d12_shader_component(D3D12_SHADER_COMPONENT_MAPPING component)642 static const char *debug_d3d12_shader_component(D3D12_SHADER_COMPONENT_MAPPING component)
643 {
644 switch (component)
645 {
646 case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0:
647 return "r";
648 case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1:
649 return "g";
650 case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2:
651 return "b";
652 case D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3:
653 return "a";
654 case D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0:
655 return "0";
656 case D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1:
657 return "1";
658 }
659
660 FIXME("Invalid component mapping %#x.\n", component);
661 return "invalid";
662 }
663
debug_d3d12_shader_component_mapping(unsigned int mapping)664 const char *debug_d3d12_shader_component_mapping(unsigned int mapping)
665 {
666 return vkd3d_dbg_sprintf("{%s, %s, %s, %s}",
667 debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(0, mapping)),
668 debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(1, mapping)),
669 debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(2, mapping)),
670 debug_d3d12_shader_component(D3D12_DECODE_SHADER_4_COMPONENT_MAPPING(3, mapping)));
671 }
672
debug_vk_extent_3d(VkExtent3D extent)673 const char *debug_vk_extent_3d(VkExtent3D extent)
674 {
675 return vkd3d_dbg_sprintf("(%u, %u, %u)",
676 (unsigned int)extent.width,
677 (unsigned int)extent.height,
678 (unsigned int)extent.depth);
679 }
680
debug_vk_queue_flags(VkQueueFlags flags)681 const char *debug_vk_queue_flags(VkQueueFlags flags)
682 {
683 char buffer[120];
684
685 buffer[0] = '\0';
686 #define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; }
687 FLAG_TO_STR(VK_QUEUE_GRAPHICS_BIT)
688 FLAG_TO_STR(VK_QUEUE_COMPUTE_BIT)
689 FLAG_TO_STR(VK_QUEUE_TRANSFER_BIT)
690 FLAG_TO_STR(VK_QUEUE_SPARSE_BINDING_BIT)
691 #undef FLAG_TO_STR
692 if (flags)
693 FIXME("Unrecognized flag(s) %#x.\n", flags);
694
695 if (!buffer[0])
696 return "0";
697 return vkd3d_dbg_sprintf("%s", &buffer[3]);
698 }
699
debug_vk_memory_heap_flags(VkMemoryHeapFlags flags)700 const char *debug_vk_memory_heap_flags(VkMemoryHeapFlags flags)
701 {
702 char buffer[80];
703
704 buffer[0] = '\0';
705 #define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; }
706 FLAG_TO_STR(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
707 FLAG_TO_STR(VK_MEMORY_HEAP_MULTI_INSTANCE_BIT)
708 #undef FLAG_TO_STR
709 if (flags)
710 FIXME("Unrecognized flag(s) %#x.\n", flags);
711
712 if (!buffer[0])
713 return "0";
714 return vkd3d_dbg_sprintf("%s", &buffer[3]);
715 }
716
debug_vk_memory_property_flags(VkMemoryPropertyFlags flags)717 const char *debug_vk_memory_property_flags(VkMemoryPropertyFlags flags)
718 {
719 char buffer[200];
720
721 buffer[0] = '\0';
722 #define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; }
723 FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
724 FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
725 FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
726 FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
727 FLAG_TO_STR(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
728 #undef FLAG_TO_STR
729 if (flags)
730 FIXME("Unrecognized flag(s) %#x.\n", flags);
731
732 if (!buffer[0])
733 return "0";
734 return vkd3d_dbg_sprintf("%s", &buffer[3]);
735 }
736
hresult_from_errno(int rc)737 HRESULT hresult_from_errno(int rc)
738 {
739 switch (rc)
740 {
741 case 0:
742 return S_OK;
743 case ENOMEM:
744 return E_OUTOFMEMORY;
745 case EINVAL:
746 return E_INVALIDARG;
747 default:
748 FIXME("Unhandled errno %d.\n", rc);
749 return E_FAIL;
750 }
751 }
752
hresult_from_vk_result(VkResult vr)753 HRESULT hresult_from_vk_result(VkResult vr)
754 {
755 switch (vr)
756 {
757 case VK_SUCCESS:
758 return S_OK;
759 case VK_ERROR_OUT_OF_DEVICE_MEMORY:
760 WARN("Out of device memory.\n");
761 /* fall-through */
762 case VK_ERROR_OUT_OF_HOST_MEMORY:
763 return E_OUTOFMEMORY;
764 default:
765 FIXME("Unhandled VkResult %d.\n", vr);
766 /* fall-through */
767 case VK_ERROR_DEVICE_LOST:
768 case VK_ERROR_EXTENSION_NOT_PRESENT:
769 return E_FAIL;
770 }
771 }
772
hresult_from_vkd3d_result(int vkd3d_result)773 HRESULT hresult_from_vkd3d_result(int vkd3d_result)
774 {
775 switch (vkd3d_result)
776 {
777 case VKD3D_OK:
778 return S_OK;
779 case VKD3D_ERROR_INVALID_SHADER:
780 WARN("Invalid shader bytecode.\n");
781 /* fall-through */
782 case VKD3D_ERROR:
783 return E_FAIL;
784 case VKD3D_ERROR_OUT_OF_MEMORY:
785 return E_OUTOFMEMORY;
786 case VKD3D_ERROR_INVALID_ARGUMENT:
787 return E_INVALIDARG;
788 case VKD3D_ERROR_NOT_IMPLEMENTED:
789 return E_NOTIMPL;
790 default:
791 FIXME("Unhandled vkd3d result %d.\n", vkd3d_result);
792 return E_FAIL;
793 }
794 }
795
796 #define LOAD_GLOBAL_PFN(name) \
797 if (!(procs->name = (void *)vkGetInstanceProcAddr(NULL, #name))) \
798 { \
799 ERR("Could not get global proc addr for '" #name "'.\n"); \
800 return E_FAIL; \
801 }
802
vkd3d_load_vk_global_procs(struct vkd3d_vk_global_procs * procs,PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr)803 HRESULT vkd3d_load_vk_global_procs(struct vkd3d_vk_global_procs *procs,
804 PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr)
805 {
806 memset(procs, 0, sizeof(*procs));
807
808 procs->vkGetInstanceProcAddr = vkGetInstanceProcAddr;
809
810 LOAD_GLOBAL_PFN(vkCreateInstance)
811 LOAD_GLOBAL_PFN(vkEnumerateInstanceExtensionProperties)
812
813 TRACE("Loaded global Vulkan procs.\n");
814 return S_OK;
815 }
816
817 #define LOAD_INSTANCE_PFN(name) \
818 if (!(procs->name = (void *)global_procs->vkGetInstanceProcAddr(instance, #name))) \
819 { \
820 ERR("Could not get instance proc addr for '" #name "'.\n"); \
821 return E_FAIL; \
822 }
823 #define LOAD_INSTANCE_OPTIONAL_PFN(name) \
824 procs->name = (void *)global_procs->vkGetInstanceProcAddr(instance, #name);
825
vkd3d_load_vk_instance_procs(struct vkd3d_vk_instance_procs * procs,const struct vkd3d_vk_global_procs * global_procs,VkInstance instance)826 HRESULT vkd3d_load_vk_instance_procs(struct vkd3d_vk_instance_procs *procs,
827 const struct vkd3d_vk_global_procs *global_procs, VkInstance instance)
828 {
829 memset(procs, 0, sizeof(*procs));
830
831 #define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
832 #define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPTIONAL_PFN
833 #include "vulkan_procs.h"
834
835 TRACE("Loaded procs for VkInstance %p.\n", instance);
836 return S_OK;
837 }
838
839 #define COPY_PARENT_PFN(name) procs->name = parent_procs->name;
840 #define LOAD_DEVICE_PFN(name) \
841 if (!(procs->name = (void *)procs->vkGetDeviceProcAddr(device, #name))) \
842 { \
843 ERR("Could not get device proc addr for '" #name "'.\n"); \
844 return E_FAIL; \
845 }
846 #define LOAD_DEVICE_OPTIONAL_PFN(name) \
847 procs->name = (void *)procs->vkGetDeviceProcAddr(device, #name);
848
vkd3d_load_vk_device_procs(struct vkd3d_vk_device_procs * procs,const struct vkd3d_vk_instance_procs * parent_procs,VkDevice device)849 HRESULT vkd3d_load_vk_device_procs(struct vkd3d_vk_device_procs *procs,
850 const struct vkd3d_vk_instance_procs *parent_procs, VkDevice device)
851 {
852 memset(procs, 0, sizeof(*procs));
853
854 #define VK_INSTANCE_PFN COPY_PARENT_PFN
855 #define VK_DEVICE_PFN LOAD_DEVICE_PFN
856 #define VK_DEVICE_EXT_PFN LOAD_DEVICE_OPTIONAL_PFN
857 #include "vulkan_procs.h"
858
859 TRACE("Loaded procs for VkDevice %p.\n", device);
860 return S_OK;
861 }
862
863 #if HAVE_DECL_PROGRAM_INVOCATION_NAME
864
vkd3d_get_program_name(char program_name[PATH_MAX])865 bool vkd3d_get_program_name(char program_name[PATH_MAX])
866 {
867 char *name, *p, *real_path = NULL;
868
869 if ((name = strrchr(program_invocation_name, '/')))
870 {
871 real_path = realpath("/proc/self/exe", NULL);
872
873 /* Try to strip command line arguments. */
874 if (real_path && (p = strrchr(real_path, '/'))
875 && !strncmp(real_path, program_invocation_name, strlen(real_path)))
876 {
877 name = p;
878 }
879
880 ++name;
881 }
882 else if ((name = strrchr(program_invocation_name, '\\')))
883 {
884 ++name;
885 }
886 else
887 {
888 name = program_invocation_name;
889 }
890
891 strncpy(program_name, name, PATH_MAX);
892 program_name[PATH_MAX - 1] = '\0';
893 free(real_path);
894 return true;
895 }
896
897 #else
898
vkd3d_get_program_name(char program_name[PATH_MAX])899 bool vkd3d_get_program_name(char program_name[PATH_MAX])
900 {
901 *program_name = '\0';
902 return false;
903 }
904
905 #endif /* HAVE_DECL_PROGRAM_INVOCATION_NAME */
906
vkd3d_private_store_get_private_data(const struct vkd3d_private_store * store,const GUID * tag)907 static struct vkd3d_private_data *vkd3d_private_store_get_private_data(
908 const struct vkd3d_private_store *store, const GUID *tag)
909 {
910 struct vkd3d_private_data *data;
911
912 LIST_FOR_EACH_ENTRY(data, &store->content, struct vkd3d_private_data, entry)
913 {
914 if (IsEqualGUID(&data->tag, tag))
915 return data;
916 }
917
918 return NULL;
919 }
920
vkd3d_private_store_set_private_data(struct vkd3d_private_store * store,const GUID * tag,const void * data,unsigned int data_size,bool is_object)921 static HRESULT vkd3d_private_store_set_private_data(struct vkd3d_private_store *store,
922 const GUID *tag, const void *data, unsigned int data_size, bool is_object)
923 {
924 struct vkd3d_private_data *d, *old_data;
925 const void *ptr = data;
926
927 if (!data)
928 {
929 if ((d = vkd3d_private_store_get_private_data(store, tag)))
930 {
931 vkd3d_private_data_destroy(d);
932 return S_OK;
933 }
934
935 return S_FALSE;
936 }
937
938 if (is_object)
939 {
940 if (data_size != sizeof(IUnknown *))
941 return E_INVALIDARG;
942 ptr = &data;
943 }
944
945 if (!(d = vkd3d_malloc(offsetof(struct vkd3d_private_data, u.data[data_size]))))
946 return E_OUTOFMEMORY;
947
948 d->tag = *tag;
949 d->size = data_size;
950 d->is_object = is_object;
951 memcpy(d->u.data, ptr, data_size);
952 if (is_object)
953 IUnknown_AddRef(d->u.object);
954
955 if ((old_data = vkd3d_private_store_get_private_data(store, tag)))
956 vkd3d_private_data_destroy(old_data);
957 list_add_tail(&store->content, &d->entry);
958
959 return S_OK;
960 }
961
vkd3d_get_private_data(struct vkd3d_private_store * store,const GUID * tag,unsigned int * out_size,void * out)962 HRESULT vkd3d_get_private_data(struct vkd3d_private_store *store,
963 const GUID *tag, unsigned int *out_size, void *out)
964 {
965 const struct vkd3d_private_data *data;
966 HRESULT hr = S_OK;
967 unsigned int size;
968 int rc;
969
970 if (!out_size)
971 return E_INVALIDARG;
972
973 if ((rc = pthread_mutex_lock(&store->mutex)))
974 {
975 ERR("Failed to lock mutex, error %d.\n", rc);
976 return hresult_from_errno(rc);
977 }
978
979 if (!(data = vkd3d_private_store_get_private_data(store, tag)))
980 {
981 *out_size = 0;
982 hr = DXGI_ERROR_NOT_FOUND;
983 goto done;
984 }
985
986 size = *out_size;
987 *out_size = data->size;
988 if (!out)
989 goto done;
990
991 if (size < data->size)
992 {
993 hr = DXGI_ERROR_MORE_DATA;
994 goto done;
995 }
996
997 if (data->is_object)
998 IUnknown_AddRef(data->u.object);
999 memcpy(out, data->u.data, data->size);
1000
1001 done:
1002 pthread_mutex_unlock(&store->mutex);
1003 return hr;
1004 }
1005
vkd3d_set_private_data(struct vkd3d_private_store * store,const GUID * tag,unsigned int data_size,const void * data)1006 HRESULT vkd3d_set_private_data(struct vkd3d_private_store *store,
1007 const GUID *tag, unsigned int data_size, const void *data)
1008 {
1009 HRESULT hr;
1010 int rc;
1011
1012 if ((rc = pthread_mutex_lock(&store->mutex)))
1013 {
1014 ERR("Failed to lock mutex, error %d.\n", rc);
1015 return hresult_from_errno(rc);
1016 }
1017
1018 hr = vkd3d_private_store_set_private_data(store, tag, data, data_size, false);
1019
1020 pthread_mutex_unlock(&store->mutex);
1021 return hr;
1022 }
1023
vkd3d_set_private_data_interface(struct vkd3d_private_store * store,const GUID * tag,const IUnknown * object)1024 HRESULT vkd3d_set_private_data_interface(struct vkd3d_private_store *store,
1025 const GUID *tag, const IUnknown *object)
1026 {
1027 const void *data = object ? object : (void *)&object;
1028 HRESULT hr;
1029 int rc;
1030
1031 if ((rc = pthread_mutex_lock(&store->mutex)))
1032 {
1033 ERR("Failed to lock mutex, error %d.\n", rc);
1034 return hresult_from_errno(rc);
1035 }
1036
1037 hr = vkd3d_private_store_set_private_data(store, tag, data, sizeof(object), !!object);
1038
1039 pthread_mutex_unlock(&store->mutex);
1040 return hr;
1041 }
1042
vkd3d_set_vk_object_name_utf8(struct d3d12_device * device,uint64_t vk_object,VkDebugReportObjectTypeEXT vk_object_type,const char * name)1043 VkResult vkd3d_set_vk_object_name_utf8(struct d3d12_device *device, uint64_t vk_object,
1044 VkDebugReportObjectTypeEXT vk_object_type, const char *name)
1045 {
1046 const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
1047 VkDebugMarkerObjectNameInfoEXT info;
1048
1049 if (!device->vk_info.EXT_debug_marker)
1050 return VK_SUCCESS;
1051
1052 info.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
1053 info.pNext = NULL;
1054 info.objectType = vk_object_type;
1055 info.object = vk_object;
1056 info.pObjectName = name;
1057 return VK_CALL(vkDebugMarkerSetObjectNameEXT(device->vk_device, &info));
1058 }
1059
vkd3d_set_vk_object_name(struct d3d12_device * device,uint64_t vk_object,VkDebugReportObjectTypeEXT vk_object_type,const WCHAR * name)1060 HRESULT vkd3d_set_vk_object_name(struct d3d12_device *device, uint64_t vk_object,
1061 VkDebugReportObjectTypeEXT vk_object_type, const WCHAR *name)
1062 {
1063 char *name_utf8;
1064 VkResult vr;
1065
1066 if (!name)
1067 return E_INVALIDARG;
1068
1069 if (!device->vk_info.EXT_debug_marker)
1070 return S_OK;
1071
1072 if (!(name_utf8 = vkd3d_strdup_w_utf8(name, device->wchar_size)))
1073 return E_OUTOFMEMORY;
1074
1075 vr = vkd3d_set_vk_object_name_utf8(device, vk_object, vk_object_type, name_utf8);
1076
1077 vkd3d_free(name_utf8);
1078
1079 return hresult_from_vk_result(vr);
1080 }
1081