Merge pull request #2220 from KhronosGroup/pr-2208

Land PR 2208 and fix more issues with sample mask
This commit is contained in:
Hans-Kristian Arntzen 2023-10-23 15:21:23 +02:00 committed by GitHub
commit 637cff3d05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 685 additions and 83 deletions

View File

@ -1,5 +1,5 @@
static int gl_SampleMaskIn; static int gl_SampleMaskIn[1];
static int gl_SampleMask; static int gl_SampleMask[1];
static float4 FragColor; static float4 FragColor;
struct SPIRV_Cross_Input struct SPIRV_Cross_Input
@ -16,15 +16,15 @@ struct SPIRV_Cross_Output
void frag_main() void frag_main()
{ {
FragColor = 1.0f.xxxx; FragColor = 1.0f.xxxx;
gl_SampleMask = gl_SampleMaskIn; gl_SampleMask[0] = gl_SampleMaskIn[0];
} }
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{ {
gl_SampleMaskIn = stage_input.gl_SampleMaskIn; gl_SampleMaskIn[0] = stage_input.gl_SampleMaskIn;
frag_main(); frag_main();
SPIRV_Cross_Output stage_output; SPIRV_Cross_Output stage_output;
stage_output.gl_SampleMask = gl_SampleMask; stage_output.gl_SampleMask = gl_SampleMask[0];
stage_output.FragColor = FragColor; stage_output.FragColor = FragColor;
return stage_output; return stage_output;
} }

View File

@ -1,5 +1,5 @@
static int gl_SampleID; static int gl_SampleID;
static int gl_SampleMaskIn; static int gl_SampleMaskIn[1];
static float4 FragColor; static float4 FragColor;
struct SPIRV_Cross_Input struct SPIRV_Cross_Input
@ -15,7 +15,7 @@ struct SPIRV_Cross_Output
void frag_main() void frag_main()
{ {
if ((gl_SampleMaskIn & (1 << gl_SampleID)) != 0) if ((gl_SampleMaskIn[0] & (1 << gl_SampleID)) != 0)
{ {
FragColor = 1.0f.xxxx; FragColor = 1.0f.xxxx;
} }
@ -24,7 +24,7 @@ void frag_main()
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{ {
gl_SampleID = stage_input.gl_SampleID; gl_SampleID = stage_input.gl_SampleID;
gl_SampleMaskIn = stage_input.gl_SampleMaskIn; gl_SampleMaskIn[0] = stage_input.gl_SampleMaskIn;
frag_main(); frag_main();
SPIRV_Cross_Output stage_output; SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor; stage_output.FragColor = FragColor;

View File

@ -1,4 +1,4 @@
static int gl_SampleMask; static int gl_SampleMask[1];
static float4 FragColor; static float4 FragColor;
struct SPIRV_Cross_Output struct SPIRV_Cross_Output
@ -10,14 +10,14 @@ struct SPIRV_Cross_Output
void frag_main() void frag_main()
{ {
FragColor = 1.0f.xxxx; FragColor = 1.0f.xxxx;
gl_SampleMask = 0; gl_SampleMask[0] = 0;
} }
SPIRV_Cross_Output main() SPIRV_Cross_Output main()
{ {
frag_main(); frag_main();
SPIRV_Cross_Output stage_output; SPIRV_Cross_Output stage_output;
stage_output.gl_SampleMask = gl_SampleMask; stage_output.gl_SampleMask = gl_SampleMask[0];
stage_output.FragColor = FragColor; stage_output.FragColor = FragColor;
return stage_output; return stage_output;
} }

View File

@ -11,7 +11,7 @@ struct main0_out
[[ early_fragment_tests ]] fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask, post_depth_coverage]]) [[ early_fragment_tests ]] fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask, post_depth_coverage]])
{ {
main0_out out = {}; main0_out out = {};
out.FragColor = float4(float(gl_SampleMaskIn)); out.FragColor = float4(float(int(gl_SampleMaskIn)));
return out; return out;
} }

View File

@ -11,7 +11,7 @@ struct main0_out
[[ early_fragment_tests ]] fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask, post_depth_coverage]]) [[ early_fragment_tests ]] fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask, post_depth_coverage]])
{ {
main0_out out = {}; main0_out out = {};
out.FragColor = float4(float(gl_SampleMaskIn)); out.FragColor = float4(float(int(gl_SampleMaskIn)));
return out; return out;
} }

View File

@ -13,7 +13,7 @@ fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask]], uint gl_SampleID
{ {
main0_out out = {}; main0_out out = {};
out.FragColor = float4(1.0); out.FragColor = float4(1.0);
out.gl_SampleMask = (gl_SampleMaskIn & 0x22 & (1 << gl_SampleID)); out.gl_SampleMask = int((gl_SampleMaskIn & 0x22 & (1 << gl_SampleID)));
out.gl_SampleMask &= 0x22; out.gl_SampleMask &= 0x22;
return out; return out;
} }

View File

@ -13,7 +13,7 @@ fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask]])
{ {
main0_out out = {}; main0_out out = {};
out.FragColor = float4(1.0); out.FragColor = float4(1.0);
out.gl_SampleMask = (gl_SampleMaskIn & 0x22); out.gl_SampleMask = int((gl_SampleMaskIn & 0x22));
out.gl_SampleMask &= 0x22; out.gl_SampleMask &= 0x22;
return out; return out;
} }

View File

@ -1,8 +1,49 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wmissing-braces"
#include <metal_stdlib> #include <metal_stdlib>
#include <simd/simd.h> #include <simd/simd.h>
using namespace metal; using namespace metal;
template<typename T, size_t Num>
struct spvUnsafeArray
{
T elements[Num ? Num : 1];
thread T& operator [] (size_t pos) thread
{
return elements[pos];
}
constexpr const thread T& operator [] (size_t pos) const thread
{
return elements[pos];
}
device T& operator [] (size_t pos) device
{
return elements[pos];
}
constexpr const device T& operator [] (size_t pos) const device
{
return elements[pos];
}
constexpr const constant T& operator [] (size_t pos) const constant
{
return elements[pos];
}
threadgroup T& operator [] (size_t pos) threadgroup
{
return elements[pos];
}
constexpr const threadgroup T& operator [] (size_t pos) const threadgroup
{
return elements[pos];
}
};
struct type_View struct type_View
{ {
float4x4 View_TranslatedWorldToClip; float4x4 View_TranslatedWorldToClip;
@ -489,12 +530,12 @@ fragment main0_out main0(main0_in in [[stage_in]], constant type_View& View [[bu
if (View.View_NumSceneColorMSAASamples > 1) if (View.View_NumSceneColorMSAASamples > 1)
{ {
_268 = _255 * float4(float(View.View_NumSceneColorMSAASamples) * 0.25); _268 = _255 * float4(float(View.View_NumSceneColorMSAASamples) * 0.25);
_269 = gl_SampleMaskIn & 15u; _269 = (spvUnsafeArray<uint, 1>({ uint(gl_SampleMaskIn) }))[0] & 15u;
} }
else else
{ {
_268 = _255; _268 = _255;
_269 = gl_SampleMaskIn; _269 = (spvUnsafeArray<uint, 1>({ uint(gl_SampleMaskIn) }))[0];
} }
out.out_var_SV_Target0 = _268; out.out_var_SV_Target0 = _268;
out.gl_SampleMask = _269; out.gl_SampleMask = _269;

View File

@ -0,0 +1,26 @@
static uint gl_SampleMaskIn[1];
static uint gl_SampleMask[1];
struct SPIRV_Cross_Input
{
uint gl_SampleMaskIn : SV_Coverage;
};
struct SPIRV_Cross_Output
{
uint gl_SampleMask : SV_Coverage;
};
void frag_main()
{
uint copy_sample_mask[1] = gl_SampleMaskIn;
gl_SampleMask = copy_sample_mask;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
gl_SampleMaskIn[0] = stage_input.gl_SampleMaskIn;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_SampleMask = gl_SampleMask[0];
return stage_output;
}

View File

@ -0,0 +1,26 @@
static int gl_SampleMaskIn[1];
static int gl_SampleMask[1];
struct SPIRV_Cross_Input
{
uint gl_SampleMaskIn : SV_Coverage;
};
struct SPIRV_Cross_Output
{
uint gl_SampleMask : SV_Coverage;
};
void frag_main()
{
int copy_sample_mask[1] = gl_SampleMaskIn;
gl_SampleMask = copy_sample_mask;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
gl_SampleMaskIn[0] = stage_input.gl_SampleMaskIn;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_SampleMask = gl_SampleMask[0];
return stage_output;
}

View File

@ -1,5 +1,5 @@
static int gl_SampleMaskIn; static int gl_SampleMaskIn[1];
static int gl_SampleMask; static int gl_SampleMask[1];
static float4 FragColor; static float4 FragColor;
struct SPIRV_Cross_Input struct SPIRV_Cross_Input
@ -16,15 +16,15 @@ struct SPIRV_Cross_Output
void frag_main() void frag_main()
{ {
FragColor = 1.0f.xxxx; FragColor = 1.0f.xxxx;
gl_SampleMask = gl_SampleMaskIn; gl_SampleMask[0] = gl_SampleMaskIn[0];
} }
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{ {
gl_SampleMaskIn = stage_input.gl_SampleMaskIn; gl_SampleMaskIn[0] = stage_input.gl_SampleMaskIn;
frag_main(); frag_main();
SPIRV_Cross_Output stage_output; SPIRV_Cross_Output stage_output;
stage_output.gl_SampleMask = gl_SampleMask; stage_output.gl_SampleMask = gl_SampleMask[0];
stage_output.FragColor = FragColor; stage_output.FragColor = FragColor;
return stage_output; return stage_output;
} }

View File

@ -1,5 +1,5 @@
static int gl_SampleID; static int gl_SampleID;
static int gl_SampleMaskIn; static int gl_SampleMaskIn[1];
static float4 FragColor; static float4 FragColor;
struct SPIRV_Cross_Input struct SPIRV_Cross_Input
@ -15,7 +15,7 @@ struct SPIRV_Cross_Output
void frag_main() void frag_main()
{ {
if ((gl_SampleMaskIn & (1 << gl_SampleID)) != 0) if ((gl_SampleMaskIn[0] & (1 << gl_SampleID)) != 0)
{ {
FragColor = 1.0f.xxxx; FragColor = 1.0f.xxxx;
} }
@ -24,7 +24,7 @@ void frag_main()
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{ {
gl_SampleID = stage_input.gl_SampleID; gl_SampleID = stage_input.gl_SampleID;
gl_SampleMaskIn = stage_input.gl_SampleMaskIn; gl_SampleMaskIn[0] = stage_input.gl_SampleMaskIn;
frag_main(); frag_main();
SPIRV_Cross_Output stage_output; SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor; stage_output.FragColor = FragColor;

View File

@ -1,4 +1,4 @@
static int gl_SampleMask; static int gl_SampleMask[1];
static float4 FragColor; static float4 FragColor;
struct SPIRV_Cross_Output struct SPIRV_Cross_Output
@ -10,14 +10,14 @@ struct SPIRV_Cross_Output
void frag_main() void frag_main()
{ {
FragColor = 1.0f.xxxx; FragColor = 1.0f.xxxx;
gl_SampleMask = 0; gl_SampleMask[0] = 0;
} }
SPIRV_Cross_Output main() SPIRV_Cross_Output main()
{ {
frag_main(); frag_main();
SPIRV_Cross_Output stage_output; SPIRV_Cross_Output stage_output;
stage_output.gl_SampleMask = gl_SampleMask; stage_output.gl_SampleMask = gl_SampleMask[0];
stage_output.FragColor = FragColor; stage_output.FragColor = FragColor;
return stage_output; return stage_output;
} }

View File

@ -0,0 +1,59 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wmissing-braces"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
template<typename T, size_t Num>
struct spvUnsafeArray
{
T elements[Num ? Num : 1];
thread T& operator [] (size_t pos) thread
{
return elements[pos];
}
constexpr const thread T& operator [] (size_t pos) const thread
{
return elements[pos];
}
device T& operator [] (size_t pos) device
{
return elements[pos];
}
constexpr const device T& operator [] (size_t pos) const device
{
return elements[pos];
}
constexpr const constant T& operator [] (size_t pos) const constant
{
return elements[pos];
}
threadgroup T& operator [] (size_t pos) threadgroup
{
return elements[pos];
}
constexpr const threadgroup T& operator [] (size_t pos) const threadgroup
{
return elements[pos];
}
};
struct main0_out
{
uint gl_SampleMask [[sample_mask]];
};
fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask]])
{
main0_out out = {};
spvUnsafeArray<uint, 1> copy_sample_mask = spvUnsafeArray<uint, 1>({ uint(gl_SampleMaskIn) });
out.gl_SampleMask = copy_sample_mask[0];
return out;
}

View File

@ -0,0 +1,59 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wmissing-braces"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
template<typename T, size_t Num>
struct spvUnsafeArray
{
T elements[Num ? Num : 1];
thread T& operator [] (size_t pos) thread
{
return elements[pos];
}
constexpr const thread T& operator [] (size_t pos) const thread
{
return elements[pos];
}
device T& operator [] (size_t pos) device
{
return elements[pos];
}
constexpr const device T& operator [] (size_t pos) const device
{
return elements[pos];
}
constexpr const constant T& operator [] (size_t pos) const constant
{
return elements[pos];
}
threadgroup T& operator [] (size_t pos) threadgroup
{
return elements[pos];
}
constexpr const threadgroup T& operator [] (size_t pos) const threadgroup
{
return elements[pos];
}
};
struct main0_out
{
uint gl_SampleMask [[sample_mask]];
};
fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask]])
{
main0_out out = {};
spvUnsafeArray<int, 1> copy_sample_mask = spvUnsafeArray<int, 1>({ int(gl_SampleMaskIn) });
out.gl_SampleMask = copy_sample_mask[0];
return out;
}

View File

@ -11,7 +11,7 @@ struct main0_out
[[ early_fragment_tests ]] fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask, post_depth_coverage]]) [[ early_fragment_tests ]] fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask, post_depth_coverage]])
{ {
main0_out out = {}; main0_out out = {};
out.FragColor = float4(float(gl_SampleMaskIn)); out.FragColor = float4(float(int(gl_SampleMaskIn)));
return out; return out;
} }

View File

@ -11,7 +11,7 @@ struct main0_out
[[ early_fragment_tests ]] fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask, post_depth_coverage]]) [[ early_fragment_tests ]] fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask, post_depth_coverage]])
{ {
main0_out out = {}; main0_out out = {};
out.FragColor = float4(float(gl_SampleMaskIn)); out.FragColor = float4(float(int(gl_SampleMaskIn)));
return out; return out;
} }

View File

@ -13,7 +13,7 @@ fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask]], uint gl_SampleID
{ {
main0_out out = {}; main0_out out = {};
out.FragColor = float4(1.0); out.FragColor = float4(1.0);
out.gl_SampleMask = (gl_SampleMaskIn & 0x22 & (1 << gl_SampleID)); out.gl_SampleMask = int((gl_SampleMaskIn & 0x22 & (1 << gl_SampleID)));
out.gl_SampleMask &= 0x22; out.gl_SampleMask &= 0x22;
return out; return out;
} }

View File

@ -13,7 +13,7 @@ fragment main0_out main0(uint gl_SampleMaskIn [[sample_mask]])
{ {
main0_out out = {}; main0_out out = {};
out.FragColor = float4(1.0); out.FragColor = float4(1.0);
out.gl_SampleMask = (gl_SampleMaskIn & 0x22); out.gl_SampleMask = int((gl_SampleMaskIn & 0x22));
out.gl_SampleMask &= 0x22; out.gl_SampleMask &= 0x22;
return out; return out;
} }

View File

@ -0,0 +1,16 @@
#version 450
void main()
{
uint _16_unrolled[1];
for (int i = 0; i < int(1); i++)
{
_16_unrolled[i] = int(gl_SampleMaskIn[i]);
}
uint copy_sample_mask[1] = _16_unrolled;
for (int i = 0; i < int(1); i++)
{
gl_SampleMask[i] = int(copy_sample_mask[i]);
}
}

View File

@ -0,0 +1,16 @@
#version 450
void main()
{
int _21_unrolled[1];
for (int i = 0; i < int(1); i++)
{
_21_unrolled[i] = gl_SampleMaskIn[i];
}
int copy_sample_mask[1] = _21_unrolled;
for (int i = 0; i < int(1); i++)
{
gl_SampleMask[i] = copy_sample_mask[i];
}
}

View File

@ -1,8 +1,49 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wmissing-braces"
#include <metal_stdlib> #include <metal_stdlib>
#include <simd/simd.h> #include <simd/simd.h>
using namespace metal; using namespace metal;
template<typename T, size_t Num>
struct spvUnsafeArray
{
T elements[Num ? Num : 1];
thread T& operator [] (size_t pos) thread
{
return elements[pos];
}
constexpr const thread T& operator [] (size_t pos) const thread
{
return elements[pos];
}
device T& operator [] (size_t pos) device
{
return elements[pos];
}
constexpr const device T& operator [] (size_t pos) const device
{
return elements[pos];
}
constexpr const constant T& operator [] (size_t pos) const constant
{
return elements[pos];
}
threadgroup T& operator [] (size_t pos) threadgroup
{
return elements[pos];
}
constexpr const threadgroup T& operator [] (size_t pos) const threadgroup
{
return elements[pos];
}
};
struct type_View struct type_View
{ {
float4x4 View_TranslatedWorldToClip; float4x4 View_TranslatedWorldToClip;
@ -489,12 +530,12 @@ fragment main0_out main0(main0_in in [[stage_in]], constant type_View& View [[bu
if (View.View_NumSceneColorMSAASamples > 1) if (View.View_NumSceneColorMSAASamples > 1)
{ {
_268 = _255 * float4(float(View.View_NumSceneColorMSAASamples) * 0.25); _268 = _255 * float4(float(View.View_NumSceneColorMSAASamples) * 0.25);
_269 = gl_SampleMaskIn & 15u; _269 = (spvUnsafeArray<uint, 1>({ uint(gl_SampleMaskIn) }))[0] & 15u;
} }
else else
{ {
_268 = _255; _268 = _255;
_269 = gl_SampleMaskIn; _269 = (spvUnsafeArray<uint, 1>({ uint(gl_SampleMaskIn) }))[0];
} }
out.out_var_SV_Target0 = _268; out.out_var_SV_Target0 = _268;
out.gl_SampleMask = _269; out.gl_SampleMask = _269;

View File

@ -0,0 +1,40 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 11
; Bound: 30
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %gl_SampleMaskIn %gl_SampleMask
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %copy_sample_mask "copy_sample_mask"
OpName %gl_SampleMaskIn "gl_SampleMaskIn"
OpName %out_sample_mask "out_sample_mask"
OpName %gl_SampleMask "gl_SampleMask"
OpDecorate %gl_SampleMaskIn Flat
OpDecorate %gl_SampleMaskIn BuiltIn SampleMask
OpDecorate %gl_SampleMask BuiltIn SampleMask
%void = OpTypeVoid
%3 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_int_uint_1 = OpTypeArray %uint %uint_1
%_ptr_Function__arr_int_uint_1 = OpTypePointer Function %_arr_int_uint_1
%_ptr_Input__arr_int_uint_1 = OpTypePointer Input %_arr_int_uint_1
%gl_SampleMaskIn = OpVariable %_ptr_Input__arr_int_uint_1 Input
%_ptr_Output__arr_int_uint_1 = OpTypePointer Output %_arr_int_uint_1
%gl_SampleMask = OpVariable %_ptr_Output__arr_int_uint_1 Output
%main = OpFunction %void None %3
%5 = OpLabel
%copy_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%out_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%loaded_sample_mask_in = OpLoad %_arr_int_uint_1 %gl_SampleMaskIn
OpStore %copy_sample_mask %loaded_sample_mask_in
%loaded_copy = OpLoad %_arr_int_uint_1 %copy_sample_mask
OpStore %gl_SampleMask %loaded_copy
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,45 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 11
; Bound: 30
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %gl_SampleMaskIn %gl_SampleMask
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %copy_sample_mask "copy_sample_mask"
OpName %gl_SampleMaskIn "gl_SampleMaskIn"
OpName %out_sample_mask "out_sample_mask"
OpName %gl_SampleMask "gl_SampleMask"
OpDecorate %gl_SampleMaskIn Flat
OpDecorate %gl_SampleMaskIn BuiltIn SampleMask
OpDecorate %gl_SampleMask BuiltIn SampleMask
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_int_uint_1 = OpTypeArray %int %uint_1
%_ptr_Function__arr_int_uint_1 = OpTypePointer Function %_arr_int_uint_1
%int_0 = OpConstant %int 0
%_ptr_Input__arr_int_uint_1 = OpTypePointer Input %_arr_int_uint_1
%gl_SampleMaskIn = OpVariable %_ptr_Input__arr_int_uint_1 Input
%_ptr_Input_int = OpTypePointer Input %int
%_ptr_Function_int = OpTypePointer Function %int
%_ptr_Output__arr_int_uint_1 = OpTypePointer Output %_arr_int_uint_1
%gl_SampleMask = OpVariable %_ptr_Output__arr_int_uint_1 Output
%_ptr_Output_int = OpTypePointer Output %int
%main = OpFunction %void None %3
%5 = OpLabel
%copy_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%out_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%loaded_sample_mask_in = OpLoad %_arr_int_uint_1 %gl_SampleMaskIn
OpStore %copy_sample_mask %loaded_sample_mask_in
%loaded_copy = OpLoad %_arr_int_uint_1 %copy_sample_mask
OpStore %gl_SampleMask %loaded_copy
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,40 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 11
; Bound: 30
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %gl_SampleMaskIn %gl_SampleMask
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %copy_sample_mask "copy_sample_mask"
OpName %gl_SampleMaskIn "gl_SampleMaskIn"
OpName %out_sample_mask "out_sample_mask"
OpName %gl_SampleMask "gl_SampleMask"
OpDecorate %gl_SampleMaskIn Flat
OpDecorate %gl_SampleMaskIn BuiltIn SampleMask
OpDecorate %gl_SampleMask BuiltIn SampleMask
%void = OpTypeVoid
%3 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_int_uint_1 = OpTypeArray %uint %uint_1
%_ptr_Function__arr_int_uint_1 = OpTypePointer Function %_arr_int_uint_1
%_ptr_Input__arr_int_uint_1 = OpTypePointer Input %_arr_int_uint_1
%gl_SampleMaskIn = OpVariable %_ptr_Input__arr_int_uint_1 Input
%_ptr_Output__arr_int_uint_1 = OpTypePointer Output %_arr_int_uint_1
%gl_SampleMask = OpVariable %_ptr_Output__arr_int_uint_1 Output
%main = OpFunction %void None %3
%5 = OpLabel
%copy_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%out_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%loaded_sample_mask_in = OpLoad %_arr_int_uint_1 %gl_SampleMaskIn
OpStore %copy_sample_mask %loaded_sample_mask_in
%loaded_copy = OpLoad %_arr_int_uint_1 %copy_sample_mask
OpStore %gl_SampleMask %loaded_copy
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,45 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 11
; Bound: 30
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %gl_SampleMaskIn %gl_SampleMask
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %copy_sample_mask "copy_sample_mask"
OpName %gl_SampleMaskIn "gl_SampleMaskIn"
OpName %out_sample_mask "out_sample_mask"
OpName %gl_SampleMask "gl_SampleMask"
OpDecorate %gl_SampleMaskIn Flat
OpDecorate %gl_SampleMaskIn BuiltIn SampleMask
OpDecorate %gl_SampleMask BuiltIn SampleMask
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_int_uint_1 = OpTypeArray %int %uint_1
%_ptr_Function__arr_int_uint_1 = OpTypePointer Function %_arr_int_uint_1
%int_0 = OpConstant %int 0
%_ptr_Input__arr_int_uint_1 = OpTypePointer Input %_arr_int_uint_1
%gl_SampleMaskIn = OpVariable %_ptr_Input__arr_int_uint_1 Input
%_ptr_Input_int = OpTypePointer Input %int
%_ptr_Function_int = OpTypePointer Function %int
%_ptr_Output__arr_int_uint_1 = OpTypePointer Output %_arr_int_uint_1
%gl_SampleMask = OpVariable %_ptr_Output__arr_int_uint_1 Output
%_ptr_Output_int = OpTypePointer Output %int
%main = OpFunction %void None %3
%5 = OpLabel
%copy_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%out_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%loaded_sample_mask_in = OpLoad %_arr_int_uint_1 %gl_SampleMaskIn
OpStore %copy_sample_mask %loaded_sample_mask_in
%loaded_copy = OpLoad %_arr_int_uint_1 %copy_sample_mask
OpStore %gl_SampleMask %loaded_copy
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,40 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 11
; Bound: 30
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %gl_SampleMaskIn %gl_SampleMask
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %copy_sample_mask "copy_sample_mask"
OpName %gl_SampleMaskIn "gl_SampleMaskIn"
OpName %out_sample_mask "out_sample_mask"
OpName %gl_SampleMask "gl_SampleMask"
OpDecorate %gl_SampleMaskIn Flat
OpDecorate %gl_SampleMaskIn BuiltIn SampleMask
OpDecorate %gl_SampleMask BuiltIn SampleMask
%void = OpTypeVoid
%3 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_int_uint_1 = OpTypeArray %uint %uint_1
%_ptr_Function__arr_int_uint_1 = OpTypePointer Function %_arr_int_uint_1
%_ptr_Input__arr_int_uint_1 = OpTypePointer Input %_arr_int_uint_1
%gl_SampleMaskIn = OpVariable %_ptr_Input__arr_int_uint_1 Input
%_ptr_Output__arr_int_uint_1 = OpTypePointer Output %_arr_int_uint_1
%gl_SampleMask = OpVariable %_ptr_Output__arr_int_uint_1 Output
%main = OpFunction %void None %3
%5 = OpLabel
%copy_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%out_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%loaded_sample_mask_in = OpLoad %_arr_int_uint_1 %gl_SampleMaskIn
OpStore %copy_sample_mask %loaded_sample_mask_in
%loaded_copy = OpLoad %_arr_int_uint_1 %copy_sample_mask
OpStore %gl_SampleMask %loaded_copy
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,45 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 11
; Bound: 30
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %gl_SampleMaskIn %gl_SampleMask
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %copy_sample_mask "copy_sample_mask"
OpName %gl_SampleMaskIn "gl_SampleMaskIn"
OpName %out_sample_mask "out_sample_mask"
OpName %gl_SampleMask "gl_SampleMask"
OpDecorate %gl_SampleMaskIn Flat
OpDecorate %gl_SampleMaskIn BuiltIn SampleMask
OpDecorate %gl_SampleMask BuiltIn SampleMask
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_int_uint_1 = OpTypeArray %int %uint_1
%_ptr_Function__arr_int_uint_1 = OpTypePointer Function %_arr_int_uint_1
%int_0 = OpConstant %int 0
%_ptr_Input__arr_int_uint_1 = OpTypePointer Input %_arr_int_uint_1
%gl_SampleMaskIn = OpVariable %_ptr_Input__arr_int_uint_1 Input
%_ptr_Input_int = OpTypePointer Input %int
%_ptr_Function_int = OpTypePointer Function %int
%_ptr_Output__arr_int_uint_1 = OpTypePointer Output %_arr_int_uint_1
%gl_SampleMask = OpVariable %_ptr_Output__arr_int_uint_1 Output
%_ptr_Output_int = OpTypePointer Output %int
%main = OpFunction %void None %3
%5 = OpLabel
%copy_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%out_sample_mask = OpVariable %_ptr_Function__arr_int_uint_1 Function
%loaded_sample_mask_in = OpLoad %_arr_int_uint_1 %gl_SampleMaskIn
OpStore %copy_sample_mask %loaded_sample_mask_in
%loaded_copy = OpLoad %_arr_int_uint_1 %copy_sample_mask
OpStore %gl_SampleMask %loaded_copy
OpReturn
OpFunctionEnd

View File

@ -10158,10 +10158,11 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
if (!pending_array_enclose) if (!pending_array_enclose)
expr += "]"; expr += "]";
} }
else if (index_is_literal || !builtin_translates_to_nonarray(BuiltIn(get_decoration(base, DecorationBuiltIn))))
{
// Some builtins are arrays in SPIR-V but not in other languages, e.g. gl_SampleMask[] is an array in SPIR-V but not in Metal. // Some builtins are arrays in SPIR-V but not in other languages, e.g. gl_SampleMask[] is an array in SPIR-V but not in Metal.
// By throwing away the index, we imply the index was 0, which it must be for gl_SampleMask. // By throwing away the index, we imply the index was 0, which it must be for gl_SampleMask.
else if (!builtin_translates_to_nonarray(BuiltIn(get_decoration(base, DecorationBuiltIn)))) // For literal indices we are working on composites, so we ignore this since we have already converted to proper array.
{
append_index(index, is_literal); append_index(index, is_literal);
} }
@ -17737,6 +17738,25 @@ void CompilerGLSL::cast_from_variable_load(uint32_t source_id, std::string &expr
expr = bitcast_expression(expr_type, expected_type, expr); expr = bitcast_expression(expr_type, expected_type, expr);
} }
SPIRType::BaseType CompilerGLSL::get_builtin_basetype(BuiltIn builtin, SPIRType::BaseType default_type)
{
// TODO: Fill in for more builtins.
switch (builtin)
{
case BuiltInLayer:
case BuiltInPrimitiveId:
case BuiltInViewportIndex:
case BuiltInFragStencilRefEXT:
case BuiltInSampleMask:
case BuiltInPrimitiveShadingRateKHR:
case BuiltInShadingRateKHR:
return SPIRType::Int;
default:
return default_type;
}
}
void CompilerGLSL::cast_to_variable_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type) void CompilerGLSL::cast_to_variable_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type)
{ {
auto *var = maybe_get_backing_variable(target_id); auto *var = maybe_get_backing_variable(target_id);
@ -17748,24 +17768,7 @@ void CompilerGLSL::cast_to_variable_store(uint32_t target_id, std::string &expr,
return; return;
auto builtin = static_cast<BuiltIn>(get_decoration(target_id, DecorationBuiltIn)); auto builtin = static_cast<BuiltIn>(get_decoration(target_id, DecorationBuiltIn));
auto expected_type = expr_type.basetype; auto expected_type = get_builtin_basetype(builtin, expr_type.basetype);
// TODO: Fill in for more builtins.
switch (builtin)
{
case BuiltInLayer:
case BuiltInPrimitiveId:
case BuiltInViewportIndex:
case BuiltInFragStencilRefEXT:
case BuiltInSampleMask:
case BuiltInPrimitiveShadingRateKHR:
case BuiltInShadingRateKHR:
expected_type = SPIRType::Int;
break;
default:
break;
}
if (expected_type != expr_type.basetype) if (expected_type != expr_type.basetype)
{ {

View File

@ -993,6 +993,7 @@ protected:
// Builtins in GLSL are always specific signedness, but the SPIR-V can declare them // Builtins in GLSL are always specific signedness, but the SPIR-V can declare them
// as either unsigned or signed. // as either unsigned or signed.
// Sometimes we will need to automatically perform casts on load and store to make this work. // Sometimes we will need to automatically perform casts on load and store to make this work.
virtual SPIRType::BaseType get_builtin_basetype(spv::BuiltIn builtin, SPIRType::BaseType default_type);
virtual void cast_to_variable_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type); virtual void cast_to_variable_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type);
virtual void cast_from_variable_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type); virtual void cast_from_variable_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type);
void unroll_array_from_complex_load(uint32_t target_id, uint32_t source_id, std::string &expr); void unroll_array_from_complex_load(uint32_t target_id, uint32_t source_id, std::string &expr);

View File

@ -1149,15 +1149,31 @@ void CompilerHLSL::emit_builtin_variables()
builtins.merge_or(active_output_builtins); builtins.merge_or(active_output_builtins);
std::unordered_map<uint32_t, ID> builtin_to_initializer; std::unordered_map<uint32_t, ID> builtin_to_initializer;
// We need to declare sample mask with the same type that module declares it.
// Sample mask is somewhat special in that SPIR-V has an array, and we can copy that array, so we need to
// match sign.
SPIRType::BaseType sample_mask_in_basetype = SPIRType::Void;
SPIRType::BaseType sample_mask_out_basetype = SPIRType::Void;
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) { ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
if (!is_builtin_variable(var) || var.storage != StorageClassOutput || !var.initializer) if (!is_builtin_variable(var))
return; return;
auto &type = this->get<SPIRType>(var.basetype);
auto builtin = BuiltIn(get_decoration(var.self, DecorationBuiltIn));
if (var.storage == StorageClassInput && builtin == BuiltInSampleMask)
sample_mask_in_basetype = type.basetype;
else if (var.storage == StorageClassOutput && builtin == BuiltInSampleMask)
sample_mask_out_basetype = type.basetype;
if (var.initializer && var.storage == StorageClassOutput)
{
auto *c = this->maybe_get<SPIRConstant>(var.initializer); auto *c = this->maybe_get<SPIRConstant>(var.initializer);
if (!c) if (!c)
return; return;
auto &type = this->get<SPIRType>(var.basetype);
if (type.basetype == SPIRType::Struct) if (type.basetype == SPIRType::Struct)
{ {
uint32_t member_count = uint32_t(type.member_types.size()); uint32_t member_count = uint32_t(type.member_types.size());
@ -1171,7 +1187,10 @@ void CompilerHLSL::emit_builtin_variables()
} }
} }
else if (has_decoration(var.self, DecorationBuiltIn)) else if (has_decoration(var.self, DecorationBuiltIn))
builtin_to_initializer[get_decoration(var.self, DecorationBuiltIn)] = var.initializer; {
builtin_to_initializer[builtin] = var.initializer;
}
}
}); });
// Emit global variables for the interface variables which are statically used by the shader. // Emit global variables for the interface variables which are statically used by the shader.
@ -1288,7 +1307,11 @@ void CompilerHLSL::emit_builtin_variables()
break; break;
case BuiltInSampleMask: case BuiltInSampleMask:
type = "int"; if (active_input_builtins.get(BuiltInSampleMask))
type = sample_mask_in_basetype == SPIRType::UInt ? "uint" : "int";
else
type = sample_mask_out_basetype == SPIRType::UInt ? "uint" : "int";
array_size = 1;
break; break;
case BuiltInPrimitiveId: case BuiltInPrimitiveId:
@ -1322,6 +1345,10 @@ void CompilerHLSL::emit_builtin_variables()
// declared the input variable and we need to add the output one now. // declared the input variable and we need to add the output one now.
if (builtin == BuiltInSampleMask && storage == StorageClassInput && this->active_output_builtins.get(i)) if (builtin == BuiltInSampleMask && storage == StorageClassInput && this->active_output_builtins.get(i))
{ {
type = sample_mask_out_basetype == SPIRType::UInt ? "uint" : "int";
if (array_size)
statement("static ", type, " ", this->builtin_to_glsl(builtin, StorageClassOutput), "[", array_size, "]", init_expr, ";");
else
statement("static ", type, " ", this->builtin_to_glsl(builtin, StorageClassOutput), init_expr, ";"); statement("static ", type, " ", this->builtin_to_glsl(builtin, StorageClassOutput), init_expr, ";");
} }
}); });
@ -1536,6 +1563,18 @@ void CompilerHLSL::replace_illegal_names()
CompilerGLSL::replace_illegal_names(); CompilerGLSL::replace_illegal_names();
} }
SPIRType::BaseType CompilerHLSL::get_builtin_basetype(BuiltIn builtin, SPIRType::BaseType default_type)
{
switch (builtin)
{
case BuiltInSampleMask:
// We declare sample mask array with module type, so always use default_type here.
return default_type;
default:
return CompilerGLSL::get_builtin_basetype(builtin, default_type);
}
}
void CompilerHLSL::emit_resources() void CompilerHLSL::emit_resources()
{ {
auto &execution = get_entry_point(); auto &execution = get_entry_point();
@ -3121,6 +3160,10 @@ void CompilerHLSL::emit_hlsl_entry_point()
statement(builtin, " = int(stage_input.", builtin, ");"); statement(builtin, " = int(stage_input.", builtin, ");");
break; break;
case BuiltInSampleMask:
statement(builtin, "[0] = stage_input.", builtin, ";");
break;
case BuiltInNumWorkgroups: case BuiltInNumWorkgroups:
case BuiltInPointCoord: case BuiltInPointCoord:
case BuiltInSubgroupSize: case BuiltInSubgroupSize:
@ -3295,6 +3338,10 @@ void CompilerHLSL::emit_hlsl_entry_point()
cull, "];"); cull, "];");
break; break;
case BuiltInSampleMask:
statement("stage_output.gl_SampleMask = gl_SampleMask[0];");
break;
default: default:
{ {
auto builtin_expr = builtin_to_glsl(static_cast<BuiltIn>(i), StorageClassOutput); auto builtin_expr = builtin_to_glsl(static_cast<BuiltIn>(i), StorageClassOutput);
@ -6751,11 +6798,6 @@ void CompilerHLSL::set_hlsl_force_storage_buffer_as_uav(uint32_t desc_set, uint3
force_uav_buffer_bindings.insert(pair); force_uav_buffer_bindings.insert(pair);
} }
bool CompilerHLSL::builtin_translates_to_nonarray(spv::BuiltIn builtin) const
{
return (builtin == BuiltInSampleMask);
}
bool CompilerHLSL::is_user_type_structured(uint32_t id) const bool CompilerHLSL::is_user_type_structured(uint32_t id) const
{ {
if (hlsl_options.preserve_structured_buffers) if (hlsl_options.preserve_structured_buffers)

View File

@ -290,6 +290,8 @@ private:
const char *to_storage_qualifiers_glsl(const SPIRVariable &var) override; const char *to_storage_qualifiers_glsl(const SPIRVariable &var) override;
void replace_illegal_names() override; void replace_illegal_names() override;
SPIRType::BaseType get_builtin_basetype(spv::BuiltIn builtin, SPIRType::BaseType default_type) override;
bool is_hlsl_force_storage_buffer_as_uav(ID id) const; bool is_hlsl_force_storage_buffer_as_uav(ID id) const;
Options hlsl_options; Options hlsl_options;
@ -400,9 +402,6 @@ private:
bool used = false; bool used = false;
} base_vertex_info; } base_vertex_info;
// Returns true for BuiltInSampleMask because gl_SampleMask[] is an array in SPIR-V, but SV_Coverage is a scalar in HLSL.
bool builtin_translates_to_nonarray(spv::BuiltIn builtin) const override;
// Returns true if the specified ID has a UserTypeGOOGLE decoration for StructuredBuffer or RWStructuredBuffer resources. // Returns true if the specified ID has a UserTypeGOOGLE decoration for StructuredBuffer or RWStructuredBuffer resources.
bool is_user_type_structured(uint32_t id) const override; bool is_user_type_structured(uint32_t id) const override;

View File

@ -4911,9 +4911,18 @@ void CompilerMSL::emit_store_statement(uint32_t lhs_expression, uint32_t rhs_exp
bool transpose = lhs_e && lhs_e->need_transpose; bool transpose = lhs_e && lhs_e->need_transpose;
// No physical type remapping, and no packed type, so can just emit a store directly. if (has_decoration(lhs_expression, DecorationBuiltIn) &&
if (!lhs_remapped_type && !lhs_packed_type) BuiltIn(get_decoration(lhs_expression, DecorationBuiltIn)) == BuiltInSampleMask &&
type_is_top_level_array(type))
{ {
// Storing an array to SampleMask, have to remove the array-ness before storing.
statement(to_expression(lhs_expression), " = ", to_enclosed_unpacked_expression(rhs_expression), "[0];");
register_write(lhs_expression);
}
else if (!lhs_remapped_type && !lhs_packed_type)
{
// No physical type remapping, and no packed type, so can just emit a store directly.
// We might not be dealing with remapped physical types or packed types, // We might not be dealing with remapped physical types or packed types,
// but we might be doing a clean store to a row-major matrix. // but we might be doing a clean store to a row-major matrix.
// In this case, we just flip transpose states, and emit the store, a transpose must be in the RHS expression, if any. // In this case, we just flip transpose states, and emit the store, a transpose must be in the RHS expression, if any.
@ -17178,6 +17187,7 @@ void CompilerMSL::cast_from_variable_load(uint32_t source_id, std::string &expr,
case BuiltInInstanceIndex: case BuiltInInstanceIndex:
case BuiltInBaseInstance: case BuiltInBaseInstance:
case BuiltInBaseVertex: case BuiltInBaseVertex:
case BuiltInSampleMask:
expected_type = SPIRType::UInt; expected_type = SPIRType::UInt;
expected_width = 32; expected_width = 32;
break; break;
@ -17195,9 +17205,17 @@ void CompilerMSL::cast_from_variable_load(uint32_t source_id, std::string &expr,
break; break;
} }
if (expected_type != expr_type.basetype) if (type_is_top_level_array(expr_type) && builtin == BuiltInSampleMask)
{ {
if (!expr_type.array.empty() && (builtin == BuiltInTessLevelInner || builtin == BuiltInTessLevelOuter)) // Needs special handling.
auto wrap_expr = join(type_to_glsl(expr_type), "({ ");
wrap_expr += join(type_to_glsl(get<SPIRType>(expr_type.parent_type)), "(", expr, ")");
wrap_expr += " })";
expr = std::move(wrap_expr);
}
else if (expected_type != expr_type.basetype)
{
if (type_is_top_level_array(expr_type) && (builtin == BuiltInTessLevelInner || builtin == BuiltInTessLevelOuter))
{ {
// Triggers when loading TessLevel directly as an array. // Triggers when loading TessLevel directly as an array.
// Need explicit padding + cast. // Need explicit padding + cast.