Merge pull request #509 from KhronosGroup/hlsl-semantic-counter-buffer

Add support for new HLSL semantic/counter buffer decorations.
This commit is contained in:
Hans-Kristian Arntzen 2018-04-04 13:23:39 +02:00 committed by GitHub
commit d0133c5dd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 328 additions and 2 deletions

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

View File

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

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

View 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

View 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

View File

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

View File

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

View File

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