1/* 2 * Copyright © Microsoft Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include "dzn_private.h" 25 26#define D3D12_IGNORE_SDK_LAYERS 27#define COBJMACROS 28#include <directx/d3d12.h> 29 30#include <vulkan/vulkan.h> 31 32#include "util/format/u_format.h" 33#include "util/log.h" 34 35#include <directx/d3d12sdklayers.h> 36#include <util/u_dl.h> 37 38static const DXGI_FORMAT formats[PIPE_FORMAT_COUNT] = { 39#define MAP_FORMAT_NORM(FMT) \ 40 [PIPE_FORMAT_ ## FMT ## _UNORM] = DXGI_FORMAT_ ## FMT ## _UNORM, \ 41 [PIPE_FORMAT_ ## FMT ## _SNORM] = DXGI_FORMAT_ ## FMT ## _SNORM, 42 43#define MAP_FORMAT_INT(FMT) \ 44 [PIPE_FORMAT_ ## FMT ## _UINT] = DXGI_FORMAT_ ## FMT ## _UINT, \ 45 [PIPE_FORMAT_ ## FMT ## _SINT] = DXGI_FORMAT_ ## FMT ## _SINT, 46 47#define MAP_FORMAT_SRGB(FMT) \ 48 [PIPE_FORMAT_ ## FMT ## _SRGB] = DXGI_FORMAT_ ## FMT ## _UNORM_SRGB, 49 50#define MAP_FORMAT_FLOAT(FMT) \ 51 [PIPE_FORMAT_ ## FMT ## _FLOAT] = DXGI_FORMAT_ ## FMT ## _FLOAT, 52 53#define MAP_EMU_FORMAT_NO_ALPHA(BITS, TYPE) \ 54 [PIPE_FORMAT_L ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \ 55 [PIPE_FORMAT_I ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \ 56 [PIPE_FORMAT_L ## BITS ## A ## BITS ## _ ## TYPE] = \ 57 DXGI_FORMAT_R ## BITS ## G ## BITS ## _ ## TYPE, 58 59#define MAP_EMU_FORMAT(BITS, TYPE) \ 60 [PIPE_FORMAT_A ## BITS ## _ ## TYPE] = DXGI_FORMAT_R ## BITS ## _ ## TYPE, \ 61 MAP_EMU_FORMAT_NO_ALPHA(BITS, TYPE) 62 63 MAP_FORMAT_NORM(R8) 64 MAP_FORMAT_INT(R8) 65 66 MAP_FORMAT_NORM(R8G8) 67 MAP_FORMAT_INT(R8G8) 68 69 MAP_FORMAT_NORM(R8G8B8A8) 70 MAP_FORMAT_INT(R8G8B8A8) 71 MAP_FORMAT_SRGB(R8G8B8A8) 72 73 [PIPE_FORMAT_B8G8R8X8_UNORM] = DXGI_FORMAT_B8G8R8X8_UNORM, 74 [PIPE_FORMAT_B8G8R8A8_UNORM] = DXGI_FORMAT_B8G8R8A8_UNORM, 75 [PIPE_FORMAT_B4G4R4A4_UNORM] = DXGI_FORMAT_B4G4R4A4_UNORM, 76 [PIPE_FORMAT_A4R4G4B4_UNORM] = DXGI_FORMAT_B4G4R4A4_UNORM, 77 [PIPE_FORMAT_B5G6R5_UNORM] = DXGI_FORMAT_B5G6R5_UNORM, 78 [PIPE_FORMAT_B5G5R5A1_UNORM] = DXGI_FORMAT_B5G5R5A1_UNORM, 79 80 MAP_FORMAT_SRGB(B8G8R8A8) 81 82 MAP_FORMAT_INT(R32) 83 MAP_FORMAT_FLOAT(R32) 84 MAP_FORMAT_INT(R32G32) 85 MAP_FORMAT_FLOAT(R32G32) 86 MAP_FORMAT_INT(R32G32B32) 87 MAP_FORMAT_FLOAT(R32G32B32) 88 MAP_FORMAT_INT(R32G32B32A32) 89 MAP_FORMAT_FLOAT(R32G32B32A32) 90 91 MAP_FORMAT_NORM(R16) 92 MAP_FORMAT_INT(R16) 93 MAP_FORMAT_FLOAT(R16) 94 95 MAP_FORMAT_NORM(R16G16) 96 MAP_FORMAT_INT(R16G16) 97 MAP_FORMAT_FLOAT(R16G16) 98 99 MAP_FORMAT_NORM(R16G16B16A16) 100 MAP_FORMAT_INT(R16G16B16A16) 101 MAP_FORMAT_FLOAT(R16G16B16A16) 102 103 [PIPE_FORMAT_A8_UNORM] = DXGI_FORMAT_A8_UNORM, 104 MAP_EMU_FORMAT_NO_ALPHA(8, UNORM) 105 MAP_EMU_FORMAT(8, SNORM) 106 MAP_EMU_FORMAT(8, SINT) 107 MAP_EMU_FORMAT(8, UINT) 108 MAP_EMU_FORMAT(16, UNORM) 109 MAP_EMU_FORMAT(16, SNORM) 110 MAP_EMU_FORMAT(16, SINT) 111 MAP_EMU_FORMAT(16, UINT) 112 MAP_EMU_FORMAT(16, FLOAT) 113 MAP_EMU_FORMAT(32, SINT) 114 MAP_EMU_FORMAT(32, UINT) 115 MAP_EMU_FORMAT(32, FLOAT) 116 117 [PIPE_FORMAT_R9G9B9E5_FLOAT] = DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 118 [PIPE_FORMAT_R11G11B10_FLOAT] = DXGI_FORMAT_R11G11B10_FLOAT, 119 [PIPE_FORMAT_R10G10B10A2_UINT] = DXGI_FORMAT_R10G10B10A2_UINT, 120 [PIPE_FORMAT_R10G10B10A2_UNORM] = DXGI_FORMAT_R10G10B10A2_UNORM, 121 122 [PIPE_FORMAT_DXT1_RGB] = DXGI_FORMAT_BC1_UNORM, 123 [PIPE_FORMAT_DXT1_RGBA] = DXGI_FORMAT_BC1_UNORM, 124 [PIPE_FORMAT_DXT3_RGBA] = DXGI_FORMAT_BC2_UNORM, 125 [PIPE_FORMAT_DXT5_RGBA] = DXGI_FORMAT_BC3_UNORM, 126 127 [PIPE_FORMAT_DXT1_SRGB] = DXGI_FORMAT_BC1_UNORM_SRGB, 128 [PIPE_FORMAT_DXT1_SRGBA] = DXGI_FORMAT_BC1_UNORM_SRGB, 129 [PIPE_FORMAT_DXT3_SRGBA] = DXGI_FORMAT_BC2_UNORM_SRGB, 130 [PIPE_FORMAT_DXT5_SRGBA] = DXGI_FORMAT_BC3_UNORM_SRGB, 131 132 [PIPE_FORMAT_RGTC1_UNORM] = DXGI_FORMAT_BC4_UNORM, 133 [PIPE_FORMAT_RGTC1_SNORM] = DXGI_FORMAT_BC4_SNORM, 134 [PIPE_FORMAT_RGTC2_UNORM] = DXGI_FORMAT_BC5_UNORM, 135 [PIPE_FORMAT_RGTC2_SNORM] = DXGI_FORMAT_BC5_SNORM, 136 137 [PIPE_FORMAT_BPTC_RGB_UFLOAT] = DXGI_FORMAT_BC6H_UF16, 138 [PIPE_FORMAT_BPTC_RGB_FLOAT] = DXGI_FORMAT_BC6H_SF16, 139 [PIPE_FORMAT_BPTC_RGBA_UNORM] = DXGI_FORMAT_BC7_UNORM, 140 [PIPE_FORMAT_BPTC_SRGBA] = DXGI_FORMAT_BC7_UNORM_SRGB, 141 142 [PIPE_FORMAT_Z32_FLOAT] = DXGI_FORMAT_R32_TYPELESS, 143 [PIPE_FORMAT_Z16_UNORM] = DXGI_FORMAT_R16_TYPELESS, 144 [PIPE_FORMAT_Z24X8_UNORM] = DXGI_FORMAT_R24G8_TYPELESS, 145 [PIPE_FORMAT_X24S8_UINT] = DXGI_FORMAT_R24G8_TYPELESS, 146 147 [PIPE_FORMAT_Z24_UNORM_S8_UINT] = DXGI_FORMAT_R24G8_TYPELESS, 148 [PIPE_FORMAT_Z32_FLOAT_S8X24_UINT] = DXGI_FORMAT_R32G8X24_TYPELESS, 149 [PIPE_FORMAT_X32_S8X24_UINT] = DXGI_FORMAT_R32G8X24_TYPELESS, 150}; 151 152DXGI_FORMAT 153dzn_pipe_to_dxgi_format(enum pipe_format in) 154{ 155 return formats[in]; 156} 157 158DXGI_FORMAT 159dzn_get_typeless_dxgi_format(DXGI_FORMAT in) 160{ 161 if (in >= DXGI_FORMAT_R32G32B32A32_TYPELESS && in <= DXGI_FORMAT_R32G32B32A32_SINT) 162 return DXGI_FORMAT_R32G32B32A32_TYPELESS; 163 if (in >= DXGI_FORMAT_R32G32B32_TYPELESS && in <= DXGI_FORMAT_R32G32B32_SINT) 164 return DXGI_FORMAT_R32G32B32_TYPELESS; 165 if (in >= DXGI_FORMAT_R16G16B16A16_TYPELESS && in <= DXGI_FORMAT_R16G16B16A16_SINT) 166 return DXGI_FORMAT_R16G16B16A16_TYPELESS; 167 if (in >= DXGI_FORMAT_R32G32_TYPELESS && in <= DXGI_FORMAT_R32G32_SINT) 168 return DXGI_FORMAT_R32G32_TYPELESS; 169 if (in >= DXGI_FORMAT_R32G8X24_TYPELESS && in <= DXGI_FORMAT_X32_TYPELESS_G8X24_UINT) 170 return DXGI_FORMAT_R32G8X24_TYPELESS; 171 if (in >= DXGI_FORMAT_R10G10B10A2_TYPELESS && in <= DXGI_FORMAT_R10G10B10A2_UINT) 172 return DXGI_FORMAT_R10G10B10A2_TYPELESS; 173 if (in >= DXGI_FORMAT_R8G8B8A8_TYPELESS && in <= DXGI_FORMAT_R8G8B8A8_SINT) 174 return DXGI_FORMAT_R8G8B8A8_TYPELESS; 175 if (in >= DXGI_FORMAT_R16G16_TYPELESS && in <= DXGI_FORMAT_R16G16_SINT) 176 return DXGI_FORMAT_R16G16_TYPELESS; 177 if (in >= DXGI_FORMAT_R32_TYPELESS && in <= DXGI_FORMAT_R32_SINT) 178 return DXGI_FORMAT_R32_TYPELESS; 179 if (in >= DXGI_FORMAT_R24G8_TYPELESS && in <= DXGI_FORMAT_X24_TYPELESS_G8_UINT) 180 return DXGI_FORMAT_R24G8_TYPELESS; 181 if (in >= DXGI_FORMAT_R8G8_TYPELESS && in <= DXGI_FORMAT_R8G8_SINT) 182 return DXGI_FORMAT_R8G8_TYPELESS; 183 if (in >= DXGI_FORMAT_R16_TYPELESS && in <= DXGI_FORMAT_R16_SINT) 184 return DXGI_FORMAT_R16_TYPELESS; 185 if (in >= DXGI_FORMAT_R8_TYPELESS && in <= DXGI_FORMAT_R8_SINT) 186 return DXGI_FORMAT_R8_TYPELESS; 187 if (in >= DXGI_FORMAT_BC1_TYPELESS && in <= DXGI_FORMAT_BC1_UNORM_SRGB) 188 return DXGI_FORMAT_BC1_TYPELESS; 189 if (in >= DXGI_FORMAT_BC2_TYPELESS && in <= DXGI_FORMAT_BC2_UNORM_SRGB) 190 return DXGI_FORMAT_BC2_TYPELESS; 191 if (in >= DXGI_FORMAT_BC3_TYPELESS && in <= DXGI_FORMAT_BC3_UNORM_SRGB) 192 return DXGI_FORMAT_BC3_TYPELESS; 193 if (in >= DXGI_FORMAT_BC4_TYPELESS && in <= DXGI_FORMAT_BC4_SNORM) 194 return DXGI_FORMAT_BC4_TYPELESS; 195 if (in >= DXGI_FORMAT_BC5_TYPELESS && in <= DXGI_FORMAT_BC5_SNORM) 196 return DXGI_FORMAT_BC5_TYPELESS; 197 if (in == DXGI_FORMAT_B8G8R8A8_UNORM || 198 (in >= DXGI_FORMAT_B8G8R8A8_TYPELESS && in <= DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)) 199 return DXGI_FORMAT_B8G8R8A8_TYPELESS; 200 if (in == DXGI_FORMAT_B8G8R8X8_UNORM || 201 (in >= DXGI_FORMAT_B8G8R8X8_TYPELESS && in <= DXGI_FORMAT_B8G8R8X8_UNORM_SRGB)) 202 return DXGI_FORMAT_B8G8R8X8_TYPELESS; 203 if (in >= DXGI_FORMAT_BC6H_TYPELESS && in <= DXGI_FORMAT_BC6H_SF16) 204 return DXGI_FORMAT_BC6H_TYPELESS; 205 if (in >= DXGI_FORMAT_BC7_TYPELESS && in <= DXGI_FORMAT_BC7_UNORM_SRGB) 206 return DXGI_FORMAT_BC7_TYPELESS; 207 208 return in; 209} 210 211struct dzn_sampler_filter_info { 212 VkFilter min, mag; 213 VkSamplerMipmapMode mipmap; 214}; 215 216#define FILTER(__min, __mag, __mipmap) \ 217{ \ 218 .min = VK_FILTER_ ## __min, \ 219 .mag = VK_FILTER_ ## __mag, \ 220 .mipmap = VK_SAMPLER_MIPMAP_MODE_ ## __mipmap, \ 221} 222 223static const struct dzn_sampler_filter_info filter_table[] = { 224 [D3D12_FILTER_MIN_MAG_MIP_POINT] = FILTER(NEAREST, NEAREST, NEAREST), 225 [D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR] = FILTER(NEAREST, NEAREST, LINEAR), 226 [D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT] = FILTER(NEAREST, LINEAR, NEAREST), 227 [D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR] = FILTER(NEAREST, LINEAR, LINEAR), 228 [D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT] = FILTER(LINEAR, NEAREST, NEAREST), 229 [D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR] = FILTER(LINEAR, NEAREST, LINEAR), 230 [D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT] = FILTER(LINEAR, LINEAR, NEAREST), 231 [D3D12_FILTER_MIN_MAG_MIP_LINEAR] = FILTER(LINEAR, LINEAR, LINEAR), 232}; 233 234D3D12_FILTER 235dzn_translate_sampler_filter(const VkSamplerCreateInfo *create_info) 236{ 237 D3D12_FILTER filter = (D3D12_FILTER)0; 238 239 if (!create_info->anisotropyEnable) { 240 unsigned i; 241 for (i = 0; i < ARRAY_SIZE(filter_table); i++) { 242 if (create_info->minFilter == filter_table[i].min && 243 create_info->magFilter == filter_table[i].mag && 244 create_info->mipmapMode == filter_table[i].mipmap) { 245 filter = (D3D12_FILTER)i; 246 break; 247 } 248 } 249 250 assert(i < ARRAY_SIZE(filter_table)); 251 } else { 252 filter = D3D12_FILTER_ANISOTROPIC; 253 } 254 255 if (create_info->compareEnable) 256 filter = (D3D12_FILTER)(filter + D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT); 257 258 return filter; 259} 260 261D3D12_COMPARISON_FUNC 262dzn_translate_compare_op(VkCompareOp in) 263{ 264 switch (in) { 265 case VK_COMPARE_OP_NEVER: return D3D12_COMPARISON_FUNC_NEVER; 266 case VK_COMPARE_OP_LESS: return D3D12_COMPARISON_FUNC_LESS; 267 case VK_COMPARE_OP_EQUAL: return D3D12_COMPARISON_FUNC_EQUAL; 268 case VK_COMPARE_OP_LESS_OR_EQUAL: return D3D12_COMPARISON_FUNC_LESS_EQUAL; 269 case VK_COMPARE_OP_GREATER: return D3D12_COMPARISON_FUNC_GREATER; 270 case VK_COMPARE_OP_NOT_EQUAL: return D3D12_COMPARISON_FUNC_NOT_EQUAL; 271 case VK_COMPARE_OP_GREATER_OR_EQUAL: return D3D12_COMPARISON_FUNC_GREATER_EQUAL; 272 case VK_COMPARE_OP_ALWAYS: return D3D12_COMPARISON_FUNC_ALWAYS; 273 default: unreachable("Invalid compare op"); 274 } 275} 276 277void 278dzn_translate_viewport(D3D12_VIEWPORT *out, 279 const VkViewport *in) 280{ 281 out->TopLeftX = in->x; 282 out->TopLeftY = in->height < 0 ? in->height + in->y : in->y; 283 out->Width = in->width; 284 out->Height = fabs(in->height); 285 out->MinDepth = MIN2(in->minDepth, in->maxDepth); 286 out->MaxDepth = MAX2(in->maxDepth, in->minDepth); 287} 288 289void 290dzn_translate_rect(D3D12_RECT *out, 291 const VkRect2D *in) 292{ 293 out->left = in->offset.x; 294 out->top = in->offset.y; 295 out->right = in->offset.x + in->extent.width; 296 out->bottom = in->offset.y + in->extent.height; 297} 298 299static ID3D12Debug * 300get_debug_interface() 301{ 302 typedef HRESULT(WINAPI *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID riid, void **ppFactory); 303 PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface; 304 305 struct util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT); 306 if (!d3d12_mod) { 307 mesa_loge("failed to load D3D12\n"); 308 return NULL; 309 } 310 311 D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)util_dl_get_proc_address(d3d12_mod, "D3D12GetDebugInterface"); 312 if (!D3D12GetDebugInterface) { 313 mesa_loge("failed to load D3D12GetDebugInterface from D3D12.DLL\n"); 314 return NULL; 315 } 316 317 ID3D12Debug *debug; 318 if (FAILED(D3D12GetDebugInterface(&IID_ID3D12Debug, (void **)&debug))) { 319 mesa_loge("D3D12GetDebugInterface failed\n"); 320 return NULL; 321 } 322 323 return debug; 324} 325 326void 327d3d12_enable_debug_layer(void) 328{ 329 ID3D12Debug *debug = get_debug_interface(); 330 if (debug) { 331 ID3D12Debug_EnableDebugLayer(debug); 332 ID3D12Debug_Release(debug); 333 } 334} 335 336void 337d3d12_enable_gpu_validation(void) 338{ 339 ID3D12Debug *debug = get_debug_interface(); 340 if (debug) { 341 ID3D12Debug3 *debug3; 342 if (SUCCEEDED(ID3D12Debug_QueryInterface(debug, 343 &IID_ID3D12Debug3, 344 (void **)&debug3))) { 345 ID3D12Debug3_SetEnableGPUBasedValidation(debug3, true); 346 ID3D12Debug3_Release(debug3); 347 } 348 ID3D12Debug_Release(debug); 349 } 350} 351 352ID3D12Device2 * 353d3d12_create_device(IUnknown *adapter, bool experimental_features) 354{ 355 typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown *, D3D_FEATURE_LEVEL, REFIID, void **); 356 PFN_D3D12CREATEDEVICE D3D12CreateDevice; 357 358 struct util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT); 359 if (!d3d12_mod) { 360 mesa_loge("failed to load D3D12\n"); 361 return NULL; 362 } 363 364#ifdef _WIN32 365 if (experimental_features) 366#endif 367 { 368 typedef HRESULT(WINAPI *PFN_D3D12ENABLEEXPERIMENTALFEATURES)(UINT, const IID *, void *, UINT *); 369 PFN_D3D12ENABLEEXPERIMENTALFEATURES D3D12EnableExperimentalFeatures = 370 (PFN_D3D12ENABLEEXPERIMENTALFEATURES)util_dl_get_proc_address(d3d12_mod, "D3D12EnableExperimentalFeatures"); 371 if (FAILED(D3D12EnableExperimentalFeatures(1, &D3D12ExperimentalShaderModels, NULL, NULL))) { 372 mesa_loge("failed to enable experimental shader models\n"); 373 return NULL; 374 } 375 } 376 377 D3D12CreateDevice = (PFN_D3D12CREATEDEVICE)util_dl_get_proc_address(d3d12_mod, "D3D12CreateDevice"); 378 if (!D3D12CreateDevice) { 379 mesa_loge("failed to load D3D12CreateDevice from D3D12\n"); 380 return NULL; 381 } 382 383 ID3D12Device2 *dev; 384 if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, 385 &IID_ID3D12Device2, 386 (void **)&dev))) 387 return dev; 388 389 mesa_loge("D3D12CreateDevice failed\n"); 390 return NULL; 391} 392 393PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE 394d3d12_get_serialize_root_sig(void) 395{ 396 struct util_dl_library *d3d12_mod = util_dl_open(UTIL_DL_PREFIX "d3d12" UTIL_DL_EXT); 397 if (!d3d12_mod) { 398 mesa_loge("failed to load D3D12\n"); 399 return NULL; 400 } 401 402 return (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE) 403 util_dl_get_proc_address(d3d12_mod, "D3D12SerializeVersionedRootSignature"); 404} 405