From 75ec076c348f15e30f51f8a8696ff86d51fdaa39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20R=C3=A1kos=20=28RasterGrid=29?= Date: Fri, 6 Mar 2026 15:52:30 +0100 Subject: [PATCH 1/2] ci: Test both Windows debug and release builds --- .github/workflows/vvl.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/vvl.yml b/.github/workflows/vvl.yml index 06399d547..910436969 100644 --- a/.github/workflows/vvl.yml +++ b/.github/workflows/vvl.yml @@ -181,6 +181,10 @@ jobs: strategy: matrix: arch: [ amd64, amd64_x86 ] + config: [ debug, release ] + exclude: + - arch: amd64_x86 + config: debug steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 @@ -203,7 +207,7 @@ jobs: ${{ github.workspace }}/external/Vulkan-Utility-Libraries/build/install key: windows-dependencies-${{ matrix.arch }}-${{ hashfiles('scripts/known_good.json') }} - name: Build - run: python3 scripts/tests_vksc.py --build --config debug --cmake='-DUPDATE_DEPS_SKIP_EXISTING_INSTALL=ON' + run: python3 scripts/tests_vksc.py --build --config ${{ matrix.config }} --cmake='-DUPDATE_DEPS_SKIP_EXISTING_INSTALL=ON' - name: Test Max Profile run: python scripts/tests_vksc.py --test env: From 2696f7136093ad831fbb677d1b89c5d27a5ec19d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20R=C3=A1kos=20=28RasterGrid=29?= Date: Mon, 9 Mar 2026 13:40:40 +0100 Subject: [PATCH 2/2] layers: Fix handling of unaligned matrix columns There are wider issues with the entire handling of location and component assignment in VVL, but this change does not attempt to fix them. This issue was discovered "thanks to" an MSVC compiler bug that incorrectly optimized a piece of this code such that a division by zero exception was caused in this piece of code: if (vector_components != 0 && j != 0 && j % vector_components == 0) { While that is a clear compiler bug, it did reveal a few other bugs in the code around this conditional. --- layers/state_tracker/shader_module.cpp | 42 +++++++++++++++----------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/layers/state_tracker/shader_module.cpp b/layers/state_tracker/shader_module.cpp index 2bccc0373..09d2026f3 100644 --- a/layers/state_tracker/shader_module.cpp +++ b/layers/state_tracker/shader_module.cpp @@ -2072,11 +2072,12 @@ static uint32_t GetStructInterfaceSlots(const Module& module_state, std::shared_ const uint32_t locations = module_state.GetLocationsConsumedByType(member_type); // If we have a |mat4x3| it is 12 components, but spread over the first 3 components of each Location - uint32_t vector_components = 0; + uint32_t column_components = 0; if (member_type->Opcode() == spv::OpTypeMatrix) { const Instruction* column_type = module_state.FindDef(member_type->Word(2)); - vector_components = module_state.GetComponentsConsumedByType(column_type); + column_components = module_state.GetComponentsConsumedByType(column_type); } + const uint32_t padding_components = (4 - column_components % 4) % 4; // Info needed to test type matching later const Instruction* numerical_type = module_state.GetBaseTypeInstruction(member_type); @@ -2084,12 +2085,13 @@ static uint32_t GetStructInterfaceSlots(const Module& module_state, std::shared_ const uint32_t numerical_type_width = numerical_type->GetBitWidth(); for (uint32_t j = 0; j < locations; j++) { - uint32_t matrix_offset = 0; for (uint32_t k = 0; k < components; k++) { - if (vector_components != 0 && j != 0 && j % vector_components == 0) { - matrix_offset += (4 - vector_components); // skip to next Location + // Skip padding for matrix columns + uint32_t component_offset = 0; + if (padding_components != 0) { + component_offset = padding_components * (k / column_components); } - slots.emplace_back(starting_location + locations_added, k + matrix_offset, numerical_type_opcode, + slots.emplace_back(starting_location + locations_added, k + component_offset, numerical_type_opcode, numerical_type_width); } locations_added++; @@ -2124,11 +2126,12 @@ std::vector StageInterfaceVariable::GetInterfaceSlots(StageInterf const uint32_t components = module_state.GetComponentsConsumedByType(member_type); // If we have a |mat4x3| it is 12 components, but spread over the first 3 components of each Location - uint32_t vector_components = 0; + uint32_t column_components = 0; if (member_type->Opcode() == spv::OpTypeMatrix) { const Instruction* column_type = module_state.FindDef(member_type->Word(2)); - vector_components = module_state.GetComponentsConsumedByType(column_type); + column_components = module_state.GetComponentsConsumedByType(column_type); } + const uint32_t padding_components = (4 - column_components % 4) % 4; // Info needed to test type matching later const Instruction* numerical_type = module_state.GetBaseTypeInstruction(member_type); @@ -2142,12 +2145,13 @@ std::vector StageInterfaceVariable::GetInterfaceSlots(StageInterf } const uint32_t numerical_type_width = numerical_type->GetBitWidth(); - uint32_t matrix_offset = 0; for (uint32_t j = 0; j < components; j++) { - if (vector_components != 0 && j != 0 && j % vector_components == 0) { - matrix_offset += (4 - vector_components); // skip to next Location + // Skip padding for matrix columns + uint32_t component_offset = 0; + if (padding_components != 0) { + component_offset = padding_components * (j / column_components); } - slots.emplace_back(base_location, j + matrix_offset, numerical_type_opcode, numerical_type_width); + slots.emplace_back(base_location, j + component_offset, numerical_type_opcode, numerical_type_width); } base_location++; // If using, each members starts a new Location } @@ -2172,23 +2176,25 @@ std::vector StageInterfaceVariable::GetInterfaceSlots(StageInterf const uint32_t components = module_state.GetComponentsConsumedByType(member_type); // If we have a |mat4x3| it is 12 components, but spread over the first 3 components of each Location - uint32_t vector_components = 0; + uint32_t column_components = 0; if (member_type->Opcode() == spv::OpTypeMatrix) { const Instruction* column_type = module_state.FindDef(member_type->Word(2)); - vector_components = module_state.GetComponentsConsumedByType(column_type); + column_components = module_state.GetComponentsConsumedByType(column_type); } + const uint32_t padding_components = (4 - column_components % 4) % 4; // Info needed to test type matching later const Instruction* numerical_type = module_state.GetBaseTypeInstruction(member_type); const uint32_t numerical_type_opcode = numerical_type->Opcode(); const uint32_t numerical_type_width = numerical_type->GetBitWidth(); - uint32_t matrix_offset = 0; for (uint32_t j = 0; j < components; j++) { - if (vector_components != 0 && j != 0 && j % vector_components == 0) { - matrix_offset += (4 - vector_components); // skip to next Location + // Skip padding for matrix columns + uint32_t component_offset = 0; + if (padding_components != 0) { + component_offset = padding_components * (j / column_components); } - slots.emplace_back(location, starting_component + j + matrix_offset, numerical_type_opcode, + slots.emplace_back(location, starting_component + j + component_offset, numerical_type_opcode, numerical_type_width); } }