[hlsl-writer] Emit uniform variables.
This CL adds emission of uniform storage class variables to the HLSL backend. If the variable is a base type (float, int, etc) it is emitted as a `cbuffer`. If the variable is a struct it will emit as a `ConstantBuffer`. Bug: tint:7 Change-Id: I9932d30df24c023c58d3a2ba4167bcb7ccb85dae Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/26920 Commit-Queue: dan sinclair <dsinclair@chromium.org> Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
parent
7df4a845d9
commit
bfaa6f8e57
|
@ -787,6 +787,50 @@ bool GeneratorImpl::EmitEntryPointData(ast::EntryPoint* ep) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool emitted_uniform = false;
|
||||||
|
for (auto data : func->referenced_uniform_variables()) {
|
||||||
|
auto* var = data.first;
|
||||||
|
// TODO(dsinclair): We're using the binding to make up the buffer number but
|
||||||
|
// we should instead be using a provided mapping that uses both buffer and
|
||||||
|
// set. https://bugs.chromium.org/p/tint/issues/detail?id=104
|
||||||
|
auto* binding = data.second.binding;
|
||||||
|
if (binding == nullptr) {
|
||||||
|
error_ = "unable to find binding information for uniform: " + var->name();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// auto* set = data.second.set;
|
||||||
|
|
||||||
|
auto* type = var->type()->UnwrapAliasesIfNeeded();
|
||||||
|
if (type->IsStruct()) {
|
||||||
|
auto* strct = type->AsStruct();
|
||||||
|
|
||||||
|
out_ << "ConstantBuffer<" << strct->name() << "> " << var->name()
|
||||||
|
<< " : register(b" << binding->value() << ");" << std::endl;
|
||||||
|
} else {
|
||||||
|
// TODO(dsinclair): There is outstanding spec work to require all uniform
|
||||||
|
// buffers to be [[block]] decorated, which means structs. This is
|
||||||
|
// currently not the case, so this code handles the cases where the data
|
||||||
|
// is not a block.
|
||||||
|
// Relevant: https://github.com/gpuweb/gpuweb/issues/1004
|
||||||
|
// https://github.com/gpuweb/gpuweb/issues/1008
|
||||||
|
out_ << "cbuffer : register(b" << binding->value() << ") {" << std::endl;
|
||||||
|
|
||||||
|
increment_indent();
|
||||||
|
make_indent();
|
||||||
|
if (!EmitType(type, "")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_ << " " << var->name() << ";" << std::endl;
|
||||||
|
decrement_indent();
|
||||||
|
out_ << "};" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
emitted_uniform = true;
|
||||||
|
}
|
||||||
|
if (emitted_uniform) {
|
||||||
|
out_ << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
auto ep_name = ep->name();
|
auto ep_name = ep->name();
|
||||||
if (ep_name.empty()) {
|
if (ep_name.empty()) {
|
||||||
ep_name = ep->function_name();
|
ep_name = ep->function_name();
|
||||||
|
|
|
@ -29,9 +29,12 @@
|
||||||
#include "src/ast/scalar_constructor_expression.h"
|
#include "src/ast/scalar_constructor_expression.h"
|
||||||
#include "src/ast/set_decoration.h"
|
#include "src/ast/set_decoration.h"
|
||||||
#include "src/ast/sint_literal.h"
|
#include "src/ast/sint_literal.h"
|
||||||
|
#include "src/ast/struct.h"
|
||||||
|
#include "src/ast/type/alias_type.h"
|
||||||
#include "src/ast/type/array_type.h"
|
#include "src/ast/type/array_type.h"
|
||||||
#include "src/ast/type/f32_type.h"
|
#include "src/ast/type/f32_type.h"
|
||||||
#include "src/ast/type/i32_type.h"
|
#include "src/ast/type/i32_type.h"
|
||||||
|
#include "src/ast/type/struct_type.h"
|
||||||
#include "src/ast/type/vector_type.h"
|
#include "src/ast/type/vector_type.h"
|
||||||
#include "src/ast/type/void_type.h"
|
#include "src/ast/type/void_type.h"
|
||||||
#include "src/ast/variable.h"
|
#include "src/ast/variable.h"
|
||||||
|
@ -280,7 +283,7 @@ frag_main_out frag_main(frag_main_in tint_in) {
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest, DISABLED_Emit_Function_EntryPoint_With_Uniform) {
|
TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_With_Uniform) {
|
||||||
ast::type::VoidType void_type;
|
ast::type::VoidType void_type;
|
||||||
ast::type::F32Type f32;
|
ast::type::F32Type f32;
|
||||||
ast::type::VectorType vec4(&f32, 4);
|
ast::type::VectorType vec4(&f32, 4);
|
||||||
|
@ -326,7 +329,91 @@ TEST_F(HlslGeneratorImplTest, DISABLED_Emit_Function_EntryPoint_With_Uniform) {
|
||||||
|
|
||||||
GeneratorImpl g(&mod);
|
GeneratorImpl g(&mod);
|
||||||
ASSERT_TRUE(g.Generate()) << g.error();
|
ASSERT_TRUE(g.Generate()) << g.error();
|
||||||
EXPECT_EQ(g.result(), R"( ... )");
|
EXPECT_EQ(g.result(), R"(cbuffer : register(b0) {
|
||||||
|
vector<float, 4> coord;
|
||||||
|
};
|
||||||
|
|
||||||
|
void frag_main() {
|
||||||
|
float v = coord.x;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_With_UniformStruct) {
|
||||||
|
ast::type::VoidType void_type;
|
||||||
|
ast::type::F32Type f32;
|
||||||
|
ast::type::VectorType vec4(&f32, 4);
|
||||||
|
|
||||||
|
ast::StructMemberList members;
|
||||||
|
members.push_back(std::make_unique<ast::StructMember>(
|
||||||
|
"coord", &vec4, ast::StructMemberDecorationList{}));
|
||||||
|
|
||||||
|
auto str = std::make_unique<ast::Struct>();
|
||||||
|
str->set_members(std::move(members));
|
||||||
|
|
||||||
|
ast::type::StructType s(std::move(str));
|
||||||
|
s.set_name("Uniforms");
|
||||||
|
auto alias = std::make_unique<ast::type::AliasType>("Uniforms", &s);
|
||||||
|
|
||||||
|
Context ctx;
|
||||||
|
ast::Module mod;
|
||||||
|
TypeDeterminer td(&ctx, &mod);
|
||||||
|
|
||||||
|
auto coord_var =
|
||||||
|
std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
|
||||||
|
"uniforms", ast::StorageClass::kUniform, alias.get()));
|
||||||
|
|
||||||
|
mod.AddAliasType(alias.get());
|
||||||
|
|
||||||
|
ast::VariableDecorationList decos;
|
||||||
|
decos.push_back(std::make_unique<ast::BindingDecoration>(0));
|
||||||
|
decos.push_back(std::make_unique<ast::SetDecoration>(1));
|
||||||
|
coord_var->set_decorations(std::move(decos));
|
||||||
|
|
||||||
|
td.RegisterVariableForTesting(coord_var.get());
|
||||||
|
mod.AddGlobalVariable(std::move(coord_var));
|
||||||
|
|
||||||
|
ast::VariableList params;
|
||||||
|
auto func = std::make_unique<ast::Function>("frag_main", std::move(params),
|
||||||
|
&void_type);
|
||||||
|
|
||||||
|
auto var =
|
||||||
|
std::make_unique<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
|
||||||
|
var->set_constructor(std::make_unique<ast::MemberAccessorExpression>(
|
||||||
|
std::make_unique<ast::MemberAccessorExpression>(
|
||||||
|
std::make_unique<ast::IdentifierExpression>("uniforms"),
|
||||||
|
std::make_unique<ast::IdentifierExpression>("coord")),
|
||||||
|
std::make_unique<ast::IdentifierExpression>("x")));
|
||||||
|
|
||||||
|
auto body = std::make_unique<ast::BlockStatement>();
|
||||||
|
body->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
|
||||||
|
body->append(std::make_unique<ast::ReturnStatement>());
|
||||||
|
func->set_body(std::move(body));
|
||||||
|
|
||||||
|
mod.AddFunction(std::move(func));
|
||||||
|
|
||||||
|
auto ep = std::make_unique<ast::EntryPoint>(ast::PipelineStage::kFragment, "",
|
||||||
|
"frag_main");
|
||||||
|
mod.AddEntryPoint(std::move(ep));
|
||||||
|
|
||||||
|
ASSERT_TRUE(td.Determine()) << td.error();
|
||||||
|
|
||||||
|
GeneratorImpl g(&mod);
|
||||||
|
ASSERT_TRUE(g.Generate()) << g.error();
|
||||||
|
EXPECT_EQ(g.result(), R"(typedef struct {
|
||||||
|
vector<float, 4> coord;
|
||||||
|
} Uniforms;
|
||||||
|
|
||||||
|
ConstantBuffer<Uniforms> uniforms : register(b0);
|
||||||
|
|
||||||
|
void frag_main() {
|
||||||
|
float v = uniforms.coord.x;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest,
|
TEST_F(HlslGeneratorImplTest,
|
||||||
|
|
|
@ -1347,6 +1347,10 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::EntryPoint* ep) {
|
||||||
// we should instead be using a provided mapping that uses both buffer and
|
// we should instead be using a provided mapping that uses both buffer and
|
||||||
// set. https://bugs.chromium.org/p/tint/issues/detail?id=104
|
// set. https://bugs.chromium.org/p/tint/issues/detail?id=104
|
||||||
auto* binding = data.second.binding;
|
auto* binding = data.second.binding;
|
||||||
|
if (binding == nullptr) {
|
||||||
|
error_ = "unable to find binding information for uniform: " + var->name();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// auto* set = data.second.set;
|
// auto* set = data.second.set;
|
||||||
|
|
||||||
out_ << "constant ";
|
out_ << "constant ";
|
||||||
|
|
Loading…
Reference in New Issue