summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/user-guide/a3-02-reference-capability-atoms.md3
-rw-r--r--source/slang/slang-check-decl.cpp18
-rw-r--r--source/slang/slang-diagnostic-defs.h10
-rw-r--r--source/slang/slang-parameter-binding.cpp2
-rw-r--r--source/slang/slang-type-layout.cpp12
-rw-r--r--source/slang/slang-type-layout.h10
-rw-r--r--tests/diagnostics/incomplete-type.slang11
-rw-r--r--tools/slang-test/test-reporter.cpp5
-rw-r--r--tools/slang-unit-test/unit-test-link-time-type-reflection.cpp228
9 files changed, 253 insertions, 46 deletions
diff --git a/docs/user-guide/a3-02-reference-capability-atoms.md b/docs/user-guide/a3-02-reference-capability-atoms.md
index 015104310..7f759ca24 100644
--- a/docs/user-guide/a3-02-reference-capability-atoms.md
+++ b/docs/user-guide/a3-02-reference-capability-atoms.md
@@ -984,6 +984,9 @@ Compound Capabilities
`cpp_cuda_hlsl_spirv`
> CPP, CUDA, HLSL, and SPIRV code-gen targets
+`cpp_cuda_metal_spirv`
+> CPP, CUDA, Metal, and SPIRV code-gen targets
+
`cpp_cuda_spirv`
> CPP, CUDA and SPIRV code-gen targets
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 4711eaddd..4362f0926 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -2922,13 +2922,6 @@ void SemanticsDeclBodyVisitor::checkVarDeclCommon(VarDeclBase* varDecl)
if (auto elementType = getConstantBufferElementType(varDecl->getType()))
{
- if (doesTypeHaveTag(elementType, TypeTag::Incomplete))
- {
- getSink()->diagnose(
- varDecl->type.exp->loc,
- Diagnostics::incompleteTypeCannotBeUsedInBuffer,
- elementType);
- }
if (doesTypeHaveTag(elementType, TypeTag::Unsized))
{
// If the element type is unsized, it can only be an array of resource types that we can
@@ -2947,17 +2940,6 @@ void SemanticsDeclBodyVisitor::checkVarDeclCommon(VarDeclBase* varDecl)
}
}
}
- else if (varDecl->findModifier<HLSLUniformModifier>())
- {
- auto varType = varDecl->getType();
- if (doesTypeHaveTag(varType, TypeTag::Incomplete))
- {
- getSink()->diagnose(
- varDecl->type.exp->loc,
- Diagnostics::incompleteTypeCannotBeUsedInUniformParameter,
- varType);
- }
- }
maybeRegisterDifferentiableType(getASTBuilder(), varDecl->getType());
}
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 2febd317e..64b1423ac 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -1455,16 +1455,6 @@ DIAGNOSTIC(
"modifier '$0' is redundant or conflicting with existing modifier '$1'")
DIAGNOSTIC(31203, Error, cannotExportIncompleteType, "cannot export incomplete type '$0'")
DIAGNOSTIC(
- 31204,
- Error,
- incompleteTypeCannotBeUsedInBuffer,
- "incomplete type '$0' cannot be used in a buffer")
-DIAGNOSTIC(
- 31205,
- Error,
- incompleteTypeCannotBeUsedInUniformParameter,
- "incomplete type '$0' cannot be used in a uniform parameter")
-DIAGNOSTIC(
31206,
Error,
memoryQualifierNotAllowedOnANonImageTypeParameter,
diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp
index 4b91056fc..b79f96022 100644
--- a/source/slang/slang-parameter-binding.cpp
+++ b/source/slang/slang-parameter-binding.cpp
@@ -2420,7 +2420,7 @@ static RefPtr<TypeLayout> processEntryPointVaryingParameter(
if (auto structDeclRef = declRef.as<StructDecl>())
{
RefPtr<StructTypeLayout> structLayout = new StructTypeLayout();
- structLayout->type = type;
+ structLayout->type = declRefType;
// We will recursively walk the fields of a `struct` type
// to compute layouts for those fields.
diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp
index efd41bd86..fb40382c5 100644
--- a/source/slang/slang-type-layout.cpp
+++ b/source/slang/slang-type-layout.cpp
@@ -4918,7 +4918,8 @@ static TypeLayoutResult _createTypeLayout(TypeLayoutContext& context, Type* type
else if (auto vecType = as<VectorExpressionType>(type))
{
auto elementType = vecType->getElementType();
- size_t elementCount = (size_t)getIntVal(vecType->getElementCount());
+ size_t elementCount =
+ (size_t)getIntVal(context.tryResolveLinkTimeVal(vecType->getElementCount()));
auto element = _createTypeLayout(context, elementType);
@@ -4944,8 +4945,9 @@ static TypeLayoutResult _createTypeLayout(TypeLayoutContext& context, Type* type
}
else if (auto matType = as<MatrixExpressionType>(type))
{
- size_t rowCount = (size_t)getIntVal(matType->getRowCount());
- size_t colCount = (size_t)getIntVal(matType->getColumnCount());
+ size_t rowCount = (size_t)getIntVal(context.tryResolveLinkTimeVal(matType->getRowCount()));
+ size_t colCount =
+ (size_t)getIntVal(context.tryResolveLinkTimeVal(matType->getColumnCount()));
auto elementType = matType->getElementType();
auto elementResult = _createTypeLayout(context, elementType);
@@ -5031,7 +5033,7 @@ static TypeLayoutResult _createTypeLayout(TypeLayoutContext& context, Type* type
context,
arrayType,
arrayType->getElementType(),
- arrayType->getElementCount());
+ context.tryResolveLinkTimeVal(arrayType->getElementCount()));
}
else if (auto atomicType = as<AtomicType>(type))
{
@@ -5181,7 +5183,7 @@ static TypeLayoutResult _createTypeLayout(TypeLayoutContext& context, Type* type
StructTypeLayoutBuilder typeLayoutBuilder;
StructTypeLayoutBuilder pendingDataTypeLayoutBuilder;
- typeLayoutBuilder.beginLayout(type, rules);
+ typeLayoutBuilder.beginLayout(declRefType, rules);
auto typeLayout = typeLayoutBuilder.getTypeLayout();
_addLayout(context, type, typeLayout);
diff --git a/source/slang/slang-type-layout.h b/source/slang/slang-type-layout.h
index bcb842013..84840c043 100644
--- a/source/slang/slang-type-layout.h
+++ b/source/slang/slang-type-layout.h
@@ -1231,6 +1231,16 @@ struct TypeLayoutContext
}
return result;
}
+
+ IntVal* tryResolveLinkTimeVal(IntVal* inVal) const
+ {
+ if (!programLayout)
+ return inVal;
+ auto constIntVal = programLayout->getProgram()->tryFoldIntVal(inVal);
+ if (constIntVal)
+ return constIntVal;
+ return inVal;
+ }
};
//
diff --git a/tests/diagnostics/incomplete-type.slang b/tests/diagnostics/incomplete-type.slang
deleted file mode 100644
index 873673045..000000000
--- a/tests/diagnostics/incomplete-type.slang
+++ /dev/null
@@ -1,11 +0,0 @@
-//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK):
-
-extern struct ExtType;
-
-struct MyType
-{
- ExtType arr[2];
-}
-
-// CHECK: ([[#@LINE+1]]): error 31204
-ConstantBuffer<MyType> buffer;
diff --git a/tools/slang-test/test-reporter.cpp b/tools/slang-test/test-reporter.cpp
index 3aba10566..00f570b6c 100644
--- a/tools/slang-test/test-reporter.cpp
+++ b/tools/slang-test/test-reporter.cpp
@@ -610,9 +610,9 @@ void TestReporter::message(TestMessageType type, const String& message)
if (canWriteStdError())
{
+ fprintf(stderr, "[%s] ", m_currentInfo.name.getBuffer());
if (type == TestMessageType::RunError || type == TestMessageType::TestFailure)
{
- fprintf(stderr, "error: ");
fputs(message.getBuffer(), stderr);
fprintf(stderr, "\n");
}
@@ -627,6 +627,9 @@ void TestReporter::message(TestMessageType type, const String& message)
{
m_currentMessage << "\n";
}
+
+ if (m_currentInfo.name.getLength())
+ m_currentMessage << "[" << m_currentInfo.name << "] ";
m_currentMessage.append(message);
}
diff --git a/tools/slang-unit-test/unit-test-link-time-type-reflection.cpp b/tools/slang-unit-test/unit-test-link-time-type-reflection.cpp
new file mode 100644
index 000000000..c42fd2f16
--- /dev/null
+++ b/tools/slang-unit-test/unit-test-link-time-type-reflection.cpp
@@ -0,0 +1,228 @@
+// unit-test-translation-unit-import.cpp
+
+#include "../../source/core/slang-io.h"
+#include "../../source/core/slang-process.h"
+#include "slang-com-ptr.h"
+#include "slang.h"
+#include "unit-test/slang-unit-test.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace Slang;
+
+static String getTypeFullName(slang::TypeReflection* type)
+{
+ ComPtr<ISlangBlob> blob;
+ type->getFullName(blob.writeRef());
+ return String((const char*)blob->getBufferPointer());
+}
+
+// Test that the reflection API provides correct info about modules with link-time types.
+
+SLANG_UNIT_TEST(linkTimeTypeReflection)
+{
+ // Source for a module that contains can be specialized with a link-time type.
+ const char* userSourceBody = R"(
+ interface IMaterial { float4 load(); }
+ extern struct Material : IMaterial;
+ ConstantBuffer<Material> gMaterial;
+
+ RWTexture2D tex;
+
+ extern static const int count;
+ uniform uint4 buffers[count];
+
+ [numthreads(1,1,1)]
+ [shader("compute")]
+ void computeMain() {
+ tex[uint2(0, 0)] = gMaterial.load();
+ }
+ )";
+
+ String moduleName = "linkTimeTypeReflection_Compute";
+
+ ComPtr<slang::IGlobalSession> globalSession;
+ SLANG_CHECK(slang_createGlobalSession(SLANG_API_VERSION, globalSession.writeRef()) == SLANG_OK);
+ slang::TargetDesc targetDesc = {};
+ targetDesc.format = SLANG_SPIRV_ASM;
+ targetDesc.profile = globalSession->findProfile("spirv_1_5");
+ slang::SessionDesc sessionDesc = {};
+ sessionDesc.targetCount = 1;
+ sessionDesc.targets = &targetDesc;
+ ComPtr<slang::ISession> session;
+ SLANG_CHECK(globalSession->createSession(sessionDesc, session.writeRef()) == SLANG_OK);
+
+ ComPtr<slang::IBlob> diagnosticBlob;
+ auto module = session->loadModuleFromSourceString(
+ moduleName.getBuffer(),
+ (moduleName + ".slang").getBuffer(),
+ userSourceBody,
+ diagnosticBlob.writeRef());
+ SLANG_CHECK_ABORT(module != nullptr);
+
+ // Source for a module that defines the link-time type.
+ String configModuleSource = "import " + moduleName + ";\n" + R"(
+ export struct Material : IMaterial = MyMaterial;
+ export static const int count = 11;
+
+ struct MyMaterial : IMaterial {
+ int data;
+ Texture2D diffuse;
+ float4 load() { return diffuse.Load(uint3(0,0,0)); }
+ }
+ )";
+ auto configModule = session->loadModuleFromSourceString(
+ "config",
+ "config.slang",
+ configModuleSource.getBuffer(),
+ diagnosticBlob.writeRef());
+ SLANG_CHECK_ABORT(configModule != nullptr);
+
+ slang::IComponentType* components[] = {module, configModule};
+
+ ComPtr<slang::IComponentType> compositeProgram;
+ session->createCompositeComponentType(
+ components,
+ 2,
+ compositeProgram.writeRef(),
+ diagnosticBlob.writeRef());
+ SLANG_CHECK_ABORT(compositeProgram != nullptr);
+
+ ComPtr<slang::IComponentType> linkedProgram;
+ compositeProgram->link(linkedProgram.writeRef(), diagnosticBlob.writeRef());
+ SLANG_CHECK_ABORT(linkedProgram != nullptr);
+
+ auto programLayout = linkedProgram->getLayout();
+ auto var0 = programLayout->getParameterByIndex(0);
+
+ // `gMaterial`'s binding starts at 1, because there is an implicit global uniform buffer.
+ SLANG_CHECK(var0->getOffset(slang::ParameterCategory::DescriptorTableSlot) == 1);
+ SLANG_CHECK(var0->getTypeLayout()->getSize(slang::ParameterCategory::DescriptorTableSlot) == 2);
+
+ auto elementLayout = var0->getTypeLayout()->getElementTypeLayout();
+ SLANG_CHECK_ABORT(elementLayout != nullptr);
+ SLANG_CHECK(elementLayout->getSize() == 16);
+
+ auto var1 = programLayout->getParameterByIndex(1);
+ SLANG_CHECK(var1->getOffset(slang::ParameterCategory::DescriptorTableSlot) == 3);
+
+ auto var2 = programLayout->getParameterByIndex(2);
+ SLANG_CHECK(var2->getTypeLayout()->getSize() == 11 * 16);
+
+ ComPtr<slang::IBlob> codeBlob;
+ linkedProgram->getTargetCode(0, codeBlob.writeRef(), diagnosticBlob.writeRef());
+
+ SLANG_CHECK_ABORT(codeBlob.get());
+
+ auto spirvStr = UnownedStringSlice((const char*)codeBlob->getBufferPointer());
+
+ SLANG_CHECK(spirvStr.indexOf(toSlice("OpDecorate %tex Binding 3")) != -1);
+}
+
+
+// Test that the reflection API provides correct info about modules using link-time constants in a
+// `Conditional` field.
+
+SLANG_UNIT_TEST(linkTimeConditionalReflection)
+{
+ // Source for a module that contains can be specialized with a link-time constant.
+ const char* userSourceBody = R"(
+ module LinkTimeConditional;
+
+ extern static const bool hasNormal;
+ extern static const bool hasColor;
+
+ struct VertexOut
+ {
+ float4 pos : SV_Position;
+ float someData;
+ Conditional<float3, hasNormal> normal;
+ Conditional<float3, hasColor> color;
+ }
+
+ [shader("vertex")]
+ VertexOut vertexMain()
+ {
+ VertexOut v;
+ v.pos = float4(0,0,0,1);
+ v.someData = 2.0f;
+ v.normal.set(float3(1,0,0));
+ v.color.set(float3(1,1,1));
+ return v;
+ }
+ )";
+
+ String moduleName = "LinkTimeConditional";
+
+ ComPtr<slang::IGlobalSession> globalSession;
+ SLANG_CHECK(slang_createGlobalSession(SLANG_API_VERSION, globalSession.writeRef()) == SLANG_OK);
+ slang::TargetDesc targetDesc = {};
+ targetDesc.format = SLANG_SPIRV_ASM;
+ targetDesc.profile = globalSession->findProfile("spirv_1_5");
+ slang::SessionDesc sessionDesc = {};
+ sessionDesc.targetCount = 1;
+ sessionDesc.targets = &targetDesc;
+ ComPtr<slang::ISession> session;
+ SLANG_CHECK(globalSession->createSession(sessionDesc, session.writeRef()) == SLANG_OK);
+
+ ComPtr<slang::IBlob> diagnosticBlob;
+ auto module = session->loadModuleFromSourceString(
+ moduleName.getBuffer(),
+ (moduleName + ".slang").getBuffer(),
+ userSourceBody,
+ diagnosticBlob.writeRef());
+ SLANG_CHECK_ABORT(module != nullptr);
+
+ // Source for a module that defines the link-time constants.
+ String configModuleSource = R"(
+ export static const bool hasNormal = false;
+ export static const bool hasColor = true;
+ )";
+ auto configModule = session->loadModuleFromSourceString(
+ "config",
+ "config.slang",
+ configModuleSource.getBuffer(),
+ diagnosticBlob.writeRef());
+ SLANG_CHECK_ABORT(configModule != nullptr);
+
+ ComPtr<slang::IEntryPoint> entryPoint;
+ module->getDefinedEntryPoint(0, entryPoint.writeRef());
+
+ slang::IComponentType* components[] = {module, configModule, entryPoint};
+
+ ComPtr<slang::IComponentType> compositeProgram;
+ session->createCompositeComponentType(
+ components,
+ 3,
+ compositeProgram.writeRef(),
+ diagnosticBlob.writeRef());
+ SLANG_CHECK_ABORT(compositeProgram != nullptr);
+
+ ComPtr<slang::IComponentType> linkedProgram;
+ compositeProgram->link(linkedProgram.writeRef(), diagnosticBlob.writeRef());
+ SLANG_CHECK_ABORT(linkedProgram != nullptr);
+
+ auto programLayout = linkedProgram->getLayout();
+
+ auto entryPointLayout = programLayout->getEntryPointByIndex(0);
+
+ auto resultLayout = entryPointLayout->getResultVarLayout();
+ SLANG_CHECK_ABORT(resultLayout != nullptr);
+
+ // Number of varying output is 2, because `pos` is a system value that doesn't count towards
+ // varying output.
+ SLANG_CHECK(
+ resultLayout->getTypeLayout()->getSize(slang::ParameterCategory::VaryingOutput) == 2);
+
+ ComPtr<slang::IBlob> codeBlob;
+ linkedProgram->getTargetCode(0, codeBlob.writeRef(), diagnosticBlob.writeRef());
+
+ SLANG_CHECK_ABORT(codeBlob.get());
+
+ auto spirvStr = UnownedStringSlice((const char*)codeBlob->getBufferPointer());
+
+ // Test that the resulting spirv defines output at location 1, but not at location 2.
+ SLANG_CHECK(spirvStr.indexOf(toSlice("Location 1")) != -1);
+ SLANG_CHECK(spirvStr.indexOf(toSlice("Location 2")) == -1);
+}