summaryrefslogtreecommitdiffstats
path: root/tools/gfx/debug-layer
diff options
context:
space:
mode:
authorlucy96chen <47800040+lucy96chen@users.noreply.github.com>2022-08-04 16:59:28 -0700
committerGitHub <noreply@github.com>2022-08-04 16:59:28 -0700
commit12a846e8facf090aaeb68fcabf55867f5eaed747 (patch)
treecc7c70c447200c1b45f20efc47e43e17828ec84d /tools/gfx/debug-layer
parent11b29eff99910d55a54658b8a1d053cc4ec076fc (diff)
Split debug-layer into smaller files (#2344)
* checkpoint commit * debug-layer split, does not compile * Almost compiles, rebasing before making any further changes * everything compiles and passes tests locally * Added tools/gfx/debug-layer to premake and ran premake Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'tools/gfx/debug-layer')
-rw-r--r--tools/gfx/debug-layer/debug-base.h74
-rw-r--r--tools/gfx/debug-layer/debug-buffer.cpp67
-rw-r--r--tools/gfx/debug-layer/debug-buffer.h34
-rw-r--r--tools/gfx/debug-layer/debug-command-buffer.cpp153
-rw-r--r--tools/gfx/debug-layer/debug-command-buffer.h54
-rw-r--r--tools/gfx/debug-layer/debug-command-encoder.cpp498
-rw-r--r--tools/gfx/debug-layer/debug-command-encoder.h253
-rw-r--r--tools/gfx/debug-layer/debug-command-queue.cpp77
-rw-r--r--tools/gfx/debug-layer/debug-command-queue.h29
-rw-r--r--tools/gfx/debug-layer/debug-device.cpp598
-rw-r--r--tools/gfx/debug-layer/debug-device.h147
-rw-r--r--tools/gfx/debug-layer/debug-fence.cpp38
-rw-r--r--tools/gfx/debug-layer/debug-fence.h24
-rw-r--r--tools/gfx/debug-layer/debug-framebuffer.h32
-rw-r--r--tools/gfx/debug-layer/debug-helper-functions.cpp156
-rw-r--r--tools/gfx/debug-layer/debug-helper-functions.h172
-rw-r--r--tools/gfx/debug-layer/debug-pipeline-state.cpp20
-rw-r--r--tools/gfx/debug-layer/debug-pipeline-state.h23
-rw-r--r--tools/gfx/debug-layer/debug-query.cpp29
-rw-r--r--tools/gfx/debug-layer/debug-query.h26
-rw-r--r--tools/gfx/debug-layer/debug-render-pass.h22
-rw-r--r--tools/gfx/debug-layer/debug-resource-views.cpp49
-rw-r--r--tools/gfx/debug-layer/debug-resource-views.h37
-rw-r--r--tools/gfx/debug-layer/debug-sampler-state.cpp21
-rw-r--r--tools/gfx/debug-layer/debug-sampler-state.h24
-rw-r--r--tools/gfx/debug-layer/debug-shader-object.cpp184
-rw-r--r--tools/gfx/debug-layer/debug-shader-object.h101
-rw-r--r--tools/gfx/debug-layer/debug-shader-program.cpp17
-rw-r--r--tools/gfx/debug-layer/debug-shader-program.h27
-rw-r--r--tools/gfx/debug-layer/debug-shader-table.h20
-rw-r--r--tools/gfx/debug-layer/debug-swap-chain.cpp93
-rw-r--r--tools/gfx/debug-layer/debug-swap-chain.h38
-rw-r--r--tools/gfx/debug-layer/debug-texture.cpp45
-rw-r--r--tools/gfx/debug-layer/debug-texture.h29
-rw-r--r--tools/gfx/debug-layer/debug-transient-heap.cpp40
-rw-r--r--tools/gfx/debug-layer/debug-transient-heap.h26
-rw-r--r--tools/gfx/debug-layer/debug-vertex-layout.h22
37 files changed, 3299 insertions, 0 deletions
diff --git a/tools/gfx/debug-layer/debug-base.h b/tools/gfx/debug-layer/debug-base.h
new file mode 100644
index 000000000..aa269cc7b
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-base.h
@@ -0,0 +1,74 @@
+// debug-base.h
+#pragma once
+
+#include "slang-gfx.h"
+#include "slang-com-ptr.h"
+#include "core/slang-com-object.h"
+#include "../command-encoder-com-forward.h"
+#include "../renderer-shared.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+ class DebugObjectBase : public Slang::ComObject
+ {
+ public:
+ uint64_t uid;
+ DebugObjectBase()
+ {
+ static uint64_t uidCounter = 0;
+ uid = ++uidCounter;
+ }
+ };
+
+ template<typename TInterface>
+ class DebugObject
+ : public TInterface
+ , public DebugObjectBase
+ {
+ public:
+ Slang::ComPtr<TInterface> baseObject;
+ };
+
+ template <typename TInterface>
+ class UnownedDebugObject
+ : public TInterface
+ , public DebugObjectBase
+ {
+ public:
+ TInterface* baseObject = nullptr;
+ };
+
+ class DebugDevice;
+ class DebugShaderTable;
+ class DebugQueryPool;
+ class DebugBufferResource;
+ class DebugTextureResource;
+ class DebugResourceView;
+ class DebugAccelerationStructure;
+ class DebugSamplerState;
+ class DebugShaderObject;
+ class DebugRootShaderObject;
+ class DebugCommandBuffer;
+ class DebugResourceCommandEncoderImpl;
+ class DebugComputeCommandEncoder;
+ class DebugResourceCommandEncoder;
+ class DebugRenderCommandEncoder;
+ class DebugRayTracingCommandEncoder;
+ class DebugFence;
+ class DebugCommandQueue;
+ class DebugFramebuffer;
+ class DebugFramebufferLayout;
+ class DebugInputLayout;
+ class DebugPipelineState;
+ class DebugRenderPassLayout;
+ class DebugShaderProgram;
+ class DebugTransientResourceHeap;
+ class DebugSwapchain;
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-buffer.cpp b/tools/gfx/debug-layer/debug-buffer.cpp
new file mode 100644
index 000000000..19a5e4716
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-buffer.cpp
@@ -0,0 +1,67 @@
+// debug-buffer.cpp
+#include "debug-buffer.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+IResource::Type DebugBufferResource::getType()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getType();
+}
+
+IBufferResource::Desc* DebugBufferResource::getDesc()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getDesc();
+}
+
+DeviceAddress DebugBufferResource::getDeviceAddress()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getDeviceAddress();
+}
+
+Result DebugBufferResource::getNativeResourceHandle(InteropHandle* outHandle)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getNativeResourceHandle(outHandle);
+}
+
+Result DebugBufferResource::getSharedHandle(InteropHandle* outHandle)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getSharedHandle(outHandle);
+}
+
+Result DebugBufferResource::setDebugName(const char* name)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->setDebugName(name);
+}
+
+const char* DebugBufferResource::getDebugName()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getDebugName();
+}
+
+Result DebugBufferResource::map(MemoryRange* rangeToRead, void** outPointer)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->map(rangeToRead, outPointer);
+}
+
+Result DebugBufferResource::unmap(MemoryRange* writtenRange)
+{
+ return baseObject->unmap(writtenRange);
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-buffer.h b/tools/gfx/debug-layer/debug-buffer.h
new file mode 100644
index 000000000..56c79c3d5
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-buffer.h
@@ -0,0 +1,34 @@
+// debug-buffer.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugBufferResource : public DebugObject<IBufferResource>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ IBufferResource* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW Type SLANG_MCALL getType() override;
+ virtual SLANG_NO_THROW Desc* SLANG_MCALL getDesc() override;
+ virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override;
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) override;
+ virtual SLANG_NO_THROW const char* SLANG_MCALL getDebugName() override;
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ map(MemoryRange* rangeToRead, void** outPointer) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL unmap(MemoryRange* writtenRange) override;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-command-buffer.cpp b/tools/gfx/debug-layer/debug-command-buffer.cpp
new file mode 100644
index 000000000..3785bcd43
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-command-buffer.cpp
@@ -0,0 +1,153 @@
+// debug-command-buffer.cpp
+#include "debug-command-buffer.h"
+
+#include "debug-framebuffer.h"
+#include "debug-render-pass.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+DebugCommandBuffer::DebugCommandBuffer()
+{
+ SLANG_GFX_API_FUNC;
+ m_renderCommandEncoder.commandBuffer = this;
+ m_computeCommandEncoder.commandBuffer = this;
+ m_resourceCommandEncoder.commandBuffer = this;
+ m_rayTracingCommandEncoder.commandBuffer = this;
+}
+
+void DebugCommandBuffer::encodeRenderCommands(
+ IRenderPassLayout* renderPass,
+ IFramebuffer* framebuffer,
+ IRenderCommandEncoder** outEncoder)
+{
+ SLANG_GFX_API_FUNC;
+ checkCommandBufferOpenWhenCreatingEncoder();
+ checkEncodersClosedBeforeNewEncoder();
+ auto innerRenderPass =
+ renderPass ? static_cast<DebugRenderPassLayout*>(renderPass)->baseObject : nullptr;
+ auto innerFramebuffer =
+ framebuffer ? static_cast<DebugFramebuffer*>(framebuffer)->baseObject : nullptr;
+ m_renderCommandEncoder.isOpen = true;
+ baseObject->encodeRenderCommands(
+ innerRenderPass, innerFramebuffer, &m_renderCommandEncoder.baseObject);
+ if (m_renderCommandEncoder.baseObject)
+ *outEncoder = &m_renderCommandEncoder;
+ else
+ *outEncoder = nullptr;
+}
+
+void DebugCommandBuffer::encodeComputeCommands(IComputeCommandEncoder** outEncoder)
+{
+ SLANG_GFX_API_FUNC;
+ checkCommandBufferOpenWhenCreatingEncoder();
+ checkEncodersClosedBeforeNewEncoder();
+ m_computeCommandEncoder.isOpen = true;
+ baseObject->encodeComputeCommands(&m_computeCommandEncoder.baseObject);
+ if (m_computeCommandEncoder.baseObject)
+ {
+ *outEncoder = &m_computeCommandEncoder;
+ }
+ else
+ {
+ *outEncoder = nullptr;
+ }
+}
+
+void DebugCommandBuffer::encodeResourceCommands(IResourceCommandEncoder** outEncoder)
+{
+ SLANG_GFX_API_FUNC;
+ checkCommandBufferOpenWhenCreatingEncoder();
+ checkEncodersClosedBeforeNewEncoder();
+ m_resourceCommandEncoder.isOpen = true;
+ baseObject->encodeResourceCommands(&m_resourceCommandEncoder.baseObject);
+ if (m_resourceCommandEncoder.baseObject)
+ {
+ *outEncoder = &m_resourceCommandEncoder;
+ }
+ else
+ {
+ *outEncoder = nullptr;
+ }
+}
+
+void DebugCommandBuffer::encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder)
+{
+ SLANG_GFX_API_FUNC;
+ checkCommandBufferOpenWhenCreatingEncoder();
+ checkEncodersClosedBeforeNewEncoder();
+ m_rayTracingCommandEncoder.isOpen = true;
+ baseObject->encodeRayTracingCommands(&m_rayTracingCommandEncoder.baseObject);
+ if (m_rayTracingCommandEncoder.baseObject)
+ {
+ *outEncoder = &m_rayTracingCommandEncoder;
+ }
+ else
+ {
+ *outEncoder = nullptr;
+ }
+}
+
+void DebugCommandBuffer::close()
+{
+ SLANG_GFX_API_FUNC;
+ if (!isOpen)
+ {
+ GFX_DIAGNOSE_ERROR("command buffer is already closed.");
+ }
+ if (m_renderCommandEncoder.isOpen)
+ {
+ GFX_DIAGNOSE_ERROR(
+ "A render command encoder on this command buffer is still open. "
+ "IRenderCommandEncoder::endEncoding() must be called before closing a command buffer.");
+ }
+ if (m_computeCommandEncoder.isOpen)
+ {
+ GFX_DIAGNOSE_ERROR(
+ "A compute command encoder on this command buffer is still open. "
+ "IComputeCommandEncoder::endEncoding() must be called before closing a command buffer.");
+ }
+ if (m_resourceCommandEncoder.isOpen)
+ {
+ GFX_DIAGNOSE_ERROR(
+ "A resource command encoder on this command buffer is still open. "
+ "IResourceCommandEncoder::endEncoding() must be called before closing a command buffer.");
+ }
+ isOpen = false;
+ baseObject->close();
+}
+
+Result DebugCommandBuffer::getNativeHandle(InteropHandle* outHandle)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getNativeHandle(outHandle);
+}
+
+void DebugCommandBuffer::checkEncodersClosedBeforeNewEncoder()
+{
+ if (m_renderCommandEncoder.isOpen || m_resourceCommandEncoder.isOpen ||
+ m_computeCommandEncoder.isOpen)
+ {
+ GFX_DIAGNOSE_ERROR(
+ "A previouse command encoder created on this command buffer is still open. "
+ "endEncoding() must be called on the encoder before creating an encoder.");
+ }
+}
+
+void DebugCommandBuffer::checkCommandBufferOpenWhenCreatingEncoder()
+{
+ if (!isOpen)
+ {
+ GFX_DIAGNOSE_ERROR("The command buffer is already closed. Encoders can only be retrieved "
+ "while the command buffer is open.");
+ }
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-command-buffer.h b/tools/gfx/debug-layer/debug-command-buffer.h
new file mode 100644
index 000000000..d7633960b
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-command-buffer.h
@@ -0,0 +1,54 @@
+// debug-command-buffer.h
+#pragma once
+#include "debug-base.h"
+
+#include "debug-command-encoder.h"
+#include "debug-shader-object.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugCommandBuffer : public DebugObject<ICommandBuffer>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ DebugTransientResourceHeap* m_transientHeap;
+
+private:
+ DebugRenderCommandEncoder m_renderCommandEncoder;
+ DebugComputeCommandEncoder m_computeCommandEncoder;
+ DebugResourceCommandEncoder m_resourceCommandEncoder;
+ DebugRayTracingCommandEncoder m_rayTracingCommandEncoder;
+
+public:
+ DebugCommandBuffer();
+ ICommandBuffer* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW void SLANG_MCALL encodeRenderCommands(
+ IRenderPassLayout* renderPass,
+ IFramebuffer* framebuffer,
+ IRenderCommandEncoder** outEncoder) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ encodeComputeCommands(IComputeCommandEncoder** outEncoder) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ encodeResourceCommands(IResourceCommandEncoder** outEncoder) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL close() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
+
+private:
+ void checkEncodersClosedBeforeNewEncoder();
+ void checkCommandBufferOpenWhenCreatingEncoder();
+public:
+ DebugRootShaderObject rootObject;
+ bool isOpen = true;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-command-encoder.cpp b/tools/gfx/debug-layer/debug-command-encoder.cpp
new file mode 100644
index 000000000..c2d146a8b
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-command-encoder.cpp
@@ -0,0 +1,498 @@
+// debug-command-encoder.cpp
+#include "debug-command-encoder.h"
+
+#include "debug-buffer.h"
+#include "debug-command-buffer.h"
+#include "debug-pipeline-state.h"
+#include "debug-query.h"
+#include "debug-resource-views.h"
+#include "debug-texture.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+void DebugComputeCommandEncoder::endEncoding()
+{
+ SLANG_GFX_API_FUNC;
+ isOpen = false;
+ baseObject->endEncoding();
+}
+
+Result DebugComputeCommandEncoder::bindPipeline(
+ IPipelineState* state,
+ IShaderObject** outRootShaderObject)
+{
+ SLANG_GFX_API_FUNC;
+
+ auto innerState = static_cast<DebugPipelineState*>(state)->baseObject;
+ IShaderObject* innerRootObject = nullptr;
+ commandBuffer->rootObject.reset();
+ auto result = baseObject->bindPipeline(innerState, &innerRootObject);
+ commandBuffer->rootObject.baseObject.attach(innerRootObject);
+ *outRootShaderObject = &commandBuffer->rootObject;
+ return result;
+}
+
+Result DebugComputeCommandEncoder::bindPipelineWithRootObject(
+ IPipelineState* state, IShaderObject* rootObject)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->bindPipelineWithRootObject(getInnerObj(state), getInnerObj(rootObject));
+}
+
+void DebugComputeCommandEncoder::dispatchCompute(int x, int y, int z)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->dispatchCompute(x, y, z);
+}
+
+void DebugComputeCommandEncoder::dispatchComputeIndirect(
+ IBufferResource* cmdBuffer, Offset offset)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->dispatchComputeIndirect(getInnerObj(cmdBuffer), offset);
+}
+
+void DebugRenderCommandEncoder::endEncoding()
+{
+ SLANG_GFX_API_FUNC;
+ isOpen = false;
+ baseObject->endEncoding();
+}
+
+Result DebugRenderCommandEncoder::bindPipeline(
+ IPipelineState* state,
+ IShaderObject** outRootShaderObject)
+{
+ SLANG_GFX_API_FUNC;
+
+ auto innerState = static_cast<DebugPipelineState*>(state)->baseObject;
+ IShaderObject* innerRootObject = nullptr;
+ commandBuffer->rootObject.reset();
+ auto result = baseObject->bindPipeline(innerState, &innerRootObject);
+ commandBuffer->rootObject.baseObject.attach(innerRootObject);
+ *outRootShaderObject = &commandBuffer->rootObject;
+ return result;
+}
+
+Result DebugRenderCommandEncoder::bindPipelineWithRootObject(
+ IPipelineState* state, IShaderObject* rootObject)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->bindPipelineWithRootObject(getInnerObj(state), getInnerObj(rootObject));
+}
+
+void DebugRenderCommandEncoder::setViewports(GfxCount count, const Viewport* viewports)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->setViewports(count, viewports);
+}
+
+void DebugRenderCommandEncoder::setScissorRects(GfxCount count, const ScissorRect* scissors)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->setScissorRects(count, scissors);
+}
+
+void DebugRenderCommandEncoder::setPrimitiveTopology(PrimitiveTopology topology)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->setPrimitiveTopology(topology);
+}
+
+void DebugRenderCommandEncoder::setVertexBuffers(
+ GfxIndex startSlot,
+ GfxCount slotCount,
+ IBufferResource* const* buffers,
+ const Offset* offsets)
+{
+ SLANG_GFX_API_FUNC;
+
+ List<IBufferResource*> innerBuffers;
+ for (GfxIndex i = 0; i < slotCount; i++)
+ {
+ innerBuffers.add(static_cast<DebugBufferResource*>(buffers[i])->baseObject.get());
+ }
+ baseObject->setVertexBuffers(startSlot, slotCount, innerBuffers.getBuffer(), offsets);
+}
+
+void DebugRenderCommandEncoder::setIndexBuffer(
+ IBufferResource* buffer, Format indexFormat, Offset offset)
+{
+ SLANG_GFX_API_FUNC;
+ auto innerBuffer = static_cast<DebugBufferResource*>(buffer)->baseObject.get();
+ baseObject->setIndexBuffer(innerBuffer, indexFormat, offset);
+}
+
+void DebugRenderCommandEncoder::draw(GfxCount vertexCount, GfxIndex startVertex)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->draw(vertexCount, startVertex);
+}
+
+void DebugRenderCommandEncoder::drawIndexed(
+ GfxCount indexCount, GfxIndex startIndex, GfxIndex baseVertex)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->drawIndexed(indexCount, startIndex, baseVertex);
+}
+
+void DebugRenderCommandEncoder::drawIndirect(
+ GfxCount maxDrawCount,
+ IBufferResource* argBuffer,
+ Offset argOffset,
+ IBufferResource* countBuffer,
+ Offset countOffset)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->drawIndirect(
+ maxDrawCount, getInnerObj(argBuffer), argOffset, getInnerObj(countBuffer), countOffset);
+}
+
+void DebugRenderCommandEncoder::drawIndexedIndirect(
+ GfxCount maxDrawCount,
+ IBufferResource* argBuffer,
+ Offset argOffset,
+ IBufferResource* countBuffer,
+ Offset countOffset)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->drawIndexedIndirect(
+ maxDrawCount, getInnerObj(argBuffer), argOffset, getInnerObj(countBuffer), countOffset);
+}
+
+void DebugRenderCommandEncoder::setStencilReference(uint32_t referenceValue)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->setStencilReference(referenceValue);
+}
+
+Result DebugRenderCommandEncoder::setSamplePositions(
+ GfxCount samplesPerPixel, GfxCount pixelCount, const SamplePosition* samplePositions)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->setSamplePositions(samplesPerPixel, pixelCount, samplePositions);
+}
+
+void DebugRenderCommandEncoder::drawInstanced(
+ GfxCount vertexCount,
+ GfxCount instanceCount,
+ GfxIndex startVertex,
+ GfxIndex startInstanceLocation)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->drawInstanced(
+ vertexCount, instanceCount, startVertex, startInstanceLocation);
+}
+
+void DebugRenderCommandEncoder::drawIndexedInstanced(
+ GfxCount indexCount,
+ GfxCount instanceCount,
+ GfxIndex startIndexLocation,
+ GfxIndex baseVertexLocation,
+ GfxIndex startInstanceLocation)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->drawIndexedInstanced(
+ indexCount, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation);
+}
+
+void DebugResourceCommandEncoder::endEncoding()
+{
+ SLANG_GFX_API_FUNC;
+ isOpen = false;
+ baseObject->endEncoding();
+}
+
+void DebugResourceCommandEncoderImpl::writeTimestamp(IQueryPool* pool, GfxIndex index)
+{
+ SLANG_GFX_API_FUNC;
+ getBaseResourceEncoder()->writeTimestamp(static_cast<DebugQueryPool*>(pool)->baseObject, index);
+}
+
+void DebugResourceCommandEncoderImpl::copyBuffer(
+ IBufferResource* dst,
+ Offset dstOffset,
+ IBufferResource* src,
+ Offset srcOffset,
+ Size size)
+{
+ SLANG_GFX_API_FUNC;
+ auto dstImpl = static_cast<DebugBufferResource*>(dst);
+ auto srcImpl = static_cast<DebugBufferResource*>(src);
+ getBaseResourceEncoder()->copyBuffer(
+ dstImpl->baseObject, dstOffset, srcImpl->baseObject, srcOffset, size);
+}
+
+void DebugResourceCommandEncoderImpl::uploadBufferData(
+ IBufferResource* dst,
+ Offset offset,
+ Size size,
+ void* data)
+{
+ SLANG_GFX_API_FUNC;
+ auto dstImpl = static_cast<DebugBufferResource*>(dst);
+ getBaseResourceEncoder()->uploadBufferData(dstImpl->baseObject, offset, size, data);
+}
+
+void DebugResourceCommandEncoderImpl::textureBarrier(
+ GfxCount count,
+ ITextureResource* const* textures,
+ ResourceState src,
+ ResourceState dst)
+{
+ SLANG_GFX_API_FUNC;
+
+ List<ITextureResource*> innerTextures;
+ for (GfxIndex i = 0; i < count; i++)
+ {
+ innerTextures.add(static_cast<DebugTextureResource*>(textures[i])->baseObject.get());
+ }
+ getBaseResourceEncoder()->textureBarrier(count, innerTextures.getBuffer(), src, dst);
+}
+
+void DebugResourceCommandEncoderImpl::bufferBarrier(
+ GfxCount count,
+ IBufferResource* const* buffers,
+ ResourceState src,
+ ResourceState dst)
+{
+ SLANG_GFX_API_FUNC;
+
+ List<IBufferResource*> innerBuffers;
+ for(GfxIndex i = 0; i < count; i++)
+ {
+ innerBuffers.add(static_cast<DebugBufferResource*>(buffers[i])->baseObject.get());
+ }
+ getBaseResourceEncoder()->bufferBarrier(count, innerBuffers.getBuffer(), src, dst);
+}
+
+void DebugResourceCommandEncoderImpl::copyTexture(
+ ITextureResource* dst,
+ ResourceState dstState,
+ SubresourceRange dstSubresource,
+ ITextureResource::Offset3D dstOffset,
+ ITextureResource* src,
+ ResourceState srcState,
+ SubresourceRange srcSubresource,
+ ITextureResource::Offset3D srcOffset,
+ ITextureResource::Extents extent)
+{
+ SLANG_GFX_API_FUNC;
+ getBaseResourceEncoder()->copyTexture(
+ getInnerObj(dst),
+ dstState,
+ dstSubresource,
+ dstOffset,
+ getInnerObj(src),
+ srcState,
+ srcSubresource,
+ srcOffset,
+ extent);
+}
+
+void DebugResourceCommandEncoderImpl::uploadTextureData(
+ ITextureResource* dst,
+ SubresourceRange subResourceRange,
+ ITextureResource::Offset3D offset,
+ ITextureResource::Extents extent,
+ ITextureResource::SubresourceData* subResourceData,
+ GfxCount subResourceDataCount)
+{
+ SLANG_GFX_API_FUNC;
+ getBaseResourceEncoder()->uploadTextureData(
+ getInnerObj(dst), subResourceRange, offset, extent, subResourceData, subResourceDataCount);
+}
+
+void DebugResourceCommandEncoderImpl::clearResourceView(
+ IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags)
+{
+ SLANG_GFX_API_FUNC;
+ switch (view->getViewDesc()->type)
+ {
+ case IResourceView::Type::DepthStencil:
+ case IResourceView::Type::RenderTarget:
+ case IResourceView::Type::UnorderedAccess:
+ break;
+ default:
+ GFX_DIAGNOSE_ERROR_FORMAT(
+ "Resource view %lld cannot be cleared. Only DepthStencil, "
+ "RenderTarget or UnorderedAccess views can be cleared.",
+ getDebugObj(view)->uid);
+ }
+ getBaseResourceEncoder()->clearResourceView(getInnerObj(view), clearValue, flags);
+}
+
+void DebugResourceCommandEncoderImpl::resolveResource(
+ ITextureResource* source,
+ ResourceState sourceState,
+ SubresourceRange sourceRange,
+ ITextureResource* dest,
+ ResourceState destState,
+ SubresourceRange destRange)
+{
+ SLANG_GFX_API_FUNC;
+ getBaseResourceEncoder()->resolveResource(
+ getInnerObj(source), sourceState, sourceRange, getInnerObj(dest), destState, destRange);
+}
+
+void DebugResourceCommandEncoderImpl::resolveQuery(
+ IQueryPool* queryPool, GfxIndex index, GfxCount count, IBufferResource* buffer, Offset offset)
+{
+ SLANG_GFX_API_FUNC;
+ getBaseResourceEncoder()->resolveQuery(getInnerObj(queryPool), index, count, buffer, offset);
+}
+
+void DebugResourceCommandEncoderImpl::copyTextureToBuffer(
+ IBufferResource* dst,
+ Offset dstOffset,
+ Size dstSize,
+ Size dstRowStride,
+ ITextureResource* src,
+ ResourceState srcState,
+ SubresourceRange srcSubresource,
+ ITextureResource::Offset3D srcOffset,
+ ITextureResource::Extents extent)
+{
+ SLANG_GFX_API_FUNC;
+ getBaseResourceEncoder()->copyTextureToBuffer(
+ getInnerObj(dst), dstOffset, dstSize, dstRowStride, getInnerObj(src), srcState, srcSubresource, srcOffset, extent);
+}
+
+void DebugResourceCommandEncoderImpl::textureSubresourceBarrier(
+ ITextureResource* texture,
+ SubresourceRange subresourceRange,
+ ResourceState src,
+ ResourceState dst)
+{
+ SLANG_GFX_API_FUNC;
+ getBaseResourceEncoder()->textureSubresourceBarrier(
+ getInnerObj(texture), subresourceRange, src, dst);
+}
+
+void DebugResourceCommandEncoderImpl::beginDebugEvent(const char* name, float rgbColor[3])
+{
+ SLANG_GFX_API_FUNC;
+ getBaseResourceEncoder()->beginDebugEvent(name, rgbColor);
+}
+
+void DebugResourceCommandEncoderImpl::endDebugEvent()
+{
+ SLANG_GFX_API_FUNC;
+ getBaseResourceEncoder()->endDebugEvent();
+}
+
+void DebugRayTracingCommandEncoder::endEncoding()
+{
+ SLANG_GFX_API_FUNC;
+ isOpen = false;
+ baseObject->endEncoding();
+}
+
+void DebugRayTracingCommandEncoder::buildAccelerationStructure(
+ const IAccelerationStructure::BuildDesc& desc,
+ GfxCount propertyQueryCount,
+ AccelerationStructureQueryDesc* queryDescs)
+{
+ SLANG_GFX_API_FUNC;
+ IAccelerationStructure::BuildDesc innerDesc = desc;
+ innerDesc.dest = getInnerObj(innerDesc.dest);
+ innerDesc.source = getInnerObj(innerDesc.source);
+ List<AccelerationStructureQueryDesc> innerQueryDescs;
+ innerQueryDescs.addRange(queryDescs, propertyQueryCount);
+ for (auto& innerQueryDesc : innerQueryDescs)
+ {
+ innerQueryDesc.queryPool = getInnerObj(innerQueryDesc.queryPool);
+ }
+ validateAccelerationStructureBuildInputs(desc.inputs);
+ baseObject->buildAccelerationStructure(
+ innerDesc, propertyQueryCount, innerQueryDescs.getBuffer());
+}
+
+void DebugRayTracingCommandEncoder::copyAccelerationStructure(
+ IAccelerationStructure* dest,
+ IAccelerationStructure* src,
+ AccelerationStructureCopyMode mode)
+{
+ SLANG_GFX_API_FUNC;
+ auto innerDest = getInnerObj(dest);
+ auto innerSrc = getInnerObj(src);
+ baseObject->copyAccelerationStructure(innerDest, innerSrc, mode);
+}
+
+void DebugRayTracingCommandEncoder::queryAccelerationStructureProperties(
+ GfxCount accelerationStructureCount,
+ IAccelerationStructure* const* accelerationStructures,
+ GfxCount queryCount,
+ AccelerationStructureQueryDesc* queryDescs)
+{
+ SLANG_GFX_API_FUNC;
+ List<IAccelerationStructure*> innerAS;
+ for (GfxIndex i = 0; i < accelerationStructureCount; i++)
+ {
+ innerAS.add(getInnerObj(accelerationStructures[i]));
+ }
+ List<AccelerationStructureQueryDesc> innerQueryDescs;
+ innerQueryDescs.addRange(queryDescs, queryCount);
+ for (auto& innerQueryDesc : innerQueryDescs)
+ {
+ innerQueryDesc.queryPool = getInnerObj(innerQueryDesc.queryPool);
+ }
+ baseObject->queryAccelerationStructureProperties(
+ accelerationStructureCount, innerAS.getBuffer(), queryCount, innerQueryDescs.getBuffer());
+}
+
+void DebugRayTracingCommandEncoder::serializeAccelerationStructure(
+ DeviceAddress dest,
+ IAccelerationStructure* source)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->serializeAccelerationStructure(dest, getInnerObj(source));
+}
+
+void DebugRayTracingCommandEncoder::deserializeAccelerationStructure(
+ IAccelerationStructure* dest,
+ DeviceAddress source)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->deserializeAccelerationStructure(getInnerObj(dest), source);
+}
+
+void DebugRayTracingCommandEncoder::bindPipeline(
+ IPipelineState* state, IShaderObject** outRootObject)
+{
+ SLANG_GFX_API_FUNC;
+ auto innerPipeline = getInnerObj(state);
+ IShaderObject* innerRootObject = nullptr;
+ commandBuffer->rootObject.reset();
+ baseObject->bindPipeline(innerPipeline, &innerRootObject);
+ commandBuffer->rootObject.baseObject.attach(innerRootObject);
+ *outRootObject = &commandBuffer->rootObject;
+}
+
+Result DebugRayTracingCommandEncoder::bindPipelineWithRootObject(
+ IPipelineState* state, IShaderObject* rootObject)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->bindPipelineWithRootObject(getInnerObj(state), getInnerObj(rootObject));
+}
+
+void DebugRayTracingCommandEncoder::dispatchRays(
+ GfxIndex rayGenShaderIndex,
+ IShaderTable* shaderTable,
+ GfxCount width,
+ GfxCount height,
+ GfxCount depth)
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->dispatchRays(rayGenShaderIndex, getInnerObj(shaderTable), width, height, depth);
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-command-encoder.h b/tools/gfx/debug-layer/debug-command-encoder.h
new file mode 100644
index 000000000..8a0ffbfdb
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-command-encoder.h
@@ -0,0 +1,253 @@
+// debug-command-encoder.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugResourceCommandEncoderImpl
+{
+public:
+ virtual DebugCommandBuffer* getCommandBuffer() = 0;
+ virtual bool getIsOpen() = 0;
+ virtual IResourceCommandEncoder* getBaseResourceEncoder() = 0;
+
+public:
+ virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer(
+ IBufferResource* dst,
+ Offset dstOffset,
+ IBufferResource* src,
+ Offset srcOffset,
+ Size size);
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ uploadBufferData(IBufferResource* dst, Offset offset, Size size, void* data);
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ writeTimestamp(IQueryPool* pool, GfxIndex index);
+ virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier(
+ GfxCount count,
+ ITextureResource* const* textures,
+ ResourceState src,
+ ResourceState dst);
+ virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier(
+ GfxCount count,
+ IBufferResource* const* buffers,
+ ResourceState src,
+ ResourceState dst);
+ virtual SLANG_NO_THROW void SLANG_MCALL copyTexture(
+ ITextureResource* dst,
+ ResourceState dstState,
+ SubresourceRange dstSubresource,
+ ITextureResource::Offset3D dstOffset,
+ ITextureResource* src,
+ ResourceState srcState,
+ SubresourceRange srcSubresource,
+ ITextureResource::Offset3D srcOffset,
+ ITextureResource::Extents extent);
+ virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData(
+ ITextureResource* dst,
+ SubresourceRange subResourceRange,
+ ITextureResource::Offset3D offset,
+ ITextureResource::Extents extent,
+ ITextureResource::SubresourceData* subResourceData,
+ GfxCount subResourceDataCount);
+ virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView(
+ IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags);
+ virtual SLANG_NO_THROW void SLANG_MCALL resolveResource(
+ ITextureResource* source,
+ ResourceState sourceState,
+ SubresourceRange sourceRange,
+ ITextureResource* dest,
+ ResourceState destState,
+ SubresourceRange destRange);
+ virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer(
+ IBufferResource* dst,
+ Offset dstOffset,
+ Size dstSize,
+ Size dstRowStride,
+ ITextureResource* src,
+ ResourceState srcState,
+ SubresourceRange srcSubresource,
+ ITextureResource::Offset3D srcOffset,
+ ITextureResource::Extents extent);
+ virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier(
+ ITextureResource* texture,
+ SubresourceRange subresourceRange,
+ ResourceState src,
+ ResourceState dst);
+ virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(
+ IQueryPool* queryPool,
+ GfxIndex index,
+ GfxCount count,
+ IBufferResource* buffer,
+ Offset offset);
+ virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]);
+ virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent();
+};
+
+class DebugComputeCommandEncoder
+ : public UnownedDebugObject<IComputeCommandEncoder>
+ , public DebugResourceCommandEncoderImpl
+{
+public:
+ SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(DebugResourceCommandEncoderImpl)
+ virtual DebugCommandBuffer* getCommandBuffer() override { return commandBuffer; }
+ virtual bool getIsOpen() override { return isOpen; }
+ virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; }
+
+public:
+ virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ bindPipeline(IPipelineState* state, IShaderObject** outRootShaderObject) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL dispatchCompute(int x, int y, int z) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ dispatchComputeIndirect(IBufferResource* cmdBuffer, Offset offset) override;
+
+public:
+ DebugCommandBuffer* commandBuffer;
+ bool isOpen = false;
+};
+
+class DebugResourceCommandEncoder
+ : public UnownedDebugObject<IResourceCommandEncoder>
+ , public DebugResourceCommandEncoderImpl
+{
+public:
+ SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(DebugResourceCommandEncoderImpl)
+ virtual DebugCommandBuffer* getCommandBuffer() override { return commandBuffer; }
+ virtual bool getIsOpen() override { return isOpen; }
+ virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; }
+
+
+public:
+ virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override;
+
+public:
+ DebugCommandBuffer* commandBuffer;
+ bool isOpen = false;
+};
+
+class DebugRenderCommandEncoder
+ : public UnownedDebugObject<IRenderCommandEncoder>
+ , public DebugResourceCommandEncoderImpl
+{
+public:
+ SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(DebugResourceCommandEncoderImpl)
+ virtual DebugCommandBuffer* getCommandBuffer() override
+ {
+ return commandBuffer;
+ }
+ virtual bool getIsOpen() override { return isOpen; }
+ virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; }
+
+public:
+ virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ bindPipeline(IPipelineState* state, IShaderObject** outRootShaderObject) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ setViewports(GfxCount count, const Viewport* viewports) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ setScissorRects(GfxCount count, const ScissorRect* scissors) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ setPrimitiveTopology(PrimitiveTopology topology) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers(
+ GfxIndex startSlot,
+ GfxCount slotCount,
+ IBufferResource* const* buffers,
+ const Offset* offsets) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ setIndexBuffer(IBufferResource* buffer, Format indexFormat, Offset offset = 0) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ draw(GfxCount vertexCount, GfxIndex startVertex = 0) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ drawIndexed(GfxCount indexCount, GfxIndex startIndex = 0, GfxIndex baseVertex = 0) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL drawIndirect(
+ GfxCount maxDrawCount,
+ IBufferResource* argBuffer,
+ Offset argOffset,
+ IBufferResource* countBuffer,
+ Offset countOffset) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedIndirect(
+ GfxCount maxDrawCount,
+ IBufferResource* argBuffer,
+ Offset argOffset,
+ IBufferResource* countBuffer,
+ Offset countOffset) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions(
+ GfxCount samplesPerPixel,
+ GfxCount pixelCount,
+ const SamplePosition* samplePositions) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL drawInstanced(
+ GfxCount vertexCount,
+ GfxCount instanceCount,
+ GfxIndex startVertex,
+ GfxIndex startInstanceLocation) override;
+
+ virtual SLANG_NO_THROW void SLANG_MCALL drawIndexedInstanced(
+ GfxCount indexCount,
+ GfxCount instanceCount,
+ GfxIndex startIndexLocation,
+ GfxIndex baseVertexLocation,
+ GfxIndex startInstanceLocation) override;
+
+public:
+ DebugCommandBuffer* commandBuffer;
+ bool isOpen = false;
+};
+
+class DebugRayTracingCommandEncoder
+ : public UnownedDebugObject<IRayTracingCommandEncoder>
+ , public DebugResourceCommandEncoderImpl
+{
+public:
+ SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(DebugResourceCommandEncoderImpl)
+ virtual DebugCommandBuffer* getCommandBuffer() override { return commandBuffer; }
+ virtual bool getIsOpen() override { return isOpen; }
+ virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; }
+
+public:
+ virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure(
+ const IAccelerationStructure::BuildDesc& desc,
+ GfxCount propertyQueryCount,
+ AccelerationStructureQueryDesc* queryDescs) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL copyAccelerationStructure(
+ IAccelerationStructure* dest,
+ IAccelerationStructure* src,
+ AccelerationStructureCopyMode mode) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL queryAccelerationStructureProperties(
+ GfxCount accelerationStructureCount,
+ IAccelerationStructure* const* accelerationStructures,
+ GfxCount queryCount,
+ AccelerationStructureQueryDesc* queryDescs) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ serializeAccelerationStructure(DeviceAddress dest, IAccelerationStructure* source) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL deserializeAccelerationStructure(
+ IAccelerationStructure* dest,
+ DeviceAddress source) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ bindPipeline(IPipelineState* state, IShaderObject** outRootObject) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL dispatchRays(
+ GfxIndex rayGenShaderIndex,
+ IShaderTable* shaderTable,
+ GfxCount width,
+ GfxCount height,
+ GfxCount depth) override;
+
+public:
+ DebugCommandBuffer* commandBuffer;
+ bool isOpen = false;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-command-queue.cpp b/tools/gfx/debug-layer/debug-command-queue.cpp
new file mode 100644
index 000000000..253541abb
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-command-queue.cpp
@@ -0,0 +1,77 @@
+// debug-command-queue.cpp
+#include "debug-command-queue.h"
+
+#include "debug-command-buffer.h"
+#include "debug-fence.h"
+#include "debug-transient-heap.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+const ICommandQueue::Desc& DebugCommandQueue::getDesc()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getDesc();
+}
+
+void DebugCommandQueue::executeCommandBuffers(GfxCount count, ICommandBuffer* const* commandBuffers, IFence* fence, uint64_t valueToSignal)
+{
+ SLANG_GFX_API_FUNC;
+ List<ICommandBuffer*> innerCommandBuffers;
+ for (GfxIndex i = 0; i < count; i++)
+ {
+ auto cmdBufferIn = commandBuffers[i];
+ auto cmdBufferImpl = static_cast<DebugCommandBuffer*>(cmdBufferIn);
+ auto innerCmdBuffer = cmdBufferImpl->baseObject.get();
+ innerCommandBuffers.add(innerCmdBuffer);
+ if (cmdBufferImpl->isOpen)
+ {
+ GFX_DIAGNOSE_ERROR_FORMAT(
+ "Command buffer %lld is still open. A command buffer must be closed "
+ "before submitting to a command queue.",
+ cmdBufferImpl->uid);
+ }
+ if (i > 0)
+ {
+ if (cmdBufferImpl->m_transientHeap != getDebugObj(commandBuffers[0])->m_transientHeap)
+ {
+ GFX_DIAGNOSE_ERROR("Command buffers passed to a single executeCommandBuffers "
+ "call must be allocated from the same transient heap.");
+ }
+ }
+ }
+ baseObject->executeCommandBuffers(count, innerCommandBuffers.getBuffer(), getInnerObj(fence), valueToSignal);
+}
+
+void DebugCommandQueue::waitOnHost()
+{
+ SLANG_GFX_API_FUNC;
+ baseObject->waitOnHost();
+}
+
+Result DebugCommandQueue::waitForFenceValuesOnDevice(
+ GfxCount fenceCount, IFence** fences, uint64_t* waitValues)
+{
+ SLANG_GFX_API_FUNC;
+ List<IFence*> innerFences;
+ for (GfxIndex i = 0; i < fenceCount; ++i)
+ {
+ innerFences.add(getInnerObj(fences[i]));
+ }
+ return baseObject->waitForFenceValuesOnDevice(fenceCount, innerFences.getBuffer(), waitValues);
+}
+
+Result DebugCommandQueue::getNativeHandle(InteropHandle* outHandle)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getNativeHandle(outHandle);
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-command-queue.h b/tools/gfx/debug-layer/debug-command-queue.h
new file mode 100644
index 000000000..3c9afa98b
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-command-queue.h
@@ -0,0 +1,29 @@
+// debug-command-queue.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugCommandQueue : public DebugObject<ICommandQueue>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ ICommandQueue* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ executeCommandBuffers(GfxCount count, ICommandBuffer* const* commandBuffers, IFence* fence, uint64_t valueToSignal) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL waitOnHost() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL waitForFenceValuesOnDevice(
+ GfxCount fenceCount, IFence** fences, uint64_t* waitValues) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-device.cpp b/tools/gfx/debug-layer/debug-device.cpp
new file mode 100644
index 000000000..aae7f9cea
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-device.cpp
@@ -0,0 +1,598 @@
+// debug-device.cpp
+#include "debug-device.h"
+
+#include "debug-buffer.h"
+#include "debug-command-queue.h"
+#include "debug-fence.h"
+#include "debug-framebuffer.h"
+#include "debug-helper-functions.h"
+#include "debug-pipeline-state.h"
+#include "debug-query.h"
+#include "debug-render-pass.h"
+#include "debug-resource-views.h"
+#include "debug-sampler-state.h"
+#include "debug-shader-object.h"
+#include "debug-shader-program.h"
+#include "debug-shader-table.h"
+#include "debug-swap-chain.h"
+#include "debug-texture.h"
+#include "debug-transient-heap.h"
+#include "debug-vertex-layout.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+Result DebugDevice::getNativeDeviceHandles(InteropHandles* outHandles)
+{
+ return baseObject->getNativeDeviceHandles(outHandles);
+}
+
+Result DebugDevice::getFeatures(const char** outFeatures, Size bufferSize, GfxCount* outFeatureCount)
+{
+ SLANG_GFX_API_FUNC;
+
+ return baseObject->getFeatures(outFeatures, bufferSize, outFeatureCount);
+}
+
+Result DebugDevice::getFormatSupportedResourceStates(Format format, ResourceStateSet* outStates)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getFormatSupportedResourceStates(format, outStates);
+}
+
+DebugDevice::DebugDevice()
+{
+ SLANG_GFX_API_FUNC_NAME("CreateDevice");
+ GFX_DIAGNOSE_INFO("Debug layer is enabled.");
+}
+
+SLANG_NO_THROW bool SLANG_MCALL DebugDevice::hasFeature(const char* feature)
+{
+ SLANG_GFX_API_FUNC;
+
+ return baseObject->hasFeature(feature);
+}
+
+Result DebugDevice::getSlangSession(slang::ISession** outSlangSession)
+{
+ SLANG_GFX_API_FUNC;
+
+ return baseObject->getSlangSession(outSlangSession);
+}
+
+Result DebugDevice::createTransientResourceHeap(
+ const ITransientResourceHeap::Desc& desc,
+ ITransientResourceHeap** outHeap)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugTransientResourceHeap> outObject = new DebugTransientResourceHeap();
+ auto result = baseObject->createTransientResourceHeap(desc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outHeap, outObject);
+ return result;
+}
+
+Result DebugDevice::createTextureResource(
+ const ITextureResource::Desc& desc,
+ const ITextureResource::SubresourceData* initData,
+ ITextureResource** outResource)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugTextureResource> outObject = new DebugTextureResource();
+ auto result =
+ baseObject->createTextureResource(desc, initData, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outResource, outObject);
+ return result;
+}
+
+Result DebugDevice::createTextureFromNativeHandle(
+ InteropHandle handle,
+ const ITextureResource::Desc& srcDesc,
+ ITextureResource** outResource)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugTextureResource> outObject = new DebugTextureResource();
+ auto result = baseObject->createTextureFromNativeHandle(handle, srcDesc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outResource, outObject);
+ return result;
+}
+
+Result DebugDevice::createTextureFromSharedHandle(
+ InteropHandle handle,
+ const ITextureResource::Desc& srcDesc,
+ const size_t size,
+ ITextureResource** outResource)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugTextureResource> outObject = new DebugTextureResource();
+ auto result = baseObject->createTextureFromSharedHandle(handle, srcDesc, size, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outResource, outObject);
+ return result;
+}
+
+Result DebugDevice::createBufferResource(
+ const IBufferResource::Desc& desc,
+ const void* initData,
+ IBufferResource** outResource)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugBufferResource> outObject = new DebugBufferResource();
+ auto result = baseObject->createBufferResource(desc, initData, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outResource, outObject);
+ return result;
+}
+
+Result DebugDevice::createBufferFromNativeHandle(
+ InteropHandle handle,
+ const IBufferResource::Desc& srcDesc,
+ IBufferResource** outResource)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugBufferResource> outObject = new DebugBufferResource();
+ auto result = baseObject->createBufferFromNativeHandle(handle, srcDesc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outResource, outObject);
+ return result;
+}
+
+Result DebugDevice::createBufferFromSharedHandle(
+ InteropHandle handle,
+ const IBufferResource::Desc& srcDesc,
+ IBufferResource** outResource)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugBufferResource> outObject = new DebugBufferResource();
+ auto result = baseObject->createBufferFromSharedHandle(handle, srcDesc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outResource, outObject);
+ return result;
+}
+
+Result DebugDevice::createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugSamplerState> outObject = new DebugSamplerState();
+ auto result = baseObject->createSamplerState(desc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outSampler, outObject);
+ return result;
+}
+
+Result DebugDevice::createTextureView(
+ ITextureResource* texture,
+ IResourceView::Desc const& desc,
+ IResourceView** outView)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugResourceView> outObject = new DebugResourceView();
+ auto result = baseObject->createTextureView(
+ static_cast<DebugTextureResource*>(texture)->baseObject,
+ desc,
+ outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outView, outObject);
+ return result;
+}
+
+Result DebugDevice::createBufferView(
+ IBufferResource* buffer,
+ IBufferResource* counterBuffer,
+ IResourceView::Desc const& desc,
+ IResourceView** outView)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugResourceView> outObject = new DebugResourceView();
+ auto result = baseObject->createBufferView(
+ static_cast<DebugBufferResource*>(buffer)->baseObject,
+ counterBuffer ? static_cast<DebugBufferResource*>(counterBuffer)->baseObject : nullptr,
+ desc,
+ outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outView, outObject);
+ return result;
+}
+
+Result DebugDevice::getAccelerationStructurePrebuildInfo(
+ const IAccelerationStructure::BuildInputs& buildInputs,
+ IAccelerationStructure::PrebuildInfo* outPrebuildInfo)
+{
+ SLANG_GFX_API_FUNC;
+ validateAccelerationStructureBuildInputs(buildInputs);
+ return baseObject->getAccelerationStructurePrebuildInfo(buildInputs, outPrebuildInfo);
+}
+
+Result DebugDevice::createAccelerationStructure(
+ const IAccelerationStructure::CreateDesc& desc,
+ IAccelerationStructure** outAS)
+{
+ SLANG_GFX_API_FUNC;
+ auto innerDesc = desc;
+ innerDesc.buffer = getInnerObj(innerDesc.buffer);
+ RefPtr<DebugAccelerationStructure> outObject = new DebugAccelerationStructure();
+ auto result = baseObject->createAccelerationStructure(innerDesc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outAS, outObject);
+ return SLANG_OK;
+}
+
+Result DebugDevice::createFramebufferLayout(
+ IFramebufferLayout::Desc const& desc,
+ IFramebufferLayout** outFrameBuffer)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugFramebufferLayout> outObject = new DebugFramebufferLayout();
+ auto result = baseObject->createFramebufferLayout(desc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outFrameBuffer, outObject);
+ return result;
+}
+
+Result DebugDevice::createFramebuffer(IFramebuffer::Desc const& desc, IFramebuffer** outFrameBuffer)
+{
+ SLANG_GFX_API_FUNC;
+
+ auto innerDesc = desc;
+ innerDesc.layout =
+ desc.layout ? static_cast<DebugFramebufferLayout*>(desc.layout)->baseObject.get() : nullptr;
+ innerDesc.depthStencilView =
+ desc.depthStencilView
+ ? static_cast<DebugResourceView*>(desc.depthStencilView)->baseObject.get()
+ : nullptr;
+ List<IResourceView*> innerRenderTargets;
+ for (GfxIndex i = 0; i < desc.renderTargetCount; i++)
+ {
+ auto innerRenderTarget =
+ desc.renderTargetViews[i]
+ ? static_cast<DebugResourceView*>(desc.renderTargetViews[i])->baseObject.get()
+ : nullptr;
+ innerRenderTargets.add(innerRenderTarget);
+ }
+ innerDesc.renderTargetViews = innerRenderTargets.getBuffer();
+
+ RefPtr<DebugFramebuffer> outObject = new DebugFramebuffer();
+ auto result = baseObject->createFramebuffer(innerDesc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outFrameBuffer, outObject);
+ return result;
+}
+
+Result DebugDevice::createRenderPassLayout(
+ const IRenderPassLayout::Desc& desc,
+ IRenderPassLayout** outRenderPassLayout)
+{
+ SLANG_GFX_API_FUNC;
+
+ auto innerDesc = desc;
+ innerDesc.framebufferLayout =
+ desc.framebufferLayout? static_cast<DebugFramebufferLayout*>(desc.framebufferLayout)->baseObject.get()
+ : nullptr;
+ RefPtr<DebugRenderPassLayout> outObject = new DebugRenderPassLayout();
+ auto result = baseObject->createRenderPassLayout(innerDesc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outRenderPassLayout, outObject);
+ return result;
+}
+
+Result DebugDevice::createSwapchain(
+ ISwapchain::Desc const& desc,
+ WindowHandle window,
+ ISwapchain** outSwapchain)
+{
+ SLANG_GFX_API_FUNC;
+
+ auto innerDesc = desc;
+ innerDesc.queue = static_cast<DebugCommandQueue*>(desc.queue)->baseObject.get();
+ RefPtr<DebugSwapchain> outObject = new DebugSwapchain();
+ outObject->queue = static_cast<DebugCommandQueue*>(desc.queue);
+ auto result = baseObject->createSwapchain(innerDesc, window, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outSwapchain, outObject);
+ return Result();
+}
+
+Result DebugDevice::createInputLayout(
+ IInputLayout::Desc const& desc,
+ IInputLayout** outLayout)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugInputLayout> outObject = new DebugInputLayout();
+ auto result = baseObject->createInputLayout(
+ desc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outLayout, outObject);
+ return result;
+}
+
+Result DebugDevice::createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugCommandQueue> outObject = new DebugCommandQueue();
+ auto result = baseObject->createCommandQueue(desc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outQueue, outObject);
+ return result;
+}
+
+Result DebugDevice::createShaderObject(
+ slang::TypeReflection* type,
+ ShaderObjectContainerType containerType,
+ IShaderObject** outShaderObject)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugShaderObject> outObject = new DebugShaderObject();
+ auto typeName = type->getName();
+ auto result =
+ baseObject->createShaderObject(type, containerType, outObject->baseObject.writeRef());
+ outObject->m_typeName = typeName;
+ outObject->m_device = this;
+ outObject->m_slangType = type;
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outShaderObject, outObject);
+ return result;
+}
+
+Result DebugDevice::createMutableShaderObject(
+ slang::TypeReflection* type,
+ ShaderObjectContainerType containerType,
+ IShaderObject** outShaderObject)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugShaderObject> outObject = new DebugShaderObject();
+ auto typeName = type->getName();
+ auto result =
+ baseObject->createMutableShaderObject(type, containerType, outObject->baseObject.writeRef());
+ outObject->m_typeName = typeName;
+ outObject->m_device = this;
+ outObject->m_slangType = type;
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outShaderObject, outObject);
+ return result;
+}
+
+Result DebugDevice::createMutableRootShaderObject(
+ IShaderProgram* program, IShaderObject** outRootObject)
+{
+ SLANG_GFX_API_FUNC;
+ RefPtr<DebugShaderObject> outObject = new DebugShaderObject();
+ auto result = baseObject->createMutableRootShaderObject(
+ getInnerObj(program), outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ outObject->m_device = this;
+ outObject->m_slangType = nullptr;
+ outObject->m_rootComponentType = getDebugObj(program)->m_slangProgram;
+ returnComPtr(outRootObject, outObject);
+ return result;
+}
+
+Result DebugDevice::createShaderObjectFromTypeLayout(
+ slang::TypeLayoutReflection* typeLayout, IShaderObject** outShaderObject)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugShaderObject> outObject = new DebugShaderObject();
+ auto result = baseObject->createShaderObjectFromTypeLayout(typeLayout, outObject->baseObject.writeRef());
+ auto type = typeLayout->getType();
+ auto typeName = type->getName();
+ outObject->m_typeName = typeName;
+ outObject->m_device = this;
+ outObject->m_slangType = type;
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outShaderObject, outObject);
+ return result;
+}
+
+Result DebugDevice::createMutableShaderObjectFromTypeLayout(
+ slang::TypeLayoutReflection* typeLayout, IShaderObject** outShaderObject)
+{
+ SLANG_GFX_API_FUNC;
+ RefPtr<DebugShaderObject> outObject = new DebugShaderObject();
+ auto result = baseObject->createMutableShaderObjectFromTypeLayout(
+ typeLayout, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ auto type = typeLayout->getType();
+ auto typeName = type->getName();
+ outObject->m_typeName = typeName;
+ outObject->m_device = this;
+ outObject->m_slangType = type;
+ returnComPtr(outShaderObject, outObject);
+ return result;
+}
+
+Result DebugDevice::createProgram(
+ const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnostics)
+{
+ SLANG_GFX_API_FUNC;
+
+ RefPtr<DebugShaderProgram> outObject = new DebugShaderProgram(desc);
+ auto result = baseObject->createProgram(desc, outObject->baseObject.writeRef(), outDiagnostics);
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outProgram, outObject);
+ return result;
+}
+
+Result DebugDevice::createGraphicsPipelineState(
+ const GraphicsPipelineStateDesc& desc,
+ IPipelineState** outState)
+{
+ SLANG_GFX_API_FUNC;
+
+ GraphicsPipelineStateDesc innerDesc = desc;
+ innerDesc.program =
+ desc.program ? static_cast<DebugShaderProgram*>(desc.program)->baseObject : nullptr;
+ innerDesc.inputLayout =
+ desc.inputLayout ? static_cast<DebugInputLayout*>(desc.inputLayout)->baseObject : nullptr;
+ innerDesc.framebufferLayout =
+ desc.framebufferLayout
+ ? static_cast<DebugFramebufferLayout*>(desc.framebufferLayout)->baseObject
+ : nullptr;
+ RefPtr<DebugPipelineState> outObject = new DebugPipelineState();
+ auto result =
+ baseObject->createGraphicsPipelineState(innerDesc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outState, outObject);
+ return result;
+}
+
+Result DebugDevice::createComputePipelineState(
+ const ComputePipelineStateDesc& desc,
+ IPipelineState** outState)
+{
+ SLANG_GFX_API_FUNC;
+
+ ComputePipelineStateDesc innerDesc = desc;
+ innerDesc.program = static_cast<DebugShaderProgram*>(desc.program)->baseObject;
+
+ RefPtr<DebugPipelineState> outObject = new DebugPipelineState();
+ auto result =
+ baseObject->createComputePipelineState(innerDesc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outState, outObject);
+ return result;
+}
+
+Result DebugDevice::createRayTracingPipelineState(
+ const RayTracingPipelineStateDesc& desc,
+ IPipelineState** outState)
+{
+ SLANG_GFX_API_FUNC;
+
+ RayTracingPipelineStateDesc innerDesc = desc;
+ innerDesc.program = static_cast<DebugShaderProgram*>(desc.program)->baseObject;
+
+ RefPtr<DebugPipelineState> outObject = new DebugPipelineState();
+ auto result =
+ baseObject->createRayTracingPipelineState(innerDesc, outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outState, outObject);
+ return result;
+}
+
+SlangResult DebugDevice::readTextureResource(
+ ITextureResource* resource,
+ ResourceState state,
+ ISlangBlob** outBlob,
+ size_t* outRowPitch,
+ size_t* outPixelSize)
+{
+ SLANG_GFX_API_FUNC;
+ auto resourceImpl = static_cast<DebugTextureResource*>(resource);
+ return baseObject->readTextureResource(
+ resourceImpl->baseObject, state, outBlob, outRowPitch, outPixelSize);
+}
+
+SlangResult DebugDevice::readBufferResource(
+ IBufferResource* buffer,
+ size_t offset,
+ size_t size,
+ ISlangBlob** outBlob)
+{
+ SLANG_GFX_API_FUNC;
+ auto bufferImpl = static_cast<DebugBufferResource*>(buffer);
+ return baseObject->readBufferResource(bufferImpl->baseObject, offset, size, outBlob);
+}
+
+const DeviceInfo& DebugDevice::getDeviceInfo() const
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getDeviceInfo();
+}
+
+Result DebugDevice::createQueryPool(const IQueryPool::Desc& desc, IQueryPool** outPool)
+{
+ SLANG_GFX_API_FUNC;
+ RefPtr<DebugQueryPool> result = new DebugQueryPool();
+ result->desc = desc;
+ SLANG_RETURN_ON_FAIL(baseObject->createQueryPool(desc, result->baseObject.writeRef()));
+ returnComPtr(outPool, result);
+ return SLANG_OK;
+}
+
+Result DebugDevice::createFence(const IFence::Desc& desc, IFence** outFence)
+{
+ SLANG_GFX_API_FUNC;
+ RefPtr<DebugFence> result = new DebugFence();
+ SLANG_RETURN_ON_FAIL(baseObject->createFence(desc, result->baseObject.writeRef()));
+ returnComPtr(outFence, result);
+ return SLANG_OK;
+}
+
+Result DebugDevice::waitForFences(
+ GfxCount fenceCount, IFence** fences, uint64_t* values , bool waitForAll, uint64_t timeout)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->waitForFences(fenceCount, fences, values, waitForAll, timeout);
+}
+
+Result DebugDevice::getTextureAllocationInfo(
+ const ITextureResource::Desc& desc, size_t* outSize, size_t* outAlignment)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getTextureAllocationInfo(desc, outSize, outAlignment);
+}
+
+Result DebugDevice::getTextureRowAlignment(size_t* outAlignment)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getTextureRowAlignment(outAlignment);
+}
+
+Result DebugDevice::createShaderTable(const IShaderTable::Desc& desc, IShaderTable** outTable)
+{
+ SLANG_GFX_API_FUNC;
+ RefPtr<DebugShaderTable> result = new DebugShaderTable();
+ SLANG_RETURN_ON_FAIL(baseObject->createShaderTable(desc, result->baseObject.writeRef()));
+ returnComPtr(outTable, result);
+ return SLANG_OK;
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-device.h b/tools/gfx/debug-layer/debug-device.h
new file mode 100644
index 000000000..83a67428f
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-device.h
@@ -0,0 +1,147 @@
+// debug-device.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugDevice : public DebugObject<IDevice>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ DebugDevice();
+ IDevice* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW Result SLANG_MCALL getNativeDeviceHandles(InteropHandles* outHandles) override;
+ virtual SLANG_NO_THROW bool SLANG_MCALL hasFeature(const char* feature) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getFeatures(const char** outFeatures, Size bufferSize, GfxCount* outFeatureCount) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getFormatSupportedResourceStates(Format format, ResourceStateSet* outStates) override;
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getSlangSession(slang::ISession** outSlangSession) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createTransientResourceHeap(
+ const ITransientResourceHeap::Desc& desc,
+ ITransientResourceHeap** outHeap) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(
+ const ITextureResource::Desc& desc,
+ const ITextureResource::SubresourceData* initData,
+ ITextureResource** outResource) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromNativeHandle(
+ InteropHandle handle,
+ const ITextureResource::Desc& srcDesc,
+ ITextureResource** outResource) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromSharedHandle(
+ InteropHandle handle,
+ const ITextureResource::Desc& srcDesc,
+ const Size size,
+ ITextureResource** outResource) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource(
+ const IBufferResource::Desc& desc,
+ const void* initData,
+ IBufferResource** outResource) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromNativeHandle(
+ InteropHandle handle,
+ const IBufferResource::Desc& srcDesc,
+ IBufferResource** outResource) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromSharedHandle(
+ InteropHandle handle,
+ const IBufferResource::Desc& srcDesc,
+ IBufferResource** outResource) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView(
+ ITextureResource* texture,
+ IResourceView::Desc const& desc,
+ IResourceView** outView) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView(
+ IBufferResource* buffer,
+ IBufferResource* counterBuffer,
+ IResourceView::Desc const& desc,
+ IResourceView** outView) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getAccelerationStructurePrebuildInfo(
+ const IAccelerationStructure::BuildInputs& buildInputs,
+ IAccelerationStructure::PrebuildInfo* outPrebuildInfo) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createAccelerationStructure(
+ const IAccelerationStructure::CreateDesc& desc,
+ IAccelerationStructure** outView) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createFramebufferLayout(
+ IFramebufferLayout::Desc const& desc,
+ IFramebufferLayout** outFrameBuffer) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebuffer(IFramebuffer::Desc const& desc, IFramebuffer** outFrameBuffer) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createRenderPassLayout(
+ const IRenderPassLayout::Desc& desc,
+ IRenderPassLayout** outRenderPassLayout) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
+ ISwapchain::Desc const& desc,
+ WindowHandle window,
+ ISwapchain** outSwapchain) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout(
+ IInputLayout::Desc const& desc,
+ IInputLayout** outLayout) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObject(
+ slang::TypeReflection* type,
+ ShaderObjectContainerType container,
+ IShaderObject** outObject) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createMutableShaderObject(
+ slang::TypeReflection* type,
+ ShaderObjectContainerType container,
+ IShaderObject** outObject) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObjectFromTypeLayout(
+ slang::TypeLayoutReflection* typeLayout, IShaderObject** outObject) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createMutableShaderObjectFromTypeLayout(
+ slang::TypeLayoutReflection* typeLayout, IShaderObject** outObject) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createMutableRootShaderObject(IShaderProgram* program, IShaderObject** outObject) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnostics) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState(
+ const GraphicsPipelineStateDesc& desc,
+ IPipelineState** outState) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(
+ const ComputePipelineStateDesc& desc,
+ IPipelineState** outState) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createRayTracingPipelineState(
+ const RayTracingPipelineStateDesc& desc,
+ IPipelineState** outState) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
+ ITextureResource* resource,
+ ResourceState state,
+ ISlangBlob** outBlob,
+ Size* outRowPitch,
+ Size* outPixelSize) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL readBufferResource(
+ IBufferResource* buffer,
+ Offset offset,
+ Size size,
+ ISlangBlob** outBlob) override;
+ virtual SLANG_NO_THROW const DeviceInfo& SLANG_MCALL getDeviceInfo() const override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createQueryPool(
+ const IQueryPool::Desc& desc,
+ IQueryPool** outPool) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFence(const IFence::Desc& desc, IFence** outFence) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL waitForFences(
+ GfxCount fenceCount,
+ IFence** fences,
+ uint64_t* values,
+ bool waitForAll,
+ uint64_t timeout) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getTextureAllocationInfo(
+ const ITextureResource::Desc& desc, size_t* outSize, size_t* outAlignment) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getTextureRowAlignment(size_t* outAlignment) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createShaderTable(const IShaderTable::Desc& desc, IShaderTable** outTable) override;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-fence.cpp b/tools/gfx/debug-layer/debug-fence.cpp
new file mode 100644
index 000000000..7ecbfabd7
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-fence.cpp
@@ -0,0 +1,38 @@
+// debug-fence.cpp
+#include "debug-fence.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+Result DebugFence::getSharedHandle(InteropHandle* outHandle)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getSharedHandle(outHandle);
+}
+
+Result DebugFence::getNativeHandle(InteropHandle* outNativeHandle)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getNativeHandle(outNativeHandle);
+}
+
+Result DebugFence::getCurrentValue(uint64_t* outValue)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getCurrentValue(outValue);
+}
+
+Result DebugFence::setCurrentValue(uint64_t value)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->setCurrentValue(value);
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-fence.h b/tools/gfx/debug-layer/debug-fence.h
new file mode 100644
index 000000000..980596d90
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-fence.h
@@ -0,0 +1,24 @@
+// debug-fence.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugFence : public DebugObject<IFence>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+ IFence* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW Result SLANG_MCALL getCurrentValue(uint64_t* outValue) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL setCurrentValue(uint64_t value) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outNativeHandle) override;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-framebuffer.h b/tools/gfx/debug-layer/debug-framebuffer.h
new file mode 100644
index 000000000..76e05040c
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-framebuffer.h
@@ -0,0 +1,32 @@
+// debug-framebuffer.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugFramebuffer
+ : public DebugObject<IFramebuffer>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ IFramebuffer* getInterface(const Slang::Guid& guid);
+};
+
+class DebugFramebufferLayout : public DebugObject<IFramebufferLayout>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ IFramebufferLayout* getInterface(const Slang::Guid& guid);
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-helper-functions.cpp b/tools/gfx/debug-layer/debug-helper-functions.cpp
new file mode 100644
index 000000000..0d2c1d110
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-helper-functions.cpp
@@ -0,0 +1,156 @@
+// debug-helper-functions.cpp
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+thread_local const char* _currentFunctionName = nullptr;
+
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(Device)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL_PARENT(BufferResource, Resource)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL_PARENT(TextureResource, Resource)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(CommandBuffer)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(CommandQueue)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(Framebuffer)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(FramebufferLayout)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(InputLayout)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(RenderPassLayout)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(PipelineState)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(ResourceView)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(SamplerState)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(ShaderObject)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(ShaderProgram)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(Swapchain)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(TransientResourceHeap)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(QueryPool)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL_PARENT(AccelerationStructure, ResourceView)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(Fence)
+SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(ShaderTable)
+
+String _gfxGetFuncName(const char* input)
+{
+ UnownedStringSlice str(input);
+ auto prefixIndex = str.indexOf(UnownedStringSlice("Debug"));
+ if (prefixIndex == -1)
+ return input;
+ auto endIndex = str.lastIndexOf('(');
+ if (endIndex == -1)
+ endIndex = str.getLength();
+ auto startIndex = prefixIndex + 5;
+ StringBuilder sb;
+ sb.appendChar('I');
+ sb.append(str.subString(startIndex, endIndex - startIndex));
+ return sb.ProduceString();
+}
+
+void validateAccelerationStructureBuildInputs(
+ const IAccelerationStructure::BuildInputs& buildInputs)
+{
+ switch (buildInputs.kind)
+ {
+ case IAccelerationStructure::Kind::TopLevel:
+ if (!buildInputs.instanceDescs)
+ {
+ GFX_DIAGNOSE_ERROR("IAccelerationStructure::BuildInputs::instanceDescs cannot be null "
+ "when creating a top-level acceleration structure.");
+ }
+ break;
+ case IAccelerationStructure::Kind::BottomLevel:
+ if (!buildInputs.geometryDescs)
+ {
+ GFX_DIAGNOSE_ERROR("IAccelerationStructure::BuildInputs::geometryDescs cannot be null "
+ "when creating a bottom-level acceleration structure.");
+ }
+ for (int i = 0; i < buildInputs.descCount; i++)
+ {
+ switch (buildInputs.geometryDescs[i].type)
+ {
+ case IAccelerationStructure::GeometryType::Triangles:
+ switch (buildInputs.geometryDescs[i].content.triangles.vertexFormat)
+ {
+ case Format::R32G32B32_FLOAT:
+ case Format::R32G32_FLOAT:
+ case Format::R16G16B16A16_FLOAT:
+ case Format::R16G16_FLOAT:
+ case Format::R16G16B16A16_SNORM:
+ case Format::R16G16_SNORM:
+ break;
+ default:
+ GFX_DIAGNOSE_ERROR(
+ "Unsupported IAccelerationStructure::TriangleDesc::vertexFormat. Valid "
+ "values are R32G32B32_FLOAT, R32G32_FLOAT, R16G16B16A16_FLOAT, R16G16_FLOAT, "
+ "R16G16B16A16_SNORM or R16G16_SNORM.");
+ }
+ if (buildInputs.geometryDescs[i].content.triangles.indexCount)
+ {
+ switch (buildInputs.geometryDescs[i].content.triangles.indexFormat)
+ {
+ case Format::R32_UINT:
+ case Format::R16_UINT:
+ break;
+ default:
+ GFX_DIAGNOSE_ERROR(
+ "Unsupported IAccelerationStructure::TriangleDesc::indexFormat. Valid "
+ "values are Unknown, R32_UINT or R16_UINT.");
+ }
+ if (!buildInputs.geometryDescs[i].content.triangles.indexData)
+ {
+ GFX_DIAGNOSE_ERROR(
+ "IAccelerationStructure::TriangleDesc::indexData cannot be null if "
+ "IAccelerationStructure::TriangleDesc::indexCount is not 0");
+ }
+ }
+ if (buildInputs.geometryDescs[i].content.triangles.indexFormat != Format::Unknown)
+ {
+ if (buildInputs.geometryDescs[i].content.triangles.indexCount == 0)
+ {
+ GFX_DIAGNOSE_ERROR(
+ "IAccelerationStructure::TriangleDesc::indexCount cannot be 0 if "
+ "IAccelerationStructure::TriangleDesc::indexFormat is not Format::Unknown");
+ }
+ if (buildInputs.geometryDescs[i].content.triangles.indexData == 0)
+ {
+ GFX_DIAGNOSE_ERROR(
+ "IAccelerationStructure::TriangleDesc::indexData cannot be null if "
+ "IAccelerationStructure::TriangleDesc::indexFormat is not "
+ "Format::Unknown");
+ }
+ }
+ else
+ {
+ if (buildInputs.geometryDescs[i].content.triangles.indexCount != 0)
+ {
+ GFX_DIAGNOSE_ERROR(
+ "IAccelerationStructure::TriangleDesc::indexCount must be 0 if "
+ "IAccelerationStructure::TriangleDesc::indexFormat is "
+ "Format::Unknown");
+ }
+ if (buildInputs.geometryDescs[i].content.triangles.indexData != 0)
+ {
+ GFX_DIAGNOSE_ERROR(
+ "IAccelerationStructure::TriangleDesc::indexData must be null if "
+ "IAccelerationStructure::TriangleDesc::indexFormat is "
+ "Format::Unknown");
+ }
+ }
+ if (!buildInputs.geometryDescs[i].content.triangles.vertexData)
+ {
+ GFX_DIAGNOSE_ERROR(
+ "IAccelerationStructure::TriangleDesc::vertexData cannot be null.");
+ }
+ break;
+ }
+ }
+ break;
+ default:
+ GFX_DIAGNOSE_ERROR("Invalid value of IAccelerationStructure::Kind.");
+ break;
+ }
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-helper-functions.h b/tools/gfx/debug-layer/debug-helper-functions.h
new file mode 100644
index 000000000..1842cf458
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-helper-functions.h
@@ -0,0 +1,172 @@
+// debug-helper-functions.h
+#pragma once
+#include "debug-base.h"
+
+#include "debug-buffer.h"
+#include "debug-command-buffer.h"
+#include "debug-command-queue.h"
+#include "debug-device.h"
+#include "debug-fence.h"
+#include "debug-framebuffer.h"
+#include "debug-pipeline-state.h"
+#include "debug-query.h"
+#include "debug-render-pass.h"
+#include "debug-resource-views.h"
+#include "debug-sampler-state.h"
+#include "debug-shader-object.h"
+#include "debug-shader-program.h"
+#include "debug-shader-table.h"
+#include "debug-swap-chain.h"
+#include "debug-texture.h"
+#include "debug-transient-heap.h"
+#include "debug-vertex-layout.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+#ifdef __FUNCSIG__
+# define SLANG_FUNC_SIG __FUNCSIG__
+#elif defined(__PRETTY_FUNCTION__)
+# define SLANG_FUNC_SIG __FUNCSIG__
+#elif defined(__FUNCTION__)
+# define SLANG_FUNC_SIG __FUNCTION__
+#else
+# define SLANG_FUNC_SIG "UnknownFunction"
+#endif
+
+extern thread_local const char* _currentFunctionName;
+struct SetCurrentFuncRAII
+{
+ SetCurrentFuncRAII(const char* funcName) { _currentFunctionName = funcName; }
+ ~SetCurrentFuncRAII() { _currentFunctionName = nullptr; }
+};
+#define SLANG_GFX_API_FUNC SetCurrentFuncRAII setFuncNameRAII(SLANG_FUNC_SIG)
+#define SLANG_GFX_API_FUNC_NAME(x) SetCurrentFuncRAII setFuncNameRAII(x)
+
+/// Returns the public API function name from a `SLANG_FUNC_SIG` string.
+String _gfxGetFuncName(const char* input);
+
+template <typename... TArgs>
+char* _gfxDiagnoseFormat(
+ char* buffer, // Initial buffer to output formatted string.
+ size_t shortBufferSize, // Size of the initial buffer.
+ List<char>& bufferArray, // A list for allocating a large buffer if needed.
+ const char* format, // The format string.
+ TArgs... args)
+{
+ int length = sprintf_s(buffer, shortBufferSize, format, args...);
+ if (length < 0)
+ return buffer;
+ if (length > 255)
+ {
+ bufferArray.setCount(length + 1);
+ buffer = bufferArray.getBuffer();
+ sprintf_s(buffer, bufferArray.getCount(), format, args...);
+ }
+ return buffer;
+}
+
+template <typename... TArgs>
+void _gfxDiagnoseImpl(DebugMessageType type, const char* format, TArgs... args)
+{
+ char shortBuffer[256];
+ List<char> bufferArray;
+ auto buffer =
+ _gfxDiagnoseFormat(shortBuffer, sizeof(shortBuffer), bufferArray, format, args...);
+ getDebugCallback()->handleMessage(type, DebugMessageSource::Layer, buffer);
+}
+
+#define GFX_DIAGNOSE_ERROR(message) \
+ _gfxDiagnoseImpl( \
+ DebugMessageType::Error, \
+ "%s: %s", \
+ _gfxGetFuncName(_currentFunctionName ? _currentFunctionName : SLANG_FUNC_SIG).getBuffer(), \
+ message)
+#define GFX_DIAGNOSE_WARNING(message) \
+ _gfxDiagnoseImpl( \
+ DebugMessageType::Warning, \
+ "%s: %s", \
+ _gfxGetFuncName(_currentFunctionName ? _currentFunctionName : SLANG_FUNC_SIG).getBuffer(), \
+ message)
+#define GFX_DIAGNOSE_INFO(message) \
+ _gfxDiagnoseImpl( \
+ DebugMessageType::Info, \
+ "%s: %s", \
+ _gfxGetFuncName(_currentFunctionName ? _currentFunctionName : SLANG_FUNC_SIG).getBuffer(), \
+ message)
+#define GFX_DIAGNOSE_FORMAT(type, format, ...) \
+ { \
+ char shortBuffer[256]; \
+ List<char> bufferArray; \
+ auto message = _gfxDiagnoseFormat( \
+ shortBuffer, sizeof(shortBuffer), bufferArray, format, __VA_ARGS__); \
+ _gfxDiagnoseImpl( \
+ type, \
+ "%s: %s", \
+ _gfxGetFuncName(_currentFunctionName ? _currentFunctionName : SLANG_FUNC_SIG) \
+ .getBuffer(), \
+ message); \
+ }
+#define GFX_DIAGNOSE_ERROR_FORMAT(...) GFX_DIAGNOSE_FORMAT(DebugMessageType::Error, __VA_ARGS__)
+
+#define SLANG_GFX_DEBUG_GET_INTERFACE_IMPL(typeName) \
+ I##typeName* Debug##typeName::getInterface(const Slang::Guid& guid) \
+ { \
+ return (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_I##typeName) \
+ ? static_cast<I##typeName*>(this) \
+ : nullptr; \
+ }
+#define SLANG_GFX_DEBUG_GET_INTERFACE_IMPL_PARENT(typeName, parentType) \
+ I##typeName* Debug##typeName::getInterface(const Slang::Guid& guid) \
+ { \
+ return (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_I##typeName || \
+ guid == GfxGUID::IID_I##parentType) \
+ ? static_cast<I##typeName*>(this) \
+ : nullptr; \
+ }
+
+// Utility conversion functions to get Debug* object or the inner object from a user provided
+// pointer.
+#define SLANG_GFX_DEBUG_GET_OBJ_IMPL(type) \
+ inline Debug##type* getDebugObj(I##type* ptr) { return static_cast<Debug##type*>(ptr); } \
+ inline I##type* getInnerObj(I##type* ptr) \
+ { \
+ if (!ptr) return nullptr; \
+ auto debugObj = getDebugObj(ptr); \
+ return debugObj->baseObject; \
+ }
+
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(Device)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(BufferResource)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(TextureResource)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(CommandBuffer)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(CommandQueue)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(ComputeCommandEncoder)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(RenderCommandEncoder)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(ResourceCommandEncoder)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(RayTracingCommandEncoder)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(Framebuffer)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(FramebufferLayout)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(InputLayout)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(RenderPassLayout)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(PipelineState)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(ResourceView)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(SamplerState)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(ShaderObject)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(ShaderProgram)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(Swapchain)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(TransientResourceHeap)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(QueryPool)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(AccelerationStructure)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(Fence)
+SLANG_GFX_DEBUG_GET_OBJ_IMPL(ShaderTable)
+
+void validateAccelerationStructureBuildInputs(
+ const IAccelerationStructure::BuildInputs& buildInputs);
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-pipeline-state.cpp b/tools/gfx/debug-layer/debug-pipeline-state.cpp
new file mode 100644
index 000000000..8dde0403e
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-pipeline-state.cpp
@@ -0,0 +1,20 @@
+// debug-pipeline-state.cpp
+#include "debug-pipeline-state.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+Result DebugPipelineState::getNativeHandle(InteropHandle* outHandle)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getNativeHandle(outHandle);
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-pipeline-state.h b/tools/gfx/debug-layer/debug-pipeline-state.h
new file mode 100644
index 000000000..a539499c2
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-pipeline-state.h
@@ -0,0 +1,23 @@
+// debug-pipeline-state.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugPipelineState : public DebugObject<IPipelineState>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ IPipelineState* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-query.cpp b/tools/gfx/debug-layer/debug-query.cpp
new file mode 100644
index 000000000..44e0ed116
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-query.cpp
@@ -0,0 +1,29 @@
+// debug-query.cpp
+#include "debug-query.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+Result DebugQueryPool::getResult(GfxIndex index, GfxCount count, uint64_t* data)
+{
+ SLANG_GFX_API_FUNC;
+
+ if (index < 0 || index + count > desc.count)
+ GFX_DIAGNOSE_ERROR("index is out of bounds.");
+ return baseObject->getResult(index, count, data);
+}
+
+Result DebugQueryPool::reset()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->reset();
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-query.h b/tools/gfx/debug-layer/debug-query.h
new file mode 100644
index 000000000..890745387
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-query.h
@@ -0,0 +1,26 @@
+// debug-query.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugQueryPool : public DebugObject<IQueryPool>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+ IQueryPool::Desc desc;
+public:
+ IQueryPool* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getResult(GfxIndex index, GfxCount count, uint64_t* data) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL reset() override;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-render-pass.h b/tools/gfx/debug-layer/debug-render-pass.h
new file mode 100644
index 000000000..1b17977db
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-render-pass.h
@@ -0,0 +1,22 @@
+// debug-render-pass.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugRenderPassLayout : public DebugObject<IRenderPassLayout>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ IRenderPassLayout* getInterface(const Slang::Guid& guid);
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-resource-views.cpp b/tools/gfx/debug-layer/debug-resource-views.cpp
new file mode 100644
index 000000000..404459181
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-resource-views.cpp
@@ -0,0 +1,49 @@
+// debug-resource-views.cpp
+#include "debug-resource-views.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+IResourceView::Desc* DebugResourceView::getViewDesc()
+{
+ SLANG_GFX_API_FUNC;
+
+ return baseObject->getViewDesc();
+}
+
+Result DebugResourceView::getNativeHandle(InteropHandle* outNativeHandle)
+{
+ SLANG_GFX_API_FUNC;
+
+ return baseObject->getNativeHandle(outNativeHandle);
+}
+
+DeviceAddress DebugAccelerationStructure::getDeviceAddress()
+{
+ SLANG_GFX_API_FUNC;
+
+ return baseObject->getDeviceAddress();
+}
+
+Result DebugAccelerationStructure::getNativeHandle(InteropHandle* outNativeHandle)
+{
+ SLANG_GFX_API_FUNC;
+
+ return baseObject->getNativeHandle(outNativeHandle);
+}
+
+IResourceView::Desc* DebugAccelerationStructure::getViewDesc()
+{
+ SLANG_GFX_API_FUNC;
+
+ return baseObject->getViewDesc();
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-resource-views.h b/tools/gfx/debug-layer/debug-resource-views.h
new file mode 100644
index 000000000..b9a9b4539
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-resource-views.h
@@ -0,0 +1,37 @@
+// debug-resource-views.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugResourceView : public DebugObject<IResourceView>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ IResourceView* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outNativeHandle) override;
+};
+
+class DebugAccelerationStructure : public DebugObject<IAccelerationStructure>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ IAccelerationStructure* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getNativeHandle(InteropHandle* outNativeHandle) override;
+ virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() override;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-sampler-state.cpp b/tools/gfx/debug-layer/debug-sampler-state.cpp
new file mode 100644
index 000000000..892abc665
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-sampler-state.cpp
@@ -0,0 +1,21 @@
+// debug-sampler-state.cpp
+#include "debug-sampler-state.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+Result DebugSamplerState::getNativeHandle(InteropHandle* outNativeHandle)
+{
+ SLANG_GFX_API_FUNC;
+
+ return baseObject->getNativeHandle(outNativeHandle);
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-sampler-state.h b/tools/gfx/debug-layer/debug-sampler-state.h
new file mode 100644
index 000000000..d0b082ec5
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-sampler-state.h
@@ -0,0 +1,24 @@
+// debug-sampler-state.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugSamplerState : public DebugObject<ISamplerState>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ ISamplerState* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getNativeHandle(InteropHandle* outNativeHandle) override;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-shader-object.cpp b/tools/gfx/debug-layer/debug-shader-object.cpp
new file mode 100644
index 000000000..e6644a6f6
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-shader-object.cpp
@@ -0,0 +1,184 @@
+// debug-shader-object.cpp
+#include "debug-shader-object.h"
+
+#include "debug-resource-views.h"
+#include "debug-sampler-state.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+ShaderObjectContainerType DebugShaderObject::getContainerType()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getContainerType();
+}
+
+slang::TypeLayoutReflection* DebugShaderObject::getElementTypeLayout()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getElementTypeLayout();
+}
+
+GfxCount DebugShaderObject::getEntryPointCount()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getEntryPointCount();
+}
+
+Result DebugShaderObject::getEntryPoint(GfxIndex index, IShaderObject** entryPoint)
+{
+ SLANG_GFX_API_FUNC;
+ if (m_entryPoints.getCount() == 0)
+ {
+ for (GfxIndex i = 0; i < getEntryPointCount(); i++)
+ {
+ RefPtr<DebugShaderObject> entryPointObj = new DebugShaderObject();
+ SLANG_RETURN_ON_FAIL(
+ baseObject->getEntryPoint(i, entryPointObj->baseObject.writeRef()));
+ m_entryPoints.add(entryPointObj);
+ }
+ }
+ if (index > (GfxCount)m_entryPoints.getCount())
+ {
+ GFX_DIAGNOSE_ERROR("`index` must not exceed `entryPointCount`.");
+ return SLANG_FAIL;
+ }
+ returnComPtr(entryPoint, m_entryPoints[index]);
+ return SLANG_OK;
+}
+
+Result DebugShaderObject::setData(ShaderOffset const& offset, void const* data, Size size)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->setData(offset, data, size);
+}
+
+Result DebugShaderObject::getObject(ShaderOffset const& offset, IShaderObject** object)
+{
+ SLANG_GFX_API_FUNC;
+
+ ComPtr<IShaderObject> innerObject;
+ auto resultCode = baseObject->getObject(offset, innerObject.writeRef());
+ SLANG_RETURN_ON_FAIL(resultCode);
+ RefPtr<DebugShaderObject> debugShaderObject;
+ if (m_objects.TryGetValue(ShaderOffsetKey{offset}, debugShaderObject))
+ {
+ if (debugShaderObject->baseObject == innerObject)
+ {
+ returnComPtr(object, debugShaderObject);
+ return resultCode;
+ }
+ }
+ debugShaderObject = new DebugShaderObject();
+ debugShaderObject->baseObject = innerObject;
+ debugShaderObject->m_typeName = innerObject->getElementTypeLayout()->getName();
+ m_objects[ShaderOffsetKey{offset}] = debugShaderObject;
+ returnComPtr(object, debugShaderObject);
+ return resultCode;
+}
+
+Result DebugShaderObject::setObject(ShaderOffset const& offset, IShaderObject* object)
+{
+ SLANG_GFX_API_FUNC;
+ auto objectImpl = static_cast<DebugShaderObject*>(object);
+ m_objects[ShaderOffsetKey{offset}] = objectImpl;
+ return baseObject->setObject(offset, objectImpl->baseObject.get());
+}
+
+Result DebugShaderObject::setResource(ShaderOffset const& offset, IResourceView* resourceView)
+{
+ SLANG_GFX_API_FUNC;
+ auto viewImpl = static_cast<DebugResourceView*>(resourceView);
+ m_resources[ShaderOffsetKey{offset}] = viewImpl;
+ return baseObject->setResource(offset, viewImpl->baseObject.get());
+}
+
+Result DebugShaderObject::setSampler(ShaderOffset const& offset, ISamplerState* sampler)
+{
+ SLANG_GFX_API_FUNC;
+ auto samplerImpl = static_cast<DebugSamplerState*>(sampler);
+ m_samplers[ShaderOffsetKey{offset}] = samplerImpl;
+ return baseObject->setSampler(offset, samplerImpl->baseObject.get());
+}
+
+Result DebugShaderObject::setCombinedTextureSampler(
+ ShaderOffset const& offset,
+ IResourceView* textureView,
+ ISamplerState* sampler)
+{
+ SLANG_GFX_API_FUNC;
+ auto samplerImpl = static_cast<DebugSamplerState*>(sampler);
+ m_samplers[ShaderOffsetKey{offset}] = samplerImpl;
+ auto viewImpl = static_cast<DebugResourceView*>(textureView);
+ m_resources[ShaderOffsetKey{offset}] = viewImpl;
+ return baseObject->setCombinedTextureSampler(
+ offset, viewImpl->baseObject.get(), samplerImpl->baseObject.get());
+}
+
+Result DebugShaderObject::setSpecializationArgs(
+ ShaderOffset const& offset,
+ const slang::SpecializationArg* args,
+ GfxCount count)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->setSpecializationArgs(offset, args, count);
+}
+
+Result DebugShaderObject::getCurrentVersion(
+ ITransientResourceHeap* transientHeap, IShaderObject** outObject)
+{
+ SLANG_GFX_API_FUNC;
+ ComPtr<IShaderObject> innerObject;
+ SLANG_RETURN_ON_FAIL(baseObject->getCurrentVersion(getInnerObj(transientHeap), innerObject.writeRef()));
+ RefPtr<DebugShaderObject> debugShaderObject = new DebugShaderObject();
+ debugShaderObject->baseObject = innerObject;
+ debugShaderObject->m_typeName = innerObject->getElementTypeLayout()->getName();
+ returnComPtr(outObject, debugShaderObject);
+ return SLANG_OK;
+}
+
+const void* DebugShaderObject::getRawData()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getRawData();
+}
+
+size_t DebugShaderObject::getSize()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getSize();
+}
+
+Result DebugShaderObject::setConstantBufferOverride(IBufferResource* constantBuffer)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->setConstantBufferOverride(getInnerObj(constantBuffer));
+}
+
+Result DebugRootShaderObject::setSpecializationArgs(
+ ShaderOffset const& offset,
+ const slang::SpecializationArg* args,
+ GfxCount count)
+{
+ SLANG_GFX_API_FUNC;
+
+ return baseObject->setSpecializationArgs(offset, args, count);
+}
+
+void DebugRootShaderObject::reset()
+{
+ m_entryPoints.clear();
+ m_objects.Clear();
+ m_resources.Clear();
+ m_samplers.Clear();
+ baseObject.detach();
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-shader-object.h b/tools/gfx/debug-layer/debug-shader-object.h
new file mode 100644
index 000000000..8007e653a
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-shader-object.h
@@ -0,0 +1,101 @@
+// debug-shader-object.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+struct ShaderOffsetKey
+{
+ ShaderOffset offset;
+ bool operator==(ShaderOffsetKey other)
+ {
+ return offset.bindingArrayIndex == other.offset.bindingArrayIndex &&
+ offset.bindingRangeIndex == other.offset.bindingRangeIndex &&
+ offset.uniformOffset == other.offset.uniformOffset;
+ }
+ Slang::HashCode getHashCode()
+ {
+ return Slang::combineHash(
+ (Slang::HashCode)offset.uniformOffset,
+ Slang::combineHash(
+ (Slang::HashCode)offset.bindingArrayIndex,
+ (Slang::HashCode)offset.bindingRangeIndex));
+ }
+};
+
+class DebugShaderObject : public DebugObject<IShaderObject>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ IShaderObject* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW slang::TypeLayoutReflection* SLANG_MCALL getElementTypeLayout() override;
+ virtual SLANG_NO_THROW ShaderObjectContainerType SLANG_MCALL getContainerType() override;
+ virtual SLANG_NO_THROW GfxCount SLANG_MCALL getEntryPointCount() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getEntryPoint(GfxIndex index, IShaderObject** entryPoint) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ setData(ShaderOffset const& offset, void const* data, size_t size) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getObject(ShaderOffset const& offset, IShaderObject** object) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ setObject(ShaderOffset const& offset, IShaderObject* object) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ setResource(ShaderOffset const& offset, IResourceView* resourceView) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ setSampler(ShaderOffset const& offset, ISamplerState* sampler) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL setCombinedTextureSampler(
+ ShaderOffset const& offset,
+ IResourceView* textureView,
+ ISamplerState* sampler) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL setSpecializationArgs(
+ ShaderOffset const& offset,
+ const slang::SpecializationArg* args,
+ GfxCount count) override;
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL getCurrentVersion(
+ ITransientResourceHeap* transientHeap, IShaderObject** outObject) override;
+ virtual SLANG_NO_THROW const void* SLANG_MCALL getRawData() override;
+ virtual SLANG_NO_THROW size_t SLANG_MCALL getSize() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ setConstantBufferOverride(IBufferResource* constantBuffer) override;
+
+public:
+ // Type name of an ordinary shader object.
+ Slang::String m_typeName;
+
+ // The slang Type of an ordinary shader object. This is null for root objects.
+ slang::TypeReflection* m_slangType = nullptr;
+
+ // The slang program from which a root shader object is created, this is null for ordinary
+ // objects.
+ Slang::ComPtr<slang::IComponentType> m_rootComponentType;
+
+ DebugDevice* m_device;
+
+ Slang::List<Slang::RefPtr<DebugShaderObject>> m_entryPoints;
+ Slang::Dictionary<ShaderOffsetKey, Slang::RefPtr<DebugShaderObject>> m_objects;
+ Slang::Dictionary<ShaderOffsetKey, Slang::RefPtr<DebugResourceView>> m_resources;
+ Slang::Dictionary<ShaderOffsetKey, Slang::RefPtr<DebugSamplerState>> m_samplers;
+};
+
+class DebugRootShaderObject : public DebugShaderObject
+{
+public:
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override { return 1; }
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; }
+ virtual SLANG_NO_THROW Result SLANG_MCALL setSpecializationArgs(
+ ShaderOffset const& offset,
+ const slang::SpecializationArg* args,
+ GfxCount count) override;
+ void reset();
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-shader-program.cpp b/tools/gfx/debug-layer/debug-shader-program.cpp
new file mode 100644
index 000000000..264087abd
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-shader-program.cpp
@@ -0,0 +1,17 @@
+// debug-shader-program.cpp
+#include "debug-shader-program.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+DebugShaderProgram::DebugShaderProgram(const IShaderProgram::Desc& desc)
+{
+ m_slangProgram = desc.slangGlobalScope;
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-shader-program.h b/tools/gfx/debug-layer/debug-shader-program.h
new file mode 100644
index 000000000..050ee8e3c
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-shader-program.h
@@ -0,0 +1,27 @@
+// debug-shader-program.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugShaderProgram : public DebugObject<IShaderProgram>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ IShaderProgram* getInterface(const Slang::Guid& guid);
+
+ DebugShaderProgram(const IShaderProgram::Desc& desc);
+
+public:
+ Slang::ComPtr<slang::IComponentType> m_slangProgram;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-shader-table.h b/tools/gfx/debug-layer/debug-shader-table.h
new file mode 100644
index 000000000..b94bde94c
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-shader-table.h
@@ -0,0 +1,20 @@
+// debug-shader-table.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugShaderTable : public DebugObject<IShaderTable>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+ IShaderTable* getInterface(const Slang::Guid& guid);
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-swap-chain.cpp b/tools/gfx/debug-layer/debug-swap-chain.cpp
new file mode 100644
index 000000000..3c8058b5c
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-swap-chain.cpp
@@ -0,0 +1,93 @@
+// debug-swap-chain.cpp
+#include "debug-swap-chain.h"
+
+#include "debug-command-queue.h"
+#include "debug-texture.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+const ISwapchain::Desc& DebugSwapchain::getDesc()
+{
+ SLANG_GFX_API_FUNC;
+ desc = baseObject->getDesc();
+ desc.queue = queue.Ptr();
+ return desc;
+}
+
+Result DebugSwapchain::getImage(GfxIndex index, ITextureResource** outResource)
+{
+ SLANG_GFX_API_FUNC;
+ maybeRebuildImageList();
+ if (index > (GfxCount)m_images.getCount())
+ {
+ GFX_DIAGNOSE_ERROR_FORMAT(
+ "`index`(%d) must not exceed total number of images (%d) in the swapchain.",
+ index,
+ (uint32_t)m_images.getCount());
+ }
+ returnComPtr(outResource, m_images[index]);
+ return SLANG_OK;
+}
+
+Result DebugSwapchain::present()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->present();
+}
+
+int DebugSwapchain::acquireNextImage()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->acquireNextImage();
+}
+
+Result DebugSwapchain::resize(GfxCount width, GfxCount height)
+{
+ SLANG_GFX_API_FUNC;
+ for (auto& image : m_images)
+ {
+ if (image->debugGetReferenceCount() != 1)
+ {
+ GFX_DIAGNOSE_ERROR("all swapchain images must be released before calling resize().");
+ return SLANG_FAIL;
+ }
+ }
+ m_images.clearAndDeallocate();
+ return baseObject->resize(width, height);
+}
+
+bool DebugSwapchain::isOccluded()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->isOccluded();
+}
+
+Result DebugSwapchain::setFullScreenMode(bool mode)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->setFullScreenMode(mode);
+}
+
+void DebugSwapchain::maybeRebuildImageList()
+{
+ SLANG_GFX_API_FUNC;
+ if (m_images.getCount() != 0)
+ return;
+ m_images.clearAndDeallocate();
+ for (GfxIndex i = 0; i < baseObject->getDesc().imageCount; i++)
+ {
+ RefPtr<DebugTextureResource> image = new DebugTextureResource();
+ baseObject->getImage(i, image->baseObject.writeRef());
+ m_images.add(image);
+ }
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-swap-chain.h b/tools/gfx/debug-layer/debug-swap-chain.h
new file mode 100644
index 000000000..83a467d65
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-swap-chain.h
@@ -0,0 +1,38 @@
+// debug-swap-chain.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugSwapchain : public DebugObject<ISwapchain>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ ISwapchain* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getImage(GfxIndex index, ITextureResource** outResource) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL present() override;
+ virtual SLANG_NO_THROW int SLANG_MCALL acquireNextImage() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL resize(GfxCount width, GfxCount height) override;
+ virtual SLANG_NO_THROW bool SLANG_MCALL isOccluded() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL setFullScreenMode(bool mode) override;
+
+public:
+ Slang::RefPtr<DebugCommandQueue> queue;
+ Desc desc;
+
+private:
+ Slang::List<Slang::RefPtr<DebugTextureResource>> m_images;
+ void maybeRebuildImageList();
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-texture.cpp b/tools/gfx/debug-layer/debug-texture.cpp
new file mode 100644
index 000000000..ad3dce4fe
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-texture.cpp
@@ -0,0 +1,45 @@
+// debug-texture.cpp
+#include "debug-texture.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+IResource::Type DebugTextureResource::getType()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getType();
+}
+
+ITextureResource::Desc* DebugTextureResource::getDesc()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getDesc();
+}
+
+Result DebugTextureResource::getNativeResourceHandle(InteropHandle* outHandle)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getNativeResourceHandle(outHandle);
+}
+
+Result DebugTextureResource::getSharedHandle(InteropHandle* outHandle)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->getSharedHandle(outHandle);
+}
+
+Result DebugTextureResource::setDebugName(const char* name)
+{
+ return baseObject->setDebugName(name);
+}
+
+const char* DebugTextureResource::getDebugName() { return baseObject->getDebugName(); }
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-texture.h b/tools/gfx/debug-layer/debug-texture.h
new file mode 100644
index 000000000..79e3aa3cf
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-texture.h
@@ -0,0 +1,29 @@
+// debug-texture.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugTextureResource : public DebugObject<ITextureResource>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ ITextureResource* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW Type SLANG_MCALL getType() override;
+ virtual SLANG_NO_THROW Desc* SLANG_MCALL getDesc() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) override;
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) override;
+ virtual SLANG_NO_THROW const char* SLANG_MCALL getDebugName() override;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-transient-heap.cpp b/tools/gfx/debug-layer/debug-transient-heap.cpp
new file mode 100644
index 000000000..91e575742
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-transient-heap.cpp
@@ -0,0 +1,40 @@
+// debug-transient-heap.cpp
+#include "debug-transient-heap.h"
+
+#include "debug-command-buffer.h"
+
+#include "debug-helper-functions.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+Result DebugTransientResourceHeap::synchronizeAndReset()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->synchronizeAndReset();
+}
+
+Result DebugTransientResourceHeap::finish()
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->finish();
+}
+
+Result DebugTransientResourceHeap::createCommandBuffer(ICommandBuffer** outCommandBuffer)
+{
+ SLANG_GFX_API_FUNC;
+ RefPtr<DebugCommandBuffer> outObject = new DebugCommandBuffer();
+ outObject->m_transientHeap = this;
+ auto result = baseObject->createCommandBuffer(outObject->baseObject.writeRef());
+ if (SLANG_FAILED(result))
+ return result;
+ returnComPtr(outCommandBuffer, outObject);
+ return result;
+}
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-transient-heap.h b/tools/gfx/debug-layer/debug-transient-heap.h
new file mode 100644
index 000000000..dd89d8a21
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-transient-heap.h
@@ -0,0 +1,26 @@
+// debug-transient-heap.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugTransientResourceHeap : public DebugObject<ITransientResourceHeap>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ ITransientResourceHeap* getInterface(const Slang::Guid& guid);
+ virtual SLANG_NO_THROW Result SLANG_MCALL synchronizeAndReset() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL finish() override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createCommandBuffer(ICommandBuffer** outCommandBuffer) override;
+};
+
+} // namespace debug
+} // namespace gfx
diff --git a/tools/gfx/debug-layer/debug-vertex-layout.h b/tools/gfx/debug-layer/debug-vertex-layout.h
new file mode 100644
index 000000000..db3053c57
--- /dev/null
+++ b/tools/gfx/debug-layer/debug-vertex-layout.h
@@ -0,0 +1,22 @@
+// debug-vertex-layout.h
+#pragma once
+#include "debug-base.h"
+
+namespace gfx
+{
+using namespace Slang;
+
+namespace debug
+{
+
+class DebugInputLayout : public DebugObject<IInputLayout>
+{
+public:
+ SLANG_COM_OBJECT_IUNKNOWN_ALL;
+
+public:
+ IInputLayout* getInterface(const Slang::Guid& guid);
+};
+
+} // namespace debug
+} // namespace gfx