Merge pull request #546 from KhronosGroup/fix-545

Fix multiple uses of combined image samplers on Vulkan GLSL
This commit is contained in:
Hans-Kristian Arntzen 2018-04-27 10:47:31 +02:00 committed by GitHub
commit bbf6b60350
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 472 additions and 90 deletions

View File

@ -0,0 +1,30 @@
Texture2D<float4> uTex : register(t1);
SamplerState uSampler : register(s0);
static float4 FragColor;
static float2 vUV;
struct SPIRV_Cross_Input
{
float2 vUV : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
void frag_main()
{
FragColor = uTex.Sample(uSampler, vUV);
FragColor += uTex.Sample(uSampler, vUV, int2(1, 1));
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
vUV = stage_input.vUV;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,23 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_in
{
float2 vUV [[user(locn0)]];
};
struct main0_out
{
float4 FragColor [[color(0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> uTex [[texture(1)]], sampler uSampler [[sampler(0)]])
{
main0_out out = {};
out.FragColor = uTex.sample(uSampler, in.vUV);
out.FragColor += uTex.sample(uSampler, in.vUV, int2(1));
return out;
}

View File

@ -1,11 +0,0 @@
#version 450
#extension GL_AMD_shader_fragment_mask : require
layout(binding = 0) uniform sampler2DMS t;
void main()
{
vec4 test2 = fragmentFetchAMD(t, 4u);
uint testi2 = fragmentMaskFetchAMD(t);
}

View File

@ -0,0 +1,13 @@
#version 450
uniform sampler2D SPIRV_Cross_CombineduTexuSampler;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec2 vUV;
void main()
{
FragColor = texture(SPIRV_Cross_CombineduTexuSampler, vUV);
FragColor += textureOffset(SPIRV_Cross_CombineduTexuSampler, vUV, ivec2(1));
}

View File

@ -0,0 +1,14 @@
#version 450
layout(set = 0, binding = 1) uniform texture2D uTex;
layout(set = 0, binding = 0) uniform sampler uSampler;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec2 vUV;
void main()
{
FragColor = texture(sampler2D(uTex, uSampler), vUV);
FragColor += textureOffset(sampler2D(uTex, uSampler), vUV, ivec2(1));
}

View File

@ -0,0 +1,18 @@
#version 450
struct Registers
{
int index;
};
uniform Registers registers;
uniform sampler2D SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler[4];
layout(location = 0) out vec4 FragColor;
void main()
{
FragColor = (texelFetch(SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler[registers.index], ivec2(10), 0) + texelFetch(SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler[registers.index], ivec2(4), 0)) + texelFetch(SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler[registers.index], ivec2(4), 0);
}

View File

@ -7,28 +7,73 @@ struct VertexOutput
vec2 uv;
};
struct HSOut
{
vec4 pos;
vec2 uv;
};
struct HSConstantOut
{
float EdgeTess[3];
float InsideTess;
};
struct VertexOutput_1
{
vec2 uv;
};
struct HSOut_1
{
vec2 uv;
};
layout(location = 0) in VertexOutput_1 p[];
layout(location = 0) out VertexOutput_1 _entryPointOutput[3];
layout(location = 0) out HSOut_1 _entryPointOutput[3];
HSOut _hs_main(VertexOutput p_1[3], uint i)
{
HSOut _output;
_output.pos = p_1[i].pos;
_output.uv = p_1[i].uv;
return _output;
}
HSConstantOut PatchHS(VertexOutput _patch[3])
{
HSConstantOut _output;
_output.EdgeTess[0] = (vec2(1.0) + _patch[0].uv).x;
_output.EdgeTess[1] = (vec2(1.0) + _patch[0].uv).x;
_output.EdgeTess[2] = (vec2(1.0) + _patch[0].uv).x;
_output.InsideTess = (vec2(1.0) + _patch[0].uv).x;
return _output;
}
void main()
{
VertexOutput param[3] = VertexOutput[](VertexOutput(gl_in[0].gl_Position, p[0].uv), VertexOutput(gl_in[1].gl_Position, p[1].uv), VertexOutput(gl_in[2].gl_Position, p[2].uv));
gl_out[gl_InvocationID].gl_Position = param[gl_InvocationID].pos;
_entryPointOutput[gl_InvocationID].uv = param[gl_InvocationID].uv;
VertexOutput p_1[3];
p_1[0].pos = gl_in[0].gl_Position;
p_1[0].uv = p[0].uv;
p_1[1].pos = gl_in[1].gl_Position;
p_1[1].uv = p[1].uv;
p_1[2].pos = gl_in[2].gl_Position;
p_1[2].uv = p[2].uv;
uint i = gl_InvocationID;
VertexOutput param[3] = p_1;
uint param_1 = i;
HSOut flattenTemp = _hs_main(param, param_1);
gl_out[gl_InvocationID].gl_Position = flattenTemp.pos;
_entryPointOutput[gl_InvocationID].uv = flattenTemp.uv;
barrier();
if (int(gl_InvocationID) == 0)
{
vec2 _174 = vec2(1.0) + p[0].uv;
float _175 = _174.x;
gl_TessLevelOuter[0] = _175;
gl_TessLevelOuter[1] = _175;
gl_TessLevelOuter[2] = _175;
gl_TessLevelInner[0] = _175;
VertexOutput param_2[3] = p_1;
HSConstantOut _patchConstantResult = PatchHS(param_2);
gl_TessLevelOuter[0] = _patchConstantResult.EdgeTess[0];
gl_TessLevelOuter[1] = _patchConstantResult.EdgeTess[1];
gl_TessLevelOuter[2] = _patchConstantResult.EdgeTess[2];
gl_TessLevelInner[0] = _patchConstantResult.InsideTess;
}
}

View File

@ -1,15 +0,0 @@
#version 310 es
#extension GL_OVR_multiview2 : require
layout(binding = 0, std140) uniform MVPs
{
mat4 MVP[2];
} _19;
layout(location = 0) in vec4 Position;
void main()
{
gl_Position = _19.MVP[gl_ViewID_OVR] * Position;
}

View File

@ -0,0 +1,30 @@
Texture2D<float4> uTex : register(t1);
SamplerState uSampler : register(s0);
static float4 FragColor;
static float2 vUV;
struct SPIRV_Cross_Input
{
float2 vUV : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 FragColor : SV_Target0;
};
void frag_main()
{
FragColor = uTex.Sample(uSampler, vUV);
FragColor += uTex.Sample(uSampler, vUV, int2(1, 1));
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
vUV = stage_input.vUV;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,23 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_in
{
float2 vUV [[user(locn0)]];
};
struct main0_out
{
float4 FragColor [[color(0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> uTex [[texture(1)]], sampler uSampler [[sampler(0)]])
{
main0_out out = {};
out.FragColor = uTex.sample(uSampler, in.vUV);
out.FragColor += uTex.sample(uSampler, in.vUV, int2(1));
return out;
}

View File

@ -1,11 +0,0 @@
#version 450
#extension GL_AMD_shader_fragment_mask : require
layout(binding = 0) uniform sampler2DMS t;
void main()
{
vec4 test2 = fragmentFetchAMD(t, 4u);
uint testi2 = fragmentMaskFetchAMD(t);
}

View File

@ -0,0 +1,13 @@
#version 450
uniform sampler2D SPIRV_Cross_CombineduTexuSampler;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec2 vUV;
void main()
{
FragColor = texture(SPIRV_Cross_CombineduTexuSampler, vUV);
FragColor += textureOffset(SPIRV_Cross_CombineduTexuSampler, vUV, ivec2(1));
}

View File

@ -0,0 +1,14 @@
#version 450
layout(set = 0, binding = 1) uniform texture2D uTex;
layout(set = 0, binding = 0) uniform sampler uSampler;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec2 vUV;
void main()
{
FragColor = texture(sampler2D(uTex, uSampler), vUV);
FragColor += textureOffset(sampler2D(uTex, uSampler), vUV, ivec2(1));
}

View File

@ -0,0 +1,28 @@
#version 450
struct Registers
{
int index;
};
uniform Registers registers;
uniform sampler2D SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler[4];
layout(location = 0) out vec4 FragColor;
vec4 sample_from_func(sampler2D SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler_1[4])
{
return texelFetch(SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler_1[registers.index], ivec2(4), 0);
}
vec4 sample_one_from_func(sampler2D SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler_1)
{
return texelFetch(SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler_1, ivec2(4), 0);
}
void main()
{
FragColor = (texelFetch(SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler[registers.index], ivec2(10), 0) + sample_from_func(SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler)) + sample_one_from_func(SPIRV_Cross_CombineduSamplerSPIRV_Cross_DummySampler[registers.index]);
}

View File

@ -1,15 +0,0 @@
#version 310 es
#extension GL_OVR_multiview2 : require
layout(binding = 0, std140) uniform MVPs
{
mat4 MVP[2];
} _19;
layout(location = 0) in vec4 Position;
void main()
{
gl_Position = _19.MVP[gl_ViewID_OVR] * Position;
}

View File

@ -0,0 +1,57 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 36
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %FragColor %vUV
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %FragColor "FragColor"
OpName %uTex "uTex"
OpName %uSampler "uSampler"
OpName %vUV "vUV"
OpDecorate %FragColor Location 0
OpDecorate %uTex DescriptorSet 0
OpDecorate %uTex Binding 1
OpDecorate %uSampler DescriptorSet 0
OpDecorate %uSampler Binding 0
OpDecorate %vUV Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%FragColor = OpVariable %_ptr_Output_v4float Output
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
%uTex = OpVariable %_ptr_UniformConstant_10 UniformConstant
%14 = OpTypeSampler
%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
%uSampler = OpVariable %_ptr_UniformConstant_14 UniformConstant
%18 = OpTypeSampledImage %10
%v2float = OpTypeVector %float 2
%_ptr_Input_v2float = OpTypePointer Input %v2float
%vUV = OpVariable %_ptr_Input_v2float Input
%int = OpTypeInt 32 1
%v2int = OpTypeVector %int 2
%int_1 = OpConstant %int 1
%32 = OpConstantComposite %v2int %int_1 %int_1
%main = OpFunction %void None %3
%5 = OpLabel
%13 = OpLoad %10 %uTex
%17 = OpLoad %14 %uSampler
%19 = OpSampledImage %18 %13 %17
%23 = OpLoad %v2float %vUV
%24 = OpImageSampleImplicitLod %v4float %19 %23
OpStore %FragColor %24
%28 = OpLoad %v2float %vUV
%33 = OpImageSampleImplicitLod %v4float %19 %28 ConstOffset %32
%34 = OpLoad %v4float %FragColor
%35 = OpFAdd %v4float %34 %33
OpStore %FragColor %35
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,57 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 36
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %FragColor %vUV
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %FragColor "FragColor"
OpName %uTex "uTex"
OpName %uSampler "uSampler"
OpName %vUV "vUV"
OpDecorate %FragColor Location 0
OpDecorate %uTex DescriptorSet 0
OpDecorate %uTex Binding 1
OpDecorate %uSampler DescriptorSet 0
OpDecorate %uSampler Binding 0
OpDecorate %vUV Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%FragColor = OpVariable %_ptr_Output_v4float Output
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
%uTex = OpVariable %_ptr_UniformConstant_10 UniformConstant
%14 = OpTypeSampler
%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
%uSampler = OpVariable %_ptr_UniformConstant_14 UniformConstant
%18 = OpTypeSampledImage %10
%v2float = OpTypeVector %float 2
%_ptr_Input_v2float = OpTypePointer Input %v2float
%vUV = OpVariable %_ptr_Input_v2float Input
%int = OpTypeInt 32 1
%v2int = OpTypeVector %int 2
%int_1 = OpConstant %int 1
%32 = OpConstantComposite %v2int %int_1 %int_1
%main = OpFunction %void None %3
%5 = OpLabel
%13 = OpLoad %10 %uTex
%17 = OpLoad %14 %uSampler
%19 = OpSampledImage %18 %13 %17
%23 = OpLoad %v2float %vUV
%24 = OpImageSampleImplicitLod %v4float %19 %23
OpStore %FragColor %24
%28 = OpLoad %v2float %vUV
%33 = OpImageSampleImplicitLod %v4float %19 %28 ConstOffset %32
%34 = OpLoad %v4float %FragColor
%35 = OpFAdd %v4float %34 %33
OpStore %FragColor %35
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,57 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 36
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %FragColor %vUV
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %FragColor "FragColor"
OpName %uTex "uTex"
OpName %uSampler "uSampler"
OpName %vUV "vUV"
OpDecorate %FragColor Location 0
OpDecorate %uTex DescriptorSet 0
OpDecorate %uTex Binding 1
OpDecorate %uSampler DescriptorSet 0
OpDecorate %uSampler Binding 0
OpDecorate %vUV Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%FragColor = OpVariable %_ptr_Output_v4float Output
%10 = OpTypeImage %float 2D 0 0 0 1 Unknown
%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
%uTex = OpVariable %_ptr_UniformConstant_10 UniformConstant
%14 = OpTypeSampler
%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
%uSampler = OpVariable %_ptr_UniformConstant_14 UniformConstant
%18 = OpTypeSampledImage %10
%v2float = OpTypeVector %float 2
%_ptr_Input_v2float = OpTypePointer Input %v2float
%vUV = OpVariable %_ptr_Input_v2float Input
%int = OpTypeInt 32 1
%v2int = OpTypeVector %int 2
%int_1 = OpConstant %int 1
%32 = OpConstantComposite %v2int %int_1 %int_1
%main = OpFunction %void None %3
%5 = OpLabel
%13 = OpLoad %10 %uTex
%17 = OpLoad %14 %uSampler
%19 = OpSampledImage %18 %13 %17
%23 = OpLoad %v2float %vUV
%24 = OpImageSampleImplicitLod %v4float %19 %23
OpStore %FragColor %24
%28 = OpLoad %v2float %vUV
%33 = OpImageSampleImplicitLod %v4float %19 %28 ConstOffset %32
%34 = OpLoad %v4float %FragColor
%35 = OpFAdd %v4float %34 %33
OpStore %FragColor %35
OpReturn
OpFunctionEnd

View File

@ -3681,9 +3681,15 @@ void CompilerGLSL::emit_sampled_image_op(uint32_t result_type, uint32_t result_i
{
emit_binary_func_op(result_type, result_id, image_id, samp_id,
type_to_glsl(get<SPIRType>(result_type)).c_str());
// Make sure to suppress usage tracking. It is illegal to create temporaries of opaque types.
forwarded_temporaries.erase(result_id);
}
else
emit_op(result_type, result_id, to_combined_image_sampler(image_id, samp_id), true);
{
// Make sure to suppress usage tracking. It is illegal to create temporaries of opaque types.
emit_op(result_type, result_id, to_combined_image_sampler(image_id, samp_id), true, true);
}
}
void CompilerGLSL::emit_texture_op(const Instruction &i)

View File

@ -14,6 +14,16 @@ import codecs
force_no_external_validation = False
def remove_file(path):
#print('Removing file:', path)
os.remove(path)
def create_temporary(suff = ''):
f, path = tempfile.mkstemp(suffix = suff)
os.close(f)
#print('Creating temporary:', path)
return path
def parse_stats(stats):
m = re.search('([0-9]+) work registers', stats)
registers = int(m.group(1)) if m else 0
@ -49,12 +59,11 @@ def get_shader_type(shader):
return ''
def get_shader_stats(shader):
f, path = tempfile.mkstemp()
path = create_temporary()
os.close(f)
p = subprocess.Popen(['malisc', get_shader_type(shader), '--core', 'Mali-T760', '-V', shader], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
stdout, stderr = p.communicate()
os.remove(path)
remove_file(path)
if p.returncode != 0:
print(stderr.decode('utf-8'))
@ -89,10 +98,8 @@ def validate_shader_msl(shader, opt):
def cross_compile_msl(shader, spirv, opt):
msl2 = '.msl2.' in shader
spirv_f, spirv_path = tempfile.mkstemp()
msl_f, msl_path = tempfile.mkstemp(suffix = os.path.basename(shader))
os.close(spirv_f)
os.close(msl_f)
spirv_path = create_temporary()
msl_path = create_temporary(os.path.basename(shader))
if spirv:
subprocess.check_call(['spirv-as', '-o', spirv_path, shader])
@ -169,10 +176,8 @@ def shader_to_sm(shader):
return '50'
def cross_compile_hlsl(shader, spirv, opt):
spirv_f, spirv_path = tempfile.mkstemp()
hlsl_f, hlsl_path = tempfile.mkstemp(suffix = os.path.basename(shader))
os.close(spirv_f)
os.close(hlsl_f)
spirv_path = create_temporary()
hlsl_path = create_temporary(os.path.basename(shader))
if spirv:
subprocess.check_call(['spirv-as', '-o', spirv_path, shader])
@ -201,14 +206,11 @@ def validate_shader(shader, vulkan):
subprocess.check_call(['glslangValidator', shader])
def cross_compile(shader, vulkan, spirv, invalid_spirv, eliminate, is_legacy, flatten_ubo, sso, flatten_dim, opt):
spirv_f, spirv_path = tempfile.mkstemp()
glsl_f, glsl_path = tempfile.mkstemp(suffix = os.path.basename(shader))
os.close(spirv_f)
os.close(glsl_f)
spirv_path = create_temporary()
glsl_path = create_temporary(os.path.basename(shader))
if vulkan or spirv:
vulkan_glsl_f, vulkan_glsl_path = tempfile.mkstemp(suffix = os.path.basename(shader))
os.close(vulkan_glsl_f)
vulkan_glsl_path = create_temporary('vk' + os.path.basename(shader))
if spirv:
subprocess.check_call(['spirv-as', '-o', spirv_path, shader])
@ -236,16 +238,19 @@ def cross_compile(shader, vulkan, spirv, invalid_spirv, eliminate, is_legacy, fl
spirv_cross_path = './spirv-cross'
# A shader might not be possible to make valid GLSL from, skip validation for this case.
if (not ('nocompat' in glsl_path)) and (not spirv):
if not ('nocompat' in glsl_path):
subprocess.check_call([spirv_cross_path, '--entry', 'main', '--output', glsl_path, spirv_path] + extra_args)
validate_shader(glsl_path, False)
else:
os.remove(glsl_path)
remove_file(glsl_path)
glsl_path = None
if vulkan or spirv:
subprocess.check_call([spirv_cross_path, '--entry', 'main', '--vulkan-semantics', '--output', vulkan_glsl_path, spirv_path] + extra_args)
validate_shader(vulkan_glsl_path, True)
# SPIR-V shaders might just want to validate Vulkan GLSL output, we don't always care about the output.
if not vulkan:
remove_file(vulkan_glsl_path)
return (spirv_path, glsl_path, vulkan_glsl_path if vulkan else None)
@ -283,7 +288,7 @@ def regression_check(shader, glsl, update, keep, opt):
print('Generated source code has changed for {}!'.format(reference))
# If we expect changes, update the reference file.
if os.path.exists(reference):
os.remove(reference)
remove_file(reference)
make_reference_dir(reference)
shutil.move(glsl, reference)
else:
@ -298,10 +303,10 @@ def regression_check(shader, glsl, update, keep, opt):
# Otherwise, fail the test. Keep the shader file around so we can inspect.
if not keep:
os.remove(glsl)
remove_file(glsl)
sys.exit(1)
else:
os.remove(glsl)
remove_file(glsl)
else:
print('Found new shader {}. Placing generated source code in {}'.format(joined_path, reference))
make_reference_dir(reference)
@ -361,7 +366,8 @@ def test_shader(stats, shader, update, keep, opt):
regression_check(shader, glsl, update, keep, opt)
if vulkan_glsl:
regression_check((shader[0], shader[1] + '.vk'), vulkan_glsl, update, keep, opt)
os.remove(spirv)
remove_file(spirv)
if stats and (not vulkan) and (not is_spirv) and (not desktop):
pristine_stats = get_shader_stats(joined_path)
@ -393,16 +399,16 @@ def test_shader_msl(stats, shader, update, keep, opt):
if not force_no_external_validation:
validate_shader_msl(shader, opt)
os.remove(spirv)
remove_file(spirv)
def test_shader_hlsl(stats, shader, update, keep, opt):
joined_path = os.path.join(shader[0], shader[1])
print('Testing HLSL shader:', joined_path)
is_spirv = shader_is_spirv(shader[1])
noopt = shader_is_noopt(shader[1])
spirv, msl = cross_compile_hlsl(joined_path, is_spirv, opt and (not noopt))
regression_check(shader, msl, update, keep, opt)
os.remove(spirv)
spirv, hlsl = cross_compile_hlsl(joined_path, is_spirv, opt and (not noopt))
regression_check(shader, hlsl, update, keep, opt)
remove_file(spirv)
def test_shaders_helper(stats, shader_dir, update, malisc, keep, opt, backend):
for root, dirs, files in os.walk(os.path.join(shader_dir)):