summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-04-20 13:17:29 -0700
committerGitHub <noreply@github.com>2021-04-20 13:17:29 -0700
commit34fba7b5e726136c6eee8a318ab9a75381399c00 (patch)
tree39a496c7052256cef9b089b78ab4bd48316571bd
parent6bba674f9d732eccc27dcf004611e6a8eb9bc14e (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.cpp36
-rw-r--r--examples/model-viewer/shaders.slang3
-rw-r--r--slang.h8
-rw-r--r--source/slang/slang-legalize-types.cpp5
-rw-r--r--source/slang/slang-reflection-api.cpp25
-rw-r--r--source/slang/slang-type-layout.h1
-rw-r--r--tools/gfx/d3d11/render-d3d11.cpp23
-rw-r--r--tools/gfx/d3d12/render-d3d12.cpp219
-rw-r--r--tools/gfx/open-gl/render-gl.cpp23
-rw-r--r--tools/gfx/renderer-shared.cpp22
-rw-r--r--tools/gfx/renderer-shared.h23
-rw-r--r--tools/gfx/vulkan/render-vk.cpp23
-rw-r--r--tools/platform/windows/win-window.cpp21
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);
}
diff --git a/slang.h b/slang.h
index 060ac2dce..df0a783be 100644
--- a/slang.h
+++ b/slang.h
@@ -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