diff options
| author | Yong He <yonghe@outlook.com> | 2021-10-21 15:51:18 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-21 15:51:18 -0700 |
| commit | 9304c2d04c9bfbae33cc328d404b24aba375aa4f (patch) | |
| tree | 88473d2ca0b03341f84bca17b359ae45c4becfaa | |
| parent | 66e319e34b99eff0a8d27be524ab4a831437ac1b (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-- | .gitignore | 2 | ||||
| -rw-r--r-- | examples/heterogeneous-hello-world/shader.cpp | 181 | ||||
| -rw-r--r-- | premake5.lua | 34 | ||||
| -rw-r--r-- | slang.sln | 15 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir-generics-lowering-context.h | 24 | ||||
| -rw-r--r-- | source/slang/slang-ir-lower-generics.cpp | 32 | ||||
| -rw-r--r-- | source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp | 46 | ||||
| -rw-r--r-- | tests/diagnostics/no-type-conformance.slang | 19 | ||||
| -rw-r--r-- | tests/diagnostics/no-type-conformance.slang.expected | 8 | ||||
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 2 |
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. -- @@ -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; |
