diff options
| author | Yong He <yonghe@outlook.com> | 2021-04-20 13:17:29 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-04-20 13:17:29 -0700 |
| commit | 34fba7b5e726136c6eee8a318ab9a75381399c00 (patch) | |
| tree | 39a496c7052256cef9b089b78ab4bd48316571bd | |
| parent | 6bba674f9d732eccc27dcf004611e6a8eb9bc14e (diff) | |
Various fixes to make `model-viewer` example almost working. (#1801)
* Fixing `PseudoPtr` legalization and `gfx` lifetime issues.
* Fixing `model-viewer` example.
This change contains various fixes to bring `model-viewer` example to fully functional. These fixes include:
1. Add `spReflectionTypeLayout_getSubObjectRangeSpaceOffset` function to return the space index for a sub object referenced through a `ParameterBlock` binding.
2. Make sure `D3D12Device` specifies column major matrix order creating a Slang session.
3. Fix `platform::Window::close()` and `platform::Application::quit()`.
4. Fix memory leak during `model-viewer''s model loading.
5. Fix command buffer recording in `model-viewer`.
With these changes, model viewer can now produce an image with a gray cube. The lighting is still incorrect becuase the `gfx` shader object implementation still does not handle "pending layout" resulting from global existential parameters.
* Fix d3d12 root signature creation.
* Use row-major matrix layout in model-viewer
| -rw-r--r-- | examples/model-viewer/main.cpp | 36 | ||||
| -rw-r--r-- | examples/model-viewer/shaders.slang | 3 | ||||
| -rw-r--r-- | slang.h | 8 | ||||
| -rw-r--r-- | source/slang/slang-legalize-types.cpp | 5 | ||||
| -rw-r--r-- | source/slang/slang-reflection-api.cpp | 25 | ||||
| -rw-r--r-- | source/slang/slang-type-layout.h | 1 | ||||
| -rw-r--r-- | tools/gfx/d3d11/render-d3d11.cpp | 23 | ||||
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 219 | ||||
| -rw-r--r-- | tools/gfx/open-gl/render-gl.cpp | 23 | ||||
| -rw-r--r-- | tools/gfx/renderer-shared.cpp | 22 | ||||
| -rw-r--r-- | tools/gfx/renderer-shared.h | 23 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 23 | ||||
| -rw-r--r-- | tools/platform/windows/win-window.cpp | 21 |
13 files changed, 260 insertions, 172 deletions
diff --git a/examples/model-viewer/main.cpp b/examples/model-viewer/main.cpp index 3d7a9fe34..f6aab4c4a 100644 --- a/examples/model-viewer/main.cpp +++ b/examples/model-viewer/main.cpp @@ -212,6 +212,11 @@ RefPtr<Model> loadModel( struct Callbacks : platform::ModelLoader::ICallbacks { RendererContext* context; + // Hold a reference to all material and mesh objects + // created during loading so that they can be properly + // freed. + std::vector<RefPtr<Material>> materials; + std::vector<RefPtr<Mesh>> meshes; void* createMaterial(MaterialData const& data) override { SimpleMaterial* material = new SimpleMaterial(); @@ -219,6 +224,7 @@ RefPtr<Model> loadModel( material->specularColor = data.specularColor; material->specularity = data.specularity; material->createShaderObject(context); + materials.push_back(material); return material; } @@ -228,6 +234,7 @@ RefPtr<Model> loadModel( mesh->firstIndex = data.firstIndex; mesh->indexCount = data.indexCount; mesh->material = (Material*)data.material; + meshes.push_back(mesh); return mesh; } @@ -626,7 +633,6 @@ struct LightEnv : public RefObject // struct ModelViewer : WindowedAppBase { - RendererContext context; // Most of the application state is stored in the list of loaded models, @@ -809,7 +815,9 @@ void renderFrame(int frameIndex) override // glm::mat4x4 identity = glm::mat4x4(1.0f); auto clientRect = getWindow()->getClientRect(); - glm::mat4x4 projection = glm::perspective( + if (clientRect.height == 0) + return; + glm::mat4x4 projection = glm::perspectiveRH_ZO( glm::radians(60.0f), float(clientRect.width) / float(clientRect.height), 0.1f, 1000.0f); @@ -834,6 +842,12 @@ void renderFrame(int frameIndex) override view = glm::translate(view, -cameraPosition); glm::mat4x4 viewProjection = projection * view; + auto deviceInfo = gDevice->getDeviceInfo(); + glm::mat4x4 correctionMatrix; + memcpy(&correctionMatrix, deviceInfo.identityProjectionMatrix, sizeof(float)*16); + viewProjection = correctionMatrix * viewProjection; + // glm uses column-major layout, we need to translate it to row-major. + viewProjection = glm::transpose(viewProjection); auto drawCommandBuffer = gTransientHeaps[frameIndex]->createCommandBuffer(); auto drawCommandEncoder = @@ -848,24 +862,20 @@ void renderFrame(int frameIndex) override // We are only rendering one view, so we can fill in a per-view // shader object once and use it across all draw calls. // + auto viewShaderObject = gDevice->createShaderObject(context.perViewShaderType); { ShaderCursor cursor(viewShaderObject); cursor["viewProjection"].setData(&viewProjection, sizeof(viewProjection)); cursor["eyePosition"].setData(&cameraPosition, sizeof(cameraPosition)); } - // The majority of our rendering logic is handled as a loop // over the models in the scene, and their meshes. // for(auto& model : gModels) { - auto rootObject = drawCommandEncoder->bindPipeline(gPipelineState); - ShaderCursor rootCursor(rootObject); - rootCursor["gViewParams"].setObject(viewShaderObject); drawCommandEncoder->setVertexBuffer(0, model->vertexBuffer, sizeof(Model::Vertex)); drawCommandEncoder->setIndexBuffer(model->indexBuffer, Format::R_UInt32); - // For each model we provide a parameter // block that holds the per-model transformation // parameters, corresponding to the `PerModel` type @@ -879,10 +889,8 @@ void renderFrame(int frameIndex) override cursor["inverseTransposeModelTransform"].setData( &inverseTransposeModelTransform, sizeof(inverseTransposeModelTransform)); } - rootCursor["gModelParams"].setObject(modelShaderObject); auto lightShaderObject = lightEnv->createShaderObject(); - rootCursor["gLightEnv"].setObject(lightShaderObject); // Now we loop over the meshes in the model. // @@ -893,6 +901,13 @@ void renderFrame(int frameIndex) override // for(auto& mesh : model->meshes) { + // Set the pipeline and binding state for drawing each mesh. + auto rootObject = drawCommandEncoder->bindPipeline(gPipelineState); + ShaderCursor rootCursor(rootObject); + rootCursor["gViewParams"].setObject(viewShaderObject); + rootCursor["gModelParams"].setObject(modelShaderObject); + rootCursor["gLightEnv"].setObject(lightShaderObject); + // Each mesh has a material, and each material has its own // parameter block that was created at load time, so we // can just re-use the persistent parameter block for the @@ -911,6 +926,9 @@ void renderFrame(int frameIndex) override drawCommandEncoder->drawIndexed(mesh->indexCount, mesh->firstIndex); } } + drawCommandEncoder->endEncoding(); + drawCommandBuffer->close(); + gQueue->executeCommandBuffer(drawCommandBuffer); gSwapchain->present(); } diff --git a/examples/model-viewer/shaders.slang b/examples/model-viewer/shaders.slang index 0cc0d802f..0005b427b 100644 --- a/examples/model-viewer/shaders.slang +++ b/examples/model-viewer/shaders.slang @@ -468,7 +468,6 @@ float4 fragmentMain( // `illuminance` loop in RenderMan Shading Language works. // - float3 color = gLightEnv.illuminate(g, brdf, V); - + float3 color = saturate(gLightEnv.illuminate(g, brdf, V) + float3(0.3)); return float4(color, 1); } @@ -2012,6 +2012,7 @@ extern "C" SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeCount(SlangReflectionTypeLayout* typeLayout); SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex); + SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeSpaceOffset(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex); #if 0 SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeCount(SlangReflectionTypeLayout* typeLayout); @@ -2687,6 +2688,13 @@ namespace slang (SlangReflectionTypeLayout*) this, subObjectRangeIndex); } + + SlangInt getSubObjectRangeSpaceOffset(SlangInt subObjectRangeIndex) + { + return spReflectionTypeLayout_getSubObjectRangeSpaceOffset( + (SlangReflectionTypeLayout*) this, + subObjectRangeIndex); + } }; struct Modifier diff --git a/source/slang/slang-legalize-types.cpp b/source/slang/slang-legalize-types.cpp index 755f0f207..1b72b5c00 100644 --- a/source/slang/slang-legalize-types.cpp +++ b/source/slang/slang-legalize-types.cpp @@ -1201,11 +1201,6 @@ LegalType legalizeTypeImpl( // auto legalConcreteType = legalizeType(context, pseudoPtrType->getValueType()); - // If element type hasn't change, return original type. - if (legalConcreteType.flavor == LegalType::Flavor::simple && - legalConcreteType.getSimple() == pseudoPtrType->getValueType()) - return LegalType::simple(pseudoPtrType); - // TODO: If/when we change our generation of pseudo-pointers // so that use-site code emits a "pseudo-load" then we may // need to change the logic here so that we return diff --git a/source/slang/slang-reflection-api.cpp b/source/slang/slang-reflection-api.cpp index 6f022cc90..eb1514f4c 100644 --- a/source/slang/slang-reflection-api.cpp +++ b/source/slang/slang-reflection-api.cpp @@ -1396,7 +1396,12 @@ namespace Slang // TypeLayout::ExtendedInfo::SubObjectRangeInfo subObjectRange; subObjectRange.bindingRangeIndex = bindingRangeIndex; - + subObjectRange.spaceOffset = 0; + if (kind == LayoutResourceKind::RegisterSpace) + { + auto resInfo = path->var->FindResourceInfo(LayoutResourceKind::RegisterSpace); + subObjectRange.spaceOffset = resInfo->index; + } // It is possible that the sub-object has descriptor ranges // that will need to be exposed upward, into the parent. // @@ -2010,6 +2015,24 @@ SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex(Sla return extTypeLayout->m_subObjectRanges[subObjectRangeIndex].bindingRangeIndex; } +SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeSpaceOffset( + SlangReflectionTypeLayout* inTypeLayout, + SlangInt subObjectRangeIndex) +{ + auto typeLayout = convert(inTypeLayout); + if (!typeLayout) + return 0; + + auto extTypeLayout = Slang::getExtendedTypeLayout(typeLayout); + + if (subObjectRangeIndex < 0) + return 0; + if (subObjectRangeIndex >= extTypeLayout->m_subObjectRanges.getCount()) + return 0; + + return extTypeLayout->m_subObjectRanges[subObjectRangeIndex].spaceOffset; +} + #if 0 SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeSubObjectRangeIndex(SlangReflectionTypeLayout* inTypeLayout, SlangInt index) diff --git a/source/slang/slang-type-layout.h b/source/slang/slang-type-layout.h index c4df46fe0..88ba72003 100644 --- a/source/slang/slang-type-layout.h +++ b/source/slang/slang-type-layout.h @@ -437,6 +437,7 @@ public: struct SubObjectRangeInfo { Int bindingRangeIndex; + Int spaceOffset; }; List<RefPtr<DescriptorSetInfo>> m_descriptorSets; diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp index f5dbcc0a7..a011f2760 100644 --- a/tools/gfx/d3d11/render-d3d11.cpp +++ b/tools/gfx/d3d11/render-d3d11.cpp @@ -265,20 +265,9 @@ protected: float m_clearValue[4]; }; - class FramebufferLayoutImpl - : public IFramebufferLayout - , public ComObject + class FramebufferLayoutImpl : public FramebufferLayoutBase { public: - SLANG_COM_OBJECT_IUNKNOWN_ALL - IFramebufferLayout* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout) - return static_cast<IFramebufferLayout*>(this); - return nullptr; - } - - public: ShortList<IFramebufferLayout::AttachmentLayout> m_renderTargets; bool m_hasDepthStencil = false; IFramebufferLayout::AttachmentLayout m_depthStencil; @@ -345,17 +334,9 @@ protected: } }; - class InputLayoutImpl: public IInputLayout, public ComObject + class InputLayoutImpl: public InputLayoutBase { public: - SLANG_COM_OBJECT_IUNKNOWN_ALL - IInputLayout* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IInputLayout) - return static_cast<IInputLayout*>(this); - return nullptr; - } - public: ComPtr<ID3D11InputLayout> m_layout; }; diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index e02f7d656..5026ad111 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -257,20 +257,9 @@ public: } }; - class FramebufferLayoutImpl - : public IFramebufferLayout - , public ComObject + class FramebufferLayoutImpl : public FramebufferLayoutBase { public: - SLANG_COM_OBJECT_IUNKNOWN_ALL - IFramebufferLayout* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout) - return static_cast<IFramebufferLayout*>(this); - return nullptr; - } - - public: ShortList<IFramebufferLayout::AttachmentLayout> m_renderTargets; bool m_hasDepthStencil = false; IFramebufferLayout::AttachmentLayout m_depthStencil; @@ -313,17 +302,9 @@ public: } }; - class InputLayoutImpl: public IInputLayout, public ComObject + class InputLayoutImpl : public InputLayoutBase { public: - SLANG_COM_OBJECT_IUNKNOWN_ALL - IInputLayout* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IInputLayout) - return static_cast<IInputLayout*>(this); - return nullptr; - } - public: List<D3D12_INPUT_ELEMENT_DESC> m_elements; List<char> m_text; ///< Holds all strings to keep in scope }; @@ -1033,6 +1014,35 @@ public: return result; } + Result addDescriptorRange( + Index physicalDescriptorSetIndex, + D3D12_DESCRIPTOR_RANGE_TYPE rangeType, + UINT registerIndex, + UINT spaceIndex, + UINT count) + { + auto& descriptorSet = m_descriptorSets[physicalDescriptorSetIndex]; + + D3D12_DESCRIPTOR_RANGE range = {}; + range.RangeType = rangeType; + range.NumDescriptors = count; + range.BaseShaderRegister = registerIndex; + range.RegisterSpace = spaceIndex; + range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + if (range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER) + { + descriptorSet.m_samplerRanges.add(range); + descriptorSet.m_samplerCount += range.NumDescriptors; + } + else + { + descriptorSet.m_resourceRanges.add(range); + descriptorSet.m_resourceCount += range.NumDescriptors; + } + + return SLANG_OK; + } /// Add one descriptor range as specified in Slang reflection information to the layout. /// /// The layout information is taken from `typeLayout` for the descriptor @@ -1056,8 +1066,6 @@ public: Index logicalDescriptorSetIndex, Index descriptorRangeIndex) { - auto& descriptorSet = m_descriptorSets[physicalDescriptorSetIndex]; - auto bindingType = typeLayout->getDescriptorSetDescriptorRangeType(logicalDescriptorSetIndex, descriptorRangeIndex); auto count = typeLayout->getDescriptorSetDescriptorRangeDescriptorCount(logicalDescriptorSetIndex, descriptorRangeIndex); auto index = typeLayout->getDescriptorSetDescriptorRangeIndexOffset(logicalDescriptorSetIndex, descriptorRangeIndex); @@ -1066,25 +1074,12 @@ public: D3D12_DESCRIPTOR_RANGE_TYPE rangeType; SLANG_RETURN_ON_FAIL(translateDescriptorRangeType(bindingType, &rangeType)); - D3D12_DESCRIPTOR_RANGE range = {}; - range.RangeType = rangeType; - range.NumDescriptors = (UINT) count; - range.BaseShaderRegister = (UINT) index + offset[rangeType]; - range.RegisterSpace = (UINT) space; - range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - - if (range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER) - { - descriptorSet.m_samplerRanges.add(range); - descriptorSet.m_samplerCount += range.NumDescriptors; - } - else - { - descriptorSet.m_resourceRanges.add(range); - descriptorSet.m_resourceCount += range.NumDescriptors; - } - - return SLANG_OK; + return addDescriptorRange( + physicalDescriptorSetIndex, + rangeType, + (UINT)index + offset[rangeType], + (UINT)space, + (UINT)count); } /// Add one binding range to the computed layout. @@ -1196,14 +1191,11 @@ public: addBindingRange(typeLayout, physicalDescriptorSetIndex, offset, bindingRangeIndex); } - // Next we need to recurse on the various sub-objects that the type might contain. + // Next we need to add any sub binding ranges in `ConstantBuffer` bindings. // Index subObjectCount = typeLayout->getSubObjectRangeCount(); for (Index subObjectRangeIndex = 0; subObjectRangeIndex < subObjectCount; subObjectRangeIndex++) { - // There are a few different concerns being tackled at once here, which depend on - // the type of each sub-object range. - // auto bindingRangeIndex = typeLayout->getSubObjectRangeBindingRangeIndex(subObjectRangeIndex); auto bindingType = typeLayout->getBindingRangeType(bindingRangeIndex); switch (bindingType) @@ -1221,55 +1213,116 @@ public: // guarantee that the descritpors used by non-sub-object binding ranges are all // contiguous. // - addBindingRange(typeLayout, physicalDescriptorSetIndex, offset, bindingRangeIndex); + // This call will add all descriptor ranges reported in `typeLayout` that is associated + // with `bindingRangeIndex`. + // + addBindingRange( + typeLayout, + physicalDescriptorSetIndex, + offset, + bindingRangeIndex); + + // We also need to recurse into the element type of the constant buffer to add + // any binding ranges defined in the element type. + auto subObjectType = + typeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex); + BindingRegisterOffset subOffset; + subOffset.spaceOffset = + offset.spaceOffset + + (uint32_t)typeLayout->getSubObjectRangeSpaceOffset( + subObjectRangeIndex); + addParameterBlocks( + _unwrapParameterGroups(subObjectType), + physicalDescriptorSetIndex, + subOffset); } break; + default: + break; + } + } + + addParameterBlocks(typeLayout, physicalDescriptorSetIndex, offset); + } + /// Add child parameter blocks defined in `typeLayout` to the root signature. + void addParameterBlocks( + slang::TypeLayoutReflection* typeLayout, + Index physicalDescriptorSetIndex, + BindingRegisterOffset const& offset) + { + Index subObjectCount = typeLayout->getSubObjectRangeCount(); + for (Index subObjectRangeIndex = 0; subObjectRangeIndex < subObjectCount; + subObjectRangeIndex++) + { + // There are a few different concerns being tackled at once here, which depend + // on the type of each sub-object range. + // + auto bindingRangeIndex = + typeLayout->getSubObjectRangeBindingRangeIndex(subObjectRangeIndex); + auto bindingType = typeLayout->getBindingRangeType(bindingRangeIndex); + switch (bindingType) + { case slang::BindingType::ParameterBlock: { - // A parameter block (`ParameterBlock<ConcreteType>`) will always map to a distinct - // descriptor set, and its contained view/sampler binding ranges will be bound - // through that set. + // A parameter block (`ParameterBlock<ConcreteType>`) will always map to + // a distinct descriptor set, and its contained view/sampler binding + // ranges will be bound through that set. // auto blockPhysicalDescriptorSetIndex = addDescriptorSet(); - // We will need to recursively add the binding ranges implied by the type of - // the parameter block. + // We will need to recursively add the binding ranges implied by the + // type of the parameter block. // - auto blockTypeLayout = typeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex); - - // One important detail is that the `blockTypeLayout` does not know the base register - // space that the contents of the block should use. All descriptor ranges stored in - // that layout will by default use a space offset of zero. + auto blockTypeLayout = + typeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex); + + // One important detail is that the `blockTypeLayout` does not know the + // base register space that the contents of the block should use. All + // descriptor ranges stored in that layout will by default use a space + // offset of zero. // - // We need to compute the space offset to apply when recursing into that block type - // based on the binding range we are processing here. + // We need to compute the space offset to apply when recursing into that + // block type based on the binding range we are processing here. // - auto blockLogicalDescriptorSetIndex = typeLayout->getBindingRangeDescriptorSetIndex(bindingRangeIndex); - auto blockSpaceOffset = typeLayout->getDescriptorSetSpaceOffset(blockLogicalDescriptorSetIndex); - - // The space offset for this binding range should be added to any additional space - // offset that was being passed down from above this layer. + auto spaceOffset = + typeLayout->getSubObjectRangeSpaceOffset(subObjectRangeIndex); + // The space offset for this binding range should be added to any + // additional space offset that was being passed down from above this + // layer. // - // Any other offset information (register offsets) should be ignored at this point, - // because `register` offsets from outside of the block don't affect layout within - // the block. + // Any other offset information (register offsets) should be ignored at + // this point, because `register` offsets from outside of the block + // don't affect layout within the block. // BindingRegisterOffset blockOffset; - blockOffset.spaceOffset = offset.spaceOffset + (uint32_t) blockSpaceOffset; - - // Once we have all the details worked out, we can write the binding ranges for the - // block's type into the newly-allocated descriptor set. - // - // Note: there is an important subtlety going on here. We are passing in the type - // `blockTypeLayout` which corresponds to `ParameterBlock<ConcreteType>` and *not* to - // `ConcreteType` alone. Because of that detail, the binding/descriptor ranges will - // include any "default constant buffer" range that needed to be allocated based - // on `ConcreteType`. - // - // TODO: validate that this logic is right. + blockOffset.spaceOffset = offset.spaceOffset + (uint32_t)spaceOffset; + + // Note: there is an important subtlety going on here. We are passing in + // the type `blockTypeLayout` which corresponds to + // `ParameterBlock<ConcreteType>` and *not* to `ConcreteType` alone. + // We call `_unwrapParameterGroups` on `blockTypeLayout` get the layout + // for the element type. + auto elementLayout = _unwrapParameterGroups(blockTypeLayout); + + // If the element type requires constant buffer storage, add an + // implicit constant buffer descriptor in descriptor set. + if (elementLayout->getSize(SLANG_PARAMETER_CATEGORY_UNIFORM) != 0) + { + addDescriptorRange( + blockPhysicalDescriptorSetIndex, + D3D12_DESCRIPTOR_RANGE_TYPE_CBV, + 0, + blockOffset.spaceOffset, + 1); + blockOffset.offsetForRangeType[D3D12_DESCRIPTOR_RANGE_TYPE_CBV] = 1; + } + + // Once we have all the details worked out, we can write the binding + // ranges for the block's type into the newly-allocated descriptor set. // - addBindingRangesAndParameterBlocks(blockTypeLayout, blockPhysicalDescriptorSetIndex, blockOffset); + addBindingRangesAndParameterBlocks( + elementLayout, blockPhysicalDescriptorSetIndex, blockOffset); } break; @@ -2521,7 +2574,7 @@ public: if (uuid == GfxGUID::IID_ISlangUnknown || uuid == GfxGUID::IID_ICommandEncoder || uuid == GfxGUID::IID_IRenderCommandEncoder) { - returnComPtr(outObject, static_cast<IRenderCommandEncoder*>(this)); + *outObject = static_cast<IRenderCommandEncoder*>(this); return SLANG_OK; } *outObject = nullptr; @@ -2903,7 +2956,7 @@ public: if (uuid == GfxGUID::IID_ISlangUnknown || uuid == GfxGUID::IID_ICommandEncoder || uuid == GfxGUID::IID_IComputeCommandEncoder) { - returnComPtr(outObject, static_cast<IComputeCommandEncoder*>(this)); + *outObject = static_cast<IComputeCommandEncoder*>(this); return SLANG_OK; } *outObject = nullptr; @@ -4804,7 +4857,7 @@ Result D3D12Device::createProgram(const IShaderProgram::Desc& desc, IShaderProgr (SlangInt)i, 0, kernelCode.writeRef(), diagnostics.writeRef()); if (diagnostics) { - printf("%s\n", diagnostics->getBufferPointer()); + printf("%s\n", (char*)diagnostics->getBufferPointer()); // TODO: report compile error. } SLANG_RETURN_ON_FAIL(compileResult); diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp index c0b739096..fb8502485 100644 --- a/tools/gfx/open-gl/render-gl.cpp +++ b/tools/gfx/open-gl/render-gl.cpp @@ -201,17 +201,9 @@ public: GLsizei offset; }; - class InputLayoutImpl: public IInputLayout, public ComObject + class InputLayoutImpl : public InputLayoutBase { public: - SLANG_COM_OBJECT_IUNKNOWN_ALL - IInputLayout* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IInputLayout) - return static_cast<IInputLayout*>(this); - return nullptr; - } - public: VertexAttributeDesc m_attributes[kMaxVertexStreams]; UInt m_attributeCount = 0; }; @@ -329,20 +321,9 @@ public: GLuint m_bufferID; }; - class FramebufferLayoutImpl - : public IFramebufferLayout - , public ComObject + class FramebufferLayoutImpl : public FramebufferLayoutBase { public: - SLANG_COM_OBJECT_IUNKNOWN_ALL - IFramebufferLayout* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout) - return static_cast<IFramebufferLayout*>(this); - return nullptr; - } - - public: ShortList<IFramebufferLayout::AttachmentLayout> m_renderTargets; bool m_hasDepthStencil = false; IFramebufferLayout::AttachmentLayout m_depthStencil; diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp index 333f1df54..2a12b777c 100644 --- a/tools/gfx/renderer-shared.cpp +++ b/tools/gfx/renderer-shared.cpp @@ -183,6 +183,20 @@ IShaderProgram* gfx::ShaderProgramBase::getInterface(const Guid& guid) return nullptr; } +IInputLayout* gfx::InputLayoutBase::getInterface(const Guid& guid) +{ + if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IInputLayout) + return static_cast<IInputLayout*>(this); + return nullptr; +} + +IFramebufferLayout* gfx::FramebufferLayoutBase::getInterface(const Guid& guid) +{ + if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout) + return static_cast<IFramebufferLayout*>(this); + return nullptr; +} + IPipelineState* gfx::PipelineStateBase::getInterface(const Guid& guid) { if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IPipelineState) @@ -197,6 +211,14 @@ void PipelineStateBase::initializeBase(const PipelineStateDesc& inDesc) auto program = desc.getProgram(); m_program = program; isSpecializable = (program->slangProgram && program->slangProgram->getSpecializationParamCount() != 0); + + // Hold a strong reference to inputLayout and framebufferLayout objects to prevent it from + // destruction. + if (inDesc.type == PipelineType::Graphics) + { + inputLayout = static_cast<InputLayoutBase*>(inDesc.graphics.inputLayout); + framebufferLayout = static_cast<FramebufferLayoutBase*>(inDesc.graphics.framebufferLayout); + } } IDevice* gfx::RendererBase::getInterface(const Guid& guid) diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h index ec33a3054..b19e0539b 100644 --- a/tools/gfx/renderer-shared.h +++ b/tools/gfx/renderer-shared.h @@ -395,6 +395,24 @@ public: ComPtr<slang::IComponentType> slangProgram; }; +class InputLayoutBase + : public IInputLayout + , public Slang::ComObject +{ +public: + SLANG_COM_OBJECT_IUNKNOWN_ALL + IInputLayout* getInterface(const Slang::Guid& guid); +}; + +class FramebufferLayoutBase + : public IFramebufferLayout + , public Slang::ComObject +{ +public: + SLANG_COM_OBJECT_IUNKNOWN_ALL + IFramebufferLayout* getInterface(const Slang::Guid& guid); +}; + class PipelineStateBase : public IPipelineState , public Slang::ComObject @@ -414,6 +432,11 @@ public: } } desc; + // We need to hold inputLayout and framebufferLayout objects alive, since we may use it to + // create specialized pipeline states later. + Slang::RefPtr<InputLayoutBase> inputLayout; + Slang::RefPtr<FramebufferLayoutBase> framebufferLayout; + // The pipeline state from which this pipeline state is specialized. // If null, this pipeline is either an unspecialized pipeline. Slang::RefPtr<PipelineStateBase> unspecializedPipelineState = nullptr; diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 2ce51790a..315c8d7ce 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -153,17 +153,9 @@ public: const VulkanApi* m_api; }; - class InputLayoutImpl : public IInputLayout, public ComObject + class InputLayoutImpl : public InputLayoutBase { public: - SLANG_COM_OBJECT_IUNKNOWN_ALL - IInputLayout* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IInputLayout) - return static_cast<IInputLayout*>(this); - return nullptr; - } - public: List<VkVertexInputAttributeDescription> m_vertexDescs; int m_vertexSize; }; @@ -310,20 +302,9 @@ public: VkDeviceSize size; }; - class FramebufferLayoutImpl - : public IFramebufferLayout - , public ComObject + class FramebufferLayoutImpl : public FramebufferLayoutBase { public: - SLANG_COM_OBJECT_IUNKNOWN_ALL - IFramebufferLayout* getInterface(const Guid& guid) - { - if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout) - return static_cast<IFramebufferLayout*>(this); - return nullptr; - } - - public: VkRenderPass m_renderPass; RefPtr<VKDevice> m_renderer; Array<VkAttachmentDescription, kMaxAttachments> m_attachmentDescs; diff --git a/tools/platform/windows/win-window.cpp b/tools/platform/windows/win-window.cpp index 0d80eda7b..a0175a911 100644 --- a/tools/platform/windows/win-window.cpp +++ b/tools/platform/windows/win-window.cpp @@ -294,6 +294,8 @@ void Application::run(Window* mainWindow, bool waitForEvents) while (!Win32AppContext::isTerminated) { doEventsImpl(waitForEvents); + if (Win32AppContext::isTerminated) + break; if (mainWindow) { mainWindow->events.mainLoop(); @@ -343,14 +345,7 @@ public: Win32AppContext::windows[handle] = this; } - ~Win32PlatformWindow() - { - if (handle) - { - Win32AppContext::windows.Remove(handle); - } - DestroyWindow(handle); - } + ~Win32PlatformWindow() { close(); } virtual void setClientSize(uint32_t width, uint32_t height) override { @@ -401,7 +396,15 @@ public: MoveWindow(handle, left, top, width, height, FALSE); } - virtual void close() override {} + virtual void close() override + { + if (handle) + { + Win32AppContext::windows.Remove(handle); + } + DestroyWindow(handle); + handle = NULL; + } virtual bool getFocused() override { return GetFocus() == handle; } virtual bool getVisible() override { return visible; } virtual WindowHandle getNativeHandle() override |
