Skip to content

Commit 36b7e77

Browse files
Fix specialization constant patching on D3D12.
1 parent d61cd91 commit 36b7e77

File tree

1 file changed

+15
-17
lines changed

1 file changed

+15
-17
lines changed

drivers/d3d12/rendering_shader_container_d3d12.cpp

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -94,28 +94,26 @@ uint32_t RenderingDXIL::patch_specialization_constant(
9494
const uint64_t (&p_stages_bit_offsets)[D3D12_BITCODE_OFFSETS_NUM_STAGES],
9595
HashMap<RenderingDeviceCommons::ShaderStage, Vector<uint8_t>> &r_stages_bytecodes,
9696
bool p_is_first_patch) {
97-
uint32_t patch_val = 0;
97+
int64_t patch_val = 0;
9898
switch (p_type) {
9999
case RenderingDeviceCommons::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT: {
100-
uint32_t int_value = *((const int *)p_value);
101-
ERR_FAIL_COND_V(int_value & (1 << 31), 0);
102-
patch_val = int_value;
100+
patch_val = *((const int32_t *)p_value);
103101
} break;
104102
case RenderingDeviceCommons::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL: {
105103
bool bool_value = *((const bool *)p_value);
106-
patch_val = (uint32_t)bool_value;
104+
patch_val = (int32_t)bool_value;
107105
} break;
108106
case RenderingDeviceCommons::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT: {
109-
uint32_t int_value = *((const int *)p_value);
110-
ERR_FAIL_COND_V(int_value & (1 << 31), 0);
111-
patch_val = (int_value >> 1);
107+
patch_val = *((const int32_t *)p_value);
112108
} break;
113109
}
114-
// For VBR encoding to encode the number of bits we expect (32), we need to set the MSB unconditionally.
115-
// However, signed VBR moves the MSB to the LSB, so setting the MSB to 1 wouldn't help. Therefore,
116-
// the bit we set to 1 is the one at index 30.
117-
patch_val |= (1 << 30);
118-
patch_val <<= 1; // What signed VBR does.
110+
111+
// Encode to signed VBR.
112+
if (patch_val >= 0) {
113+
patch_val <<= 1;
114+
} else {
115+
patch_val = ((-patch_val) << 1) | 1;
116+
}
119117

120118
auto tamper_bits = [](uint8_t *p_start, uint64_t p_bit_offset, uint64_t p_tb_value) -> uint64_t {
121119
uint64_t original = 0;
@@ -169,13 +167,13 @@ uint32_t RenderingDXIL::patch_specialization_constant(
169167

170168
Vector<uint8_t> &bytecode = r_stages_bytecodes[(RenderingDeviceCommons::ShaderStage)stage];
171169
#ifdef DEV_ENABLED
172-
uint64_t orig_patch_val = tamper_bits(bytecode.ptrw(), offset, patch_val);
170+
uint64_t orig_patch_val = tamper_bits(bytecode.ptrw(), offset, (uint64_t)patch_val);
173171
// Checking against the value the NIR patch should have set.
174172
DEV_ASSERT(!p_is_first_patch || ((orig_patch_val >> 1) & GODOT_NIR_SC_SENTINEL_MAGIC_MASK) == GODOT_NIR_SC_SENTINEL_MAGIC);
175-
uint64_t readback_patch_val = tamper_bits(bytecode.ptrw(), offset, patch_val);
176-
DEV_ASSERT(readback_patch_val == patch_val);
173+
uint64_t readback_patch_val = tamper_bits(bytecode.ptrw(), offset, (uint64_t)patch_val);
174+
DEV_ASSERT(readback_patch_val == (uint64_t)patch_val);
177175
#else
178-
tamper_bits(bytecode.ptrw(), offset, patch_val);
176+
tamper_bits(bytecode.ptrw(), offset, (uint64_t)patch_val);
179177
#endif
180178

181179
stages_patched_mask |= (1 << stage);

0 commit comments

Comments
 (0)