From 7f63dc986e7d4c3e0dd5aff902a0bea96e3ca6b7 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Sat, 3 Oct 2026 10:41:57 +1000 Subject: [PATCH] [client] network: fix ANGLE decoder synchronization The dequant shader returned before workgroup barriers for missing blocks. Mask those blocks to zero so ANGLE's D3D compiler accepts the shader while every invocation reaches each barrier. The vcpkg ANGLE build also omitted upstream shared-context locking. Enable both locking definitions so decode dispatches cannot race the render thread through ANGLE's shared D3D11 state manager. --- client/CMakeLists.txt | 5 ++++ .../cmake/vcpkg-triplets/x64-windows-lg.cmake | 10 +++++++ client/transports/Network/video/shaders.h | 27 +++++++++---------- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index ed46062e..eed63329 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -1,6 +1,11 @@ cmake_minimum_required(VERSION 3.20) project(looking-glass-client C CXX) +if(WIN32) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS + "${PROJECT_SOURCE_DIR}/cmake/vcpkg-triplets/x64-windows-lg.cmake") +endif() + get_filename_component(PROJECT_TOP "${PROJECT_SOURCE_DIR}/.." ABSOLUTE) if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) diff --git a/client/cmake/vcpkg-triplets/x64-windows-lg.cmake b/client/cmake/vcpkg-triplets/x64-windows-lg.cmake index eb8d8a6a..d82654ef 100644 --- a/client/cmake/vcpkg-triplets/x64-windows-lg.cmake +++ b/client/cmake/vcpkg-triplets/x64-windows-lg.cmake @@ -7,3 +7,13 @@ if(PORT STREQUAL "openssl") else() set(VCPKG_LIBRARY_LINKAGE dynamic) endif() + +if(PORT STREQUAL "angle") + # ANGLE's D3D state cache is shared across contexts. Serialize access and + # dirty cached state whenever calls switch between shared contexts. + string(CONCAT ANGLE_CONTEXT_FLAGS + " /DANGLE_ENABLE_SHARE_CONTEXT_LOCK=1" + " /DANGLE_FORCE_CONTEXT_CHECK_EVERY_CALL=1") + string(APPEND VCPKG_C_FLAGS "${ANGLE_CONTEXT_FLAGS}") + string(APPEND VCPKG_CXX_FLAGS "${ANGLE_CONTEXT_FLAGS}") +endif() diff --git a/client/transports/Network/video/shaders.h b/client/transports/Network/video/shaders.h index 4598eba5..5512d86b 100644 --- a/client/transports/Network/video/shaders.h +++ b/client/transports/Network/video/shaders.h @@ -87,22 +87,21 @@ static const char NETWORK_VIDEO_DEQUANT_SHADER_0[] = " }\n" "}\n" "void main() {\n" - " uint localIndex = gl_LocalInvocationIndex;\n" - " int blockIndex = blockOffset + int(gl_WorkGroupID.y) * blockStride +\n" + " uint localIndex = gl_LocalInvocationIndex;\n" + " int blockIndex = blockOffset + int(gl_WorkGroupID.y) * blockStride +\n" " int(gl_WorkGroupID.x);\n" - " uint sourceWord = offsets[blockIndex];\n" - " uint subblock = bitfieldExtract(localIndex,0,3);\n" - " uint blockX = bitfieldExtract(localIndex,3,2);\n" - " uint blockY = bitfieldExtract(localIndex,5,2);\n" - " uint group = blockY * 4u + blockX;\n" - " ivec2 coord = ivec2(gl_WorkGroupID.xy) * 32 +\n" + " uint sourceWord = offsets[blockIndex];\n" + " uint blockPresent = uint(sourceWord != 0xffffffffu);\n" + " // Missing blocks must still reach every workgroup barrier.\n" + " sourceWord *= blockPresent;\n" + " uint subblock = bitfieldExtract(localIndex,0,3);\n" + " uint blockX = bitfieldExtract(localIndex,3,2);\n" + " uint blockY = bitfieldExtract(localIndex,5,2);\n" + " uint group = blockY * 4u + blockX;\n" + " ivec2 coord = ivec2(gl_WorkGroupID.xy) * 32 +\n" " 8 * ivec2(blockX,blockY) + unswizzle8x8(subblock << 3u);\n" - " if (sourceWord == 0xffffffffu) {\n" - " storeValues(coord,mat2x4(vec4(0.0),vec4(0.0)));\n" - " return;\n" - " }\n" " uint sourceByte = sourceWord * 4u;\n" - " uint ballot = payload[sourceWord] & 65535u;\n" + " uint ballot = (payload[sourceWord] & 65535u) * blockPresent;\n" " if (localIndex == 0u) {\n" " uint cursor = sourceByte + 8u + 3u * uint(bitCount(ballot));\n" " for (uint index=0u; index<16u; ++index) {\n" @@ -118,7 +117,7 @@ static const char NETWORK_VIDEO_DEQUANT_SHADER_0[] = " cursor += uint(bitCount(low) + bitCount(high)) + 8u * qbits;\n" " }\n" " }\n" - " signOffset = cursor * 8u;\n" + " signOffset = cursor * 8u * blockPresent;\n" " }\n" " barrier();\n";