Skip to content
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

SPIR-V optimiser unable to remove redundant specialisation constants #5858

Open
McDaMastR opened this issue Oct 20, 2024 · 0 comments
Open

Comments

@McDaMastR
Copy link

The SPIR-V optimiser spirv-opt includes multiple options with the purpose of removing redundant values, including the following.

  • --eliminate-dead-const - Eliminate dead constants.
  • --remove-duplicates - Removes duplicate types, decorations, capabilities and extension instructions.
  • --unify-const - Remove the duplicated constants.

However, none of the above related optimisations are able to remove a redundant specialisation constant, where 'redundant' means it shares the same SpecId and default value with a separately declared <id>. The following assembly is of the module test.spvasm.

               OpCapability Shader
               OpMemoryModel Logical GLSL450
               OpEntryPoint GLCompute %ep1 "ep1" %buffer
               OpEntryPoint GLCompute %ep2 "ep2" %buffer
               OpExecutionMode %ep1 LocalSize 1 1 1
               OpExecutionMode %ep2 LocalSize 1 1 1

               OpDecorate %spec1 SpecId 0
               OpDecorate %spec2 SpecId 0
               OpDecorate %spec3 SpecId 1
               OpMemberDecorate %struct 0 Offset 0
               OpMemberDecorate %struct 1 Offset 4
               OpDecorate %struct Block

       %void = OpTypeVoid
       %uint = OpTypeInt 32 0
     %struct = OpTypeStruct %uint %uint
       %func = OpTypeFunction %void

     %uint_0 = OpConstant %uint 0
     %uint_1 = OpConstant %uint 1
      %spec1 = OpSpecConstant %uint 1
      %spec2 = OpSpecConstant %uint 1
      %spec3 = OpSpecConstant %uint 1

   %ptr_uint = OpTypePointer StorageBuffer %uint
 %ptr_struct = OpTypePointer StorageBuffer %struct
     %buffer = OpVariable %ptr_struct StorageBuffer

        %ep1 = OpFunction %void None %func
     %label1 = OpLabel
       %val1 =   OpIAdd %uint %spec1 %spec3
       %ptr1 =   OpAccessChain %ptr_uint %buffer %uint_0
                 OpStore %ptr1 %val1
                 OpReturn
               OpFunctionEnd

        %ep2 = OpFunction %void None %func
     %label2 = OpLabel
       %val2 =   OpIAdd %uint %spec2 %spec3
       %ptr2 =   OpAccessChain %ptr_uint %buffer %uint_1
                 OpStore %ptr2 %val2
                 OpReturn
               OpFunctionEnd

The two entry points add two specialisation constants together, and store the result into a storage buffer. ep1 adds spec1 and spec3, and ep2 adds spec2 and spec3. All specialisation constants have the same default value, and spec1 and spec2 have the same SpecId, making spec2 redundant. spec3 is included as an example of what would happen if spec2 was removed due to its redundancy, and was hence replaced or combined with spec1.

If you assemble this module into SPIR-V, apply the optimisations listed above, and then disassemble back into assembly as follows:

spirv-as --target-env spv1.6 -o test.spv test.spvasm
spirv-opt --target-env=spv1.6 --eliminate-dead-const --remove-duplicates --unify-const -o test2.spv test.spv
spirv-dis --no-header --nested-indent -o test2.spvasm test2.spv

The resultant module test2.spvasm will be equivalent to the original module test.spvasm, including containing the redundant specialisation constant. Both test.spv and test2.spv pass the SPIR-V validator, and all SPIRV-Tools are of the following --version.

SPIRV-Tools v2024.4 v2024.4.rc1-0-g6dcc7e35

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant