diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index f02a66f46f..e0d6f95f38 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc @@ -28,7 +28,9 @@ #include "src/semantic/struct.h" #include "src/semantic/variable.h" #include "src/type/access_control_type.h" +#include "src/type/depth_texture_type.h" #include "src/type/multisampled_texture_type.h" +#include "src/type/sampled_texture_type.h" #include "src/type/storage_texture_type.h" #include "src/writer/append_vector.h" #include "src/writer/float_to_string.h" @@ -978,9 +980,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, break; case semantic::IntrinsicType::kTextureLoad: out << ".Load("; - if (!texture_type->Is()) { - pack_mip_in_coords = true; - } + pack_mip_in_coords = true; break; case semantic::IntrinsicType::kTextureStore: out << "["; @@ -1781,8 +1781,7 @@ bool GeneratorImpl::EmitEntryPointData( auto* decl = var->Declaration(); auto* unwrapped_type = var->Type()->UnwrapAll(); - if (!unwrapped_type->Is() && - !unwrapped_type->Is()) { + if (!unwrapped_type->IsAnyOf()) { continue; // Not interested in this type } @@ -1793,8 +1792,32 @@ bool GeneratorImpl::EmitEntryPointData( if (!EmitType(out, var->Type(), "")) { return false; } - out << " " << namer_.NameFor(builder_.Symbols().NameFor(decl->symbol())) - << ";" << std::endl; + out << " " << namer_.NameFor(builder_.Symbols().NameFor(decl->symbol())); + + const char* register_space = nullptr; + + if (unwrapped_type->Is()) { + register_space = "t"; + if (unwrapped_type->Is()) { + if (auto* ac = var->Type() + ->UnwrapAliasIfNeeded() + ->As()) { + if (!ac->IsReadOnly()) { + register_space = "u"; + } + } + } + } else if (unwrapped_type->Is()) { + register_space = "s"; + } + + if (register_space) { + auto bp = decl->binding_point(); + out << " : register(" << register_space << bp.binding->value() + << ", space" << bp.group->value() << ")"; + } + + out << ";" << std::endl; add_newline = true; } @@ -2448,10 +2471,9 @@ bool GeneratorImpl::EmitSwitch(std::ostream& out, ast::SwitchStatement* stmt) { bool GeneratorImpl::EmitType(std::ostream& out, type::Type* type, const std::string& name) { - // HLSL doesn't have the read/write only markings so just unwrap the access - // control type. - if (auto* ac = type->As()) { - return EmitType(out, ac->type(), name); + auto* access = type->As(); + if (access) { + type = access->type(); } if (auto* alias = type->As()) { @@ -2505,7 +2527,9 @@ bool GeneratorImpl::EmitType(std::ostream& out, out << builder_.Symbols().NameFor(str->symbol()); } else if (auto* tex = type->As()) { if (tex->Is()) { - out << "RW"; + if (access && !access->IsReadOnly()) { + out << "RW"; + } } out << "Texture"; diff --git a/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc b/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc index 055ec812f7..d6aaa84221 100644 --- a/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc +++ b/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc @@ -338,7 +338,7 @@ texture_tint_0.GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z, _tint_tmp.w) case ValidTextureOverload::kLoadDepth2dArrayLevelF32: return R"(texture_tint_0.Load(int4(1, 2, 3, 0), 4))"; case ValidTextureOverload::kLoadStorageRO1dRgba32float: - return R"(texture_tint_0.Load(1))"; + return R"(texture_tint_0.Load(int2(1, 0)))"; case ValidTextureOverload::kLoadStorageRO2dRgba8unorm: case ValidTextureOverload::kLoadStorageRO2dRgba8snorm: case ValidTextureOverload::kLoadStorageRO2dRgba8uint: @@ -355,11 +355,11 @@ texture_tint_0.GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z, _tint_tmp.w) case ValidTextureOverload::kLoadStorageRO2dRgba32uint: case ValidTextureOverload::kLoadStorageRO2dRgba32sint: case ValidTextureOverload::kLoadStorageRO2dRgba32float: - return R"(texture_tint_0.Load(int2(1, 2)))"; + return R"(texture_tint_0.Load(int3(1, 2, 0)))"; case ValidTextureOverload::kLoadStorageRO2dArrayRgba32float: - return R"(texture_tint_0.Load(int3(1, 2, 3)))"; + return R"(texture_tint_0.Load(int4(1, 2, 3, 0)))"; case ValidTextureOverload::kLoadStorageRO3dRgba32float: - return R"(texture_tint_0.Load(int3(1, 2, 3)))"; + return R"(texture_tint_0.Load(int4(1, 2, 3, 0)))"; case ValidTextureOverload::kStoreWO1dRgba32float: return R"(texture_tint_0[1] = float4(2.0f, 3.0f, 4.0f, 5.0f))"; case ValidTextureOverload::kStoreWO2dRgba32float: diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc index 5f6f63cde8..970260a0e8 100644 --- a/src/writer/hlsl/generator_impl_type_test.cc +++ b/src/writer/hlsl/generator_impl_type_test.cc @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "gmock/gmock.h" +#include "src/ast/call_statement.h" +#include "src/ast/stage_decoration.h" #include "src/ast/struct_block_decoration.h" #include "src/type/access_control_type.h" #include "src/type/depth_texture_type.h" @@ -25,6 +28,8 @@ namespace writer { namespace hlsl { namespace { +using ::testing::HasSubstr; + using HlslGeneratorImplTest_Type = TestHelper; TEST_F(HlslGeneratorImplTest_Type, EmitType_Alias) { @@ -323,58 +328,91 @@ inline std::ostream& operator<<(std::ostream& out, HlslDepthTextureData data) { out << data.dim; return out; } -using HlslDepthtexturesTest = TestParamHelper; -TEST_P(HlslDepthtexturesTest, Emit) { +using HlslDepthTexturesTest = TestParamHelper; +TEST_P(HlslDepthTexturesTest, Emit) { auto params = GetParam(); - type::DepthTexture s(params.dim); + auto* t = create(params.dim); + + Global("tex", t, ast::StorageClass::kUniformConstant, nullptr, + ast::DecorationList{ + create(1), + create(2), + }); + + Func("main", {}, ty.void_(), + {create(Call("textureDimensions", "tex"))}, + {create(ast::PipelineStage::kFragment)}); GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitType(out, &s, "")) << gen.error(); - EXPECT_EQ(result(), params.result); + ASSERT_TRUE(gen.Generate(out)) << gen.error(); + EXPECT_THAT(result(), HasSubstr(params.result)); + + Validate(); } INSTANTIATE_TEST_SUITE_P( HlslGeneratorImplTest_Type, - HlslDepthtexturesTest, + HlslDepthTexturesTest, testing::Values( - HlslDepthTextureData{type::TextureDimension::k2d, "Texture2D"}, + HlslDepthTextureData{type::TextureDimension::k2d, + "Texture2D tex : register(t1, space2);"}, HlslDepthTextureData{type::TextureDimension::k2dArray, - "Texture2DArray"}, - HlslDepthTextureData{type::TextureDimension::kCube, "TextureCube"}, + "Texture2DArray tex : register(t1, space2);"}, + HlslDepthTextureData{type::TextureDimension::kCube, + "TextureCube tex : register(t1, space2);"}, HlslDepthTextureData{type::TextureDimension::kCubeArray, - "TextureCubeArray"})); + "TextureCubeArray tex : register(t1, space2);"})); -struct HlslTextureData { +struct HlslSampledTextureData { type::TextureDimension dim; std::string result; }; -inline std::ostream& operator<<(std::ostream& out, HlslTextureData data) { +inline std::ostream& operator<<(std::ostream& out, + HlslSampledTextureData data) { out << data.dim; return out; } -using HlslSampledtexturesTest = TestParamHelper; -TEST_P(HlslSampledtexturesTest, Emit) { +using HlslSampledTexturesTest = TestParamHelper; +TEST_P(HlslSampledTexturesTest, Emit) { auto params = GetParam(); - type::SampledTexture s(params.dim, ty.f32()); + auto* t = create(params.dim, ty.f32()); + + Global("tex", t, ast::StorageClass::kUniformConstant, nullptr, + ast::DecorationList{ + create(1), + create(2), + }); + + Func("main", {}, ty.void_(), + {create(Call("textureDimensions", "tex"))}, + {create(ast::PipelineStage::kFragment)}); GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitType(out, &s, "")) << gen.error(); - EXPECT_EQ(result(), params.result); + ASSERT_TRUE(gen.Generate(out)) << gen.error(); + EXPECT_THAT(result(), HasSubstr(params.result)); + + Validate(); } INSTANTIATE_TEST_SUITE_P( HlslGeneratorImplTest_Type, - HlslSampledtexturesTest, + HlslSampledTexturesTest, testing::Values( - HlslTextureData{type::TextureDimension::k1d, "Texture1D"}, - HlslTextureData{type::TextureDimension::k2d, "Texture2D"}, - HlslTextureData{type::TextureDimension::k2dArray, "Texture2DArray"}, - HlslTextureData{type::TextureDimension::k3d, "Texture3D"}, - HlslTextureData{type::TextureDimension::kCube, "TextureCube"}, - HlslTextureData{type::TextureDimension::kCubeArray, - "TextureCubeArray"})); + HlslSampledTextureData{type::TextureDimension::k1d, + "Texture1D tex : register(t1, space2);"}, + HlslSampledTextureData{type::TextureDimension::k2d, + "Texture2D tex : register(t1, space2);"}, + HlslSampledTextureData{type::TextureDimension::k2dArray, + "Texture2DArray tex : register(t1, space2);"}, + HlslSampledTextureData{type::TextureDimension::k3d, + "Texture3D tex : register(t1, space2);"}, + HlslSampledTextureData{type::TextureDimension::kCube, + "TextureCube tex : register(t1, space2);"}, + HlslSampledTextureData{ + type::TextureDimension::kCubeArray, + "TextureCubeArray tex : register(t1, space2);"})); TEST_F(HlslGeneratorImplTest_Type, EmitMultisampledTexture) { type::MultisampledTexture s(type::TextureDimension::k2d, ty.f32()); @@ -396,64 +434,77 @@ inline std::ostream& operator<<(std::ostream& out, out << data.dim << (data.ro ? "ReadOnly" : "WriteOnly"); return out; } -using HlslStoragetexturesTest = TestParamHelper; -TEST_P(HlslStoragetexturesTest, Emit) { +using HlslStorageTexturesTest = TestParamHelper; +TEST_P(HlslStorageTexturesTest, Emit) { auto params = GetParam(); auto* subtype = type::StorageTexture::SubtypeFor(params.imgfmt, Types()); - auto* s = create(params.dim, params.imgfmt, subtype); + auto* t = create(params.dim, params.imgfmt, subtype); auto* ac = create(params.ro ? ast::AccessControl::kReadOnly : ast::AccessControl::kWriteOnly, - s); + t); + + Global("tex", ac, ast::StorageClass::kUniformConstant, nullptr, + ast::DecorationList{ + create(1), + create(2), + }); + + Func("main", {}, ty.void_(), + {create(Call("textureDimensions", "tex"))}, + {create(ast::PipelineStage::kFragment)}); GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitType(out, ac, "")) << gen.error(); - EXPECT_EQ(result(), params.result); + ASSERT_TRUE(gen.Generate(out)) << gen.error(); + EXPECT_THAT(result(), HasSubstr(params.result)); + + Validate(); } INSTANTIATE_TEST_SUITE_P( HlslGeneratorImplTest_Type, - HlslStoragetexturesTest, - testing::Values(HlslStorageTextureData{type::TextureDimension::k1d, - type::ImageFormat::kRgba8Unorm, true, - "RWTexture1D"}, - HlslStorageTextureData{type::TextureDimension::k2d, - type::ImageFormat::kRgba16Float, - true, "RWTexture2D"}, - HlslStorageTextureData{type::TextureDimension::k2dArray, - type::ImageFormat::kR32Float, true, - "RWTexture2DArray"}, - HlslStorageTextureData{type::TextureDimension::k3d, - type::ImageFormat::kRg32Float, true, - "RWTexture3D"}, - HlslStorageTextureData{type::TextureDimension::k1d, - type::ImageFormat::kRgba32Float, - false, "RWTexture1D"}, - HlslStorageTextureData{type::TextureDimension::k2d, - type::ImageFormat::kRgba16Uint, - false, "RWTexture2D"}, - HlslStorageTextureData{type::TextureDimension::k2dArray, - type::ImageFormat::kR32Uint, false, - "RWTexture2DArray"}, - HlslStorageTextureData{type::TextureDimension::k3d, - type::ImageFormat::kRg32Uint, false, - "RWTexture3D"}, - HlslStorageTextureData{type::TextureDimension::k1d, - type::ImageFormat::kRgba32Uint, true, - "RWTexture1D"}, - HlslStorageTextureData{type::TextureDimension::k2d, - type::ImageFormat::kRgba16Sint, true, - "RWTexture2D"}, - HlslStorageTextureData{type::TextureDimension::k2dArray, - type::ImageFormat::kR32Sint, true, - "RWTexture2DArray"}, - HlslStorageTextureData{type::TextureDimension::k3d, - type::ImageFormat::kRg32Sint, true, - "RWTexture3D"}, - HlslStorageTextureData{type::TextureDimension::k1d, - type::ImageFormat::kRgba32Sint, - false, "RWTexture1D"})); + HlslStorageTexturesTest, + testing::Values( + HlslStorageTextureData{type::TextureDimension::k1d, + type::ImageFormat::kRgba8Unorm, true, + "Texture1D tex : register(t1, space2);"}, + HlslStorageTextureData{type::TextureDimension::k2d, + type::ImageFormat::kRgba16Float, true, + "Texture2D tex : register(t1, space2);"}, + HlslStorageTextureData{ + type::TextureDimension::k2dArray, type::ImageFormat::kR32Float, + true, "Texture2DArray tex : register(t1, space2);"}, + HlslStorageTextureData{type::TextureDimension::k3d, + type::ImageFormat::kRg32Float, true, + "Texture3D tex : register(t1, space2);"}, + HlslStorageTextureData{ + type::TextureDimension::k1d, type::ImageFormat::kRgba32Float, false, + "RWTexture1D tex : register(u1, space2);"}, + HlslStorageTextureData{ + type::TextureDimension::k2d, type::ImageFormat::kRgba16Uint, false, + "RWTexture2D tex : register(u1, space2);"}, + HlslStorageTextureData{ + type::TextureDimension::k2dArray, type::ImageFormat::kR32Uint, + false, "RWTexture2DArray tex : register(u1, space2);"}, + HlslStorageTextureData{ + type::TextureDimension::k3d, type::ImageFormat::kRg32Uint, false, + "RWTexture3D tex : register(u1, space2);"}, + HlslStorageTextureData{type::TextureDimension::k1d, + type::ImageFormat::kRgba32Uint, true, + "Texture1D tex : register(t1, space2);"}, + HlslStorageTextureData{type::TextureDimension::k2d, + type::ImageFormat::kRgba16Sint, true, + "Texture2D tex : register(t1, space2);"}, + HlslStorageTextureData{ + type::TextureDimension::k2dArray, type::ImageFormat::kR32Sint, true, + "Texture2DArray tex : register(t1, space2);"}, + HlslStorageTextureData{type::TextureDimension::k3d, + type::ImageFormat::kRg32Sint, true, + "Texture3D tex : register(t1, space2);"}, + HlslStorageTextureData{ + type::TextureDimension::k1d, type::ImageFormat::kRgba32Sint, false, + "RWTexture1D tex : register(u1, space2);"})); } // namespace } // namespace hlsl