spirv-reader: handle initialized gl_Position
Bug: tint:508 Change-Id: I57b811c71e9172becfa8a7b9c298824b891d4844 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54565 Auto-Submit: David Neto <dneto@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: David Neto <dneto@google.com> Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
parent
05cc833ae8
commit
944c5617ca
|
@ -1041,7 +1041,7 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
|
||||||
// The SPIR-V gl_PerVertex variable has already been remapped to
|
// The SPIR-V gl_PerVertex variable has already been remapped to
|
||||||
// a gl_Position variable.
|
// a gl_Position variable.
|
||||||
// Substitute the type.
|
// Substitute the type.
|
||||||
param_type = ty_.Vector(ty_.F32(), 4);
|
store_type = param_type = ty_.Vector(ty_.F32(), 4);
|
||||||
out_decos.emplace_back(
|
out_decos.emplace_back(
|
||||||
create<ast::BuiltinDecoration>(source, ast::Builtin::kPosition));
|
create<ast::BuiltinDecoration>(source, ast::Builtin::kPosition));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1250,6 +1250,8 @@ bool ParserImpl::EmitModuleScopeVariables() {
|
||||||
(spirv_storage_class == SpvStorageClassOutput))) {
|
(spirv_storage_class == SpvStorageClassOutput))) {
|
||||||
// Skip emitting gl_PerVertex.
|
// Skip emitting gl_PerVertex.
|
||||||
builtin_position_.per_vertex_var_id = var.result_id();
|
builtin_position_.per_vertex_var_id = var.result_id();
|
||||||
|
builtin_position_.per_vertex_var_init_id =
|
||||||
|
var.NumInOperands() > 1 ? var.GetSingleWordInOperand(1) : 0u;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (enum_converter_.ToStorageClass(spirv_storage_class)) {
|
switch (enum_converter_.ToStorageClass(spirv_storage_class)) {
|
||||||
|
@ -1322,13 +1324,33 @@ bool ParserImpl::EmitModuleScopeVariables() {
|
||||||
decos.push_back(
|
decos.push_back(
|
||||||
create<ast::BuiltinDecoration>(Source{}, ast::Builtin::kPosition));
|
create<ast::BuiltinDecoration>(Source{}, ast::Builtin::kPosition));
|
||||||
}
|
}
|
||||||
auto* var = MakeVariable(
|
ast::Expression* ast_constructor = nullptr;
|
||||||
|
if (builtin_position_.per_vertex_var_init_id) {
|
||||||
|
// The initializer is complex.
|
||||||
|
const auto* init =
|
||||||
|
def_use_mgr_->GetDef(builtin_position_.per_vertex_var_init_id);
|
||||||
|
switch (init->opcode()) {
|
||||||
|
case SpvOpConstantComposite:
|
||||||
|
case SpvOpSpecConstantComposite:
|
||||||
|
ast_constructor = MakeConstantExpression(
|
||||||
|
init->GetSingleWordInOperand(
|
||||||
|
builtin_position_.position_member_index))
|
||||||
|
.expr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return Fail() << "gl_PerVertex initializer too complex. only "
|
||||||
|
"OpCompositeConstruct and OpSpecConstantComposite "
|
||||||
|
"are supported: "
|
||||||
|
<< init->PrettyPrint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto* ast_var = MakeVariable(
|
||||||
builtin_position_.per_vertex_var_id,
|
builtin_position_.per_vertex_var_id,
|
||||||
enum_converter_.ToStorageClass(builtin_position_.storage_class),
|
enum_converter_.ToStorageClass(builtin_position_.storage_class),
|
||||||
ConvertType(builtin_position_.position_member_type_id), false, nullptr,
|
ConvertType(builtin_position_.position_member_type_id), false,
|
||||||
std::move(decos));
|
ast_constructor, std::move(decos));
|
||||||
|
|
||||||
builder_.AST().AddGlobalVariable(var);
|
builder_.AST().AddGlobalVariable(ast_var);
|
||||||
}
|
}
|
||||||
return success_;
|
return success_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -478,6 +478,8 @@ class ParserImpl : Reader {
|
||||||
/// The ID of the gl_PerVertex variable, if it was declared.
|
/// The ID of the gl_PerVertex variable, if it was declared.
|
||||||
/// We'll use this for the gl_Position variable instead.
|
/// We'll use this for the gl_Position variable instead.
|
||||||
uint32_t per_vertex_var_id = 0;
|
uint32_t per_vertex_var_id = 0;
|
||||||
|
/// The ID of the initializer to gl_PerVertex, if any.
|
||||||
|
uint32_t per_vertex_var_init_id = 0;
|
||||||
};
|
};
|
||||||
/// @returns info about the gl_Position builtin variable.
|
/// @returns info about the gl_Position builtin variable.
|
||||||
const BuiltInPositionInfo& GetBuiltInPositionInfo() {
|
const BuiltInPositionInfo& GetBuiltInPositionInfo() {
|
||||||
|
|
|
@ -4899,7 +4899,106 @@ TEST_F(SpvModuleScopeVarParserTest,
|
||||||
EXPECT_EQ(got, expected) << got;
|
EXPECT_EQ(got, expected) << got;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dneto): pipeline IO: gl_Position, with initializer
|
TEST_F(SpvModuleScopeVarParserTest,
|
||||||
|
BuiltinPosition_BuiltIn_Position_Initializer) {
|
||||||
|
const std::string assembly = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical Simple
|
||||||
|
OpEntryPoint Vertex %main "main" %1
|
||||||
|
|
||||||
|
OpMemberDecorate %10 0 BuiltIn Position
|
||||||
|
OpMemberDecorate %10 1 BuiltIn PointSize
|
||||||
|
OpMemberDecorate %10 2 BuiltIn ClipDistance
|
||||||
|
OpMemberDecorate %10 3 BuiltIn CullDistance
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%voidfn = OpTypeFunction %void
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%v4float = OpTypeVector %float 4
|
||||||
|
%uint = OpTypeInt 32 0
|
||||||
|
%uint_0 = OpConstant %uint 0
|
||||||
|
%uint_1 = OpConstant %uint 1
|
||||||
|
%arr = OpTypeArray %float %uint_1
|
||||||
|
%10 = OpTypeStruct %v4float %float %arr %arr
|
||||||
|
%11 = OpTypePointer Output %10
|
||||||
|
|
||||||
|
%float_1 = OpConstant %float 1
|
||||||
|
%float_2 = OpConstant %float 2
|
||||||
|
%float_3 = OpConstant %float 3
|
||||||
|
%float_4 = OpConstant %float 4
|
||||||
|
%float_5 = OpConstant %float 5
|
||||||
|
%float_6 = OpConstant %float 6
|
||||||
|
%float_7 = OpConstant %float 7
|
||||||
|
|
||||||
|
%init_pos = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
|
||||||
|
%init_clip = OpConstantComposite %arr %float_6
|
||||||
|
%init_cull = OpConstantComposite %arr %float_7
|
||||||
|
%init_per_vertex = OpConstantComposite %10 %init_pos %float_5 %init_clip %init_cull
|
||||||
|
|
||||||
|
%1 = OpVariable %11 Output %init_per_vertex
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
|
||||||
|
// TODO(crbug.com/tint/508): Remove this when everything is converted
|
||||||
|
// to HLSL style pipeline IO.
|
||||||
|
p->SetHLSLStylePipelineIO();
|
||||||
|
|
||||||
|
ASSERT_TRUE(p->Parse()) << p->error() << assembly;
|
||||||
|
EXPECT_TRUE(p->error().empty());
|
||||||
|
|
||||||
|
const auto got = p->program().to_str();
|
||||||
|
const std::string expected = R"(Module{
|
||||||
|
Struct main_out {
|
||||||
|
StructMember{[[ BuiltinDecoration{position}
|
||||||
|
]] gl_Position: __vec_4__f32}
|
||||||
|
}
|
||||||
|
Variable{
|
||||||
|
gl_Position
|
||||||
|
private
|
||||||
|
undefined
|
||||||
|
__vec_4__f32
|
||||||
|
{
|
||||||
|
TypeConstructor[not set]{
|
||||||
|
__vec_4__f32
|
||||||
|
ScalarConstructor[not set]{1.000000}
|
||||||
|
ScalarConstructor[not set]{2.000000}
|
||||||
|
ScalarConstructor[not set]{3.000000}
|
||||||
|
ScalarConstructor[not set]{4.000000}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Function main_1 -> __void
|
||||||
|
()
|
||||||
|
{
|
||||||
|
Return{}
|
||||||
|
}
|
||||||
|
Function main -> __type_name_main_out
|
||||||
|
StageDecoration{vertex}
|
||||||
|
()
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{main_1}
|
||||||
|
(
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Return{
|
||||||
|
{
|
||||||
|
TypeConstructor[not set]{
|
||||||
|
__type_name_main_out
|
||||||
|
Identifier[not set]{gl_Position}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
EXPECT_EQ(got, expected) << got;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(dneto): pipeline IO: read PointSize
|
// TODO(dneto): pipeline IO: read PointSize
|
||||||
// TODO(dneto): pipeline IO: write PointSize
|
// TODO(dneto): pipeline IO: write PointSize
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue