summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj2
-rw-r--r--build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters6
-rw-r--r--slang-gfx.h2
-rw-r--r--tools/gfx-unit-test/gfx-test-util.h2
-rw-r--r--tools/gfx-unit-test/resolve-resource-shader.slang54
-rw-r--r--tools/gfx-unit-test/resolve-resource-tests.cpp355
-rw-r--r--tools/gfx/cuda/render-cuda.cpp4
-rw-r--r--tools/gfx/d3d12/render-d3d12.cpp39
-rw-r--r--tools/gfx/debug-layer.cpp4
-rw-r--r--tools/gfx/debug-layer.h2
-rw-r--r--tools/gfx/immediate-renderer-base.cpp4
-rw-r--r--tools/gfx/vulkan/render-vk.cpp57
-rw-r--r--tools/gfx/vulkan/vk-api.h1
13 files changed, 516 insertions, 16 deletions
diff --git a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj
index f43d6150e..59103d30e 100644
--- a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj
+++ b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj
@@ -286,6 +286,7 @@
<ClCompile Include="..\..\..\tools\gfx-unit-test\instanced-draw-tests.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\mutable-shader-object.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\nested-parameter-block.cpp" />
+ <ClCompile Include="..\..\..\tools\gfx-unit-test\resolve-resource-tests.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\root-mutable-shader-object.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\shared-buffers-tests.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\shared-textures-tests.cpp" />
@@ -299,6 +300,7 @@
<None Include="..\..\..\tools\gfx-unit-test\graphics-smoke.slang" />
<None Include="..\..\..\tools\gfx-unit-test\mutable-shader-object.slang" />
<None Include="..\..\..\tools\gfx-unit-test\nested-parameter-block.slang" />
+ <None Include="..\..\..\tools\gfx-unit-test\resolve-resource-shader.slang" />
<None Include="..\..\..\tools\gfx-unit-test\trivial-copy.slang" />
</ItemGroup>
<ItemGroup>
diff --git a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters
index ff873deb9..aec553af8 100644
--- a/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters
+++ b/build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters
@@ -71,6 +71,9 @@
<ClCompile Include="..\..\..\tools\unit-test\slang-unit-test.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\tools\gfx-unit-test\resolve-resource-tests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\tools\gfx-unit-test\buffer-barrier-test.slang">
@@ -97,5 +100,8 @@
<None Include="..\..\..\tools\gfx-unit-test\trivial-copy.slang">
<Filter>Source Files</Filter>
</None>
+ <None Include="..\..\..\tools\gfx-unit-test\resolve-resource-shader.slang">
+ <Filter>Source Files</Filter>
+ </None>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/slang-gfx.h b/slang-gfx.h
index 5949e5463..dcd78fc5b 100644
--- a/slang-gfx.h
+++ b/slang-gfx.h
@@ -1629,8 +1629,10 @@ public:
IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags) = 0;
virtual SLANG_NO_THROW void SLANG_MCALL resolveResource(
ITextureResource* source,
+ ResourceState sourceState,
SubresourceRange sourceRange,
ITextureResource* dest,
+ ResourceState destState,
SubresourceRange destRange) = 0;
};
diff --git a/tools/gfx-unit-test/gfx-test-util.h b/tools/gfx-unit-test/gfx-test-util.h
index 3be47bc82..67660d4f5 100644
--- a/tools/gfx-unit-test/gfx-test-util.h
+++ b/tools/gfx-unit-test/gfx-test-util.h
@@ -34,7 +34,7 @@ namespace gfx_test
const void* expectedResult,
size_t expectedBufferSize);
- /// Reads back the content of `buffer` and compares it against `expectedResult`.
+ /// Reads back the content of `texture` and compares it against `expectedResult`.
void compareComputeResult(
gfx::IDevice* device,
gfx::ITextureResource* texture,
diff --git a/tools/gfx-unit-test/resolve-resource-shader.slang b/tools/gfx-unit-test/resolve-resource-shader.slang
new file mode 100644
index 000000000..f8f3319c2
--- /dev/null
+++ b/tools/gfx-unit-test/resolve-resource-shader.slang
@@ -0,0 +1,54 @@
+// resolve-resource-shader.slang
+
+// Per-vertex attributes to be assembled from bound vertex buffers.
+struct AssembledVertex
+{
+ float3 position : POSITION;
+ float3 color : COLOR;
+};
+
+// Output of the vertex shader, and input to the fragment shader.
+struct CoarseVertex
+{
+ float3 color;
+};
+
+// Output of the fragment shader
+struct Fragment
+{
+ float4 color;
+};
+
+// Vertex Shader
+
+struct VertexStageOutput
+{
+ CoarseVertex coarseVertex : CoarseVertex;
+ float4 sv_position : SV_Position;
+};
+
+[shader("vertex")]
+VertexStageOutput vertexMain(
+ AssembledVertex assembledVertex)
+{
+ VertexStageOutput output;
+
+ float3 position = assembledVertex.position;
+ float3 color = assembledVertex.color;
+
+ output.coarseVertex.color = color;
+ output.sv_position = float4(position, 1.0);
+
+ return output;
+}
+
+// Fragment Shader
+
+[shader("fragment")]
+float4 fragmentMain(
+ CoarseVertex coarseVertex : CoarseVertex) : SV_Target
+{
+ float3 color = coarseVertex.color;
+
+ return float4(color, 1.0);
+}
diff --git a/tools/gfx-unit-test/resolve-resource-tests.cpp b/tools/gfx-unit-test/resolve-resource-tests.cpp
new file mode 100644
index 000000000..2876be880
--- /dev/null
+++ b/tools/gfx-unit-test/resolve-resource-tests.cpp
@@ -0,0 +1,355 @@
+#include "tools/unit-test/slang-unit-test.h"
+
+#include "slang-gfx.h"
+#include "gfx-test-util.h"
+#include "tools/gfx-util/shader-cursor.h"
+#include "source/core/slang-basic.h"
+
+#if SLANG_WINDOWS_FAMILY
+#include <d3d12.h>
+#endif
+
+#if 0
+#include <stdlib.h>
+#include <stdio.h>
+
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+#include "external/stb/stb_image_write.h"
+#endif
+
+using namespace Slang;
+using namespace gfx;
+
+namespace
+{
+ using namespace gfx_test;
+
+#if 0
+ Slang::Result writeImage(
+ const char* filename,
+ ISlangBlob* pixels,
+ uint32_t width,
+ uint32_t height)
+ {
+ int stbResult =
+ stbi_write_hdr(filename, width, height, 4, (float*)pixels->getBufferPointer());
+
+ return stbResult ? SLANG_OK : SLANG_FAIL;
+ }
+#endif
+
+ struct Vertex
+ {
+ float position[3];
+ float color[3];
+ };
+
+ static const int kVertexCount = 12;
+ static const Vertex kVertexData[kVertexCount] =
+ {
+ // Triangle 1
+ { { 0, 0, 0.5 }, { 1, 0, 0 } },
+ { { 1, 1, 0.5 }, { 1, 0, 0 } },
+ { { -1, 1, 0.5 }, { 1, 0, 0 } },
+
+ // Triangle 2
+ { { -1, 1, 0.5 }, { 0, 1, 0 } },
+ { { 0, 0, 0.5 }, { 0, 1, 0 } },
+ { { -1, -1, 0.5 }, { 0, 1, 0 } },
+
+ // Triangle 3
+ { { -1, -1, 0.5 }, { 0, 0, 1 } },
+ { { 0, 0, 0.5 }, { 0, 0, 1 } },
+ { { 1, -1, 0.5 }, { 0, 0, 1 } },
+
+ // Triangle 4
+ { { 1, -1, 0.5 }, { 0, 0, 0 } },
+ { { 0, 0, 0.5 }, { 0, 0, 0 } },
+ { { 1, 1, 0.5 }, { 0, 0, 0 } },
+ };
+
+ const int kWidth = 256;
+ const int kHeight = 256;
+ Format format = Format::R32G32B32A32_FLOAT;
+
+ ComPtr<IBufferResource> createVertexBuffer(IDevice* device)
+ {
+ IBufferResource::Desc vertexBufferDesc;
+ vertexBufferDesc.type = IResource::Type::Buffer;
+ vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex);
+ vertexBufferDesc.defaultState = ResourceState::VertexBuffer;
+ vertexBufferDesc.allowedStates = ResourceState::VertexBuffer;
+ ComPtr<IBufferResource> vertexBuffer = device->createBufferResource(vertexBufferDesc, &kVertexData[0]);
+ SLANG_CHECK_ABORT(vertexBuffer != nullptr);
+ return vertexBuffer;
+ }
+
+ struct BaseResolveResourceTest
+ {
+ IDevice* device;
+ UnitTestContext* context;
+
+ ComPtr<ITextureResource> msaaTexture;
+ ComPtr<ITextureResource> dstTexture;
+
+ ComPtr<ITransientResourceHeap> transientHeap;
+ ComPtr<IPipelineState> pipelineState;
+ ComPtr<IRenderPassLayout> renderPass;
+ ComPtr<IFramebuffer> framebuffer;
+
+ ComPtr<IBufferResource> vertexBuffer;
+
+ struct TextureInfo
+ {
+ ITextureResource::Size extent;
+ int numMipLevels;
+ int arraySize;
+ ITextureResource::SubresourceData const* initData;
+ };
+
+ void init(IDevice* device, UnitTestContext* context)
+ {
+ this->device = device;
+ this->context = context;
+ }
+
+ void createRequiredResources(TextureInfo msaaTextureInfo, TextureInfo dstTextureInfo, Format format)
+ {
+ VertexStreamDesc vertexStreams[] = {
+ { sizeof(Vertex), InputSlotClass::PerVertex, 0 },
+ };
+
+ InputElementDesc inputElements[] = {
+ // Vertex buffer data
+ { "POSITION", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, position), 0 },
+ { "COLOR", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, color), 0 },
+ };
+
+ ITextureResource::Desc msaaTexDesc = {};
+ msaaTexDesc.type = IResource::Type::Texture2D;
+ msaaTexDesc.numMipLevels = dstTextureInfo.numMipLevels;
+ msaaTexDesc.arraySize = dstTextureInfo.arraySize;
+ msaaTexDesc.size = dstTextureInfo.extent;
+ msaaTexDesc.defaultState = ResourceState::RenderTarget;
+ msaaTexDesc.allowedStates = ResourceStateSet(
+ ResourceState::RenderTarget,
+ ResourceState::ResolveSource);
+ msaaTexDesc.format = format;
+ msaaTexDesc.sampleDesc.numSamples = 4;
+
+ GFX_CHECK_CALL_ABORT(device->createTextureResource(
+ msaaTexDesc,
+ msaaTextureInfo.initData,
+ msaaTexture.writeRef()));
+
+ ITextureResource::Desc dstTexDesc = {};
+ dstTexDesc.type = IResource::Type::Texture2D;
+ dstTexDesc.numMipLevels = dstTextureInfo.numMipLevels;
+ dstTexDesc.arraySize = dstTextureInfo.arraySize;
+ dstTexDesc.size = dstTextureInfo.extent;
+ dstTexDesc.defaultState = ResourceState::ResolveDestination;
+ dstTexDesc.allowedStates = ResourceStateSet(
+ ResourceState::ResolveDestination,
+ ResourceState::CopySource);
+ dstTexDesc.format = format;
+
+ GFX_CHECK_CALL_ABORT(device->createTextureResource(
+ dstTexDesc,
+ dstTextureInfo.initData,
+ dstTexture.writeRef()));
+
+ IInputLayout::Desc inputLayoutDesc = {};
+ inputLayoutDesc.inputElementCount = SLANG_COUNT_OF(inputElements);
+ inputLayoutDesc.inputElements = inputElements;
+ inputLayoutDesc.vertexStreamCount = SLANG_COUNT_OF(vertexStreams);
+ inputLayoutDesc.vertexStreams = vertexStreams;
+ auto inputLayout = device->createInputLayout(inputLayoutDesc);
+ SLANG_CHECK_ABORT(inputLayout != nullptr);
+
+ vertexBuffer = createVertexBuffer(device);
+
+ ITransientResourceHeap::Desc transientHeapDesc = {};
+ transientHeapDesc.constantBufferSize = 4096;
+ GFX_CHECK_CALL_ABORT(
+ device->createTransientResourceHeap(transientHeapDesc, transientHeap.writeRef()));
+
+ ComPtr<IShaderProgram> shaderProgram;
+ slang::ProgramLayout* slangReflection;
+ GFX_CHECK_CALL_ABORT(loadGraphicsProgram(device, shaderProgram, "resolve-resource-shader", "vertexMain", "fragmentMain", slangReflection));
+
+ IFramebufferLayout::AttachmentLayout attachmentLayout;
+ attachmentLayout.format = format;
+ attachmentLayout.sampleCount = 4;
+
+ IFramebufferLayout::Desc framebufferLayoutDesc;
+ framebufferLayoutDesc.renderTargetCount = 1;
+ framebufferLayoutDesc.renderTargets = &attachmentLayout;
+ ComPtr<gfx::IFramebufferLayout> framebufferLayout = device->createFramebufferLayout(framebufferLayoutDesc);
+ SLANG_CHECK_ABORT(framebufferLayout != nullptr);
+
+ GraphicsPipelineStateDesc pipelineDesc = {};
+ pipelineDesc.program = shaderProgram.get();
+ pipelineDesc.inputLayout = inputLayout;
+ pipelineDesc.framebufferLayout = framebufferLayout;
+ pipelineDesc.depthStencil.depthTestEnable = false;
+ pipelineDesc.depthStencil.depthWriteEnable = false;
+ GFX_CHECK_CALL_ABORT(
+ device->createGraphicsPipelineState(pipelineDesc, pipelineState.writeRef()));
+
+ IRenderPassLayout::Desc renderPassDesc = {};
+ renderPassDesc.framebufferLayout = framebufferLayout;
+ renderPassDesc.renderTargetCount = 1;
+ IRenderPassLayout::AttachmentAccessDesc renderTargetAccess = {};
+ renderTargetAccess.loadOp = IRenderPassLayout::AttachmentLoadOp::Clear;
+ renderTargetAccess.storeOp = IRenderPassLayout::AttachmentStoreOp::Store;
+ renderTargetAccess.initialState = ResourceState::RenderTarget;
+ renderTargetAccess.finalState = ResourceState::ResolveSource;
+ renderPassDesc.renderTargetAccess = &renderTargetAccess;
+ GFX_CHECK_CALL_ABORT(device->createRenderPassLayout(renderPassDesc, renderPass.writeRef()));
+
+ gfx::IResourceView::Desc colorBufferViewDesc;
+ memset(&colorBufferViewDesc, 0, sizeof(colorBufferViewDesc));
+ colorBufferViewDesc.format = format;
+ colorBufferViewDesc.renderTarget.shape = gfx::IResource::Type::Texture2D;
+ colorBufferViewDesc.type = gfx::IResourceView::Type::RenderTarget;
+ auto rtv = device->createTextureView(msaaTexture, colorBufferViewDesc);
+
+ gfx::IFramebuffer::Desc framebufferDesc;
+ framebufferDesc.renderTargetCount = 1;
+ framebufferDesc.depthStencilView = nullptr;
+ framebufferDesc.renderTargetViews = rtv.readRef();
+ framebufferDesc.layout = framebufferLayout;
+ GFX_CHECK_CALL_ABORT(device->createFramebuffer(framebufferDesc, framebuffer.writeRef()));
+ }
+
+ void submitGPUWork(SubresourceRange msaaSubresource, SubresourceRange dstSubresource, ITextureResource::Size extent)
+ {
+ Slang::ComPtr<ITransientResourceHeap> transientHeap;
+ ITransientResourceHeap::Desc transientHeapDesc = {};
+ transientHeapDesc.constantBufferSize = 4096;
+ GFX_CHECK_CALL_ABORT(
+ device->createTransientResourceHeap(transientHeapDesc, transientHeap.writeRef()));
+
+ ICommandQueue::Desc queueDesc = { ICommandQueue::QueueType::Graphics };
+ auto queue = device->createCommandQueue(queueDesc);
+
+ auto commandBuffer = transientHeap->createCommandBuffer();
+ auto renderEncoder = commandBuffer->encodeRenderCommands(renderPass, framebuffer);
+ auto rootObject = renderEncoder->bindPipeline(pipelineState);
+
+ gfx::Viewport viewport = {};
+ viewport.maxZ = 1.0f;
+ viewport.extentX = kWidth;
+ viewport.extentY = kHeight;
+ renderEncoder->setViewportAndScissor(viewport);
+
+ renderEncoder->setVertexBuffer(0, vertexBuffer);
+ renderEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleList);
+ renderEncoder->draw(kVertexCount, 0);
+ renderEncoder->endEncoding();
+
+ auto resourceEncoder = commandBuffer->encodeResourceCommands();
+
+ resourceEncoder->resolveResource(msaaTexture, ResourceState::ResolveSource, msaaSubresource, dstTexture, ResourceState::ResolveDestination, dstSubresource);
+ resourceEncoder->textureSubresourceBarrier(dstTexture, dstSubresource, ResourceState::ResolveDestination, ResourceState::CopySource);
+ resourceEncoder->endEncoding();
+ commandBuffer->close();
+ queue->executeCommandBuffer(commandBuffer);
+ queue->waitOnHost();
+ }
+
+ void checkTestResults(int pixelCount, int channelCount, const int* testXCoords, const int* testYCoords, float* testResults)
+ {
+ // Read texture values back from four specific pixels located within the triangles
+ // and compare against expected values (because testing every single pixel will be too long and tedious
+ // and requires maintaining reference images).
+ ComPtr<ISlangBlob> resultBlob;
+ size_t rowPitch = 0;
+ size_t pixelSize = 0;
+ GFX_CHECK_CALL_ABORT(device->readTextureResource(
+ dstTexture, ResourceState::CopySource, resultBlob.writeRef(), &rowPitch, &pixelSize));
+ auto result = (float*)resultBlob->getBufferPointer();
+
+ int cursor = 0;
+ for (int i = 0; i < pixelCount; ++i)
+ {
+ auto x = testXCoords[i];
+ auto y = testYCoords[i];
+ auto pixelPtr = result + x * channelCount + y * rowPitch / sizeof(float);
+ for (int j = 0; j < channelCount; ++j)
+ {
+ testResults[cursor] = pixelPtr[j];
+ cursor++;
+ }
+ }
+
+ float expectedResult[] = { 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.0f };
+ SLANG_CHECK(memcmp(testResults, expectedResult, 128) == 0);
+ }
+ };
+
+ // TODO: Add more tests?
+
+ struct ResolveResourceSimple : BaseResolveResourceTest
+ {
+ void run()
+ {
+ ITextureResource::Size extent = {};
+ extent.width = kWidth;
+ extent.height = kHeight;
+ extent.depth = 1;
+
+ TextureInfo msaaTextureInfo = { extent, 1, 1, nullptr };
+ TextureInfo dstTextureInfo = { extent, 1, 1, nullptr };
+
+ createRequiredResources(msaaTextureInfo, dstTextureInfo, format);
+
+ SubresourceRange msaaSubresource = {};
+ msaaSubresource.aspectMask = TextureAspect::Color;
+ msaaSubresource.mipLevel = 0;
+ msaaSubresource.mipLevelCount = 1;
+ msaaSubresource.baseArrayLayer = 0;
+ msaaSubresource.layerCount = 1;
+
+ SubresourceRange dstSubresource = {};
+ dstSubresource.aspectMask = TextureAspect::Color;
+ dstSubresource.mipLevel = 0;
+ dstSubresource.mipLevelCount = 1;
+ dstSubresource.baseArrayLayer = 0;
+ dstSubresource.layerCount = 1;
+
+ submitGPUWork(msaaSubresource, dstSubresource, extent);
+
+ const int kPixelCount = 8;
+ const int kChannelCount = 4;
+ int testXCoords[kPixelCount] = { 64, 127, 191, 64, 191, 64, 127, 191 };
+ int testYCoords[kPixelCount] = { 64, 64, 64, 127, 127, 191, 191, 191 };
+ float testResults[kPixelCount * kChannelCount];
+
+ checkTestResults(kPixelCount, kChannelCount, testXCoords, testYCoords, testResults);
+ }
+ };
+
+ template<typename T>
+ void resolveResourceTestImpl(IDevice* device, UnitTestContext* context)
+ {
+ T test;
+ test.init(device, context);
+ test.run();
+ }
+}
+
+namespace gfx_test
+{
+ SLANG_UNIT_TEST(resolveResourceSimpleD3D12)
+ {
+ runTestImpl(resolveResourceTestImpl<ResolveResourceSimple>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ }
+
+ SLANG_UNIT_TEST(resolveResourceSimpleVulkan)
+ {
+ runTestImpl(resolveResourceTestImpl<ResolveResourceSimple>, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ }
+}
diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp
index 3e55242f0..0446dc055 100644
--- a/tools/gfx/cuda/render-cuda.cpp
+++ b/tools/gfx/cuda/render-cuda.cpp
@@ -1111,13 +1111,17 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL resolveResource(
ITextureResource* source,
+ ResourceState sourceState,
SubresourceRange sourceRange,
ITextureResource* dest,
+ ResourceState destState,
SubresourceRange destRange) override
{
SLANG_UNUSED(source);
+ SLANG_UNUSED(sourceState);
SLANG_UNUSED(sourceRange);
SLANG_UNUSED(dest);
+ SLANG_UNUSED(destState);
SLANG_UNUSED(destRange);
SLANG_UNIMPLEMENTED_X("resolveResource");
}
diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp
index e0c324d34..1b146bc4e 100644
--- a/tools/gfx/d3d12/render-d3d12.cpp
+++ b/tools/gfx/d3d12/render-d3d12.cpp
@@ -4314,15 +4314,44 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL resolveResource(
ITextureResource* source,
+ ResourceState sourceState,
SubresourceRange sourceRange,
ITextureResource* dest,
+ ResourceState destState,
SubresourceRange destRange) override
{
- SLANG_UNUSED(source);
- SLANG_UNUSED(sourceRange);
- SLANG_UNUSED(dest);
- SLANG_UNUSED(destRange);
- SLANG_UNIMPLEMENTED_X("resolveResource");
+ auto srcTexture = static_cast<TextureResourceImpl*>(source);
+ auto srcDesc = srcTexture->getDesc();
+ auto dstTexture = static_cast<TextureResourceImpl*>(dest);
+ auto dstDesc = dstTexture->getDesc();
+
+ for (uint32_t layer = 0; layer < sourceRange.layerCount; ++layer)
+ {
+ for (uint32_t mip = 0; mip < sourceRange.mipLevelCount; ++mip)
+ {
+ auto srcSubresourceIndex = D3DUtil::getSubresourceIndex(
+ mip + sourceRange.mipLevel,
+ layer + sourceRange.baseArrayLayer,
+ 0,
+ srcDesc->numMipLevels,
+ srcDesc->arraySize);
+ auto dstSubresourceIndex = D3DUtil::getSubresourceIndex(
+ mip + destRange.mipLevel,
+ layer + destRange.baseArrayLayer,
+ 0,
+ dstDesc->numMipLevels,
+ dstDesc->arraySize);
+
+ DXGI_FORMAT format = D3DUtil::getMapFormat(srcDesc->format);
+
+ m_commandBuffer->m_cmdList->ResolveSubresource(
+ dstTexture->m_resource.getResource(),
+ dstSubresourceIndex,
+ srcTexture->m_resource.getResource(),
+ srcSubresourceIndex,
+ format);
+ }
+ }
}
virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer(
diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp
index 53deec385..f34a77556 100644
--- a/tools/gfx/debug-layer.cpp
+++ b/tools/gfx/debug-layer.cpp
@@ -1343,12 +1343,14 @@ void DebugResourceCommandEncoder::clearResourceView(
void DebugResourceCommandEncoder::resolveResource(
ITextureResource* source,
+ ResourceState sourceState,
SubresourceRange sourceRange,
ITextureResource* dest,
+ ResourceState destState,
SubresourceRange destRange)
{
SLANG_GFX_API_FUNC;
- baseObject->resolveResource(getInnerObj(source), sourceRange, getInnerObj(dest), destRange);
+ baseObject->resolveResource(getInnerObj(source), sourceState, sourceRange, getInnerObj(dest), destState, destRange);
}
void DebugResourceCommandEncoder::copyTextureToBuffer(
diff --git a/tools/gfx/debug-layer.h b/tools/gfx/debug-layer.h
index a2de7eb31..94f3e3f14 100644
--- a/tools/gfx/debug-layer.h
+++ b/tools/gfx/debug-layer.h
@@ -463,8 +463,10 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL resolveResource(
ITextureResource* source,
+ ResourceState sourceState,
SubresourceRange sourceRange,
ITextureResource* dest,
+ ResourceState destState,
SubresourceRange destRange) override;
virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer(
diff --git a/tools/gfx/immediate-renderer-base.cpp b/tools/gfx/immediate-renderer-base.cpp
index ab2a51275..91b89c8cf 100644
--- a/tools/gfx/immediate-renderer-base.cpp
+++ b/tools/gfx/immediate-renderer-base.cpp
@@ -385,13 +385,17 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL resolveResource(
ITextureResource* source,
+ ResourceState sourceState,
SubresourceRange sourceRange,
ITextureResource* dest,
+ ResourceState destState,
SubresourceRange destRange) override
{
SLANG_UNUSED(source);
+ SLANG_UNUSED(sourceState);
SLANG_UNUSED(sourceRange);
SLANG_UNUSED(dest);
+ SLANG_UNUSED(destState);
SLANG_UNUSED(destRange);
SLANG_UNIMPLEMENTED_X("resolveResource");
}
diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp
index f31195cc8..517580c08 100644
--- a/tools/gfx/vulkan/render-vk.cpp
+++ b/tools/gfx/vulkan/render-vk.cpp
@@ -561,6 +561,7 @@ public:
VkAttachmentReference m_depthReference;
bool m_hasDepthStencilAttachment;
uint32_t m_renderTargetCount;
+ VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
public:
~FramebufferLayoutImpl()
@@ -601,6 +602,8 @@ public:
dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
dst.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
dst.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ sampleCount = Math::Max(dst.samples, sampleCount);
}
if (desc.depthStencil)
@@ -615,6 +618,8 @@ public:
dst.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
dst.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
dst.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ sampleCount = Math::Max(dst.samples, sampleCount);
}
Array<VkAttachmentReference, kMaxRenderTargets>& colorReferences = m_colorReferences;
@@ -4780,15 +4785,43 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL resolveResource(
ITextureResource* source,
+ ResourceState sourceState,
SubresourceRange sourceRange,
ITextureResource* dest,
+ ResourceState destState,
SubresourceRange destRange) override
{
- SLANG_UNUSED(source);
- SLANG_UNUSED(sourceRange);
- SLANG_UNUSED(dest);
- SLANG_UNUSED(destRange);
- SLANG_UNIMPLEMENTED_X("resolveResource");
+ auto srcTexture = static_cast<TextureResourceImpl*>(source);
+ auto srcExtent = srcTexture->getDesc()->size;
+ auto dstTexture = static_cast<TextureResourceImpl*>(dest);
+
+ auto srcImage = srcTexture->m_image;
+ auto dstImage = dstTexture->m_image;
+
+ auto srcImageLayout = VulkanUtil::getImageLayoutFromState(sourceState);
+ auto dstImageLayout = VulkanUtil::getImageLayoutFromState(destState);
+
+ for (uint32_t layer = 0; layer < sourceRange.layerCount; ++layer)
+ {
+ for (uint32_t mip = 0; mip < sourceRange.mipLevelCount; ++mip)
+ {
+ VkImageResolve region = {};
+ region.srcSubresource.aspectMask = getAspectMask(sourceRange.aspectMask);
+ region.srcSubresource.baseArrayLayer = layer + sourceRange.baseArrayLayer;
+ region.srcSubresource.layerCount = 1;
+ region.srcSubresource.mipLevel = mip + sourceRange.mipLevel;
+ region.srcOffset = { 0, 0, 0 };
+ region.dstSubresource.aspectMask = getAspectMask(destRange.aspectMask);
+ region.dstSubresource.baseArrayLayer = layer + destRange.baseArrayLayer;
+ region.dstSubresource.layerCount = 1;
+ region.dstSubresource.mipLevel = mip + destRange.mipLevel;
+ region.dstOffset = { 0, 0, 0 };
+ region.extent = { (uint32_t)srcExtent.width, (uint32_t)srcExtent.height, (uint32_t)srcExtent.depth };
+
+ auto& vkApi = m_commandBuffer->m_renderer->m_api;
+ vkApi.vkCmdResolveImage(m_commandBuffer->m_commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, 1, &region);
+ }
+ }
}
virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer(
@@ -7092,6 +7125,10 @@ static VkImageUsageFlagBits _calcImageUsageFlags(ResourceState state)
return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
case ResourceState::CopyDestination:
return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ case ResourceState::ResolveSource:
+ return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ case ResourceState::ResolveDestination:
+ return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
default:
{
assert(!"Unsupported");
@@ -7323,7 +7360,7 @@ Result VKDevice::getTextureAllocationInfo(
imageInfo.usage = _calcImageUsageFlags(desc.allowedStates, desc.memoryType, nullptr);
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+ imageInfo.samples = (VkSampleCountFlagBits)desc.sampleDesc.numSamples;
VkImage image;
SLANG_VK_RETURN_ON_FAIL(m_api.vkCreateImage(m_device, &imageInfo, nullptr, &image));
@@ -7402,7 +7439,7 @@ Result VKDevice::createTextureResource(const ITextureResource::Desc& descIn, con
imageInfo.usage = _calcImageUsageFlags(desc.allowedStates, desc.memoryType, initData);
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+ imageInfo.samples = (VkSampleCountFlagBits)desc.sampleDesc.numSamples;
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = { VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO };
#if SLANG_WINDOWS_FAMILY
@@ -8278,10 +8315,12 @@ Result VKDevice::createGraphicsPipelineState(const GraphicsPipelineStateDesc& in
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
+ auto framebufferLayoutImpl = static_cast<FramebufferLayoutImpl*>(desc.framebufferLayout);
+
VkPipelineMultisampleStateCreateInfo multisampling = {};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
- multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ multisampling.rasterizationSamples = framebufferLayoutImpl->sampleCount;
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
@@ -8332,7 +8371,7 @@ Result VKDevice::createGraphicsPipelineState(const GraphicsPipelineStateDesc& in
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDepthStencilState = &depthStencilStateInfo;
pipelineInfo.layout = programImpl->m_rootObjectLayout->m_pipelineLayout;
- pipelineInfo.renderPass = static_cast<FramebufferLayoutImpl*>(desc.framebufferLayout)->m_renderPass;
+ pipelineInfo.renderPass = framebufferLayoutImpl->m_renderPass;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
pipelineInfo.pDynamicState = &dynamicStateInfo;
diff --git a/tools/gfx/vulkan/vk-api.h b/tools/gfx/vulkan/vk-api.h
index 72a6e73c8..7df51668f 100644
--- a/tools/gfx/vulkan/vk-api.h
+++ b/tools/gfx/vulkan/vk-api.h
@@ -98,6 +98,7 @@ namespace gfx {
x(vkCmdCopyBufferToImage)\
x(vkCmdCopyImage) \
x(vkCmdCopyImageToBuffer) \
+ x(vkCmdResolveImage) \
x(vkCmdPushConstants) \
x(vkCmdSetStencilReference) \
x(vkCmdWriteTimestamp) \