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

[naga spv-in] OpImageWrite allows input other than Vector4. #6630

Draft
wants to merge 1 commit into
base: trunk
Choose a base branch
from

Conversation

ReinaS-64892
Copy link

Connections
None

Description

Please excuse the use of machine translation (Google Translate).

It seems that an error (The value [~] can not be stored) occurs if a vector smaller than Vector4 is entered as the value of OpImageWrite.

However, according to the SPIR-V specification: https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpImageWrite

Texel is the data to write. It must be a scalar or vector with component type the same as Sampled Type of the OpTypeImage (unless that Sampled Type is OpTypeVoid).

I think that even if a value other than Vector4 is entered, there is no problem as long as it matches the format of the target texture.

Looking at the error, it seems that it must be Vector4 in naga-ir, so I think that naga::front::spv needs to absorb that difference!

For now, I have created an implementation and made a PR.

The implementation is designed to insert an Expression that expands to Vector4 depending on the format of the texture to be written to.

However, this implementation has a flaw. It works fine for languages ​​that write Vector sizes that correspond to the destination, such as hlsl, but an error occurs if it is not...

If it is implemented correctly, I thought that it should be corrected by looking at the value to be written, not the format of the texture to be written, but I did not know how to implement it. (That is why this pull request is not mergeable, but a draft.)

So I hope this PR will explain the problem.

Finally, I will also include the minimum sample code (HLSL, SPIR-V) that causes this problem.

Original japanese text

機械翻訳(google translate)を使用していることをご容赦ください。

OpImageWrite の値として Vector4 より小さいベクターが入っているとエラー (The value [~] can not be stored) になるようです。

ですが、SPIR-V の仕様書によると: https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpImageWrite

Texel is the data to write. It must be a scalar or vector with component type the same as Sampled Type of the OpTypeImage (unless that Sampled Type is OpTypeVoid).

と書かれており、Vector4 以外が入っていても対象となるテクスチャのフォーマットと適合していれば問題がないと私は思えます。

エラーを見るに naga-ir では Vector4 でないといけないようなので、 naga::front::spv がその差異を吸収する必要があると私は思います!

ひとまず、実装を作っては見たので PR を作りました。

実装としては、書き込み先のテクスチャのフォーマットに応じて Vector4 に拡張する Expression を差し込むようになっています。

ですが、この実装には欠陥があり hlsl などの書き込み先に対応した Vector サイズを書き込む言語の場合は問題がないですが、そうではない場合にかえってエラーが発生します ...

正しく実装するならば、書き込み先のテクスチャのフォーマットではなく、書き込む値の方を見て補正すべきだと私は思いましたが、私にそれを実装する方法がわかりませんでした。(このプルリクエストがマージできるものではなく、ドラフトにしている理由です。)

なので、この PR はその問題の説明になれば幸いです。

最後に、この問題が発生する最小の サンプルコード (HLSL,SPIR-V)も載せておきます。

example shader code

example float2

cbuffer gv
{
    float2 RG;
}
RWTexture2D<float2> Tex;

[numthreads(32, 32, 1)] void CSMain(uint3 id : SV_DispatchThreadID)
{
    Tex[id.xy] = RG;
}
; SPIR-V
; Version: 1.0
; Generator: Google spiregg; 0
; Bound: 26
; Schema: 0
               OpCapability Shader
               OpCapability StorageImageExtendedFormats
               OpMemoryModel Logical GLSL450
               OpEntryPoint GLCompute %CSMain "CSMain" %gl_GlobalInvocationID
               OpExecutionMode %CSMain LocalSize 32 32 1
               OpSource HLSL 600
               OpName %type_gv "type.gv"
               OpMemberName %type_gv 0 "RG"
               OpName %gv "gv"
               OpName %type_2d_image "type.2d.image"
               OpName %Tex "Tex"
               OpName %CSMain "CSMain"
               OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
               OpDecorate %gv DescriptorSet 0
               OpDecorate %gv Binding 0
               OpDecorate %Tex DescriptorSet 0
               OpDecorate %Tex Binding 1
               OpMemberDecorate %type_gv 0 Offset 0
               OpDecorate %type_gv Block
        %int = OpTypeInt 32 1
      %int_0 = OpConstant %int 0
      %float = OpTypeFloat 32
    %v2float = OpTypeVector %float 2
    %type_gv = OpTypeStruct %v2float
%_ptr_Uniform_type_gv = OpTypePointer Uniform %type_gv
%type_2d_image = OpTypeImage %float 2D 2 0 0 2 Rg32f
%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
       %uint = OpTypeInt 32 0
     %v3uint = OpTypeVector %uint 3
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
       %void = OpTypeVoid
         %17 = OpTypeFunction %void
%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
     %v2uint = OpTypeVector %uint 2
         %gv = OpVariable %_ptr_Uniform_type_gv Uniform
        %Tex = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
     %CSMain = OpFunction %void None %17
         %20 = OpLabel
         %21 = OpLoad %v3uint %gl_GlobalInvocationID
         %22 = OpAccessChain %_ptr_Uniform_v2float %gv %int_0
         %23 = OpLoad %v2float %22
         %24 = OpVectorShuffle %v2uint %21 %21 0 1
         %25 = OpLoad %type_2d_image %Tex
               OpImageWrite %25 %24 %23 None
               OpReturn
               OpFunctionEnd

example float

cbuffer gv
{
    float R;
}
RWTexture2D<float> Tex;

[numthreads(32, 32, 1)] void CSMain(uint3 id : SV_DispatchThreadID)
{
    Tex[id.xy] = R;
}
; SPIR-V
; Version: 1.0
; Generator: Google spiregg; 0
; Bound: 25
; Schema: 0
               OpCapability Shader
               OpMemoryModel Logical GLSL450
               OpEntryPoint GLCompute %CSMain "CSMain" %gl_GlobalInvocationID
               OpExecutionMode %CSMain LocalSize 32 32 1
               OpSource HLSL 600
               OpName %type_gv "type.gv"
               OpMemberName %type_gv 0 "R"
               OpName %gv "gv"
               OpName %type_2d_image "type.2d.image"
               OpName %Tex "Tex"
               OpName %CSMain "CSMain"
               OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
               OpDecorate %gv DescriptorSet 0
               OpDecorate %gv Binding 0
               OpDecorate %Tex DescriptorSet 0
               OpDecorate %Tex Binding 1
               OpMemberDecorate %type_gv 0 Offset 0
               OpDecorate %type_gv Block
        %int = OpTypeInt 32 1
      %int_0 = OpConstant %int 0
      %float = OpTypeFloat 32
    %type_gv = OpTypeStruct %float
%_ptr_Uniform_type_gv = OpTypePointer Uniform %type_gv
%type_2d_image = OpTypeImage %float 2D 2 0 0 2 R32f
%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
       %uint = OpTypeInt 32 0
     %v3uint = OpTypeVector %uint 3
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
       %void = OpTypeVoid
         %16 = OpTypeFunction %void
%_ptr_Uniform_float = OpTypePointer Uniform %float
     %v2uint = OpTypeVector %uint 2
         %gv = OpVariable %_ptr_Uniform_type_gv Uniform
        %Tex = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
     %CSMain = OpFunction %void None %16
         %19 = OpLabel
         %20 = OpLoad %v3uint %gl_GlobalInvocationID
         %21 = OpAccessChain %_ptr_Uniform_float %gv %int_0
         %22 = OpLoad %float %21
         %23 = OpVectorShuffle %v2uint %20 %20 0 1
         %24 = OpLoad %type_2d_image %Tex
               OpImageWrite %24 %23 %22 None
               OpReturn
               OpFunctionEnd

Testing
I've provided example shader code so you should be able to create your own tests based on that.
(Is this the right answer...? Sorry if I'm wrong.)

Checklist

  • Run cargo fmt.
  • Run taplo format.
  • Run cargo clippy. If applicable, add:
    • --target wasm32-unknown-unknown
    • --target wasm32-unknown-emscripten
  • Run cargo xtask test to run tests.
  • Add change to CHANGELOG.md. See simple instructions inside file.

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

Successfully merging this pull request may close these issues.

1 participant