-
Notifications
You must be signed in to change notification settings - Fork 259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update SPIRV-Tools and fix new validation errors. #6511
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
We were talking about the logical storage and physical storage in WorkGraphs meeting today coincidently.
I guess this is a thing going around recently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Closes #6508.
Issue
Recent SPIRV-Tools update adds a new verification rule that disallows explicit layouts (e.g.
Offset
decoration) on types used from Function/Private/Workgroup etc. address spaces after SPIRV 1.4.Background
SPIRV makes a distinction of physical and logical types. A physical type is a type with explicit memory layout and can be stored in a user-transparent way in memory. A logical type in contrast does not have a defined layout, and cannot be decorated with any explicit layout deocrations, such as
Offset
,ArrayStride
etc.The SPIRV spec requires that all buffer elements or global input/outputs to be a physical type, and all variables in the function/private(i.e. ordinary global vars)/workgroup address spaces to be logical.
This means that if the user writes:
We need to represent
Foo
as two distinct types when generating SPIRV: the one used insideStructuredBuffer
must be a physical type with explicit layout (specifying the offset ofFoo::x
andFoo::y
), and the one used forlocalVar
must be a logical type. Therefore we generate something like:Where
Foo_std430
is the physical type forFoo
that can be placed in a buffer, andpackStorage
andunpackStorage
functions to convert between physical and logical type when needed.The above translation is what the existing
lowerBufferElementTypeToStorageType
is doing.Currently, when we emit SPIRV, we always emit
Offset
decorations for bothFoo
andFoo_std430
. However this is against the SPIRV rules, which disallows a type to be declared as a local variable, if the type has explicit layout.Solution
To fix the SPIRV validation error complaining
Foo
cannot be used to declarelocalVar
because it has explicit layout, we simply need to mark the lowered storage types (Foo_std430
in the above example) with a[PhysicalType]
decoration, and make sure we only emit SPIRV layout decorations (ArrayStride, MatrixStride, ColMajor, RowMajor, Offset) for structs with the[PhyiscalType]
decoration.The rest of the PR is to deal with a bunch of consequences after changing the way we emit SPIRV explicit layout based on whether or not a type is marked
[PhysicalType]
.GLSLStorageBuffer
type weren't lowered bylowerBufferElementTypeToStorageType
previously, but now needs to be in order to produce valid SPIRV so that the element type is properly marked as physical.lowerBufferElementTypeToStorageType
needs to generate pack/unpack functions for unsized array types that can appear in glsl storage buffers, which we weren't handling previously.elementExtract
from a SSA register of a physical array type (can't copy it to a OpVariable and then do AccessChain, because OpVariable must be a logical type). These functions are inlined before emitting final code, because SPIRV doesn't allow us to pass pointers to functions without using VariablePointers capability. Because we no longer need to lowerElementExtract(array, i)
to first copy to local var then do access chain, the resulting code should be much simpler for pack/unpack of large arrays and should be faster to compile by the downstream compiler.loadAlign(ptr)
is going to be split into a lot of smaller loads, so we must propagate the alignment on the load through the addresses, so that each individual load/store gets the correct alignment.The updated
lowerBufferElementTypeToStorageType
pass now translates the above example code to the following:Copilot Summary
This pull request includes significant changes to the handling of pointer types and various optimizations in the SPIR-V and GLSL code generation. The most important changes include the refactoring of
ConstBufferPointerType
, updates to GLSL source emission, and improvements to SPIR-V emission and optimization.Refactoring and Simplification:
source/slang/hlsl.meta.slang
: RefactoredConstBufferPointer
to simplify its structure and improve inline functions.source/slang/slang-ast-type.h
: Removed theConstBufferPointerType
class to streamline the pointer type definitions.GLSL Source Emission:
source/slang/slang-emit-glsl.cpp
: Updated various methods to handle the new pointer type structure, includingemitBufferPointerTypeDefinition
,tryEmitInstExprImpl
, andemitSimpleTypeImpl
. [1] [2] [3]SPIR-V Emission and Optimization:
source/slang/slang-emit-spirv.cpp
: Improved handling of forward-declared pointers and added checks to emit array stride and offset decoration only for types marked as physical. [1] [2]source/slang/slang-emit.cpp
: Added force inlining and other optimization steps afterlowerBufferElementTypeToStorageType
pass. [1] [2]These changes collectively enhance the handling of pointer types and improve the efficiency and correctness of the generated GLSL and SPIR-V code.