[hlsl-writer] Add read-only storage buffers. This CL updates the HLSL backend to emit based on the AccessControlType. Bug: tint:208 tint:108 Change-Id: I25baccaaa9af99a214467fe67d55a2f4256dab8c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31105 Commit-Queue: dan sinclair <dsinclair@chromium.org> Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index c771175..7c3ed46 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc
@@ -35,6 +35,7 @@ #include "src/ast/sint_literal.h" #include "src/ast/struct.h" #include "src/ast/switch_statement.h" +#include "src/ast/type/access_control_type.h" #include "src/ast/type/alias_type.h" #include "src/ast/type/array_type.h" #include "src/ast/type/f32_type.h" @@ -1206,7 +1207,16 @@ auto* var = data.first; auto* binding = data.second.binding; - out << "RWByteAddressBuffer " << var->name() << " : register(u" + if (!var->type()->IsAccessControl()) { + error_ = "access control type required for storage buffer"; + return false; + } + auto* ac = var->type()->AsAccessControl(); + + if (ac->IsReadWrite()) { + out << "RW"; + } + out << "ByteAddressBuffer " << var->name() << " : register(u" << binding->value() << ");" << std::endl; emitted_storagebuffer = true; }
diff --git a/src/writer/hlsl/generator_impl_function_test.cc b/src/writer/hlsl/generator_impl_function_test.cc index a5cae3e..4e84f6f 100644 --- a/src/writer/hlsl/generator_impl_function_test.cc +++ b/src/writer/hlsl/generator_impl_function_test.cc
@@ -32,6 +32,7 @@ #include "src/ast/stage_decoration.h" #include "src/ast/struct.h" #include "src/ast/struct_member_offset_decoration.h" +#include "src/ast/type/access_control_type.h" #include "src/ast/type/array_type.h" #include "src/ast/type/f32_type.h" #include "src/ast/type/i32_type.h" @@ -362,7 +363,7 @@ } TEST_F(HlslGeneratorImplTest_Function, - Emit_FunctionDecoration_EntryPoint_With_StorageBuffer_Read) { + Emit_FunctionDecoration_EntryPoint_With_RW_StorageBuffer_Read) { ast::type::VoidType void_type; ast::type::F32Type f32; ast::type::I32Type i32; @@ -382,10 +383,11 @@ str->set_members(std::move(members)); ast::type::StructType s("Data", std::move(str)); + ast::type::AccessControlType ac(ast::type::AccessControl::kReadWrite, &s); auto coord_var = std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>( - "coord", ast::StorageClass::kStorageBuffer, &s)); + "coord", ast::StorageClass::kStorageBuffer, &ac)); ast::VariableDecorationList decos; decos.push_back(std::make_unique<ast::BindingDecoration>(0)); @@ -427,6 +429,72 @@ } TEST_F(HlslGeneratorImplTest_Function, + Emit_FunctionDecoration_EntryPoint_With_RO_StorageBuffer_Read) { + ast::type::VoidType void_type; + ast::type::F32Type f32; + ast::type::I32Type i32; + + ast::StructMemberList members; + ast::StructMemberDecorationList a_deco; + a_deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0)); + members.push_back( + std::make_unique<ast::StructMember>("a", &i32, std::move(a_deco))); + + ast::StructMemberDecorationList b_deco; + b_deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(4)); + members.push_back( + std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco))); + + auto str = std::make_unique<ast::Struct>(); + str->set_members(std::move(members)); + + ast::type::StructType s("Data", std::move(str)); + ast::type::AccessControlType ac(ast::type::AccessControl::kReadOnly, &s); + + auto coord_var = + std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>( + "coord", ast::StorageClass::kStorageBuffer, &ac)); + + 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); + func->add_decoration( + std::make_unique<ast::StageDecoration>(ast::PipelineStage::kFragment)); + + auto var = + std::make_unique<ast::Variable>("v", ast::StorageClass::kFunction, &f32); + var->set_constructor(std::make_unique<ast::MemberAccessorExpression>( + std::make_unique<ast::IdentifierExpression>("coord"), + std::make_unique<ast::IdentifierExpression>("b"))); + + 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)); + + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(ByteAddressBuffer coord : register(u0); + +void frag_main() { + float v = asfloat(coord.Load(4)); + return; +} + +)"); +} + +TEST_F(HlslGeneratorImplTest_Function, Emit_FunctionDecoration_EntryPoint_With_StorageBuffer_Store) { ast::type::VoidType void_type; ast::type::F32Type f32; @@ -447,10 +515,11 @@ str->set_members(std::move(members)); ast::type::StructType s("Data", std::move(str)); + ast::type::AccessControlType ac(ast::type::AccessControl::kReadWrite, &s); auto coord_var = std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>( - "coord", ast::StorageClass::kStorageBuffer, &s)); + "coord", ast::StorageClass::kStorageBuffer, &ac)); ast::VariableDecorationList decos; decos.push_back(std::make_unique<ast::BindingDecoration>(0)); @@ -830,10 +899,10 @@ ast::type::VoidType void_type; ast::type::F32Type f32; ast::type::VectorType vec4(&f32, 4); - + ast::type::AccessControlType ac(ast::type::AccessControl::kReadWrite, &vec4); auto coord_var = std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>( - "coord", ast::StorageClass::kStorageBuffer, &vec4)); + "coord", ast::StorageClass::kStorageBuffer, &ac)); ast::VariableDecorationList decos; decos.push_back(std::make_unique<ast::BindingDecoration>(0));