Merge pull request #509 from KhronosGroup/hlsl-semantic-counter-buffer
Add support for new HLSL semantic/counter buffer decorations.
This commit is contained in:
commit
d0133c5dd9
19
reference/opt/shaders/asm/comp/hlsl-functionality.asm.comp
Normal file
19
reference/opt/shaders/asm/comp/hlsl-functionality.asm.comp
Normal file
@ -0,0 +1,19 @@
|
||||
#version 450
|
||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
layout(binding = 0, std430) buffer Buf
|
||||
{
|
||||
vec4 _data[];
|
||||
} Buf_1;
|
||||
|
||||
layout(std430) buffer Buf_count
|
||||
{
|
||||
int _count;
|
||||
} Buf_count_1;
|
||||
|
||||
void main()
|
||||
{
|
||||
int _32 = atomicAdd(Buf_count_1._count, 1);
|
||||
Buf_1._data[_32] = vec4(1.0);
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
#version 450
|
||||
|
||||
struct VOut
|
||||
{
|
||||
vec4 p;
|
||||
vec4 c;
|
||||
};
|
||||
|
||||
layout(location = 0) out vec4 _entryPointOutput_c;
|
||||
|
||||
VOut _main()
|
||||
{
|
||||
VOut v;
|
||||
v.p = vec4(1.0);
|
||||
v.c = vec4(2.0);
|
||||
return v;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
VOut flattenTemp = _main();
|
||||
gl_Position = flattenTemp.p;
|
||||
_entryPointOutput_c = flattenTemp.c;
|
||||
}
|
||||
|
24
reference/shaders/asm/comp/hlsl-functionality.asm.comp
Normal file
24
reference/shaders/asm/comp/hlsl-functionality.asm.comp
Normal file
@ -0,0 +1,24 @@
|
||||
#version 450
|
||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
layout(binding = 0, std430) buffer Buf
|
||||
{
|
||||
vec4 _data[];
|
||||
} Buf_1;
|
||||
|
||||
layout(std430) buffer Buf_count
|
||||
{
|
||||
int _count;
|
||||
} Buf_count_1;
|
||||
|
||||
void _main()
|
||||
{
|
||||
int _29 = atomicAdd(Buf_count_1._count, 1);
|
||||
Buf_1._data[_29] = vec4(1.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
_main();
|
||||
}
|
||||
|
68
shaders-no-opt/asm/vert/semantic-decoration.asm.vert
Normal file
68
shaders-no-opt/asm/vert/semantic-decoration.asm.vert
Normal file
@ -0,0 +1,68 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 6
|
||||
; Bound: 36
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_GOOGLE_decorate_string"
|
||||
OpExtension "SPV_GOOGLE_hlsl_functionality1"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main" %_entryPointOutput_p %_entryPointOutput_c
|
||||
OpSource HLSL 500
|
||||
OpName %main "main"
|
||||
OpName %VOut "VOut"
|
||||
OpMemberName %VOut 0 "p"
|
||||
OpMemberName %VOut 1 "c"
|
||||
OpName %_main_ "@main("
|
||||
OpName %v "v"
|
||||
OpName %flattenTemp "flattenTemp"
|
||||
OpName %_entryPointOutput_p "@entryPointOutput.p"
|
||||
OpName %_entryPointOutput_c "@entryPointOutput.c"
|
||||
OpMemberDecorateStringGOOGLE %VOut 0 HlslSemanticGOOGLE "SV_POSITION"
|
||||
OpMemberDecorateStringGOOGLE %VOut 1 HlslSemanticGOOGLE "COLOR"
|
||||
OpDecorate %_entryPointOutput_p BuiltIn Position
|
||||
OpDecorateStringGOOGLE %_entryPointOutput_p HlslSemanticGOOGLE "SV_POSITION"
|
||||
OpDecorate %_entryPointOutput_c Location 0
|
||||
OpDecorateStringGOOGLE %_entryPointOutput_c HlslSemanticGOOGLE "COLOR"
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%VOut = OpTypeStruct %v4float %v4float
|
||||
%9 = OpTypeFunction %VOut
|
||||
%_ptr_Function_VOut = OpTypePointer Function %VOut
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%float_1 = OpConstant %float 1
|
||||
%17 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%int_1 = OpConstant %int 1
|
||||
%float_2 = OpConstant %float 2
|
||||
%22 = OpConstantComposite %v4float %float_2 %float_2 %float_2 %float_2
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%_entryPointOutput_p = OpVariable %_ptr_Output_v4float Output
|
||||
%_entryPointOutput_c = OpVariable %_ptr_Output_v4float Output
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%flattenTemp = OpVariable %_ptr_Function_VOut Function
|
||||
%28 = OpFunctionCall %VOut %_main_
|
||||
OpStore %flattenTemp %28
|
||||
%31 = OpAccessChain %_ptr_Function_v4float %flattenTemp %int_0
|
||||
%32 = OpLoad %v4float %31
|
||||
OpStore %_entryPointOutput_p %32
|
||||
%34 = OpAccessChain %_ptr_Function_v4float %flattenTemp %int_1
|
||||
%35 = OpLoad %v4float %34
|
||||
OpStore %_entryPointOutput_c %35
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%_main_ = OpFunction %VOut None %9
|
||||
%11 = OpLabel
|
||||
%v = OpVariable %_ptr_Function_VOut Function
|
||||
%19 = OpAccessChain %_ptr_Function_v4float %v %int_0
|
||||
OpStore %19 %17
|
||||
%23 = OpAccessChain %_ptr_Function_v4float %v %int_1
|
||||
OpStore %23 %22
|
||||
%24 = OpLoad %VOut %v
|
||||
OpReturnValue %24
|
||||
OpFunctionEnd
|
63
shaders/asm/comp/hlsl-functionality.asm.comp
Normal file
63
shaders/asm/comp/hlsl-functionality.asm.comp
Normal file
@ -0,0 +1,63 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 6
|
||||
; Bound: 31
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
OpExtension "SPV_GOOGLE_hlsl_functionality1"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %main "main"
|
||||
OpExecutionMode %main LocalSize 1 1 1
|
||||
OpSource HLSL 500
|
||||
OpName %main "main"
|
||||
OpName %_main_ "@main("
|
||||
OpName %Buf "Buf"
|
||||
OpMemberName %Buf 0 "@data"
|
||||
OpName %Buf_0 "Buf"
|
||||
OpName %Buf_count "Buf@count"
|
||||
OpMemberName %Buf_count 0 "@count"
|
||||
OpName %Buf_count_0 "Buf@count"
|
||||
OpDecorate %_runtimearr_v4float ArrayStride 16
|
||||
OpMemberDecorate %Buf 0 Offset 0
|
||||
OpDecorate %Buf BufferBlock
|
||||
OpDecorate %Buf_0 DescriptorSet 0
|
||||
OpDecorate %Buf_0 Binding 0
|
||||
OpMemberDecorate %Buf_count 0 Offset 0
|
||||
OpDecorate %Buf_count BufferBlock
|
||||
OpDecorate %Buf_count_0 DescriptorSet 0
|
||||
OpDecorateId %Buf_0 HlslCounterBufferGOOGLE %Buf_count_0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_runtimearr_v4float = OpTypeRuntimeArray %v4float
|
||||
%Buf = OpTypeStruct %_runtimearr_v4float
|
||||
%_ptr_Uniform_Buf = OpTypePointer Uniform %Buf
|
||||
%Buf_0 = OpVariable %_ptr_Uniform_Buf Uniform
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%Buf_count = OpTypeStruct %int
|
||||
%_ptr_Uniform_Buf_count = OpTypePointer Uniform %Buf_count
|
||||
%Buf_count_0 = OpVariable %_ptr_Uniform_Buf_count Uniform
|
||||
%_ptr_Uniform_int = OpTypePointer Uniform %int
|
||||
%int_1 = OpConstant %int 1
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%float_1 = OpConstant %float 1
|
||||
%27 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
|
||||
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%30 = OpFunctionCall %void %_main_
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%_main_ = OpFunction %void None %3
|
||||
%7 = OpLabel
|
||||
%20 = OpAccessChain %_ptr_Uniform_int %Buf_count_0 %int_0
|
||||
%25 = OpAtomicIAdd %int %20 %uint_1 %uint_0 %int_1
|
||||
%29 = OpAccessChain %_ptr_Uniform_v4float %Buf_0 %int_0 %25
|
||||
OpStore %29 %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
@ -1185,6 +1185,7 @@ struct Meta
|
||||
{
|
||||
std::string alias;
|
||||
std::string qualified_alias;
|
||||
std::string hlsl_semantic;
|
||||
Bitset decoration_flags;
|
||||
spv::BuiltIn builtin_type;
|
||||
uint32_t location = 0;
|
||||
@ -1212,6 +1213,11 @@ struct Meta
|
||||
// is not a valid identifier in any high-level language.
|
||||
std::string hlsl_magic_counter_buffer_name;
|
||||
bool hlsl_magic_counter_buffer_candidate = false;
|
||||
|
||||
// For SPV_GOOGLE_hlsl_functionality1, this avoids the workaround.
|
||||
bool hlsl_is_magic_counter_buffer = false;
|
||||
// ID for the sibling counter buffer.
|
||||
uint32_t hlsl_magic_counter_buffer = 0;
|
||||
};
|
||||
|
||||
// A user callback that remaps the type of any variable.
|
||||
|
112
spirv_cross.cpp
112
spirv_cross.cpp
@ -1012,6 +1012,7 @@ void Compiler::set_name(uint32_t id, const std::string &name)
|
||||
|
||||
// glslang uses identifiers to pass along meaningful information
|
||||
// about HLSL reflection.
|
||||
// FIXME: This should be deprecated eventually.
|
||||
auto &m = meta.at(id);
|
||||
if (source.hlsl && name.size() >= 6 && name.find("@count") == name.size() - 6)
|
||||
{
|
||||
@ -1041,6 +1042,24 @@ const SPIRType &Compiler::get_type_from_variable(uint32_t id) const
|
||||
return get<SPIRType>(get<SPIRVariable>(id).basetype);
|
||||
}
|
||||
|
||||
void Compiler::set_member_decoration_string(uint32_t id, uint32_t index, spv::Decoration decoration,
|
||||
const std::string &argument)
|
||||
{
|
||||
meta.at(id).members.resize(max(meta[id].members.size(), size_t(index) + 1));
|
||||
auto &dec = meta.at(id).members[index];
|
||||
dec.decoration_flags.set(decoration);
|
||||
|
||||
switch (decoration)
|
||||
{
|
||||
case DecorationHlslSemanticGOOGLE:
|
||||
dec.hlsl_semantic = argument;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Compiler::set_member_decoration(uint32_t id, uint32_t index, Decoration decoration, uint32_t argument)
|
||||
{
|
||||
meta.at(id).members.resize(max(meta[id].members.size(), size_t(index) + 1));
|
||||
@ -1206,6 +1225,26 @@ void Compiler::unset_member_decoration(uint32_t id, uint32_t index, Decoration d
|
||||
dec.spec_id = 0;
|
||||
break;
|
||||
|
||||
case DecorationHlslSemanticGOOGLE:
|
||||
dec.hlsl_semantic.clear();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Compiler::set_decoration_string(uint32_t id, spv::Decoration decoration, const std::string &argument)
|
||||
{
|
||||
auto &dec = meta.at(id).decoration;
|
||||
dec.decoration_flags.set(decoration);
|
||||
|
||||
switch (decoration)
|
||||
{
|
||||
case DecorationHlslSemanticGOOGLE:
|
||||
dec.hlsl_semantic = argument;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1259,6 +1298,11 @@ void Compiler::set_decoration(uint32_t id, Decoration decoration, uint32_t argum
|
||||
dec.index = argument;
|
||||
break;
|
||||
|
||||
case DecorationHlslCounterBufferGOOGLE:
|
||||
meta.at(id).hlsl_magic_counter_buffer = argument;
|
||||
meta.at(argument).hlsl_is_magic_counter_buffer = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1304,6 +1348,24 @@ bool Compiler::has_decoration(uint32_t id, Decoration decoration) const
|
||||
return get_decoration_bitset(id).get(decoration);
|
||||
}
|
||||
|
||||
const string &Compiler::get_decoration_string(uint32_t id, spv::Decoration decoration) const
|
||||
{
|
||||
auto &dec = meta.at(id).decoration;
|
||||
static const string empty;
|
||||
|
||||
if (!dec.decoration_flags.get(decoration))
|
||||
return empty;
|
||||
|
||||
switch (decoration)
|
||||
{
|
||||
case DecorationHlslSemanticGOOGLE:
|
||||
return dec.hlsl_semantic;
|
||||
|
||||
default:
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Compiler::get_decoration(uint32_t id, Decoration decoration) const
|
||||
{
|
||||
auto &dec = meta.at(id).decoration;
|
||||
@ -1371,6 +1433,21 @@ void Compiler::unset_decoration(uint32_t id, Decoration decoration)
|
||||
dec.spec_id = 0;
|
||||
break;
|
||||
|
||||
case DecorationHlslSemanticGOOGLE:
|
||||
dec.hlsl_semantic.clear();
|
||||
break;
|
||||
|
||||
case DecorationHlslCounterBufferGOOGLE:
|
||||
{
|
||||
auto &counter = meta.at(id).hlsl_magic_counter_buffer;
|
||||
if (counter)
|
||||
{
|
||||
meta.at(counter).hlsl_is_magic_counter_buffer = false;
|
||||
counter = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1548,6 +1625,7 @@ void Compiler::parse(const Instruction &instruction)
|
||||
}
|
||||
|
||||
case OpDecorate:
|
||||
case OpDecorateId:
|
||||
{
|
||||
uint32_t id = ops[0];
|
||||
|
||||
@ -1563,6 +1641,14 @@ void Compiler::parse(const Instruction &instruction)
|
||||
break;
|
||||
}
|
||||
|
||||
case OpDecorateStringGOOGLE:
|
||||
{
|
||||
uint32_t id = ops[0];
|
||||
auto decoration = static_cast<Decoration>(ops[1]);
|
||||
set_decoration_string(id, decoration, extract_string(spirv, instruction.offset + 2));
|
||||
break;
|
||||
}
|
||||
|
||||
case OpMemberDecorate:
|
||||
{
|
||||
uint32_t id = ops[0];
|
||||
@ -1575,6 +1661,15 @@ void Compiler::parse(const Instruction &instruction)
|
||||
break;
|
||||
}
|
||||
|
||||
case OpMemberDecorateStringGOOGLE:
|
||||
{
|
||||
uint32_t id = ops[0];
|
||||
uint32_t member = ops[1];
|
||||
auto decoration = static_cast<Decoration>(ops[2]);
|
||||
set_member_decoration_string(id, member, decoration, extract_string(spirv, instruction.offset + 3));
|
||||
break;
|
||||
}
|
||||
|
||||
// Build up basic types.
|
||||
case OpTypeVoid:
|
||||
{
|
||||
@ -4239,6 +4334,13 @@ bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_
|
||||
|
||||
bool Compiler::buffer_is_hlsl_counter_buffer(uint32_t id) const
|
||||
{
|
||||
// First, check for the proper decoration.
|
||||
if (meta.at(id).hlsl_is_magic_counter_buffer)
|
||||
return true;
|
||||
|
||||
// Check for legacy fallback method.
|
||||
// FIXME: This should be deprecated eventually.
|
||||
|
||||
if (meta.at(id).hlsl_magic_counter_buffer_candidate)
|
||||
{
|
||||
auto *var = maybe_get<SPIRVariable>(id);
|
||||
@ -4252,6 +4354,16 @@ bool Compiler::buffer_is_hlsl_counter_buffer(uint32_t id) const
|
||||
|
||||
bool Compiler::buffer_get_hlsl_counter_buffer(uint32_t id, uint32_t &counter_id) const
|
||||
{
|
||||
// First, check for the proper decoration.
|
||||
if (meta[id].hlsl_magic_counter_buffer != 0)
|
||||
{
|
||||
counter_id = meta[id].hlsl_magic_counter_buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for legacy fallback method.
|
||||
// FIXME: This should be deprecated eventually.
|
||||
|
||||
auto &name = get_name(id);
|
||||
uint32_t id_bound = get_current_id_bound();
|
||||
for (uint32_t i = 0; i < id_bound; i++)
|
||||
|
@ -136,6 +136,7 @@ public:
|
||||
|
||||
// Applies a decoration to an ID. Effectively injects OpDecorate.
|
||||
void set_decoration(uint32_t id, spv::Decoration decoration, uint32_t argument = 0);
|
||||
void set_decoration_string(uint32_t id, spv::Decoration decoration, const std::string &argument);
|
||||
|
||||
// Overrides the identifier OpName of an ID.
|
||||
// Identifiers beginning with underscores or identifiers which contain double underscores
|
||||
@ -157,6 +158,7 @@ public:
|
||||
// If decoration doesn't exist or decoration is not recognized,
|
||||
// 0 will be returned.
|
||||
uint32_t get_decoration(uint32_t id, spv::Decoration decoration) const;
|
||||
const std::string &get_decoration_string(uint32_t id, spv::Decoration decoration) const;
|
||||
|
||||
// Removes the decoration for a an ID.
|
||||
void unset_decoration(uint32_t id, spv::Decoration decoration);
|
||||
@ -185,6 +187,7 @@ public:
|
||||
|
||||
// Given an OpTypeStruct in ID, obtain the OpMemberDecoration for member number "index".
|
||||
uint32_t get_member_decoration(uint32_t id, uint32_t index, spv::Decoration decoration) const;
|
||||
const std::string &get_member_decoration_string(uint32_t id, uint32_t index, spv::Decoration decoration) const;
|
||||
|
||||
// Sets the member identifier for OpTypeStruct ID, member number "index".
|
||||
void set_member_name(uint32_t id, uint32_t index, const std::string &name);
|
||||
@ -206,6 +209,8 @@ public:
|
||||
|
||||
// Similar to set_decoration, but for struct members.
|
||||
void set_member_decoration(uint32_t id, uint32_t index, spv::Decoration decoration, uint32_t argument = 0);
|
||||
void set_member_decoration_string(uint32_t id, uint32_t index, spv::Decoration decoration,
|
||||
const std::string &argument);
|
||||
|
||||
// Unsets a member decoration, similar to unset_decoration.
|
||||
void unset_member_decoration(uint32_t id, uint32_t index, spv::Decoration decoration);
|
||||
@ -441,14 +446,18 @@ public:
|
||||
// which lets us link the two buffers together.
|
||||
|
||||
// Queries if a variable ID is a counter buffer which "belongs" to a regular buffer object.
|
||||
// NOTE: This query is purely based on OpName identifiers as found in the SPIR-V module, and will
|
||||
|
||||
// If SPV_GOOGLE_hlsl_functionality1 is used, this can be used even with a stripped SPIR-V module.
|
||||
// Otherwise, this query is purely based on OpName identifiers as found in the SPIR-V module, and will
|
||||
// only return true if OpSource was reported HLSL.
|
||||
// To rely on this functionality, ensure that the SPIR-V module is not stripped.
|
||||
|
||||
bool buffer_is_hlsl_counter_buffer(uint32_t id) const;
|
||||
|
||||
// Queries if a buffer object has a neighbor "counter" buffer.
|
||||
// If so, the ID of that counter buffer will be returned in counter_id.
|
||||
// NOTE: This query is purely based on OpName identifiers as found in the SPIR-V module, and will
|
||||
// If SPV_GOOGLE_hlsl_functionality1 is used, this can be used even with a stripped SPIR-V module.
|
||||
// Otherwise, this query is purely based on OpName identifiers as found in the SPIR-V module, and will
|
||||
// only return true if OpSource was reported HLSL.
|
||||
// To rely on this functionality, ensure that the SPIR-V module is not stripped.
|
||||
bool buffer_get_hlsl_counter_buffer(uint32_t id, uint32_t &counter_id) const;
|
||||
|
Loading…
Reference in New Issue
Block a user