Skip to content

Commit

Permalink
Merge pull request #2152 from KhronosGroup/fix-2143
Browse files Browse the repository at this point in the history
Land PR 2143
  • Loading branch information
HansKristian-Work authored May 19, 2023
2 parents 28b11e0 + bf752ed commit 12542fc
Show file tree
Hide file tree
Showing 14 changed files with 314 additions and 24 deletions.
4 changes: 4 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ struct CLIArguments
bool hlsl_nonwritable_uav_texture_as_srv = false;
bool hlsl_enable_16bit_types = false;
bool hlsl_flatten_matrix_vertex_input_semantics = false;
bool hlsl_preserve_structured_buffers = false;
HLSLBindingFlags hlsl_binding_flags = 0;
bool vulkan_semantics = false;
bool flatten_multidimensional_arrays = false;
Expand Down Expand Up @@ -839,6 +840,7 @@ static void print_help_hlsl()
"\t\tOpName reflection information must be intact.\n"
"\t[--hlsl-enable-16bit-types]:\n\t\tEnables native use of half/int16_t/uint16_t and ByteAddressBuffer interaction with these types. Requires SM 6.2.\n"
"\t[--hlsl-flatten-matrix-vertex-input-semantics]:\n\t\tEmits matrix vertex inputs with input semantics as if they were independent vectors, e.g. TEXCOORD{2,3,4} rather than matrix form TEXCOORD2_{0,1,2}.\n"
"\t[--hlsl-preserve-structured-buffers]:\n\t\tEmit SturucturedBuffer<T> rather than ByteAddressBuffer. Requires UserTypeGOOGLE to be emitted. Intended for DXC roundtrips.\n"
);
// clang-format on
}
Expand Down Expand Up @@ -1421,6 +1423,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
hlsl_opts.nonwritable_uav_texture_as_srv = args.hlsl_nonwritable_uav_texture_as_srv;
hlsl_opts.enable_16bit_types = args.hlsl_enable_16bit_types;
hlsl_opts.flatten_matrix_vertex_input_semantics = args.hlsl_flatten_matrix_vertex_input_semantics;
hlsl_opts.preserve_structured_buffers = args.hlsl_preserve_structured_buffers;
hlsl->set_hlsl_options(hlsl_opts);
hlsl->set_resource_binding_flags(args.hlsl_binding_flags);
if (args.hlsl_base_vertex_index_explicit_binding)
Expand Down Expand Up @@ -1622,6 +1625,7 @@ static int main_inner(int argc, char *argv[])
cbs.add("--hlsl-enable-16bit-types", [&args](CLIParser &) { args.hlsl_enable_16bit_types = true; });
cbs.add("--hlsl-flatten-matrix-vertex-input-semantics",
[&args](CLIParser &) { args.hlsl_flatten_matrix_vertex_input_semantics = true; });
cbs.add("--hlsl-preserve-structured-buffers", [&args](CLIParser &) { args.hlsl_preserve_structured_buffers = true; });
cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
cbs.add("-V", [&args](CLIParser &) { args.vulkan_semantics = true; });
cbs.add("--flatten-multidimensional-arrays", [&args](CLIParser &) { args.flatten_multidimensional_arrays = true; });
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
struct Data
{
float4 Color;
};

StructuredBuffer<Data> Colors[2] : register(t0);

static float4 out_var_SV_Target;

struct SPIRV_Cross_Output
{
float4 out_var_SV_Target : SV_Target0;
};

void frag_main()
{
out_var_SV_Target = Colors[1][3u].Color;
}

SPIRV_Cross_Output main()
{
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.out_var_SV_Target = out_var_SV_Target;
return stage_output;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
struct Data
{
float4 Color;
};

StructuredBuffer<Data> Colors : register(t0);

static float4 out_var_SV_Target;

struct SPIRV_Cross_Output
{
float4 out_var_SV_Target : SV_Target0;
};

void frag_main()
{
out_var_SV_Target = Colors[3u].Color;
}

SPIRV_Cross_Output main()
{
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.out_var_SV_Target = out_var_SV_Target;
return stage_output;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
struct Data
{
float4 Color;
};

StructuredBuffer<Data> Colors[2] : register(t0);

static float4 out_var_SV_Target;

struct SPIRV_Cross_Output
{
float4 out_var_SV_Target : SV_Target0;
};

void frag_main()
{
out_var_SV_Target = Colors[1][3u].Color;
}

SPIRV_Cross_Output main()
{
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.out_var_SV_Target = out_var_SV_Target;
return stage_output;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
struct Data
{
float4 Color;
};

StructuredBuffer<Data> Colors : register(t0);

static float4 out_var_SV_Target;

struct SPIRV_Cross_Output
{
float4 out_var_SV_Target : SV_Target0;
};

void frag_main()
{
out_var_SV_Target = Colors[3u].Color;
}

SPIRV_Cross_Output main()
{
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.out_var_SV_Target = out_var_SV_Target;
return stage_output;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
; SPIR-V
; Version: 1.3
; Generator: Google spiregg; 0
; Bound: 25
; Schema: 0
OpCapability Shader
OpExtension "SPV_GOOGLE_hlsl_functionality1"
OpExtension "SPV_GOOGLE_user_type"
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %out_var_SV_Target
OpExecutionMode %main OriginUpperLeft
OpSource HLSL 660
OpName %type_StructuredBuffer_Data "type.StructuredBuffer.Data"
OpName %Data "Data"
OpMemberName %Data 0 "Color"
OpName %Colors "Colors"
OpName %out_var_SV_Target "out.var.SV_Target"
OpName %main "main"
OpDecorateString %out_var_SV_Target UserSemantic "SV_Target"
OpDecorate %out_var_SV_Target Location 0
OpDecorate %Colors DescriptorSet 0
OpDecorate %Colors Binding 0
OpMemberDecorate %Data 0 Offset 0
OpDecorate %_runtimearr_Data ArrayStride 16
OpMemberDecorate %type_StructuredBuffer_Data 0 Offset 0
OpMemberDecorate %type_StructuredBuffer_Data 0 NonWritable
OpDecorate %type_StructuredBuffer_Data BufferBlock
OpDecorateString %Colors UserTypeGOOGLE "structuredbuffer:<Data>"
%int = OpTypeInt 32 1
%int_1 = OpConstant %int 1
%int_0 = OpConstant %int 0
%uint = OpTypeInt 32 0
%uint_3 = OpConstant %uint 3
%uint_2 = OpConstant %uint 2
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%Data = OpTypeStruct %v4float
%_runtimearr_Data = OpTypeRuntimeArray %Data
%type_StructuredBuffer_Data = OpTypeStruct %_runtimearr_Data
%_arr_type_StructuredBuffer_Data_uint_2 = OpTypeArray %type_StructuredBuffer_Data %uint_2
%_ptr_Uniform__arr_type_StructuredBuffer_Data_uint_2 = OpTypePointer Uniform %_arr_type_StructuredBuffer_Data_uint_2
%_ptr_Output_v4float = OpTypePointer Output %v4float
%void = OpTypeVoid
%20 = OpTypeFunction %void
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%Colors = OpVariable %_ptr_Uniform__arr_type_StructuredBuffer_Data_uint_2 Uniform
%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
%main = OpFunction %void None %20
%22 = OpLabel
%23 = OpAccessChain %_ptr_Uniform_v4float %Colors %int_1 %int_0 %uint_3 %int_0
%24 = OpLoad %v4float %23
OpStore %out_var_SV_Target %24
OpReturn
OpFunctionEnd
52 changes: 52 additions & 0 deletions shaders-hlsl/asm/frag/structured-buffer.structured.asm.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
; SPIR-V
; Version: 1.3
; Generator: Google spiregg; 0
; Bound: 22
; Schema: 0
OpCapability Shader
OpExtension "SPV_GOOGLE_hlsl_functionality1"
OpExtension "SPV_GOOGLE_user_type"
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %out_var_SV_Target
OpExecutionMode %main OriginUpperLeft
OpSource HLSL 660
OpName %type_StructuredBuffer_Data "type.StructuredBuffer.Data"
OpName %Data "Data"
OpMemberName %Data 0 "Color"
OpName %Colors "Colors"
OpName %out_var_SV_Target "out.var.SV_Target"
OpName %main "main"
OpDecorateString %out_var_SV_Target UserSemantic "SV_Target"
OpDecorate %out_var_SV_Target Location 0
OpDecorate %Colors DescriptorSet 0
OpDecorate %Colors Binding 0
OpMemberDecorate %Data 0 Offset 0
OpDecorate %_runtimearr_Data ArrayStride 16
OpMemberDecorate %type_StructuredBuffer_Data 0 Offset 0
OpMemberDecorate %type_StructuredBuffer_Data 0 NonWritable
OpDecorate %type_StructuredBuffer_Data BufferBlock
OpDecorateString %Colors UserTypeGOOGLE "structuredbuffer:<Data>"
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%uint = OpTypeInt 32 0
%uint_3 = OpConstant %uint 3
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%Data = OpTypeStruct %v4float
%_runtimearr_Data = OpTypeRuntimeArray %Data
%type_StructuredBuffer_Data = OpTypeStruct %_runtimearr_Data
%_ptr_Uniform_type_StructuredBuffer_Data = OpTypePointer Uniform %type_StructuredBuffer_Data
%_ptr_Output_v4float = OpTypePointer Output %v4float
%void = OpTypeVoid
%17 = OpTypeFunction %void
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%Colors = OpVariable %_ptr_Uniform_type_StructuredBuffer_Data Uniform
%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
%main = OpFunction %void None %17
%19 = OpLabel
%20 = OpAccessChain %_ptr_Uniform_v4float %Colors %int_0 %uint_3 %int_0
%21 = OpLoad %v4float %20
OpStore %out_var_SV_Target %21
OpReturn
OpFunctionEnd
1 change: 1 addition & 0 deletions spirv_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1663,6 +1663,7 @@ struct Meta
std::string alias;
std::string qualified_alias;
std::string hlsl_semantic;
std::string user_type;
Bitset decoration_flags;
spv::BuiltIn builtin_type = spv::BuiltInMax;
uint32_t location = 0;
Expand Down
7 changes: 7 additions & 0 deletions spirv_cross_parsed_ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,10 @@ void ParsedIR::set_decoration_string(ID id, Decoration decoration, const string
dec.hlsl_semantic = argument;
break;

case DecorationUserTypeGOOGLE:
dec.user_type = argument;
break;

default:
break;
}
Expand Down Expand Up @@ -659,6 +663,9 @@ const string &ParsedIR::get_decoration_string(ID id, Decoration decoration) cons
case DecorationHlslSemanticGOOGLE:
return dec.hlsl_semantic;

case DecorationUserTypeGOOGLE:
return dec.user_type;

default:
return empty_string;
}
Expand Down
56 changes: 36 additions & 20 deletions spirv_glsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9858,6 +9858,9 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
bool pending_array_enclose = false;
bool dimension_flatten = false;

// If we are translating access to a structured buffer, the first subscript '._m0' must be hidden
bool hide_first_subscript = count > 1 && is_user_type_structured(base);

const auto append_index = [&](uint32_t index, bool is_literal, bool is_ptr_chain = false) {
AccessChainFlags mod_flags = flags;
if (!is_literal)
Expand Down Expand Up @@ -10044,32 +10047,40 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
if (index >= type->member_types.size())
SPIRV_CROSS_THROW("Member index is out of bounds!");

BuiltIn builtin = BuiltInMax;
if (is_member_builtin(*type, index, &builtin) && access_chain_needs_stage_io_builtin_translation(base))
if (hide_first_subscript)
{
if (access_chain_is_arrayed)
{
expr += ".";
expr += builtin_to_glsl(builtin, type->storage);
}
else
expr = builtin_to_glsl(builtin, type->storage);
// First "._m0" subscript has been hidden, subsequent fields must be emitted even for structured buffers
hide_first_subscript = false;
}
else
{
// If the member has a qualified name, use it as the entire chain
string qual_mbr_name = get_member_qualified_name(type_id, index);
if (!qual_mbr_name.empty())
expr = qual_mbr_name;
else if (flatten_member_reference)
expr += join("_", to_member_name(*type, index));
BuiltIn builtin = BuiltInMax;
if (is_member_builtin(*type, index, &builtin) && access_chain_needs_stage_io_builtin_translation(base))
{
if (access_chain_is_arrayed)
{
expr += ".";
expr += builtin_to_glsl(builtin, type->storage);
}
else
expr = builtin_to_glsl(builtin, type->storage);
}
else
{
// Any pointer de-refences for values are handled in the first access chain.
// For pointer chains, the pointer-ness is resolved through an array access.
// The only time this is not true is when accessing array of SSBO/UBO.
// This case is explicitly handled.
expr += to_member_reference(base, *type, index, ptr_chain || i != 0);
// If the member has a qualified name, use it as the entire chain
string qual_mbr_name = get_member_qualified_name(type_id, index);
if (!qual_mbr_name.empty())
expr = qual_mbr_name;
else if (flatten_member_reference)
expr += join("_", to_member_name(*type, index));
else
{
// Any pointer de-refences for values are handled in the first access chain.
// For pointer chains, the pointer-ness is resolved through an array access.
// The only time this is not true is when accessing array of SSBO/UBO.
// This case is explicitly handled.
expr += to_member_reference(base, *type, index, ptr_chain || i != 0);
}
}
}

Expand Down Expand Up @@ -15587,6 +15598,11 @@ bool CompilerGLSL::builtin_translates_to_nonarray(spv::BuiltIn /*builtin*/) cons
return false; // GLSL itself does not need to translate array builtin types to non-array builtin types
}

bool CompilerGLSL::is_user_type_structured(uint32_t /*id*/) const
{
return false; // GLSL itself does not have structured user type, but HLSL does with StructuredBuffer and RWStructuredBuffer resources.
}

bool CompilerGLSL::check_atomic_image(uint32_t id)
{
auto &type = expression_type(id);
Expand Down
2 changes: 2 additions & 0 deletions spirv_glsl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,8 @@ class CompilerGLSL : public Compiler

virtual bool builtin_translates_to_nonarray(spv::BuiltIn builtin) const;

virtual bool is_user_type_structured(uint32_t id) const;

void emit_copy_logical_type(uint32_t lhs_id, uint32_t lhs_type_id, uint32_t rhs_id, uint32_t rhs_type_id,
SmallVector<uint32_t> chain);

Expand Down
Loading

0 comments on commit 12542fc

Please sign in to comment.