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