summaryrefslogtreecommitdiffstats
path: root/drivers/d3d12/rendering_device_driver_d3d12.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/d3d12/rendering_device_driver_d3d12.cpp')
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.cpp108
1 files changed, 63 insertions, 45 deletions
diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp
index 381d022a55..49ab4f179f 100644
--- a/drivers/d3d12/rendering_device_driver_d3d12.cpp
+++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp
@@ -3222,7 +3222,7 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(Vec
root_sig_desc.Init_1_1(root_params.size(), root_params.ptr(), 0, nullptr, root_sig_flags);
ComPtr<ID3DBlob> error_blob;
- HRESULT res = D3DX12SerializeVersionedRootSignature(&root_sig_desc, D3D_ROOT_SIGNATURE_VERSION_1_1, root_sig_blob.GetAddressOf(), error_blob.GetAddressOf());
+ HRESULT res = D3DX12SerializeVersionedRootSignature(context_driver->lib_d3d12, &root_sig_desc, D3D_ROOT_SIGNATURE_VERSION_1_1, root_sig_blob.GetAddressOf(), error_blob.GetAddressOf());
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), Vector<uint8_t>(),
"Serialization of root signature failed with error " + vformat("0x%08ux", (uint64_t)res) + " and the following message:\n" + String((char *)error_blob->GetBufferPointer(), error_blob->GetBufferSize()));
@@ -3246,10 +3246,7 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(Vec
compressed_stages.push_back(zstd);
uint32_t s = compressed_stages[i].size();
- if (s % 4 != 0) {
- s += 4 - (s % 4);
- }
- stages_binary_size += s;
+ stages_binary_size += STEPIFY(s, 4);
}
CharString shader_name_utf = p_shader_name.utf8();
@@ -3259,10 +3256,7 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(Vec
uint32_t total_size = sizeof(uint32_t) * 3; // Header + version + main datasize;.
total_size += sizeof(ShaderBinary::Data);
- total_size += binary_data.shader_name_len;
- if ((binary_data.shader_name_len % 4) != 0) { // Alignment rules are really strange.
- total_size += 4 - (binary_data.shader_name_len % 4);
- }
+ total_size += STEPIFY(binary_data.shader_name_len, 4);
for (int i = 0; i < sets_bindings.size(); i++) {
total_size += sizeof(uint32_t);
@@ -3294,13 +3288,17 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(Vec
memcpy(binptr + offset, &binary_data, sizeof(ShaderBinary::Data));
offset += sizeof(ShaderBinary::Data);
+#define ADVANCE_OFFSET_WITH_ALIGNMENT(m_bytes) \
+ { \
+ offset += m_bytes; \
+ uint32_t padding = STEPIFY(m_bytes, 4) - m_bytes; \
+ memset(binptr + offset, 0, padding); /* Avoid garbage data. */ \
+ offset += padding; \
+ }
+
if (binary_data.shader_name_len > 0) {
memcpy(binptr + offset, shader_name_utf.ptr(), binary_data.shader_name_len);
- offset += binary_data.shader_name_len;
-
- if ((binary_data.shader_name_len % 4) != 0) { // Alignment rules are really strange.
- offset += 4 - (binary_data.shader_name_len % 4);
- }
+ ADVANCE_OFFSET_WITH_ALIGNMENT(binary_data.shader_name_len);
}
for (int i = 0; i < sets_bindings.size(); i++) {
@@ -3326,14 +3324,7 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(Vec
encode_uint32(zstd_size[i], binptr + offset);
offset += sizeof(uint32_t);
memcpy(binptr + offset, compressed_stages[i].ptr(), compressed_stages[i].size());
-
- uint32_t s = compressed_stages[i].size();
-
- if (s % 4 != 0) {
- s += 4 - (s % 4);
- }
-
- offset += s;
+ ADVANCE_OFFSET_WITH_ALIGNMENT(compressed_stages[i].size());
}
memcpy(binptr + offset, root_sig_blob->GetBufferPointer(), root_sig_blob->GetBufferSize());
@@ -3382,10 +3373,7 @@ RDD::ShaderID RenderingDeviceDriverD3D12::shader_create_from_bytecode(const Vect
if (binary_data.shader_name_len) {
r_name.parse_utf8((const char *)(binptr + read_offset), binary_data.shader_name_len);
- read_offset += binary_data.shader_name_len;
- if ((binary_data.shader_name_len % 4) != 0) { // Alignment rules are really strange.
- read_offset += 4 - (binary_data.shader_name_len % 4);
- }
+ read_offset += STEPIFY(binary_data.shader_name_len, 4);
}
r_shader_desc.uniform_sets.resize(binary_data.set_count);
@@ -3458,6 +3446,7 @@ RDD::ShaderID RenderingDeviceDriverD3D12::shader_create_from_bytecode(const Vect
for (uint32_t i = 0; i < binary_data.stage_count; i++) {
ERR_FAIL_COND_V(read_offset + sizeof(uint32_t) * 3 >= binsize, ShaderID());
+
uint32_t stage = decode_uint32(binptr + read_offset);
read_offset += sizeof(uint32_t);
uint32_t dxil_size = decode_uint32(binptr + read_offset);
@@ -3472,18 +3461,17 @@ RDD::ShaderID RenderingDeviceDriverD3D12::shader_create_from_bytecode(const Vect
ERR_FAIL_COND_V(dec_dxil_size != (int32_t)dxil_size, ShaderID());
shader_info_in.stages_bytecode[ShaderStage(stage)] = dxil;
- if (zstd_size % 4 != 0) {
- zstd_size += 4 - (zstd_size % 4);
- }
-
- ERR_FAIL_COND_V(read_offset + zstd_size > binsize, ShaderID());
-
+ zstd_size = STEPIFY(zstd_size, 4);
read_offset += zstd_size;
+ ERR_FAIL_COND_V(read_offset > binsize, ShaderID());
}
const uint8_t *root_sig_data_ptr = binptr + read_offset;
- HRESULT res = D3D12CreateRootSignatureDeserializer(root_sig_data_ptr, binary_data.root_signature_len, IID_PPV_ARGS(shader_info_in.root_signature_deserializer.GetAddressOf()));
+ PFN_D3D12_CREATE_ROOT_SIGNATURE_DESERIALIZER d3d_D3D12CreateRootSignatureDeserializer = (PFN_D3D12_CREATE_ROOT_SIGNATURE_DESERIALIZER)(void *)GetProcAddress(context_driver->lib_d3d12, "D3D12CreateRootSignatureDeserializer");
+ ERR_FAIL_NULL_V(d3d_D3D12CreateRootSignatureDeserializer, ShaderID());
+
+ HRESULT res = d3d_D3D12CreateRootSignatureDeserializer(root_sig_data_ptr, binary_data.root_signature_len, IID_PPV_ARGS(shader_info_in.root_signature_deserializer.GetAddressOf()));
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ShaderID(), "D3D12CreateRootSignatureDeserializer failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
read_offset += binary_data.root_signature_len;
@@ -6033,17 +6021,23 @@ Error RenderingDeviceDriverD3D12::_initialize_device() {
HRESULT res;
if (is_in_developer_mode()) {
+ typedef HRESULT(WINAPI * PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)(_In_ UINT, _In_count_(NumFeatures) const IID *, _In_opt_count_(NumFeatures) void *, _In_opt_count_(NumFeatures) UINT *);
+ PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES d3d_D3D12EnableExperimentalFeatures = (PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)(void *)GetProcAddress(context_driver->lib_d3d12, "D3D12EnableExperimentalFeatures");
+ ERR_FAIL_NULL_V(d3d_D3D12EnableExperimentalFeatures, ERR_CANT_CREATE);
+
UUID experimental_features[] = { D3D12ExperimentalShaderModels };
- D3D12EnableExperimentalFeatures(1, experimental_features, nullptr, nullptr);
+ d3d_D3D12EnableExperimentalFeatures(1, experimental_features, nullptr, nullptr);
}
ID3D12DeviceFactory *device_factory = context_driver->device_factory_get();
if (device_factory != nullptr) {
res = device_factory->CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device.GetAddressOf()));
} else {
- res = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device.GetAddressOf()));
- }
+ PFN_D3D12_CREATE_DEVICE d3d_D3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)(void *)GetProcAddress(context_driver->lib_d3d12, "D3D12CreateDevice");
+ ERR_FAIL_NULL_V(d3d_D3D12CreateDevice, ERR_CANT_CREATE);
+ res = d3d_D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device.GetAddressOf()));
+ }
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ERR_CANT_CREATE, "D3D12CreateDevice failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
if (context_driver->use_validation_layers()) {
@@ -6142,20 +6136,44 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
multiview_capabilities.is_supported = false;
subgroup_capabilities.size = 0;
subgroup_capabilities.wave_ops_supported = false;
- shader_capabilities.shader_model = D3D_SHADER_MODEL_6_0;
+ shader_capabilities.shader_model = (D3D_SHADER_MODEL)0;
shader_capabilities.native_16bit_ops = false;
storage_buffer_capabilities.storage_buffer_16_bit_access_is_supported = false;
format_capabilities.relaxed_casting_supported = false;
- // Check shader model.
- D3D12_FEATURE_DATA_SHADER_MODEL shader_model = {};
- shader_model.HighestShaderModel = MIN(D3D_HIGHEST_SHADER_MODEL, D3D_SHADER_MODEL_6_6);
- res = device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shader_model, sizeof(shader_model));
- ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ERR_CANT_CREATE, "CheckFeatureSupport failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
+ {
+ static const D3D_SHADER_MODEL SMS_TO_CHECK[] = {
+ D3D_SHADER_MODEL_6_6,
+ D3D_SHADER_MODEL_6_5,
+ D3D_SHADER_MODEL_6_4,
+ D3D_SHADER_MODEL_6_3,
+ D3D_SHADER_MODEL_6_2,
+ D3D_SHADER_MODEL_6_1,
+ D3D_SHADER_MODEL_6_0, // Determined by NIR (dxil_min_shader_model).
+ };
+
+ D3D12_FEATURE_DATA_SHADER_MODEL shader_model = {};
+ for (uint32_t i = 0; i < ARRAY_SIZE(SMS_TO_CHECK); i++) {
+ shader_model.HighestShaderModel = SMS_TO_CHECK[i];
+ res = device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shader_model, sizeof(shader_model));
+ if (SUCCEEDED(res)) {
+ shader_capabilities.shader_model = shader_model.HighestShaderModel;
+ break;
+ }
+ if (res == E_INVALIDARG) {
+ continue; // Must assume the device doesn't know about the SM just checked.
+ }
+ ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ERR_CANT_CREATE, "CheckFeatureSupport failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
+ }
- shader_capabilities.shader_model = shader_model.HighestShaderModel;
- print_verbose("- Shader:");
- print_verbose(" model: " + itos(shader_capabilities.shader_model >> 4) + "." + itos(shader_capabilities.shader_model & 0xf));
+#define D3D_SHADER_MODEL_TO_STRING(m_sm) vformat("%d.%d", (m_sm >> 4), (m_sm & 0xf))
+
+ ERR_FAIL_COND_V_MSG(!shader_capabilities.shader_model, ERR_UNAVAILABLE,
+ vformat("No support for any of the suitable shader models (%s-%s) has been found.", D3D_SHADER_MODEL_TO_STRING(SMS_TO_CHECK[ARRAY_SIZE(SMS_TO_CHECK) - 1]), D3D_SHADER_MODEL_TO_STRING(SMS_TO_CHECK[0])));
+
+ print_verbose("- Shader:");
+ print_verbose(" model: " + D3D_SHADER_MODEL_TO_STRING(shader_capabilities.shader_model));
+ }
D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
res = device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options));