Skip to content

Commit

Permalink
Merge pull request #2397 from KhronosGroup/fix-2396
Browse files Browse the repository at this point in the history
Make SRem sign aware like all the other arithmetic ops.
  • Loading branch information
HansKristian-Work authored Oct 23, 2024
2 parents e670b39 + 5ce80e1 commit f93223f
Show file tree
Hide file tree
Showing 7 changed files with 311 additions and 3 deletions.
45 changes: 45 additions & 0 deletions reference/shaders-hlsl-no-opt/asm/frag/srem.asm.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
static int oA;
static int A;
static uint B;
static uint oB;
static int C;
static uint D;

struct SPIRV_Cross_Input
{
nointerpolation int A : TEXCOORD0;
nointerpolation uint B : TEXCOORD1;
nointerpolation int C : TEXCOORD2;
nointerpolation uint D : TEXCOORD3;
};

struct SPIRV_Cross_Output
{
int oA : SV_Target0;
uint oB : SV_Target1;
};

void frag_main()
{
oB = uint(A - int(B) * (A / int(B)));
oB = uint(A - C * (A / C));
oB = uint(int(B) - int(D) * (int(B) / int(D)));
oB = uint(int(B) - A * (int(B) / A));
oA = A - int(B) * (A / int(B));
oA = A - C * (A / C);
oA = int(B) - int(D) * (int(B) / int(D));
oA = int(B) - A * (int(B) / A);
}

SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
A = stage_input.A;
B = stage_input.B;
C = stage_input.C;
D = stage_input.D;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.oA = oA;
stage_output.oB = oB;
return stage_output;
}
33 changes: 33 additions & 0 deletions reference/shaders-msl-no-opt/asm/frag/srem.asm.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;

struct main0_out
{
int oA [[color(0)]];
uint oB [[color(1)]];
};

struct main0_in
{
int A [[user(locn0)]];
uint B [[user(locn1)]];
int C [[user(locn2)]];
uint D [[user(locn3)]];
};

fragment main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.oB = uint(in.A - int(in.B) * (in.A / int(in.B)));
out.oB = uint(in.A - in.C * (in.A / in.C));
out.oB = uint(int(in.B) - int(in.D) * (int(in.B) / int(in.D)));
out.oB = uint(int(in.B) - in.A * (int(in.B) / in.A));
out.oA = in.A - int(in.B) * (in.A / int(in.B));
out.oA = in.A - in.C * (in.A / in.C);
out.oA = int(in.B) - int(in.D) * (int(in.B) / int(in.D));
out.oA = int(in.B) - in.A * (int(in.B) / in.A);
return out;
}

21 changes: 21 additions & 0 deletions reference/shaders-no-opt/asm/frag/srem.asm.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#version 450

layout(location = 0) out int oA;
layout(location = 0) flat in int A;
layout(location = 1) flat in uint B;
layout(location = 1) out uint oB;
layout(location = 2) flat in int C;
layout(location = 3) flat in uint D;

void main()
{
oB = uint(A - int(B) * (A / int(B)));
oB = uint(A - C * (A / C));
oB = uint(int(B) - int(D) * (int(B) / int(D)));
oB = uint(int(B) - A * (int(B) / A));
oA = A - int(B) * (A / int(B));
oA = A - C * (A / C);
oA = int(B) - int(D) * (int(B) / int(D));
oA = int(B) - A * (int(B) / A);
}

66 changes: 66 additions & 0 deletions shaders-hlsl-no-opt/asm/frag/srem.asm.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos SPIR-V Tools Assembler; 0
; Bound: 30
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %oA %A %B %oB %C %D
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %oA "oA"
OpName %A "A"
OpName %B "B"
OpName %oB "oB"
OpName %C "C"
OpName %D "D"
OpDecorate %oA Location 0
OpDecorate %A Flat
OpDecorate %A Location 0
OpDecorate %B Flat
OpDecorate %B Location 1
OpDecorate %oB Location 1
OpDecorate %C Flat
OpDecorate %C Location 2
OpDecorate %D Flat
OpDecorate %D Location 3
%void = OpTypeVoid
%10 = OpTypeFunction %void
%int = OpTypeInt 32 1
%_ptr_Output_int = OpTypePointer Output %int
%oA = OpVariable %_ptr_Output_int Output
%_ptr_Input_int = OpTypePointer Input %int
%A = OpVariable %_ptr_Input_int Input
%uint = OpTypeInt 32 0
%_ptr_Input_uint = OpTypePointer Input %uint
%B = OpVariable %_ptr_Input_uint Input
%_ptr_Output_uint = OpTypePointer Output %uint
%oB = OpVariable %_ptr_Output_uint Output
%C = OpVariable %_ptr_Input_int Input
%D = OpVariable %_ptr_Input_uint Input
%main = OpFunction %void None %10
%17 = OpLabel
%18 = OpLoad %int %A
%19 = OpLoad %uint %B
%20 = OpLoad %int %C
%21 = OpLoad %uint %D
%22 = OpSRem %uint %18 %19
OpStore %oB %22
%23 = OpSRem %uint %18 %20
OpStore %oB %23
%24 = OpSRem %uint %19 %21
OpStore %oB %24
%25 = OpSRem %uint %19 %18
OpStore %oB %25
%26 = OpSRem %int %18 %19
OpStore %oA %26
%27 = OpSRem %int %18 %20
OpStore %oA %27
%28 = OpSRem %int %19 %21
OpStore %oA %28
%29 = OpSRem %int %19 %18
OpStore %oA %29
OpReturn
OpFunctionEnd
66 changes: 66 additions & 0 deletions shaders-msl-no-opt/asm/frag/srem.asm.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos SPIR-V Tools Assembler; 0
; Bound: 30
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %oA %A %B %oB %C %D
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %oA "oA"
OpName %A "A"
OpName %B "B"
OpName %oB "oB"
OpName %C "C"
OpName %D "D"
OpDecorate %oA Location 0
OpDecorate %A Flat
OpDecorate %A Location 0
OpDecorate %B Flat
OpDecorate %B Location 1
OpDecorate %oB Location 1
OpDecorate %C Flat
OpDecorate %C Location 2
OpDecorate %D Flat
OpDecorate %D Location 3
%void = OpTypeVoid
%10 = OpTypeFunction %void
%int = OpTypeInt 32 1
%_ptr_Output_int = OpTypePointer Output %int
%oA = OpVariable %_ptr_Output_int Output
%_ptr_Input_int = OpTypePointer Input %int
%A = OpVariable %_ptr_Input_int Input
%uint = OpTypeInt 32 0
%_ptr_Input_uint = OpTypePointer Input %uint
%B = OpVariable %_ptr_Input_uint Input
%_ptr_Output_uint = OpTypePointer Output %uint
%oB = OpVariable %_ptr_Output_uint Output
%C = OpVariable %_ptr_Input_int Input
%D = OpVariable %_ptr_Input_uint Input
%main = OpFunction %void None %10
%17 = OpLabel
%18 = OpLoad %int %A
%19 = OpLoad %uint %B
%20 = OpLoad %int %C
%21 = OpLoad %uint %D
%22 = OpSRem %uint %18 %19
OpStore %oB %22
%23 = OpSRem %uint %18 %20
OpStore %oB %23
%24 = OpSRem %uint %19 %21
OpStore %oB %24
%25 = OpSRem %uint %19 %18
OpStore %oB %25
%26 = OpSRem %int %18 %19
OpStore %oA %26
%27 = OpSRem %int %18 %20
OpStore %oA %27
%28 = OpSRem %int %19 %21
OpStore %oA %28
%29 = OpSRem %int %19 %18
OpStore %oA %29
OpReturn
OpFunctionEnd
66 changes: 66 additions & 0 deletions shaders-no-opt/asm/frag/srem.asm.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos SPIR-V Tools Assembler; 0
; Bound: 30
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %oA %A %B %oB %C %D
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %oA "oA"
OpName %A "A"
OpName %B "B"
OpName %oB "oB"
OpName %C "C"
OpName %D "D"
OpDecorate %oA Location 0
OpDecorate %A Flat
OpDecorate %A Location 0
OpDecorate %B Flat
OpDecorate %B Location 1
OpDecorate %oB Location 1
OpDecorate %C Flat
OpDecorate %C Location 2
OpDecorate %D Flat
OpDecorate %D Location 3
%void = OpTypeVoid
%10 = OpTypeFunction %void
%int = OpTypeInt 32 1
%_ptr_Output_int = OpTypePointer Output %int
%oA = OpVariable %_ptr_Output_int Output
%_ptr_Input_int = OpTypePointer Input %int
%A = OpVariable %_ptr_Input_int Input
%uint = OpTypeInt 32 0
%_ptr_Input_uint = OpTypePointer Input %uint
%B = OpVariable %_ptr_Input_uint Input
%_ptr_Output_uint = OpTypePointer Output %uint
%oB = OpVariable %_ptr_Output_uint Output
%C = OpVariable %_ptr_Input_int Input
%D = OpVariable %_ptr_Input_uint Input
%main = OpFunction %void None %10
%17 = OpLabel
%18 = OpLoad %int %A
%19 = OpLoad %uint %B
%20 = OpLoad %int %C
%21 = OpLoad %uint %D
%22 = OpSRem %uint %18 %19
OpStore %oB %22
%23 = OpSRem %uint %18 %20
OpStore %oB %23
%24 = OpSRem %uint %19 %21
OpStore %oB %24
%25 = OpSRem %uint %19 %18
OpStore %oB %25
%26 = OpSRem %int %18 %19
OpStore %oA %26
%27 = OpSRem %int %18 %20
OpStore %oA %27
%28 = OpSRem %int %19 %21
OpStore %oA %28
%29 = OpSRem %int %19 %18
OpStore %oA %29
OpReturn
OpFunctionEnd
17 changes: 14 additions & 3 deletions spirv_glsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13229,13 +13229,24 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
uint32_t op0 = ops[2];
uint32_t op1 = ops[3];

// Needs special handling.
auto &out_type = get<SPIRType>(result_type);

bool forward = should_forward(op0) && should_forward(op1);
auto expr = join(to_enclosed_expression(op0), " - ", to_enclosed_expression(op1), " * ", "(",
to_enclosed_expression(op0), " / ", to_enclosed_expression(op1), ")");
string cast_op0, cast_op1;
auto expected_type = binary_op_bitcast_helper(cast_op0, cast_op1, int_type, op0, op1, false);

// Needs special handling.
auto expr = join(cast_op0, " - ", cast_op1, " * ", "(", cast_op0, " / ", cast_op1, ")");

if (implicit_integer_promotion)
{
expr = join(type_to_glsl(get<SPIRType>(result_type)), '(', expr, ')');
}
else if (out_type.basetype != int_type)
{
expected_type.basetype = int_type;
expr = join(bitcast_glsl_op(out_type, expected_type), '(', expr, ')');
}

emit_op(result_type, result_id, expr, forward);
inherit_expression_dependencies(result_id, op0);
Expand Down

0 comments on commit f93223f

Please sign in to comment.