Merge pull request #978 from KhronosGroup/fix-974

HLSL/MSL: Deal correctly with nonuniformEXT qualifier.
This commit is contained in:
Hans-Kristian Arntzen 2019-05-13 17:02:47 +02:00 committed by GitHub
commit bf69c1f3ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 290 additions and 7 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View 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;
}

View File

@ -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)];
}

View 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)];
}

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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.')