Merge pull request #978 from KhronosGroup/fix-974
HLSL/MSL: Deal correctly with nonuniformEXT qualifier.
This commit is contained in:
commit
bf69c1f3ca
@ -0,0 +1,46 @@
|
||||
struct UBO_1_1
|
||||
{
|
||||
float4 v[64];
|
||||
};
|
||||
|
||||
ConstantBuffer<UBO_1_1> ubos[] : register(b0, space3);
|
||||
ByteAddressBuffer ssbos[] : register(t0, space4);
|
||||
Texture2D<float4> uSamplers[] : register(t0, space0);
|
||||
SamplerState uSamps[] : register(s0, space2);
|
||||
Texture2D<float4> uCombinedSamplers[] : register(t0, space1);
|
||||
SamplerState _uCombinedSamplers_sampler[] : register(s0, space1);
|
||||
|
||||
static int vIndex;
|
||||
static float4 FragColor;
|
||||
static float2 vUV;
|
||||
|
||||
struct SPIRV_Cross_Input
|
||||
{
|
||||
nointerpolation int vIndex : TEXCOORD0;
|
||||
float2 vUV : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float4 FragColor : SV_Target0;
|
||||
};
|
||||
|
||||
void frag_main()
|
||||
{
|
||||
int _22 = vIndex + 10;
|
||||
int _32 = vIndex + 40;
|
||||
FragColor = uSamplers[NonUniformResourceIndex(_22)].Sample(uSamps[NonUniformResourceIndex(_32)], vUV);
|
||||
FragColor = uCombinedSamplers[NonUniformResourceIndex(_22)].Sample(_uCombinedSamplers_sampler[NonUniformResourceIndex(_22)], vUV);
|
||||
FragColor += ubos[NonUniformResourceIndex(vIndex + 20)].v[_32];
|
||||
FragColor += asfloat(ssbos[NonUniformResourceIndex(vIndex + 50)].Load4((vIndex + 60) * 16 + 0));
|
||||
}
|
||||
|
||||
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
|
||||
{
|
||||
vIndex = stage_input.vIndex;
|
||||
vUV = stage_input.vUV;
|
||||
frag_main();
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.FragColor = FragColor;
|
||||
return stage_output;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4 v[64];
|
||||
};
|
||||
|
||||
struct SSBO
|
||||
{
|
||||
float4 v[1];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int vIndex [[user(locn0)]];
|
||||
float2 vUV [[user(locn1)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant UBO* ubos_0 [[buffer(0)]], constant UBO* ubos_1 [[buffer(1)]], const device SSBO* ssbos_0 [[buffer(2)]], const device SSBO* ssbos_1 [[buffer(3)]], array<texture2d<float>, 8> uSamplers [[texture(0)]], array<texture2d<float>, 8> uCombinedSamplers [[texture(8)]], array<sampler, 7> uSamps [[sampler(1)]], array<sampler, 8> uCombinedSamplersSmplr [[sampler(8)]])
|
||||
{
|
||||
constant UBO* ubos[] =
|
||||
{
|
||||
ubos_0,
|
||||
ubos_1,
|
||||
};
|
||||
|
||||
const device SSBO* ssbos[] =
|
||||
{
|
||||
ssbos_0,
|
||||
ssbos_1,
|
||||
};
|
||||
|
||||
main0_out out = {};
|
||||
int _24 = in.vIndex + 10;
|
||||
int _35 = in.vIndex + 40;
|
||||
out.FragColor = uSamplers[_24].sample(uSamps[_35], in.vUV);
|
||||
out.FragColor = uCombinedSamplers[_24].sample(uCombinedSamplersSmplr[_24], in.vUV);
|
||||
out.FragColor += ubos[(in.vIndex + 20)]->v[_35];
|
||||
out.FragColor += ssbos[(in.vIndex + 50)]->v[in.vIndex + 60];
|
||||
return out;
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
struct UBO_1_1
|
||||
{
|
||||
float4 v[64];
|
||||
};
|
||||
|
||||
ConstantBuffer<UBO_1_1> ubos[] : register(b0, space3);
|
||||
ByteAddressBuffer ssbos[] : register(t0, space4);
|
||||
Texture2D<float4> uSamplers[] : register(t0, space0);
|
||||
SamplerState uSamps[] : register(s0, space2);
|
||||
Texture2D<float4> uCombinedSamplers[] : register(t0, space1);
|
||||
SamplerState _uCombinedSamplers_sampler[] : register(s0, space1);
|
||||
|
||||
static int vIndex;
|
||||
static float4 FragColor;
|
||||
static float2 vUV;
|
||||
|
||||
struct SPIRV_Cross_Input
|
||||
{
|
||||
nointerpolation int vIndex : TEXCOORD0;
|
||||
float2 vUV : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct SPIRV_Cross_Output
|
||||
{
|
||||
float4 FragColor : SV_Target0;
|
||||
};
|
||||
|
||||
void frag_main()
|
||||
{
|
||||
int i = vIndex;
|
||||
FragColor = uSamplers[NonUniformResourceIndex(i + 10)].Sample(uSamps[NonUniformResourceIndex(i + 40)], vUV);
|
||||
int _47 = i + 10;
|
||||
FragColor = uCombinedSamplers[NonUniformResourceIndex(_47)].Sample(_uCombinedSamplers_sampler[NonUniformResourceIndex(_47)], vUV);
|
||||
FragColor += ubos[NonUniformResourceIndex(i + 20)].v[i + 40];
|
||||
FragColor += asfloat(ssbos[NonUniformResourceIndex(i + 50)].Load4((i + 60) * 16 + 0));
|
||||
}
|
||||
|
||||
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
|
||||
{
|
||||
vIndex = stage_input.vIndex;
|
||||
vUV = stage_input.vUV;
|
||||
frag_main();
|
||||
SPIRV_Cross_Output stage_output;
|
||||
stage_output.FragColor = FragColor;
|
||||
return stage_output;
|
||||
}
|
51
reference/shaders-msl/frag/nonuniform-qualifier.msl2.frag
Normal file
51
reference/shaders-msl/frag/nonuniform-qualifier.msl2.frag
Normal file
@ -0,0 +1,51 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4 v[64];
|
||||
};
|
||||
|
||||
struct SSBO
|
||||
{
|
||||
float4 v[1];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int vIndex [[user(locn0)]];
|
||||
float2 vUV [[user(locn1)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant UBO* ubos_0 [[buffer(0)]], constant UBO* ubos_1 [[buffer(1)]], const device SSBO* ssbos_0 [[buffer(2)]], const device SSBO* ssbos_1 [[buffer(3)]], array<texture2d<float>, 8> uSamplers [[texture(0)]], array<texture2d<float>, 8> uCombinedSamplers [[texture(8)]], array<sampler, 7> uSamps [[sampler(1)]], array<sampler, 8> uCombinedSamplersSmplr [[sampler(8)]])
|
||||
{
|
||||
constant UBO* ubos[] =
|
||||
{
|
||||
ubos_0,
|
||||
ubos_1,
|
||||
};
|
||||
|
||||
const device SSBO* ssbos[] =
|
||||
{
|
||||
ssbos_0,
|
||||
ssbos_1,
|
||||
};
|
||||
|
||||
main0_out out = {};
|
||||
int i = in.vIndex;
|
||||
int _24 = i + 10;
|
||||
out.FragColor = uSamplers[_24].sample(uSamps[i + 40], in.vUV);
|
||||
int _50 = i + 10;
|
||||
out.FragColor = uCombinedSamplers[_50].sample(uCombinedSamplersSmplr[_50], in.vUV);
|
||||
out.FragColor += ubos[(i + 20)]->v[i + 40];
|
||||
out.FragColor += ssbos[(i + 50)]->v[i + 60];
|
||||
return out;
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
#version 450
|
||||
#extension GL_EXT_nonuniform_qualifier : require
|
||||
|
||||
layout(set = 0, binding = 0) uniform texture2D uSamplers[];
|
||||
layout(set = 1, binding = 0) uniform sampler2D uCombinedSamplers[];
|
||||
layout(set = 2, binding = 0) uniform sampler uSamps[];
|
||||
layout(location = 0) flat in int vIndex;
|
||||
layout(location = 1) in vec2 vUV;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
layout(set = 3, binding = 0) uniform UBO
|
||||
{
|
||||
vec4 v[64];
|
||||
} ubos[];
|
||||
|
||||
layout(set = 4, binding = 0) readonly buffer SSBO
|
||||
{
|
||||
vec4 v[];
|
||||
} ssbos[];
|
||||
|
||||
void main()
|
||||
{
|
||||
int i = vIndex;
|
||||
FragColor = texture(sampler2D(uSamplers[nonuniformEXT(i + 10)], uSamps[nonuniformEXT(i + 40)]), vUV);
|
||||
FragColor = texture(uCombinedSamplers[nonuniformEXT(i + 10)], vUV);
|
||||
FragColor += ubos[nonuniformEXT(i + 20)].v[nonuniformEXT(i + 40)];
|
||||
FragColor += ssbos[nonuniformEXT(i + 50)].v[nonuniformEXT(i + 60)];
|
||||
}
|
28
shaders-msl/frag/nonuniform-qualifier.msl2.frag
Normal file
28
shaders-msl/frag/nonuniform-qualifier.msl2.frag
Normal file
@ -0,0 +1,28 @@
|
||||
#version 450
|
||||
#extension GL_EXT_nonuniform_qualifier : require
|
||||
|
||||
layout(binding = 0) uniform texture2D uSamplers[8];
|
||||
layout(binding = 8) uniform sampler2D uCombinedSamplers[8];
|
||||
layout(binding = 1) uniform sampler uSamps[7];
|
||||
layout(location = 0) flat in int vIndex;
|
||||
layout(location = 1) in vec2 vUV;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
layout(set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
vec4 v[64];
|
||||
} ubos[2];
|
||||
|
||||
layout(set = 0, binding = 2) readonly buffer SSBO
|
||||
{
|
||||
vec4 v[];
|
||||
} ssbos[2];
|
||||
|
||||
void main()
|
||||
{
|
||||
int i = vIndex;
|
||||
FragColor = texture(sampler2D(uSamplers[nonuniformEXT(i + 10)], uSamps[nonuniformEXT(i + 40)]), vUV);
|
||||
FragColor = texture(uCombinedSamplers[nonuniformEXT(i + 10)], vUV);
|
||||
FragColor += ubos[nonuniformEXT(i + 20)].v[nonuniformEXT(i + 40)];
|
||||
FragColor += ssbos[nonuniformEXT(i + 50)].v[nonuniformEXT(i + 60)];
|
||||
}
|
@ -317,7 +317,7 @@ string CompilerCPP::compile()
|
||||
backend.basic_uint_type = "uint32_t";
|
||||
backend.swizzle_is_function = true;
|
||||
backend.shared_is_implied = true;
|
||||
backend.flexible_member_array_supported = false;
|
||||
backend.unsized_array_supported = false;
|
||||
backend.explicit_struct_type = true;
|
||||
backend.use_initializer_list = true;
|
||||
|
||||
|
@ -9918,7 +9918,7 @@ string CompilerGLSL::to_array_size(const SPIRType &type, uint32_t index)
|
||||
return to_expression(size);
|
||||
else if (size)
|
||||
return convert_to_string(size);
|
||||
else if (!backend.flexible_member_array_supported)
|
||||
else if (!backend.unsized_array_supported)
|
||||
{
|
||||
// For runtime-sized arrays, we can work around
|
||||
// lack of standard support for this by simply having
|
||||
@ -11837,6 +11837,9 @@ void CompilerGLSL::bitcast_to_builtin_store(uint32_t target_id, std::string &exp
|
||||
|
||||
void CompilerGLSL::convert_non_uniform_expression(const SPIRType &type, std::string &expr)
|
||||
{
|
||||
if (*backend.nonuniform_qualifier == '\0')
|
||||
return;
|
||||
|
||||
// Handle SPV_EXT_descriptor_indexing.
|
||||
if (type.basetype == SPIRType::Sampler || type.basetype == SPIRType::SampledImage ||
|
||||
type.basetype == SPIRType::Image)
|
||||
|
@ -375,7 +375,7 @@ protected:
|
||||
const char *nonuniform_qualifier = "nonuniformEXT";
|
||||
bool swizzle_is_function = false;
|
||||
bool shared_is_implied = false;
|
||||
bool flexible_member_array_supported = true;
|
||||
bool unsized_array_supported = true;
|
||||
bool explicit_struct_type = false;
|
||||
bool use_initializer_list = false;
|
||||
bool use_typed_initializer_list = false;
|
||||
|
@ -4647,6 +4647,27 @@ uint32_t CompilerHLSL::remap_num_workgroups_builtin()
|
||||
return variable_id;
|
||||
}
|
||||
|
||||
void CompilerHLSL::validate_shader_model()
|
||||
{
|
||||
// Check for nonuniform qualifier.
|
||||
// Instead of looping over all decorations to find this, just look at capabilities.
|
||||
for (auto &cap : ir.declared_capabilities)
|
||||
{
|
||||
switch (cap)
|
||||
{
|
||||
case CapabilityShaderNonUniformEXT:
|
||||
case CapabilityRuntimeDescriptorArrayEXT:
|
||||
if (hlsl_options.shader_model < 51)
|
||||
SPIRV_CROSS_THROW("Shader model 5.1 or higher is required to use bindless resources or NonUniformResourceIndex.");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ir.addressing_model != AddressingModelLogical)
|
||||
SPIRV_CROSS_THROW("Only Logical addressing model can be used with HLSL.");
|
||||
}
|
||||
|
||||
string CompilerHLSL::compile()
|
||||
{
|
||||
// Do not deal with ES-isms like precision, older extensions and such.
|
||||
@ -4663,7 +4684,7 @@ string CompilerHLSL::compile()
|
||||
backend.basic_uint_type = "uint";
|
||||
backend.swizzle_is_function = false;
|
||||
backend.shared_is_implied = true;
|
||||
backend.flexible_member_array_supported = false;
|
||||
backend.unsized_array_supported = true;
|
||||
backend.explicit_struct_type = false;
|
||||
backend.use_initializer_list = true;
|
||||
backend.use_constructor_splatting = false;
|
||||
@ -4672,8 +4693,10 @@ string CompilerHLSL::compile()
|
||||
backend.can_declare_struct_inline = false;
|
||||
backend.can_declare_arrays_inline = false;
|
||||
backend.can_return_array = false;
|
||||
backend.nonuniform_qualifier = "NonUniformResourceIndex";
|
||||
|
||||
build_function_control_flow_graphs_and_analyze();
|
||||
validate_shader_model();
|
||||
update_active_builtins();
|
||||
analyze_image_and_sampler_usage();
|
||||
|
||||
|
@ -220,6 +220,8 @@ private:
|
||||
// Custom root constant layout, which should be emitted
|
||||
// when translating push constant ranges.
|
||||
std::vector<RootConstants> root_constants_layout;
|
||||
|
||||
void validate_shader_model();
|
||||
};
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
|
@ -577,7 +577,7 @@ string CompilerMSL::compile()
|
||||
backend.use_initializer_list = true;
|
||||
backend.use_typed_initializer_list = true;
|
||||
backend.native_row_major_matrix = false;
|
||||
backend.flexible_member_array_supported = false;
|
||||
backend.unsized_array_supported = false;
|
||||
backend.can_declare_arrays_inline = false;
|
||||
backend.can_return_array = false;
|
||||
backend.boolean_mix_support = false;
|
||||
@ -585,6 +585,7 @@ string CompilerMSL::compile()
|
||||
backend.array_is_value_type = false;
|
||||
backend.comparison_image_samples_scalar = true;
|
||||
backend.native_pointers = true;
|
||||
backend.nonuniform_qualifier = "";
|
||||
|
||||
capture_output_to_buffer = msl_options.capture_output_to_buffer;
|
||||
is_rasterization_disabled = msl_options.disable_rasterization || capture_output_to_buffer;
|
||||
|
@ -220,13 +220,18 @@ def shader_to_win_path(shader):
|
||||
|
||||
ignore_fxc = False
|
||||
def validate_shader_hlsl(shader, force_no_external_validation, paths):
|
||||
subprocess.check_call([paths.glslang, '-e', 'main', '-D', '--target-env', 'vulkan1.1', '-V', shader])
|
||||
if not '.nonuniformresource' in shader:
|
||||
# glslang HLSL does not support this, so rely on fxc to test it.
|
||||
subprocess.check_call([paths.glslang, '-e', 'main', '-D', '--target-env', 'vulkan1.1', '-V', shader])
|
||||
is_no_fxc = '.nofxc.' in shader
|
||||
global ignore_fxc
|
||||
if (not ignore_fxc) and (not force_no_external_validation) and (not is_no_fxc):
|
||||
try:
|
||||
win_path = shader_to_win_path(shader)
|
||||
subprocess.check_call(['fxc', '-nologo', shader_model_hlsl(shader), win_path])
|
||||
args = ['fxc', '-nologo', shader_model_hlsl(shader), win_path]
|
||||
if '.nonuniformresource.' in shader:
|
||||
args.append('/enable_unbounded_descriptor_tables')
|
||||
subprocess.check_call(args)
|
||||
except OSError as oe:
|
||||
if (oe.errno != errno.ENOENT): # Ignore not found errors
|
||||
print('Failed to run FXC.')
|
||||
|
Loading…
Reference in New Issue
Block a user