[hlsl] Emit module scoped variables in IR backend.
This CL adds support for module scoped variables in the HLSL IR backend.
Bug: 42251045
Change-Id: I2367054c482b4f99e1bcd7f30a2a62cb6bc0fdf1
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/194480
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/hlsl/writer/printer/printer.cc b/src/tint/lang/hlsl/writer/printer/printer.cc
index fd3411d..1373d9d 100644
--- a/src/tint/lang/hlsl/writer/printer/printer.cc
+++ b/src/tint/lang/hlsl/writer/printer/printer.cc
@@ -116,6 +116,28 @@
namespace tint::hlsl::writer {
namespace {
+// Helper for writing " : register(RX, spaceY)", where R is the register, X is
+// the binding point binding value, and Y is the binding point group value.
+struct RegisterAndSpace {
+ RegisterAndSpace(char r, BindingPoint bp) : reg(r), binding_point(bp) {}
+
+ const char reg;
+ BindingPoint const binding_point;
+};
+
+StringStream& operator<<(StringStream& s, const RegisterAndSpace& rs) {
+ s << " : register(" << rs.reg << rs.binding_point.binding;
+ // Omit the space if it's 0, as it's the default.
+ // SM 5.0 doesn't support spaces, so we don't emit them if group is 0 for better
+ // compatibility.
+ if (rs.binding_point.group == 0) {
+ s << ")";
+ } else {
+ s << ", space" << rs.binding_point.group << ")";
+ }
+ return s;
+}
+
/// PIMPL class for the HLSL generator
class Printer : public tint::TextGenerator {
public:
@@ -130,7 +152,8 @@
return std::move(valid.Failure());
}
- // TOOD(dsinclair): EmitRootBlock
+ // Emit module-scope declarations.
+ EmitRootBlock(ir_.root_block);
// Emit functions.
for (auto* func : ir_.DependencyOrderedFunctions()) {
@@ -168,6 +191,17 @@
/// Block to emit for a continuing
std::function<void()> emit_continuing_;
+ /// Emit the root block.
+ /// @param root_block the root block to emit
+ void EmitRootBlock(core::ir::Block* root_block) {
+ for (auto* inst : *root_block) {
+ Switch(
+ inst, //
+ [&](core::ir::Var* v) { return EmitGlobalVar(v); }, //
+ TINT_ICE_ON_NO_MATCH);
+ }
+ }
+
void EmitFunction(const core::ir::Function* func) {
TINT_SCOPED_ASSIGNMENT(current_function_, func);
@@ -400,6 +434,101 @@
}
}
+ void EmitGlobalVar(const core::ir::Var* var) {
+ auto* ptr = var->Result(0)->Type()->As<core::type::Pointer>();
+ TINT_ASSERT(ptr);
+
+ auto space = ptr->AddressSpace();
+
+ switch (space) {
+ case core::AddressSpace::kUniform:
+ EmitUniformVariable(var);
+ break;
+ case core::AddressSpace::kStorage:
+ EmitStorageVariable(var);
+ break;
+ case core::AddressSpace::kHandle:
+ EmitHandleVariable(var);
+ break;
+ case core::AddressSpace::kPrivate: {
+ Line() << "static";
+ EmitVar(var);
+ break;
+ }
+ case core::AddressSpace::kWorkgroup:
+ Line() << "groupshared";
+ EmitVar(var);
+ break;
+ case core::AddressSpace::kPushConstant:
+ default: {
+ TINT_ICE() << "unhandled address space " << space;
+ }
+ }
+ }
+
+ void EmitUniformVariable(const core::ir::Var* var) {
+ auto* ptr = var->Result(0)->Type()->As<core::type::Pointer>();
+ TINT_ASSERT(ptr);
+
+ auto bp = var->BindingPoint();
+ TINT_ASSERT(bp.has_value());
+
+ Line() << "cbuffer cbuffer_" << NameOf(var->Result(0)) << RegisterAndSpace('b', bp.value())
+ << " {";
+ {
+ const ScopedIndent si(this);
+
+ auto out = Line();
+ EmitTypeAndName(out, ptr->StoreType(), core::AddressSpace::kUniform, ptr->Access(),
+ NameOf(var->Result(0)));
+
+ out << ";";
+ }
+ Line() << "};";
+ }
+
+ void EmitStorageVariable(const core::ir::Var* var) {
+ auto* ptr = var->Result(0)->Type()->As<core::type::Pointer>();
+ TINT_ASSERT(ptr);
+
+ auto out = Line();
+ EmitTypeAndName(out, var->Result(0)->Type(), core::AddressSpace::kStorage, ptr->Access(),
+ NameOf(var->Result(0)));
+
+ auto bp = var->BindingPoint();
+ TINT_ASSERT(bp.has_value());
+
+ out << RegisterAndSpace(ptr->Access() == core::Access::kRead ? 't' : 'u', bp.value())
+ << ";";
+ }
+
+ void EmitHandleVariable(const core::ir::Var* var) {
+ auto* ptr = var->Result(0)->Type()->As<core::type::Pointer>();
+ TINT_ASSERT(ptr);
+
+ char register_space = ' ';
+ if (ptr->StoreType()->Is<core::type::Texture>()) {
+ register_space = 't';
+
+ auto* st = ptr->StoreType()->As<core::type::StorageTexture>();
+ if (st && st->access() != core::Access::kRead) {
+ register_space = 'u';
+ }
+ } else if (ptr->StoreType()->Is<core::type::Sampler>()) {
+ register_space = 's';
+ }
+ TINT_ASSERT(register_space != ' ');
+
+ auto bp = var->BindingPoint();
+ TINT_ASSERT(bp.has_value());
+
+ // TODO(dsinclair): Handle PixelLocal::RasterizerOrderedView attribute
+ auto out = Line();
+ EmitTypeAndName(out, var->Result(0)->Type(), ptr->AddressSpace(), ptr->Access(),
+ NameOf(var->Result(0)));
+ out << RegisterAndSpace(register_space, bp.value()) << ";";
+ }
+
void EmitVar(const core::ir::Var* var) {
auto* ptr = var->Result(0)->Type()->As<core::type::Pointer>();
TINT_ASSERT(ptr);
@@ -408,13 +537,14 @@
auto out = Line();
EmitTypeAndName(out, var->Result(0)->Type(), space, ptr->Access(), NameOf(var->Result(0)));
- out << " = ";
if (var->Initializer()) {
+ out << " = ";
EmitValue(out, var->Initializer());
} else if (space == core::AddressSpace::kPrivate ||
space == core::AddressSpace::kFunction ||
space == core::AddressSpace::kUndefined) {
+ out << " = ";
EmitZeroValue(out, ptr->UnwrapPtr());
}
out << ";";
diff --git a/src/tint/lang/hlsl/writer/var_let_test.cc b/src/tint/lang/hlsl/writer/var_let_test.cc
index 8677eb1..7c1109c 100644
--- a/src/tint/lang/hlsl/writer/var_let_test.cc
+++ b/src/tint/lang/hlsl/writer/var_let_test.cc
@@ -26,7 +26,14 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/tint/lang/core/ir/var.h"
+#include "src/tint/lang/core/type/depth_multisampled_texture.h"
+#include "src/tint/lang/core/type/depth_texture.h"
#include "src/tint/lang/core/type/f32.h"
+#include "src/tint/lang/core/type/multisampled_texture.h"
+#include "src/tint/lang/core/type/sampled_texture.h"
+#include "src/tint/lang/core/type/sampler.h"
+#include "src/tint/lang/core/type/storage_texture.h"
+#include "src/tint/lang/core/type/texture_dimension.h"
#include "src/tint/lang/core/type/type.h"
#include "src/tint/lang/hlsl/writer/helper_test.h"
@@ -90,5 +97,447 @@
)");
}
+TEST_F(HlslWriterTest, VarSampler) {
+ auto* s = b.Var("s", ty.ptr<handle>(ty.sampler()));
+ s->SetBindingPoint(1, 0);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+SamplerState s : register(s0, space1);
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
+TEST_F(HlslWriterTest, VarSamplerComparison) {
+ auto* s = b.Var("s", ty.ptr<handle>(ty.comparison_sampler()));
+ s->SetBindingPoint(0, 0);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+SamplerComparisonState s : register(s0);
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
+struct HlslDepthTextureData {
+ core::type::TextureDimension dim;
+ std::string result;
+};
+inline std::ostream& operator<<(std::ostream& out, HlslDepthTextureData data) {
+ StringStream str;
+ str << data.dim;
+ out << str.str();
+ return out;
+}
+
+using VarDepthTextureTest = HlslWriterTestWithParam<HlslDepthTextureData>;
+TEST_P(VarDepthTextureTest, Emit) {
+ auto params = GetParam();
+
+ auto* s = b.Var("tex", ty.ptr<handle>(ty.Get<core::type::DepthTexture>(params.dim)));
+ s->SetBindingPoint(2, 1);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, "\n" + params.result + R"(
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+INSTANTIATE_TEST_SUITE_P(
+ HlslWriterTest,
+ VarDepthTextureTest,
+ testing::Values(HlslDepthTextureData{core::type::TextureDimension::k2d,
+ "Texture2D tex : register(t1, space2);"},
+ HlslDepthTextureData{core::type::TextureDimension::k2dArray,
+ "Texture2DArray tex : register(t1, space2);"},
+ HlslDepthTextureData{core::type::TextureDimension::kCube,
+ "TextureCube tex : register(t1, space2);"},
+ HlslDepthTextureData{core::type::TextureDimension::kCubeArray,
+ "TextureCubeArray tex : register(t1, space2);"}));
+
+TEST_F(HlslWriterTest, VarDepthMultiSampled) {
+ auto* s = b.Var("tex", ty.ptr<handle>(ty.Get<core::type::DepthMultisampledTexture>(
+ core::type::TextureDimension::k2d)));
+ s->SetBindingPoint(2, 1);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+Texture2DMS<float4> tex : register(t1, space2);
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
+enum class TextureDataType : uint8_t { F32, U32, I32 };
+struct HlslSampledTextureData {
+ core::type::TextureDimension dim;
+ TextureDataType datatype;
+ std::string result;
+};
+
+inline std::ostream& operator<<(std::ostream& out, HlslSampledTextureData data) {
+ StringStream str;
+ str << data.dim;
+ out << str.str();
+ return out;
+}
+
+using VarSampledTextureTest = HlslWriterTestWithParam<HlslSampledTextureData>;
+TEST_P(VarSampledTextureTest, Emit) {
+ auto params = GetParam();
+
+ const core::type::Type* datatype;
+ switch (params.datatype) {
+ case TextureDataType::F32:
+ datatype = ty.f32();
+ break;
+ case TextureDataType::U32:
+ datatype = ty.u32();
+ break;
+ case TextureDataType::I32:
+ datatype = ty.i32();
+ break;
+ }
+
+ auto* s =
+ b.Var("tex", ty.ptr<handle>(ty.Get<core::type::SampledTexture>(params.dim, datatype)));
+ s->SetBindingPoint(2, 1);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, "\n" + params.result + R"(
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
+INSTANTIATE_TEST_SUITE_P(HlslWriterTest,
+ VarSampledTextureTest,
+ testing::Values(
+ HlslSampledTextureData{
+ core::type::TextureDimension::k1d,
+ TextureDataType::F32,
+ "Texture1D<float4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::k2d,
+ TextureDataType::F32,
+ "Texture2D<float4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::k2dArray,
+ TextureDataType::F32,
+ "Texture2DArray<float4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::k3d,
+ TextureDataType::F32,
+ "Texture3D<float4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::kCube,
+ TextureDataType::F32,
+ "TextureCube<float4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::kCubeArray,
+ TextureDataType::F32,
+ "TextureCubeArray<float4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::k1d,
+ TextureDataType::U32,
+ "Texture1D<uint4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::k2d,
+ TextureDataType::U32,
+ "Texture2D<uint4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::k2dArray,
+ TextureDataType::U32,
+ "Texture2DArray<uint4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::k3d,
+ TextureDataType::U32,
+ "Texture3D<uint4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::kCube,
+ TextureDataType::U32,
+ "TextureCube<uint4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::kCubeArray,
+ TextureDataType::U32,
+ "TextureCubeArray<uint4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::k1d,
+ TextureDataType::I32,
+ "Texture1D<int4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::k2d,
+ TextureDataType::I32,
+ "Texture2D<int4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::k2dArray,
+ TextureDataType::I32,
+ "Texture2DArray<int4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::k3d,
+ TextureDataType::I32,
+ "Texture3D<int4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::kCube,
+ TextureDataType::I32,
+ "TextureCube<int4> tex : register(t1, space2);",
+ },
+ HlslSampledTextureData{
+ core::type::TextureDimension::kCubeArray,
+ TextureDataType::I32,
+ "TextureCubeArray<int4> tex : register(t1, space2);",
+ }));
+
+TEST_F(HlslWriterTest, VarMultisampledTexture) {
+ auto* s = b.Var("tex", ty.ptr<handle>(ty.Get<core::type::MultisampledTexture>(
+ core::type::TextureDimension::k2d, ty.f32())));
+ s->SetBindingPoint(2, 1);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+Texture2DMS<float4> tex : register(t1, space2);
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
+struct HlslStorageTextureData {
+ core::type::TextureDimension dim;
+ core::TexelFormat imgfmt;
+ core::Access access;
+ std::string result;
+};
+
+inline std::ostream& operator<<(std::ostream& out, HlslStorageTextureData data) {
+ StringStream str;
+ str << data.dim;
+ out << str.str();
+ return out;
+}
+
+using VarStorageTextureTest = HlslWriterTestWithParam<HlslStorageTextureData>;
+TEST_P(VarStorageTextureTest, Emit) {
+ auto params = GetParam();
+
+ auto* s = b.Var("tex", ty.ptr<handle>(ty.Get<core::type::StorageTexture>(
+ params.dim, params.imgfmt, params.access, ty.f32())));
+ s->SetBindingPoint(2, 1);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, "\n" + params.result + R"(
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ HlslWriterTest,
+ VarStorageTextureTest,
+ testing::Values(
+ HlslStorageTextureData{core::type::TextureDimension::k1d, core::TexelFormat::kRgba8Unorm,
+ core::Access::kWrite,
+ "RWTexture1D<float4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2d, core::TexelFormat::kRgba16Float,
+ core::Access::kWrite,
+ "RWTexture2D<float4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2dArray, core::TexelFormat::kR32Float,
+ core::Access::kWrite,
+ "RWTexture2DArray<float4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k3d, core::TexelFormat::kRg32Float,
+ core::Access::kWrite,
+ "RWTexture3D<float4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k1d, core::TexelFormat::kRgba32Float,
+ core::Access::kWrite,
+ "RWTexture1D<float4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2d, core::TexelFormat::kRgba16Uint,
+ core::Access::kWrite,
+ "RWTexture2D<uint4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2dArray, core::TexelFormat::kR32Uint,
+ core::Access::kWrite,
+ "RWTexture2DArray<uint4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k3d, core::TexelFormat::kRg32Uint,
+ core::Access::kWrite,
+ "RWTexture3D<uint4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k1d, core::TexelFormat::kRgba32Uint,
+ core::Access::kWrite,
+ "RWTexture1D<uint4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2d, core::TexelFormat::kRgba16Sint,
+ core::Access::kWrite,
+ "RWTexture2D<int4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2dArray, core::TexelFormat::kR32Sint,
+ core::Access::kWrite,
+ "RWTexture2DArray<int4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k3d, core::TexelFormat::kRg32Sint,
+ core::Access::kWrite,
+ "RWTexture3D<int4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k1d, core::TexelFormat::kRgba32Sint,
+ core::Access::kWrite,
+ "RWTexture1D<int4> tex : register(u1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k1d, core::TexelFormat::kRgba8Unorm,
+ core::Access::kRead,
+ "Texture1D<float4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2d, core::TexelFormat::kRgba16Float,
+ core::Access::kRead,
+ "Texture2D<float4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2dArray, core::TexelFormat::kR32Float,
+ core::Access::kRead,
+ "Texture2DArray<float4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k3d, core::TexelFormat::kRg32Float,
+ core::Access::kRead,
+ "Texture3D<float4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k1d, core::TexelFormat::kRgba32Float,
+ core::Access::kRead,
+ "Texture1D<float4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2d, core::TexelFormat::kRgba16Uint,
+ core::Access::kRead, "Texture2D<uint4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2dArray, core::TexelFormat::kR32Uint,
+ core::Access::kRead,
+ "Texture2DArray<uint4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k3d, core::TexelFormat::kRg32Uint,
+ core::Access::kRead, "Texture3D<uint4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k1d, core::TexelFormat::kRgba32Uint,
+ core::Access::kRead, "Texture1D<uint4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2d, core::TexelFormat::kRgba16Sint,
+ core::Access::kRead, "Texture2D<int4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k2dArray, core::TexelFormat::kR32Sint,
+ core::Access::kRead,
+ "Texture2DArray<int4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k3d, core::TexelFormat::kRg32Sint,
+ core::Access::kRead, "Texture3D<int4> tex : register(t1, space2);"},
+ HlslStorageTextureData{core::type::TextureDimension::k1d, core::TexelFormat::kRgba32Sint,
+ core::Access::kRead, "Texture1D<int4> tex : register(t1, space2);"}
+
+ ));
+
+TEST_F(HlslWriterTest, VarUniform) {
+ auto* s = b.Var("u", ty.ptr<uniform>(ty.vec4<f32>()));
+ s->SetBindingPoint(2, 1);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+cbuffer cbuffer_u : register(b1, space2) {
+ uint4 u[1];
+};
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
+TEST_F(HlslWriterTest, VarStorageRead) {
+ auto* s = b.Var("u", ty.ptr<storage, core::Access::kRead>(ty.vec4<f32>()));
+ s->SetBindingPoint(2, 1);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+ByteAddressBuffer u : register(t1, space2);
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
+TEST_F(HlslWriterTest, VarStorageReadWrite) {
+ auto* s = b.Var("u", ty.ptr<storage, core::Access::kReadWrite>(ty.vec4<f32>()));
+ s->SetBindingPoint(2, 1);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+RWByteAddressBuffer u : register(u1, space2);
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
+TEST_F(HlslWriterTest, VarPrivate) {
+ auto* s = b.Var("u", ty.ptr<private_>(ty.vec4<f32>()));
+ s->SetBindingPoint(2, 1);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+static
+float4 u = (0.0f).xxxx;
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
+TEST_F(HlslWriterTest, VarWorkgroup) {
+ auto* s = b.Var("u", ty.ptr<workgroup>(ty.vec4<f32>()));
+ s->SetBindingPoint(2, 1);
+
+ b.ir.root_block->Append(s);
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+groupshared
+float4 u;
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
} // namespace
} // namespace tint::hlsl::writer