summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-10-21 15:51:18 -0700
committerGitHub <noreply@github.com>2021-10-21 15:51:18 -0700
commit9304c2d04c9bfbae33cc328d404b24aba375aa4f (patch)
tree88473d2ca0b03341f84bca17b359ae45c4becfaa
parent66e319e34b99eff0a8d27be524ab4a831437ac1b (diff)
Diagnostic for no type conformance + bug fix. (#1985)
* Diagnostic for no type conformance + bug fix. * Fixes. * Fix. * Include heterogeneous example only with --enable-experimental-projects premake flag Co-authored-by: Yong He <yhe@nvidia.com> Co-authored-by: jsmall-nvidia <jsmall@nvidia.com>
-rw-r--r--.gitignore2
-rw-r--r--examples/heterogeneous-hello-world/shader.cpp181
-rw-r--r--premake5.lua34
-rw-r--r--slang.sln15
-rw-r--r--source/slang/slang-diagnostic-defs.h2
-rw-r--r--source/slang/slang-ir-generics-lowering-context.h24
-rw-r--r--source/slang/slang-ir-lower-generics.cpp32
-rw-r--r--source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp46
-rw-r--r--tests/diagnostics/no-type-conformance.slang19
-rw-r--r--tests/diagnostics/no-type-conformance.slang.expected8
-rw-r--r--tools/gfx/d3d12/render-d3d12.cpp2
11 files changed, 128 insertions, 237 deletions
diff --git a/.gitignore b/.gitignore
index 9df009a6d..690392d5a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,3 +58,5 @@ prelude/*.h.cpp
/docs/Gemfile.lock
/docs/Gemfile
/source/slang/slang-stdlib-generated.h
+
+/examples/heterogeneous-hello-world/shader.cpp \ No newline at end of file
diff --git a/examples/heterogeneous-hello-world/shader.cpp b/examples/heterogeneous-hello-world/shader.cpp
index 3f08af05f..b1fff29f6 100644
--- a/examples/heterogeneous-hello-world/shader.cpp
+++ b/examples/heterogeneous-hello-world/shader.cpp
@@ -1,180 +1 @@
-#include "../../prelude/slang-cpp-prelude.h"
-
-
-#ifdef SLANG_PRELUDE_NAMESPACE
-using namespace SLANG_PRELUDE_NAMESPACE;
-#endif
-
-Vector<uint32_t, 3> operator+(Vector<uint32_t, 3> a, Vector<uint32_t, 3> b)
-{
- Vector<uint32_t, 3> r;
- r.x = a.x + b.x;
- r.y = a.y + b.y;
- r.z = a.z + b.z;
- return r;
-}
-
-Vector<uint32_t, 3> operator*(Vector<uint32_t, 3> a, Vector<uint32_t, 3> b)
-{
- Vector<uint32_t, 3> r;
- r.x = a.x * b.x;
- r.y = a.y * b.y;
- r.z = a.z * b.z;
- return r;
-}
-
-Vector<uint32_t, 3> make_VecU3(uint32_t a, uint32_t b, uint32_t c)
-{
- return Vector<uint32_t, 3>{ a, b, c};
-}
-
-void computeMain_wrapper(gfx_Device_0* device, Vector<uint32_t, 3> gridDims,
- RWStructuredBuffer<float> buffer)
-{
- gfx_ShaderProgram_0* shaderProgram = loadShaderProgram_0(device, "computeMain", "shader");
- gfx_TransientResourceHeap_0* transientHeap = buildTransientHeap_0(device);
- gfx_PipelineState_0* pipelineState = buildPipelineState_0(device, shaderProgram);
- gfx_ResourceView_0* bufferView = createBufferView_0(device, unconvertBuffer_0(buffer));
- dispatchComputation_0(device, transientHeap, pipelineState, bufferView, gridDims.x, gridDims.y, gridDims.z);
-}
-
-#line 8 "../../../examples/heterogeneous-hello-world/shader.slang"
-struct EntryPointParams_0
-{
- RWStructuredBuffer<float> ioBuffer_0;
-};
-
-
-#line 21
-struct gfx_Device_0
-{
-};
-
-
-#line 22
-struct gfx_BufferResource_0
-{
-};
-
-
-#line 23
-struct gfx_ResourceView_0
-{
-};
-
-
-#line 8
-void _computeMain(void* _S1, void* entryPointParams_0, void* _S2)
-{
-
-#line 8
- ComputeThreadVaryingInput* _S3 = (slang_bit_cast<ComputeThreadVaryingInput*>(_S1));
-
- uint32_t tid_0 = (*(&_S3->groupID) * make_VecU3(4U, 1U, 1U) + *(&_S3->groupThreadID)).x;
-
- float* _S4 = &(*(&(slang_bit_cast<EntryPointParams_0*>(entryPointParams_0))->ioBuffer_0))[tid_0];
-
-#line 12
- float i_0 = *_S4;
- bool _S5 = i_0 < 0.50000000000000000000f;
-
-#line 13
- float _S6 = i_0 + i_0;
-
-#line 13
- float _S7 = (F32_sqrt((i_0)));
-
-#line 13
- float o_0 = _S5 ? _S6 : _S7;
-
- float* _S8 = &(*(&(slang_bit_cast<EntryPointParams_0*>(entryPointParams_0))->ioBuffer_0))[tid_0];
-
-#line 15
- *_S8 = o_0;
- return;
-}
-
-
-#line 31
-gfx_Device_0* createDevice_0();
-
-gfx_BufferResource_0* createStructuredBuffer_0(gfx_Device_0* _0, FixedArray<float, 4> _1);
-
-
-gfx_ResourceView_0* createBufferView_0(gfx_Device_0* _0, gfx_BufferResource_0* _1);
-
-
-#line 4
-RWStructuredBuffer<float> convertBuffer_0(gfx_BufferResource_0* _0);
-
-
-#line 44
-void printInitialValues_0(FixedArray<float, 4> _0, int32_t _1);
-
-
-#line 50
-bool printOutputValues_0(gfx_Device_0* _0, gfx_BufferResource_0* _1, int32_t _2);
-
-
-
-
-bool executeComputation_0()
-{
-
- FixedArray<float, 4> initialArray_0 = { 3.00000000000000000000f, -20.00000000000000000000f, -6.00000000000000000000f, 8.00000000000000000000f };
-
-
- gfx_Device_0* _S9 = createDevice_0();
- gfx_BufferResource_0* _S10 = createStructuredBuffer_0(_S9, initialArray_0);
- gfx_ResourceView_0* _S11 = createBufferView_0(_S9, _S10);
- Vector<uint32_t, 3> _S12 = make_VecU3(uint32_t(int(4)), uint32_t(int(1)), uint32_t(int(1)));
- RWStructuredBuffer<float> _S13 = convertBuffer_0(_S10);
-
-#line 64
- computeMain_wrapper(_S9, _S12, _S13);
-
- printInitialValues_0(initialArray_0, int(4));
- bool _S14 = printOutputValues_0(_S9, _S10, int(4));
-
-
- return true;
-}
-
-// [numthreads(4, 1, 1)]
-SLANG_PRELUDE_EXPORT
-void computeMain_Thread(ComputeThreadVaryingInput* varyingInput, void* entryPointParams, void* globalParams)
-{
- _computeMain(varyingInput, entryPointParams, globalParams);
-}
-// [numthreads(4, 1, 1)]
-SLANG_PRELUDE_EXPORT
-void computeMain_Group(ComputeVaryingInput* varyingInput, void* entryPointParams, void* globalParams)
-{
- ComputeThreadVaryingInput threadInput = {};
- threadInput.groupID = varyingInput->startGroupID;
- for (uint32_t x = 0; x < 4; ++x)
- {
- threadInput.groupThreadID.x = x;
- _computeMain(&threadInput, entryPointParams, globalParams);
- }
-}
-// [numthreads(4, 1, 1)]
-SLANG_PRELUDE_EXPORT
-void computeMain(ComputeVaryingInput* varyingInput, void* entryPointParams, void* globalParams)
-{
- ComputeVaryingInput vi = *varyingInput;
- ComputeVaryingInput groupVaryingInput = {};
- for (uint32_t z = vi.startGroupID.z; z < vi.endGroupID.z; ++z)
- {
- groupVaryingInput.startGroupID.z = z;
- for (uint32_t y = vi.startGroupID.y; y < vi.endGroupID.y; ++y)
- {
- groupVaryingInput.startGroupID.y = y;
- for (uint32_t x = vi.startGroupID.x; x < vi.endGroupID.x; ++x)
- {
- groupVaryingInput.startGroupID.x = x;
- computeMain_Group(&groupVaryingInput, entryPointParams, globalParams);
- }
- }
- }
-}
+// This is a placeholder. The contents will be generated during build. \ No newline at end of file
diff --git a/premake5.lua b/premake5.lua
index 2643a1b6c..57658d6d7 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -152,6 +152,14 @@ newoption {
allowed = { { "true", "True"}, { "false", "False" } }
}
+newoption {
+ trigger = "enable-experimental-projects",
+ description = "(Optional) If true include experimental projects in build.",
+ value = "bool",
+ default = "false",
+ allowed = { { "true", "True"}, { "false", "False" } }
+ }
+
buildLocation = _OPTIONS["build-location"]
executeBinary = (_OPTIONS["execute-binary"] == "true")
buildGlslang = (_OPTIONS["build-glslang"] == "true")
@@ -162,7 +170,7 @@ newoption {
enableProfile = (_OPTIONS["enable-profile"] == "true")
enableEmbedStdLib = (_OPTIONS["enable-embed-stdlib"] == "true")
enableXlib = (_OPTIONS["enable-xlib"] == "true")
-
+ enableExperimental = (_OPTIONS["enable-experimental-projects"] == "true")
-- Determine the target info
targetInfo = slangUtil.getTargetInfo()
@@ -672,16 +680,20 @@ newoption {
example "cpu-hello-world"
kind "ConsoleApp"
- example "heterogeneous-hello-world"
- kind "ConsoleApp"
- -- Additionally add slangc for compiling shader.cpp
- links { "example-base", "slang", "gfx", "gfx-util", "slangc", "platform", "core" }
- -- Generate shader.cpp from shader.slang
- prebuildmessage ("Generating shader.cpp from shader.slang")
- prebuildcommands {
- "\"%{wks.location:lower()}/bin/" .. targetName .. "/%{cfg.buildcfg:lower()}/slangc\" \"%{wks.location:lower()}/examples/heterogeneous-hello-world/shader.slang\" -o \"%{wks.location:lower()}/examples/heterogeneous-hello-world/shader.cpp\" -heterogeneous -target cpp -target hlsl"
- }
-
+if enableExperimental then
+ -- TODO: Currently this project doesn't build on linux CI.
+ -- Need to fix so that we don't check in shader.cpp, which changes
+ -- everytime when it is generated on a different machine (contains absolute path)
+ example "heterogeneous-hello-world"
+ kind "ConsoleApp"
+ -- Additionally add slangc for compiling shader.cpp
+ links { "example-base", "slang", "gfx", "gfx-util", "slangc", "platform", "core" }
+ -- Generate shader.cpp from shader.slang
+ prebuildmessage ("Generating shader.cpp from shader.slang")
+ prebuildcommands {
+ "\"%{wks.location:lower()}/bin/" .. targetName .. "/%{cfg.buildcfg:lower()}/slangc\" \"%{wks.location:lower()}/examples/heterogeneous-hello-world/shader.slang\" -o \"%{wks.location:lower()}/examples/heterogeneous-hello-world/shader.cpp\" -heterogeneous -target cpp -target hlsl"
+ }
+end
-- Most of the other projects have more interesting configuration going
-- on, so let's walk through them in order of increasing complexity.
--
diff --git a/slang.sln b/slang.sln
index 1ac713f1c..75eff53aa 100644
--- a/slang.sln
+++ b/slang.sln
@@ -31,8 +31,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpu-printing", "build\visua
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello-world", "build\visual-studio\hello-world\hello-world.vcxproj", "{010BE414-ED5B-CF56-16C0-BD18027062C0}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "heterogeneous-hello-world", "build\visual-studio\heterogeneous-hello-world\heterogeneous-hello-world.vcxproj", "{150CAA5A-0177-6A66-AA92-CFCB96DC2D49}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "model-viewer", "build\visual-studio\model-viewer\model-viewer.vcxproj", "{2F8724C6-1BC3-2730-84D5-3F277030D04A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ray-tracing", "build\visual-studio\ray-tracing\ray-tracing.vcxproj", "{71AC0F50-5DFD-FA91-8661-E95372118EFB}"
@@ -241,18 +239,6 @@ Global
{010BE414-ED5B-CF56-16C0-BD18027062C0}.Release|Win32.Build.0 = Release|Win32
{010BE414-ED5B-CF56-16C0-BD18027062C0}.Release|x64.ActiveCfg = Release|x64
{010BE414-ED5B-CF56-16C0-BD18027062C0}.Release|x64.Build.0 = Release|x64
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|aarch64.ActiveCfg = Debug aarch64|ARM
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|aarch64.Build.0 = Debug aarch64|ARM
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|Win32.ActiveCfg = Debug|Win32
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|Win32.Build.0 = Debug|Win32
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|x64.ActiveCfg = Debug|x64
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Debug|x64.Build.0 = Debug|x64
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|aarch64.ActiveCfg = Release aarch64|ARM
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|aarch64.Build.0 = Release aarch64|ARM
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|Win32.ActiveCfg = Release|Win32
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|Win32.Build.0 = Release|Win32
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|x64.ActiveCfg = Release|x64
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49}.Release|x64.Build.0 = Release|x64
{2F8724C6-1BC3-2730-84D5-3F277030D04A}.Debug|aarch64.ActiveCfg = Debug aarch64|ARM
{2F8724C6-1BC3-2730-84D5-3F277030D04A}.Debug|aarch64.Build.0 = Debug aarch64|ARM
{2F8724C6-1BC3-2730-84D5-3F277030D04A}.Debug|Win32.ActiveCfg = Debug|Win32
@@ -449,7 +435,6 @@ Global
{37BED5B5-23FA-D81F-8C0C-F1167867813A} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{57C81DD3-4304-213D-AC16-39349871C957} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{010BE414-ED5B-CF56-16C0-BD18027062C0} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
- {150CAA5A-0177-6A66-AA92-CFCB96DC2D49} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{2F8724C6-1BC3-2730-84D5-3F277030D04A} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{71AC0F50-5DFD-FA91-8661-E95372118EFB} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
{17BA8E32-034E-84DA-6C12-DE8E58C5BECC} = {EB5FC2C6-D72D-B6CC-C0C1-26F3AC2E9231}
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 2add5792b..897aa9f6f 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -545,6 +545,8 @@ DIAGNOSTIC(51090, Error, cannotGenerateCodeForExternComponentType, "cannot gener
DIAGNOSTIC(51091, Error, typeCannotBePlacedInATexture, "type '$0' cannot be placed in a texture.")
DIAGNOSTIC(51092, Error, stageDoesntHaveInputWorld, "'$0' doesn't appear to have any input world")
+DIAGNOSTIC(50100, Error, noTypeConformancesFoundForInterface, "No type conformances are found for interface '$0'. Code generation for current target requires at least one implementation type present in the linkage.")
+
DIAGNOSTIC(52000, Error, multiLevelBreakUnsupported, "control flow appears to require multi-level `break`, which Slang does not yet support")
DIAGNOSTIC(52001, Warning, dxilNotFound, "dxil shared library not found, so 'dxc' output cannot be signed! Shader code will not be runnable in non-development environments.")
diff --git a/source/slang/slang-ir-generics-lowering-context.h b/source/slang/slang-ir-generics-lowering-context.h
index 78dd068b8..c875566b0 100644
--- a/source/slang/slang-ir-generics-lowering-context.h
+++ b/source/slang/slang-ir-generics-lowering-context.h
@@ -103,4 +103,28 @@ namespace Slang
// Ptr(RTTIType).
bool isTypeValue(IRInst* typeInst);
+ template<typename TFunc>
+ void workOnModule(SharedGenericsLoweringContext* sharedContext, const TFunc& func)
+ {
+ SharedIRBuilder* sharedBuilder = &sharedContext->sharedBuilderStorage;
+ sharedBuilder->module = sharedContext->module;
+ sharedBuilder->session = sharedContext->module->session;
+
+ sharedContext->addToWorkList(sharedContext->module->getModuleInst());
+
+ while (sharedContext->workList.getCount() != 0)
+ {
+ IRInst* inst = sharedContext->workList.getLast();
+
+ sharedContext->workList.removeLast();
+ sharedContext->workListSet.Remove(inst);
+
+ func(inst);
+
+ for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
+ {
+ sharedContext->addToWorkList(child);
+ }
+ }
+ }
}
diff --git a/source/slang/slang-ir-lower-generics.cpp b/source/slang/slang-ir-lower-generics.cpp
index 241827561..95046787a 100644
--- a/source/slang/slang-ir-lower-generics.cpp
+++ b/source/slang/slang-ir-lower-generics.cpp
@@ -117,6 +117,36 @@ namespace Slang
cleanUpInterfaceTypes(sharedContext);
}
+ void checkTypeConformanceExists(SharedGenericsLoweringContext* context)
+ {
+ HashSet<IRInst*> implementedInterfaces;
+
+ // Add all interface type that are implemented by at least one type to a set.
+ for (auto inst : context->module->getGlobalInsts())
+ {
+ if (inst->getOp() == kIROp_WitnessTable)
+ {
+ auto interfaceType = cast<IRWitnessTableType>(inst->getDataType())->getConformanceType();
+ implementedInterfaces.Add(interfaceType);
+ }
+ }
+ // Check if an interface type has any implementations.
+ workOnModule(context, [&](IRInst* inst)
+ {
+ if (auto lookupWitnessMethod = as<IRLookupWitnessMethod>(inst))
+ {
+ auto witnessTableType = lookupWitnessMethod->getWitnessTable()->getDataType();
+ auto interfaceType = cast<IRWitnessTableType>(witnessTableType)->getConformanceType();
+ if (!implementedInterfaces.Contains(interfaceType))
+ {
+ context->sink->diagnose(interfaceType->sourceLoc, Diagnostics::noTypeConformancesFoundForInterface, interfaceType);
+ // Add to set to prevent duplicate diagnostic messages.
+ implementedInterfaces.Add(interfaceType);
+ }
+ }
+ });
+ }
+
void lowerGenerics(
TargetRequest* targetReq,
IRModule* module,
@@ -127,6 +157,8 @@ namespace Slang
sharedContext.module = module;
sharedContext.sink = sink;
+ checkTypeConformanceExists(&sharedContext);
+
// Replace all `makeExistential` insts with `makeExistentialWithRTTI`
// before making any other changes. This is necessary because a parameter of
// generic type will be lowered into `AnyValueType`, and after that we can no longer
diff --git a/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp b/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp
index 059531107..e2d321ed4 100644
--- a/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp
+++ b/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp
@@ -157,44 +157,30 @@ struct AssociatedTypeLookupSpecializationContext
{
if (inst->getRTTIOperand()->getDataType()->getOp() == kIROp_WitnessTableIDType)
{
+ // If the operand is a witness table id, just return the operand.
inst->replaceUsesWith(inst->getRTTIOperand());
inst->removeAndDeallocate();
}
- }
-
- template<typename TFunc>
- void workOnModule(const TFunc& func)
- {
- SharedIRBuilder* sharedBuilder = &sharedContext->sharedBuilderStorage;
- sharedBuilder->module = sharedContext->module;
- sharedBuilder->session = sharedContext->module->session;
-
- sharedContext->addToWorkList(sharedContext->module->getModuleInst());
-
- while (sharedContext->workList.getCount() != 0)
+ else if (inst->getRTTIOperand()->getDataType()->getOp() == kIROp_VectorType)
{
- IRInst* inst = sharedContext->workList.getLast();
-
- sharedContext->workList.removeLast();
- sharedContext->workListSet.Remove(inst);
-
- func(inst);
- if (inst->getOp() == kIROp_lookup_interface_method)
- {
- processLookupInterfaceMethodInst(cast<IRLookupWitnessMethod>(inst));
- }
-
- for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
- {
- sharedContext->addToWorkList(child);
- }
+ // If the operand is a witness table, it is already replaced with a uint2
+ // at this point, where the first element in the uint2 is the id of the
+ // witneess table.
+ auto vectorType = inst->getRTTIOperand()->getDataType();
+ IRBuilder builder;
+ builder.sharedBuilder = &sharedContext->sharedBuilderStorage;
+ builder.setInsertBefore(inst);
+ UInt index = 0;
+ auto id = builder.emitSwizzle(as<IRVectorType>(vectorType)->getElementType(), inst->getRTTIOperand(), 1, &index);
+ inst->replaceUsesWith(id);
+ inst->removeAndDeallocate();
}
}
void processModule()
{
// Replace all `lookup_interface_method():IRWitnessTable` with call to specialized functions.
- workOnModule([this](IRInst* inst)
+ workOnModule(sharedContext, [this](IRInst* inst)
{
if (inst->getOp() == kIROp_lookup_interface_method)
{
@@ -203,7 +189,7 @@ struct AssociatedTypeLookupSpecializationContext
});
// Replace all direct uses of IRWitnessTables with its sequential ID.
- workOnModule([this](IRInst* inst)
+ workOnModule(sharedContext, [this](IRInst* inst)
{
if (inst->getOp() == kIROp_WitnessTable)
{
@@ -252,7 +238,7 @@ struct AssociatedTypeLookupSpecializationContext
}
// `GetSequentialID(WitnessTableIDOperand)` becomes just `WitnessTableIDOperand`.
- workOnModule([this](IRInst* inst)
+ workOnModule(sharedContext, [this](IRInst* inst)
{
if (inst->getOp() == kIROp_GetSequentialID)
{
diff --git a/tests/diagnostics/no-type-conformance.slang b/tests/diagnostics/no-type-conformance.slang
new file mode 100644
index 000000000..ada4f663a
--- /dev/null
+++ b/tests/diagnostics/no-type-conformance.slang
@@ -0,0 +1,19 @@
+//DIAGNOSTIC_TEST:COMMAND_LINE_SIMPLE:-target hlsl -entry computeMain -stage compute -o no-type-conformance.hlsl
+// no type conformance linked
+
+interface IFoo
+{
+ float get();
+}
+
+void foo()
+{
+ IFoo obj;
+ obj.get();
+}
+
+[numthreads(1, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ foo();
+} \ No newline at end of file
diff --git a/tests/diagnostics/no-type-conformance.slang.expected b/tests/diagnostics/no-type-conformance.slang.expected
new file mode 100644
index 000000000..bc38fa7f1
--- /dev/null
+++ b/tests/diagnostics/no-type-conformance.slang.expected
@@ -0,0 +1,8 @@
+result code = -1
+standard error = {
+tests/diagnostics/no-type-conformance.slang(4): error 50100: No type conformances are found for interface 'IFoo'. Code generation for current target requires at least one implementation type present in the linkage.
+interface IFoo
+ ^~~~
+}
+standard output = {
+}
diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp
index 4d5dfda80..8029826a3 100644
--- a/tools/gfx/d3d12/render-d3d12.cpp
+++ b/tools/gfx/d3d12/render-d3d12.cpp
@@ -3844,7 +3844,7 @@ Result D3D12Device::TransientResourceHeapImpl::createCommandBuffer(ICommandBuffe
Result D3D12Device::PipelineCommandEncoder::_bindRenderState(Submitter* submitter, RefPtr<PipelineStateBase>& newPipeline)
{
RootShaderObjectImpl* rootObjectImpl = &m_commandBuffer->m_rootShaderObject;
- m_renderer->maybeSpecializePipeline(m_currentPipeline, rootObjectImpl, newPipeline);
+ SLANG_RETURN_ON_FAIL(m_renderer->maybeSpecializePipeline(m_currentPipeline, rootObjectImpl, newPipeline));
PipelineStateBase* newPipelineImpl = static_cast<PipelineStateBase*>(newPipeline.Ptr());
auto commandList = m_d3dCmdList;
auto pipelineTypeIndex = (int)newPipelineImpl->desc.type;