1 /*
2  * Copyright © Microsoft Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "d3d12_format.h"
25 
26 #include "pipe/p_format.h"
27 #include "util/format/u_format.h"
28 #include "util/u_math.h"
29 #include "util/compiler.h"
30 
31 static const DXGI_FORMAT formats[PIPE_FORMAT_COUNT] = {
32 #define MAP_FORMAT_NORM(FMT) \
33    [PIPE_FORMAT_ ## FMT ## _UNORM] = DXGI_FORMAT_ ## FMT ## _UNORM, \
34    [PIPE_FORMAT_ ## FMT ## _SNORM] = DXGI_FORMAT_ ## FMT ## _SNORM,
35 
36 #define MAP_FORMAT_INT(FMT) \
37    [PIPE_FORMAT_ ## FMT ## _UINT] = DXGI_FORMAT_ ## FMT ## _UINT, \
38    [PIPE_FORMAT_ ## FMT ## _SINT] = DXGI_FORMAT_ ## FMT ## _SINT,
39 
40 #define MAP_FORMAT_SRGB(FMT) \
41    [PIPE_FORMAT_ ## FMT ## _SRGB] = DXGI_FORMAT_ ## FMT ## _UNORM_SRGB,
42 
43 #define MAP_FORMAT_FLOAT(FMT) \
44    [PIPE_FORMAT_ ## FMT ## _FLOAT] = DXGI_FORMAT_ ## FMT ## _FLOAT,
45 
46 #define MAP_EMU_FORMAT_NO_ALPHA(BITS, TYPE) \
47    [PIPE_FORMAT_L ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \
48    [PIPE_FORMAT_I ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \
49    [PIPE_FORMAT_L ## BITS ## A ## BITS ## _ ## TYPE] = \
50           DXGI_FORMAT_R ## BITS ## G ## BITS ## _ ## TYPE,
51 
52 #define MAP_EMU_FORMAT(BITS, TYPE) \
53    [PIPE_FORMAT_A ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \
54    MAP_EMU_FORMAT_NO_ALPHA(BITS, TYPE)
55 
56    MAP_FORMAT_NORM(R8)
57    MAP_FORMAT_INT(R8)
58 
59    MAP_FORMAT_NORM(R8G8)
60    MAP_FORMAT_INT(R8G8)
61 
62    MAP_FORMAT_NORM(R8G8B8A8)
63    MAP_FORMAT_INT(R8G8B8A8)
64    MAP_FORMAT_SRGB(R8G8B8A8)
65 
66    [PIPE_FORMAT_B8G8R8X8_UNORM] = DXGI_FORMAT_B8G8R8X8_UNORM,
67    [PIPE_FORMAT_B8G8R8A8_UNORM] = DXGI_FORMAT_B8G8R8A8_UNORM,
68 
69    MAP_FORMAT_SRGB(B8G8R8A8)
70 
71    MAP_FORMAT_INT(R32)
72    MAP_FORMAT_FLOAT(R32)
73    MAP_FORMAT_INT(R32G32)
74    MAP_FORMAT_FLOAT(R32G32)
75    MAP_FORMAT_INT(R32G32B32)
76    MAP_FORMAT_FLOAT(R32G32B32)
77    MAP_FORMAT_INT(R32G32B32A32)
78    MAP_FORMAT_FLOAT(R32G32B32A32)
79 
80    MAP_FORMAT_NORM(R16)
81    MAP_FORMAT_INT(R16)
82    MAP_FORMAT_FLOAT(R16)
83 
84    MAP_FORMAT_NORM(R16G16)
85    MAP_FORMAT_INT(R16G16)
86    MAP_FORMAT_FLOAT(R16G16)
87 
88    MAP_FORMAT_NORM(R16G16B16A16)
89    MAP_FORMAT_INT(R16G16B16A16)
90    MAP_FORMAT_FLOAT(R16G16B16A16)
91 
92    [PIPE_FORMAT_A8_UNORM] = DXGI_FORMAT_A8_UNORM,
93    MAP_EMU_FORMAT_NO_ALPHA(8, UNORM)
94    MAP_EMU_FORMAT(8, SNORM)
95    MAP_EMU_FORMAT(8, SINT)
96    MAP_EMU_FORMAT(8, UINT)
97    MAP_EMU_FORMAT(16, UNORM)
98    MAP_EMU_FORMAT(16, SNORM)
99    MAP_EMU_FORMAT(16, SINT)
100    MAP_EMU_FORMAT(16, UINT)
101    MAP_EMU_FORMAT(16, FLOAT)
102    MAP_EMU_FORMAT(32, SINT)
103    MAP_EMU_FORMAT(32, UINT)
104    MAP_EMU_FORMAT(32, FLOAT)
105 
106    [PIPE_FORMAT_R9G9B9E5_FLOAT] = DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
107    [PIPE_FORMAT_R11G11B10_FLOAT] = DXGI_FORMAT_R11G11B10_FLOAT,
108    [PIPE_FORMAT_R10G10B10A2_UINT] = DXGI_FORMAT_R10G10B10A2_UINT,
109    [PIPE_FORMAT_R10G10B10A2_UNORM] = DXGI_FORMAT_R10G10B10A2_UNORM,
110 
111    [PIPE_FORMAT_DXT1_RGB] = DXGI_FORMAT_BC1_UNORM,
112    [PIPE_FORMAT_DXT1_RGBA] = DXGI_FORMAT_BC1_UNORM,
113    [PIPE_FORMAT_DXT3_RGBA] = DXGI_FORMAT_BC2_UNORM,
114    [PIPE_FORMAT_DXT5_RGBA] = DXGI_FORMAT_BC3_UNORM,
115 
116    [PIPE_FORMAT_DXT1_SRGB] = DXGI_FORMAT_BC1_UNORM_SRGB,
117    [PIPE_FORMAT_DXT1_SRGBA] = DXGI_FORMAT_BC1_UNORM_SRGB,
118    [PIPE_FORMAT_DXT3_SRGBA] = DXGI_FORMAT_BC2_UNORM_SRGB,
119    [PIPE_FORMAT_DXT5_SRGBA] = DXGI_FORMAT_BC3_UNORM_SRGB,
120 
121    [PIPE_FORMAT_RGTC1_UNORM] = DXGI_FORMAT_BC4_UNORM,
122    [PIPE_FORMAT_RGTC1_SNORM] = DXGI_FORMAT_BC4_SNORM,
123    [PIPE_FORMAT_RGTC2_UNORM] = DXGI_FORMAT_BC5_UNORM,
124    [PIPE_FORMAT_RGTC2_SNORM] = DXGI_FORMAT_BC5_SNORM,
125 
126    [PIPE_FORMAT_Z32_FLOAT] = DXGI_FORMAT_R32_TYPELESS,
127    [PIPE_FORMAT_Z16_UNORM] = DXGI_FORMAT_R16_TYPELESS,
128    [PIPE_FORMAT_Z24X8_UNORM] = DXGI_FORMAT_R24G8_TYPELESS,
129    [PIPE_FORMAT_X24S8_UINT] = DXGI_FORMAT_R24G8_TYPELESS,
130 
131    [PIPE_FORMAT_Z24_UNORM_S8_UINT] = DXGI_FORMAT_R24G8_TYPELESS,
132    [PIPE_FORMAT_Z32_FLOAT_S8X24_UINT] = DXGI_FORMAT_R32G8X24_TYPELESS,
133    [PIPE_FORMAT_X32_S8X24_UINT] = DXGI_FORMAT_R32G8X24_TYPELESS,
134 };
135 
136 DXGI_FORMAT
d3d12_get_format(enum pipe_format format)137 d3d12_get_format(enum pipe_format format)
138 {
139    return formats[format];
140 }
141 
142 DXGI_FORMAT
d3d12_get_resource_rt_format(enum pipe_format f)143 d3d12_get_resource_rt_format(enum pipe_format f)
144 {
145    switch (f) {
146    case PIPE_FORMAT_Z16_UNORM:
147       return DXGI_FORMAT_D16_UNORM;
148    case PIPE_FORMAT_Z32_FLOAT:
149       return DXGI_FORMAT_D32_FLOAT;
150    case PIPE_FORMAT_Z24X8_UNORM:
151    case PIPE_FORMAT_X24S8_UINT:
152       return DXGI_FORMAT_D24_UNORM_S8_UINT;
153    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
154    case PIPE_FORMAT_X32_S8X24_UINT:
155       return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
156    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
157       return DXGI_FORMAT_D24_UNORM_S8_UINT;
158    default:
159       return d3d12_get_format(f);
160    }
161 }
162 
163 DXGI_FORMAT
d3d12_get_resource_srv_format(enum pipe_format f,enum pipe_texture_target target)164 d3d12_get_resource_srv_format(enum pipe_format f, enum pipe_texture_target target)
165 {
166    switch (f) {
167    case PIPE_FORMAT_Z16_UNORM:
168       return DXGI_FORMAT_R16_UNORM;
169    case PIPE_FORMAT_Z32_FLOAT:
170       return DXGI_FORMAT_R32_FLOAT;
171    case PIPE_FORMAT_Z24X8_UNORM:
172    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
173       return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
174    case PIPE_FORMAT_X24S8_UINT:
175       return DXGI_FORMAT_X24_TYPELESS_G8_UINT;
176    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
177       return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
178    case PIPE_FORMAT_X32_S8X24_UINT:
179       return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
180    case PIPE_FORMAT_A8_UNORM:
181       if (target == PIPE_BUFFER)
182          return DXGI_FORMAT_R8_UNORM; /* A8_UNORM is not supported for buffer SRV */
183       FALLTHROUGH;
184    default:
185       return d3d12_get_format(f);
186    }
187 }
188 
189 #define DEF_SWIZZLE(name, X, Y, Z, W) \
190    static const enum pipe_swizzle name ## _SWIZZLE[PIPE_SWIZZLE_MAX] = \
191       { PIPE_SWIZZLE_ ## X, PIPE_SWIZZLE_ ## Y, PIPE_SWIZZLE_ ## Z, PIPE_SWIZZLE_ ## W, \
192         PIPE_SWIZZLE_0, PIPE_SWIZZLE_1, PIPE_SWIZZLE_NONE }
193 
194 struct d3d12_format_info
d3d12_get_format_info(enum pipe_format pformat,enum pipe_texture_target target)195 d3d12_get_format_info(enum pipe_format pformat, enum pipe_texture_target target)
196 {
197    DEF_SWIZZLE(IDENTITY, X, Y, Z, W);
198    DEF_SWIZZLE(RGB1, X, Y, Z, 1);
199    DEF_SWIZZLE(ALPHA, 0, 0, 0, W);
200    DEF_SWIZZLE(BUFFER, 0, 0, 0, X);
201    DEF_SWIZZLE(INTENSITY, X, X, X, X);
202    DEF_SWIZZLE(LUMINANCE, X, X, X, 1);
203    DEF_SWIZZLE(LUMINANCE_ALPHA, X, X, X, Y);
204    DEF_SWIZZLE(DEPTH, X, X, X, X);
205    DEF_SWIZZLE(STENCIL, Y, Y, Y, Y);
206 
207    const enum pipe_swizzle *swizzle = IDENTITY_SWIZZLE;
208    unsigned plane_slice = 0;
209 
210    if (pformat == PIPE_FORMAT_DXT1_RGB ||
211        pformat == PIPE_FORMAT_DXT1_SRGB)
212       swizzle = RGB1_SWIZZLE;
213 
214    const struct util_format_description
215       *format_desc = util_format_description(pformat);
216    if (!util_format_is_srgb(pformat)) {
217       if (target == PIPE_BUFFER && util_format_is_alpha(pformat)) {
218          swizzle = BUFFER_SWIZZLE;
219       } else if (pformat == PIPE_FORMAT_A8_UNORM) {
220          /* no need to swizzle, it's natively supported */
221       } else if (util_format_is_intensity(pformat)) {
222          swizzle = INTENSITY_SWIZZLE;
223       } else if (util_format_is_luminance(pformat)) {
224          swizzle = LUMINANCE_SWIZZLE;
225       } else if (util_format_is_luminance_alpha(pformat)) {
226          swizzle = LUMINANCE_ALPHA_SWIZZLE;
227       } else if (util_format_is_alpha(pformat)) {
228          swizzle = ALPHA_SWIZZLE;
229       } else if (util_format_has_depth(format_desc)) {
230          swizzle = DEPTH_SWIZZLE;
231       } else if (util_format_has_stencil(format_desc)) {
232          /* When reading from a stencil texture we have to use plane 1, and
233           * the formats X24S8 and X32_S8X24 have the actual data in the y-channel
234           * but the shader will read the x component so we need to adjust the swizzle. */
235          plane_slice = 1;
236          swizzle = STENCIL_SWIZZLE;
237       }
238    }
239 
240    return (struct d3d12_format_info) { .swizzle = swizzle, .plane_slice = plane_slice };
241 }
242 
243 enum pipe_format
d3d12_emulated_vtx_format(enum pipe_format fmt)244 d3d12_emulated_vtx_format(enum pipe_format fmt)
245 {
246    switch (fmt) {
247    case PIPE_FORMAT_R10G10B10A2_SNORM:
248    case PIPE_FORMAT_R10G10B10A2_SSCALED:
249    case PIPE_FORMAT_R10G10B10A2_USCALED:
250    case PIPE_FORMAT_B10G10R10A2_UNORM:
251    case PIPE_FORMAT_B10G10R10A2_SNORM:
252    case PIPE_FORMAT_B10G10R10A2_SSCALED:
253    case PIPE_FORMAT_B10G10R10A2_USCALED:
254       return PIPE_FORMAT_R32_UINT;
255 
256    case PIPE_FORMAT_R8G8B8_SINT:
257       return PIPE_FORMAT_R8G8B8A8_SINT;
258    case PIPE_FORMAT_R8G8B8_UINT:
259       return PIPE_FORMAT_R8G8B8A8_UINT;
260 
261    case PIPE_FORMAT_R16G16B16_SINT:
262       return PIPE_FORMAT_R16G16B16A16_SINT;
263    case PIPE_FORMAT_R16G16B16_UINT:
264       return PIPE_FORMAT_R16G16B16A16_UINT;
265 
266    default:
267       return fmt;
268    }
269 }
270 
271 
272 unsigned
d3d12_non_opaque_plane_count(DXGI_FORMAT format)273 d3d12_non_opaque_plane_count(DXGI_FORMAT format)
274 {
275    switch (format) {
276    case DXGI_FORMAT_V208:
277    case DXGI_FORMAT_V408:
278       return 3;
279 
280    case DXGI_FORMAT_NV12:
281    case DXGI_FORMAT_P010:
282    case DXGI_FORMAT_P016:
283    case DXGI_FORMAT_YUY2:
284    case DXGI_FORMAT_Y210:
285    case DXGI_FORMAT_Y216:
286    case DXGI_FORMAT_NV11:
287       return 2;
288 
289    default:
290       return 1;
291    }
292 }
293 
294 unsigned
d3d12_get_format_start_plane(enum pipe_format fmt)295 d3d12_get_format_start_plane(enum pipe_format fmt)
296 {
297    const struct util_format_description *desc = util_format_description(fmt);
298    if (util_format_has_stencil(desc) && !util_format_has_depth(desc))
299       return 1;
300 
301    return 0;
302 }
303 
304 unsigned
d3d12_get_format_num_planes(enum pipe_format fmt)305 d3d12_get_format_num_planes(enum pipe_format fmt)
306 {
307    return util_format_is_depth_or_stencil(fmt) ?
308       util_bitcount(util_format_get_mask(fmt)) : 1;
309 }
310