From dc82c117f542c4ae4b084de349649c3e49873cc6 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 11 Mar 2026 22:43:24 +0000 Subject: [PATCH] Fix edge case of bitfield extract with count == numbits. Closes #3813 * This is only legal if offset is 0 and so degenerate, but it is valid and needs to be handled. --- .../driver/shaders/spirv/spirv_debug.cpp | 23 ++++++++++--------- util/test/demos/vk/vk_shader_debug_zoo.cpp | 9 ++++++++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.cpp b/renderdoc/driver/shaders/spirv/spirv_debug.cpp index 681aef1a3..19dfbf1ea 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug.cpp @@ -2234,17 +2234,18 @@ void ThreadState::StepNext(bool useDebugState, const uint32_t steps, for(uint8_t c = 0; c < var.columns; c++) { #undef _IMPL -#define _IMPL(I, S, U) \ - const U mask = (U(1) << comp(count, c)) - U(1); \ - \ - comp(var, c) >>= comp(offset, c); \ - comp(var, c) &= mask; \ - \ - if(opdata.op == Op::BitFieldSExtract) \ - { \ - U topbit = (mask + U(1)) >> U(1); \ - if(comp(var, c) & topbit) \ - comp(var, c) |= (~0ULL ^ mask); \ +#define _IMPL(I, S, U) \ + const U bitcount = comp(count, c); \ + const U mask = bitcount == sizeof(U) * 8 ? ~0ULL : (U(1) << bitcount) - U(1); \ + \ + comp(var, c) >>= comp(offset, c); \ + comp(var, c) &= mask; \ + \ + if(opdata.op == Op::BitFieldSExtract) \ + { \ + U topbit = (mask + U(1)) >> U(1); \ + if(comp(var, c) & topbit) \ + comp(var, c) |= (~0ULL ^ mask); \ } IMPL_FOR_INT_TYPES(_IMPL); diff --git a/util/test/demos/vk/vk_shader_debug_zoo.cpp b/util/test/demos/vk/vk_shader_debug_zoo.cpp index 70cfbdf53..0e7dd82bf 100644 --- a/util/test/demos/vk/vk_shader_debug_zoo.cpp +++ b/util/test/demos/vk/vk_shader_debug_zoo.cpp @@ -1675,6 +1675,15 @@ void main() Color = vec4(x, y, z, w); break; } + case 187: + { + uint a = zerou + 0x44b82a80; + int b = zeroi + 0x44b82a80; + + Color = vec4(float(bitfieldExtract(a, 0, 32)), float(bitfieldExtract(b, 0, 32)), + float(bitfieldExtract(a, 32, 0)), float(bitfieldExtract(b, 32, 0))); + break; + } default: break; } }