summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj1
-rw-r--r--build/visual-studio/gfx-unit-test-tool/gfx-unit-test-tool.vcxproj.filters3
-rw-r--r--slang-gfx.h3
-rw-r--r--tools/gfx-unit-test/copy-texture-tests.cpp365
-rw-r--r--tools/gfx-unit-test/gfx-test-util.cpp9
-rw-r--r--tools/gfx-unit-test/gfx-test-util.h23
-rw-r--r--tools/gfx/cuda/render-cuda.cpp6
-rw-r--r--tools/gfx/d3d12/render-d3d12.cpp138
-rw-r--r--tools/gfx/debug-layer.cpp7
-rw-r--r--tools/gfx/debug-layer.h3
-rw-r--r--tools/gfx/immediate-renderer-base.cpp6
-rw-r--r--tools/gfx/vulkan/render-vk.cpp117
-rw-r--r--tools/gfx/vulkan/vk-api.h1
13 files changed, 569 insertions, 113 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 34ab74ecf..f43d6150e 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
@@ -274,6 +274,7 @@
<ItemGroup>
<ClCompile Include="..\..\..\tools\gfx-unit-test\buffer-barrier-test.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\compute-smoke.cpp" />
+ <ClCompile Include="..\..\..\tools\gfx-unit-test\copy-texture-tests.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\create-buffer-from-handle.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\existing-device-handle-test.cpp" />
<ClCompile Include="..\..\..\tools\gfx-unit-test\format-unit-tests.cpp" />
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 4925f7f4b..ff873deb9 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
@@ -23,6 +23,9 @@
<ClCompile Include="..\..\..\tools\gfx-unit-test\compute-smoke.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\tools\gfx-unit-test\copy-texture-tests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\tools\gfx-unit-test\create-buffer-from-handle.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/slang-gfx.h b/slang-gfx.h
index 4eb1fe707..c35892eb4 100644
--- a/slang-gfx.h
+++ b/slang-gfx.h
@@ -1560,9 +1560,11 @@ public:
/// the entire resource is being copied and dstOffset, srcOffset and extent arguments are ignored.
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::Size extent) = 0;
@@ -1573,6 +1575,7 @@ public:
size_t dstOffset,
size_t dstSize,
ITextureResource* src,
+ ResourceState srcState,
SubresourceRange srcSubresource,
ITextureResource::Offset3D srcOffset,
ITextureResource::Size extent) = 0;
diff --git a/tools/gfx-unit-test/copy-texture-tests.cpp b/tools/gfx-unit-test/copy-texture-tests.cpp
new file mode 100644
index 000000000..fa206afda
--- /dev/null
+++ b/tools/gfx-unit-test/copy-texture-tests.cpp
@@ -0,0 +1,365 @@
+#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
+
+using namespace Slang;
+using namespace gfx;
+
+namespace gfx_test
+{
+ struct BaseCopyTextureTest
+ {
+ IDevice* device;
+ UnitTestContext* context;
+
+ ComPtr<ITextureResource> srcTexture;
+ ComPtr<ITextureResource> dstTexture;
+ ComPtr<IBufferResource> resultsBuffer;
+
+ size_t alignedRowPitch;
+
+ 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 srcTextureInfo, TextureInfo dstTextureInfo, Format format)
+ {
+ ITextureResource::Desc srcTexDesc = {};
+ srcTexDesc.type = IResource::Type::Texture2D;
+ srcTexDesc.numMipLevels = srcTextureInfo.numMipLevels;
+ srcTexDesc.arraySize = srcTextureInfo.arraySize;
+ srcTexDesc.size = srcTextureInfo.extent;
+ srcTexDesc.defaultState = ResourceState::UnorderedAccess;
+ srcTexDesc.allowedStates = ResourceStateSet(
+ ResourceState::UnorderedAccess,
+ ResourceState::ShaderResource,
+ ResourceState::CopySource);
+ srcTexDesc.format = format;
+
+ GFX_CHECK_CALL_ABORT(device->createTextureResource(
+ srcTexDesc,
+ srcTextureInfo.initData,
+ srcTexture.writeRef()));
+
+ ITextureResource::Desc dstTexDesc = {};
+ dstTexDesc.type = IResource::Type::Texture2D;
+ dstTexDesc.numMipLevels = dstTextureInfo.numMipLevels;
+ dstTexDesc.arraySize = dstTextureInfo.arraySize;
+ dstTexDesc.size = dstTextureInfo.extent;
+ dstTexDesc.defaultState = ResourceState::CopyDestination;
+ dstTexDesc.allowedStates = ResourceStateSet(
+ ResourceState::ShaderResource,
+ ResourceState::CopyDestination,
+ ResourceState::CopySource);
+ dstTexDesc.format = format;
+
+ GFX_CHECK_CALL_ABORT(device->createTextureResource(
+ dstTexDesc,
+ dstTextureInfo.initData,
+ dstTexture.writeRef()));
+
+ FormatInfo formatInfo;
+ gfxGetFormatInfo(format, &formatInfo);
+ UInt alignment = 256; // D3D requires rows to be aligned to a multiple of 256 bytes.
+ alignedRowPitch = (dstTextureInfo.extent.width * formatInfo.blockSizeInBytes + alignment - 1) & ~(alignment - 1);
+ IBufferResource::Desc bufferDesc = {};
+ bufferDesc.sizeInBytes = dstTextureInfo.extent.height * alignedRowPitch;
+ bufferDesc.format = gfx::Format::Unknown;
+ bufferDesc.elementSize = 0;
+ bufferDesc.allowedStates = ResourceStateSet(
+ ResourceState::ShaderResource,
+ ResourceState::UnorderedAccess,
+ ResourceState::CopyDestination,
+ ResourceState::CopySource);
+ bufferDesc.defaultState = ResourceState::CopyDestination;
+ bufferDesc.memoryType = MemoryType::DeviceLocal;
+
+ GFX_CHECK_CALL_ABORT(device->createBufferResource(
+ bufferDesc,
+ nullptr,
+ resultsBuffer.writeRef()));
+ }
+
+ void submitGPUWork(
+ SubresourceRange srcSubresource,
+ SubresourceRange dstSubresource,
+ ITextureResource::Offset3D srcOffset,
+ ITextureResource::Offset3D dstOffset,
+ ITextureResource::Size extent,
+ size_t textureSize)
+ {
+ 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 encoder = commandBuffer->encodeResourceCommands();
+
+ encoder->textureSubresourceBarrier(srcTexture, srcSubresource, ResourceState::UnorderedAccess, ResourceState::CopySource);
+ encoder->copyTexture(dstTexture, ResourceState::CopyDestination, dstSubresource, dstOffset, srcTexture, ResourceState::CopySource, srcSubresource, srcOffset, extent);
+ encoder->textureSubresourceBarrier(dstTexture, dstSubresource, ResourceState::CopyDestination, ResourceState::CopySource);
+ encoder->copyTextureToBuffer(resultsBuffer, 0, textureSize, dstTexture, ResourceState::CopySource, dstSubresource, dstOffset, extent);
+ encoder->endEncoding();
+ commandBuffer->close();
+ queue->executeCommandBuffer(commandBuffer);
+ queue->waitOnHost();
+ }
+ };
+
+ struct SimpleCopyTexture : BaseCopyTextureTest
+ {
+ Format format = Format::R8G8B8A8_UINT;
+
+ void run()
+ {
+ ITextureResource::Size extent = {};
+ extent.width = 2;
+ extent.height = 2;
+ extent.depth = 1;
+
+ uint8_t srcTexData[16] = { 255u, 0u, 0u, 255u, 0u, 255u, 0u, 255u,
+ 0u, 0u, 255u, 255u, 127u, 127u, 127u, 255u };
+ ITextureResource::SubresourceData srcSubData = { (void*)srcTexData, 8, 0 };
+
+ uint8_t dstTexData[16] = { 0u };
+ ITextureResource::SubresourceData dstSubData = { (void*)dstTexData, 8, 0 };
+
+ TextureInfo srcTextureInfo = { extent, 1, 1, &srcSubData };
+ TextureInfo dstTextureInfo = { extent, 1, 1, &dstSubData };
+
+ createRequiredResources(srcTextureInfo, dstTextureInfo, format);
+
+ SubresourceRange srcSubresource = {};
+ srcSubresource.aspectMask = TextureAspect::Color;
+ srcSubresource.mipLevel = 0;
+ srcSubresource.mipLevelCount = 1;
+ srcSubresource.baseArrayLayer = 0;
+ srcSubresource.layerCount = 1;
+
+ ITextureResource::Offset3D srcOffset;
+
+ SubresourceRange dstSubresource = {};
+ dstSubresource.aspectMask = TextureAspect::Color;
+ dstSubresource.mipLevel = 0;
+ dstSubresource.mipLevelCount = 1;
+ dstSubresource.baseArrayLayer = 0;
+ dstSubresource.layerCount = 1;
+
+ ITextureResource::Offset3D dstOffset;
+
+ submitGPUWork(srcSubresource, dstSubresource, srcOffset, dstOffset, extent, 16);
+
+ if (device->getDeviceInfo().deviceType == DeviceType::DirectX12)
+ {
+ // D3D12 has to pad out the rows in order to adhere to alignment, so when comparing results
+ // we need to make sure not to include the padding.
+ size_t testOffset = 0;
+ for (Int i = 0; i < extent.height; ++i)
+ {
+ compareComputeResult(
+ device,
+ resultsBuffer,
+ testOffset,
+ srcTexData + 8 * i,
+ 8);
+ testOffset += alignedRowPitch;
+ }
+ }
+ else if (device->getDeviceInfo().deviceType == DeviceType::Vulkan)
+ {
+ compareComputeResult(
+ device,
+ resultsBuffer,
+ 0,
+ srcTexData,
+ 16);
+ }
+ }
+ };
+
+ struct Texel
+ {
+ float channels[4];
+ };
+
+ struct SubresourceStuff : RefObject
+ {
+ List<Texel> texels;
+ };
+
+ struct TextureStuff : RefObject
+ {
+ List<RefPtr<SubresourceStuff>> subresourceObjects;
+ List<ITextureResource::SubresourceData> subresourceDatas;
+ };
+
+ struct CopyTextureSection : BaseCopyTextureTest
+ {
+ Format format = Format::R32G32B32A32_FLOAT;
+
+ RefPtr<TextureStuff> generateTextureData(int width, int height, uint32_t mipLevels, uint32_t arrayLayers)
+ {
+ RefPtr<TextureStuff> texture = new TextureStuff();
+ for (int layer = 0; layer < arrayLayers; ++layer)
+ {
+ for (int mip = 0; mip < mipLevels; ++mip)
+ {
+ RefPtr<SubresourceStuff> subresource = new SubresourceStuff();
+ texture->subresourceObjects.add(subresource);
+
+ int mipWidth = Math::Max(width >> mip, 1);
+ int mipHeight = Math::Max(height >> mip, 1);
+
+ int mipTexelCount = mipWidth * mipHeight;
+ subresource->texels.setCount(mipTexelCount);
+ for (int h = 0; h < mipHeight; ++h)
+ {
+ for (int w = 0; w < mipWidth; ++w)
+ {
+ // 4 channels per pixel
+ subresource->texels[h * mipWidth + w].channels[0] = w;
+ subresource->texels[h * mipWidth + w].channels[1] = h;
+ subresource->texels[h * mipWidth + w].channels[2] = mip;
+ subresource->texels[h * mipWidth + w].channels[3] = layer;
+ }
+ }
+
+ ITextureResource::SubresourceData subData = {};
+ subData.data = subresource->texels.getBuffer();
+ subData.strideY = mipWidth * sizeof(Texel);
+ subData.strideZ = mipHeight * subData.strideY;
+ texture->subresourceDatas.add(subData);
+ }
+ }
+ return texture;
+ }
+
+ // TODO: Things to test in the future
+ // 1. Size of src texture(W, H, mips, layers)
+ // 2. Size of dst texture(...)
+ // 3. src subresource(mip, layer)
+ // 4. dst subresource(mip, layer)
+ // 5. copy extents(x, y)
+ // 6. copy src coords(x, y)
+ // 7. copy dst coords(x, y)
+ // 8. Final buffer offset
+
+ void run()
+ {
+ ITextureResource::Size extent = {};
+ extent.width = 4;
+ extent.height = 4;
+ extent.depth = 1;
+
+ auto mipLevelCount = 2;
+ auto arrayLayerCount = 2;
+
+ auto srcTextureStuff = generateTextureData(extent.width, extent.height, mipLevelCount, arrayLayerCount);
+
+ TextureInfo srcTextureInfo = { extent, mipLevelCount, arrayLayerCount, srcTextureStuff->subresourceDatas.getBuffer() };
+ TextureInfo dstTextureInfo = { extent, mipLevelCount, arrayLayerCount, nullptr };
+
+ createRequiredResources(srcTextureInfo, dstTextureInfo, format);
+
+ SubresourceRange srcSubresource = {};
+ srcSubresource.aspectMask = TextureAspect::Color;
+ srcSubresource.mipLevel = 0;
+ srcSubresource.mipLevelCount = 1;
+ srcSubresource.baseArrayLayer = 1;
+ srcSubresource.layerCount = 1;
+
+ ITextureResource::Offset3D srcOffset;
+
+ SubresourceRange dstSubresource = {};
+ dstSubresource.aspectMask = TextureAspect::Color;
+ dstSubresource.mipLevel = 0;
+ dstSubresource.mipLevelCount = 1;
+ dstSubresource.baseArrayLayer = 0;
+ dstSubresource.layerCount = 1;
+
+ ITextureResource::Offset3D dstOffset;
+
+ submitGPUWork(srcSubresource, dstSubresource, srcOffset, dstOffset, extent, extent.height * 256);
+
+ ITextureResource::SubresourceData expectedData = srcTextureStuff->subresourceDatas[2];
+ if (device->getDeviceInfo().deviceType == DeviceType::DirectX12)
+ {
+ // D3D12 has to pad out the rows in order to adhere to alignment, so when comparing results
+ // we need to make sure not to include the padding.
+ size_t testOffset = 0;
+ size_t dataOffset = 0;
+ auto rowStride = expectedData.strideY / 4;
+ for (Int i = 0; i < extent.height; ++i)
+ {
+ compareComputeResult(
+ device,
+ resultsBuffer,
+ testOffset,
+ (float*) expectedData.data + rowStride * i,
+ rowStride * 4);
+ testOffset += alignedRowPitch;
+ }
+ dataOffset += srcTextureStuff->subresourceDatas[0].strideZ / 4;
+ }
+ else if (device->getDeviceInfo().deviceType == DeviceType::Vulkan)
+ {
+ compareComputeResult(
+ device,
+ resultsBuffer,
+ 0,
+ expectedData.data,
+ 64);
+ }
+ }
+ };
+
+ template<typename T>
+ void copyTextureTestImpl(IDevice* device, UnitTestContext* context)
+ {
+ T test;
+ test.init(device, context);
+ test.run();
+ }
+
+ SLANG_UNIT_TEST(copyTextureSimpleD3D12)
+ {
+ runTestImpl(copyTextureTestImpl<SimpleCopyTexture>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ }
+
+ SLANG_UNIT_TEST(copyTextureSectionD3D12)
+ {
+ runTestImpl(copyTextureTestImpl<CopyTextureSection>, unitTestContext, Slang::RenderApiFlag::D3D12);
+ }
+
+ SLANG_UNIT_TEST(copyTextureSimpleVulkan)
+ {
+ runTestImpl(copyTextureTestImpl<SimpleCopyTexture>, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ }
+
+ SLANG_UNIT_TEST(copyTextureSectionVulkan)
+ {
+ runTestImpl(copyTextureTestImpl<CopyTextureSection>, unitTestContext, Slang::RenderApiFlag::Vulkan);
+ }
+}
diff --git a/tools/gfx-unit-test/gfx-test-util.cpp b/tools/gfx-unit-test/gfx-test-util.cpp
index 7514f22cf..c95c3d0e5 100644
--- a/tools/gfx-unit-test/gfx-test-util.cpp
+++ b/tools/gfx-unit-test/gfx-test-util.cpp
@@ -117,7 +117,7 @@ namespace gfx_test
gfx::IDevice* device,
gfx::ITextureResource* texture,
gfx::ResourceState state,
- float* expectedResult,
+ void* expectedResult,
size_t expectedResultRowPitch,
size_t rowCount)
{
@@ -139,15 +139,16 @@ namespace gfx_test
}
}
- void compareComputeResult(gfx::IDevice* device, gfx::IBufferResource* buffer, uint8_t* expectedResult, size_t expectedBufferSize)
+ void compareComputeResult(gfx::IDevice* device, gfx::IBufferResource* buffer, size_t offset, const void* expectedResult, size_t expectedBufferSize)
{
// Read back the results.
ComPtr<ISlangBlob> resultBlob;
GFX_CHECK_CALL_ABORT(device->readBufferResource(
- buffer, 0, expectedBufferSize, resultBlob.writeRef()));
+ buffer, offset, expectedBufferSize, resultBlob.writeRef()));
SLANG_CHECK(resultBlob->getBufferSize() == expectedBufferSize);
+ auto result = (float*)resultBlob->getBufferPointer();
// Compare results.
- SLANG_CHECK(memcmp(resultBlob->getBufferPointer(), expectedResult, expectedBufferSize) == 0);
+ SLANG_CHECK(memcmp(resultBlob->getBufferPointer(), (uint8_t*)expectedResult, expectedBufferSize) == 0);
}
void compareComputeResultFuzzy(const float* result, float* expectedResult, size_t expectedBufferSize)
diff --git a/tools/gfx-unit-test/gfx-test-util.h b/tools/gfx-unit-test/gfx-test-util.h
index 04c602359..3be47bc82 100644
--- a/tools/gfx-unit-test/gfx-test-util.h
+++ b/tools/gfx-unit-test/gfx-test-util.h
@@ -30,7 +30,8 @@ namespace gfx_test
void compareComputeResult(
gfx::IDevice* device,
gfx::IBufferResource* buffer,
- uint8_t* expectedResult,
+ size_t offset,
+ const void* expectedResult,
size_t expectedBufferSize);
/// Reads back the content of `buffer` and compares it against `expectedResult`.
@@ -38,7 +39,7 @@ namespace gfx_test
gfx::IDevice* device,
gfx::ITextureResource* texture,
gfx::ResourceState state,
- float* expectedResult,
+ void* expectedResult,
size_t expectedResultRowPitch,
size_t rowCount);
@@ -65,24 +66,8 @@ namespace gfx_test
expectedBuffer.setCount(bufferSize);
memcpy(expectedBuffer.getBuffer(), expectedResult.begin(), bufferSize);
if (std::is_same<T, float>::value) return compareComputeResultFuzzy(device, buffer, (float*)expectedBuffer.getBuffer(), bufferSize);
- return compareComputeResult(device, buffer, expectedBuffer.getBuffer(), bufferSize);
+ return compareComputeResult(device, buffer, 0, expectedBuffer.getBuffer(), bufferSize);
}
-
-// TODO: Implement compareComputeResultFuzzy() and keep or just directly use compareComputeResult() above and add a second overload for uint/int?
-// template<typename T, Slang::Index count>
-// void compareComputeResult(
-// gfx::IDevice* device,
-// gfx::ITextureResource* texture,
-// gfx::ResourceState state,
-// Slang::Array<T, count> expectedResult)
-// {
-// Slang::List<uint8_t> expectedBuffer;
-// size_t bufferSize = sizeof(T) * count;
-// expectedBuffer.setCount(bufferSize);
-// memcpy(expectedBuffer.getBuffer(), expectedResult.begin(), bufferSize);
-// if (std::is_same<T, float>::value) return compareComputeResultFuzzy(device, buffer, (float*)expectedBuffer.getBuffer(), bufferSize);
-// return compareComputeResult(device, texture, state, expectedBuffer.getBuffer(), bufferSize);
-// }
Slang::ComPtr<gfx::IDevice> createTestingDevice(UnitTestContext* context, Slang::RenderApiFlag::Enum api);
diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp
index 2c3f1eb56..3e55242f0 100644
--- a/tools/gfx/cuda/render-cuda.cpp
+++ b/tools/gfx/cuda/render-cuda.cpp
@@ -1060,17 +1060,21 @@ public:
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::Size extent) override
{
SLANG_UNUSED(dst);
+ SLANG_UNUSED(dstState);
SLANG_UNUSED(dstSubresource);
SLANG_UNUSED(dstOffset);
SLANG_UNUSED(src);
+ SLANG_UNUSED(srcState);
SLANG_UNUSED(srcSubresource);
SLANG_UNUSED(srcOffset);
SLANG_UNUSED(extent);
@@ -1123,6 +1127,7 @@ public:
size_t dstOffset,
size_t dstSize,
ITextureResource* src,
+ ResourceState srcState,
SubresourceRange srcSubresource,
ITextureResource::Offset3D srcOffset,
ITextureResource::Size extent) override
@@ -1131,6 +1136,7 @@ public:
SLANG_UNUSED(dstOffset);
SLANG_UNUSED(dstSize);
SLANG_UNUSED(src);
+ SLANG_UNUSED(srcState);
SLANG_UNUSED(srcSubresource);
SLANG_UNUSED(srcOffset);
SLANG_UNUSED(extent);
diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp
index 8005f6d15..634fca03e 100644
--- a/tools/gfx/d3d12/render-d3d12.cpp
+++ b/tools/gfx/d3d12/render-d3d12.cpp
@@ -3954,9 +3954,11 @@ public:
}
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::Size extent) override
@@ -4247,10 +4249,13 @@ public:
size_t dstOffset,
size_t dstSize,
ITextureResource* src,
+ ResourceState srcState,
SubresourceRange srcSubresource,
ITextureResource::Offset3D srcOffset,
ITextureResource::Size extent) override
{
+ assert(srcSubresource.mipLevelCount <= 1);
+
auto srcTexture = static_cast<TextureResourceImpl*>(src);
auto dstBuffer = static_cast<BufferResourceImpl*>(dst);
auto baseSubresourceIndex = D3DUtil::getSubresourceIndex(
@@ -4269,74 +4274,71 @@ public:
for (uint32_t layer = 0; layer < srcSubresource.layerCount; layer++)
{
- for (uint32_t mipId = 0; mipId < srcSubresource.mipLevelCount; mipId++)
+ // Get the footprint
+ D3D12_RESOURCE_DESC texDesc =
+ srcTexture->m_resource.getResource()->GetDesc();
+
+ D3D12_TEXTURE_COPY_LOCATION dstRegion = {};
+ dstRegion.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+ dstRegion.pResource = dstBuffer->m_resource.getResource();
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT& footprint = dstRegion.PlacedFootprint;
+
+ D3D12_TEXTURE_COPY_LOCATION srcRegion = {};
+ srcRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ srcRegion.SubresourceIndex = D3DUtil::getSubresourceIndex(
+ srcSubresource.mipLevel,
+ layer + srcSubresource.baseArrayLayer,
+ 0,
+ srcTexture->getDesc()->numMipLevels,
+ srcTexture->getDesc()->arraySize);
+ srcRegion.pResource = srcTexture->m_resource.getResource();
+
+ footprint.Offset = dstOffset;
+ footprint.Footprint.Format = texDesc.Format;
+ uint32_t mipLevel = srcSubresource.mipLevel;
+ if (extent.width != 0xFFFFFFFF)
{
- // Get the footprint
- D3D12_RESOURCE_DESC texDesc =
- srcTexture->m_resource.getResource()->GetDesc();
-
- D3D12_TEXTURE_COPY_LOCATION dstRegion = {};
- dstRegion.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- dstRegion.pResource = dstBuffer->m_resource.getResource();
- D3D12_PLACED_SUBRESOURCE_FOOTPRINT& footprint = dstRegion.PlacedFootprint;
-
- D3D12_TEXTURE_COPY_LOCATION srcRegion = {};
- srcRegion.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- srcRegion.SubresourceIndex = D3DUtil::getSubresourceIndex(
- mipId + srcSubresource.mipLevel,
- layer + srcSubresource.baseArrayLayer,
- 0,
- srcTexture->getDesc()->numMipLevels,
- srcTexture->getDesc()->arraySize);
- srcRegion.pResource = srcTexture->m_resource.getResource();
-
- footprint.Offset = 0;
- footprint.Footprint.Format = texDesc.Format;
- uint32_t mipLevel = mipId + srcSubresource.mipLevel;
- if (extent.width != 0xFFFFFFFF)
- {
- footprint.Footprint.Width = extent.width;
- }
- else
- {
- footprint.Footprint.Width =
- Math::Max(1, (textureSize.width >> mipLevel)) - srcOffset.x;
- }
- if (extent.height != 0xFFFFFFFF)
- {
- footprint.Footprint.Height = extent.height;
- }
- else
- {
- footprint.Footprint.Height =
- Math::Max(1, (textureSize.height >> mipLevel)) - srcOffset.y;
- }
- if (extent.depth != 0xFFFFFFFF)
- {
- footprint.Footprint.Depth = extent.depth;
- }
- else
- {
- footprint.Footprint.Depth =
- Math::Max(1, (textureSize.depth >> mipLevel)) - srcOffset.z;
- }
- footprint.Footprint.RowPitch = (UINT)D3DUtil::calcAligned(
- footprint.Footprint.Width * (UInt)formatInfo.blockSizeInBytes,
- (uint32_t)D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
-
- auto bufferSize = footprint.Footprint.RowPitch *
- footprint.Footprint.Height * footprint.Footprint.Depth;
-
- D3D12_BOX srcBox = {};
- srcBox.left = srcOffset.x;
- srcBox.top = srcOffset.y;
- srcBox.front = srcOffset.z;
- srcBox.right = srcOffset.x + extent.width;
- srcBox.bottom = srcOffset.y + extent.height;
- srcBox.back = srcOffset.z + extent.depth;
- m_commandBuffer->m_cmdList->CopyTextureRegion(
- &dstRegion, (UINT)dstOffset, 0, 0, &srcRegion, &srcBox);
+ footprint.Footprint.Width = extent.width;
+ }
+ else
+ {
+ footprint.Footprint.Width =
+ Math::Max(1, (textureSize.width >> mipLevel)) - srcOffset.x;
+ }
+ if (extent.height != 0xFFFFFFFF)
+ {
+ footprint.Footprint.Height = extent.height;
+ }
+ else
+ {
+ footprint.Footprint.Height =
+ Math::Max(1, (textureSize.height >> mipLevel)) - srcOffset.y;
+ }
+ if (extent.depth != 0xFFFFFFFF)
+ {
+ footprint.Footprint.Depth = extent.depth;
}
+ else
+ {
+ footprint.Footprint.Depth =
+ Math::Max(1, (textureSize.depth >> mipLevel)) - srcOffset.z;
+ }
+ footprint.Footprint.RowPitch = (UINT)D3DUtil::calcAligned(
+ footprint.Footprint.Width * (UInt)formatInfo.blockSizeInBytes,
+ (uint32_t)D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+
+ auto bufferSize = footprint.Footprint.RowPitch *
+ footprint.Footprint.Height * footprint.Footprint.Depth;
+
+ D3D12_BOX srcBox = {};
+ srcBox.left = srcOffset.x;
+ srcBox.top = srcOffset.y;
+ srcBox.front = srcOffset.z;
+ srcBox.right = srcOffset.x + extent.width;
+ srcBox.bottom = srcOffset.y + extent.height;
+ srcBox.back = srcOffset.z + extent.depth;
+ m_commandBuffer->m_cmdList->CopyTextureRegion(
+ &dstRegion, 0, 0, 0, &srcRegion, &srcBox);
}
}
@@ -4377,7 +4379,7 @@ public:
auto aspect = Math::getLowestBit((int32_t)aspectMask);
aspectMask &= ~aspect;
auto planeIndex = D3DUtil::getPlaneSlice(d3dFormat, (TextureAspect)aspect);
- for (uint32_t layer = 0; layer < subresourceRange.baseArrayLayer; layer++)
+ for (uint32_t layer = 0; layer < subresourceRange.layerCount; layer++)
{
for (uint32_t mip = 0; mip < subresourceRange.mipLevelCount; mip++)
{
@@ -6046,7 +6048,7 @@ Result D3D12Device::createTextureResource(const ITextureResource::Desc& descIn,
for (int j = 0; j < numMipMaps; ++j)
{
- auto srcSubresource = initData[j];
+ auto srcSubresource = initData[subResourceIndex + j];
const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& layout = layouts[j];
const D3D12_SUBRESOURCE_FOOTPRINT& footprint = layout.Footprint;
diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp
index 83ef129c4..fa8fc6fda 100644
--- a/tools/gfx/debug-layer.cpp
+++ b/tools/gfx/debug-layer.cpp
@@ -1277,9 +1277,11 @@ void DebugResourceCommandEncoder::bufferBarrier(
void DebugResourceCommandEncoder::copyTexture(
ITextureResource* dst,
+ ResourceState dstState,
SubresourceRange dstSubresource,
ITextureResource::Offset3D dstOffset,
ITextureResource* src,
+ ResourceState srcState,
SubresourceRange srcSubresource,
ITextureResource::Offset3D srcOffset,
ITextureResource::Size extent)
@@ -1287,9 +1289,11 @@ void DebugResourceCommandEncoder::copyTexture(
SLANG_GFX_API_FUNC;
baseObject->copyTexture(
getInnerObj(dst),
+ dstState,
dstSubresource,
dstOffset,
getInnerObj(src),
+ srcState,
srcSubresource,
srcOffset,
extent);
@@ -1342,13 +1346,14 @@ void DebugResourceCommandEncoder::copyTextureToBuffer(
size_t dstOffset,
size_t dstSize,
ITextureResource* src,
+ ResourceState srcState,
SubresourceRange srcSubresource,
ITextureResource::Offset3D srcOffset,
ITextureResource::Size extent)
{
SLANG_GFX_API_FUNC;
baseObject->copyTextureToBuffer(
- getInnerObj(dst), dstOffset, dstSize, getInnerObj(src), srcSubresource, srcOffset, extent);
+ getInnerObj(dst), dstOffset, dstSize, getInnerObj(src), srcState, srcSubresource, srcOffset, extent);
}
void DebugResourceCommandEncoder::textureSubresourceBarrier(
diff --git a/tools/gfx/debug-layer.h b/tools/gfx/debug-layer.h
index 096c35147..04dafadf2 100644
--- a/tools/gfx/debug-layer.h
+++ b/tools/gfx/debug-layer.h
@@ -430,9 +430,11 @@ public:
ResourceState dst) override;
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::Size extent) override;
@@ -461,6 +463,7 @@ public:
size_t dstOffset,
size_t dstSize,
ITextureResource* src,
+ ResourceState srcState,
SubresourceRange srcSubresource,
ITextureResource::Offset3D srcOffset,
ITextureResource::Size extent) override;
diff --git a/tools/gfx/immediate-renderer-base.cpp b/tools/gfx/immediate-renderer-base.cpp
index 912e20df1..ab2a51275 100644
--- a/tools/gfx/immediate-renderer-base.cpp
+++ b/tools/gfx/immediate-renderer-base.cpp
@@ -334,17 +334,21 @@ public:
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::Size extent) override
{
SLANG_UNUSED(dst);
+ SLANG_UNUSED(dstState);
SLANG_UNUSED(dstSubresource);
SLANG_UNUSED(dstOffset);
SLANG_UNUSED(src);
+ SLANG_UNUSED(srcState);
SLANG_UNUSED(srcSubresource);
SLANG_UNUSED(srcOffset);
SLANG_UNUSED(extent);
@@ -397,6 +401,7 @@ public:
size_t dstOffset,
size_t dstSize,
ITextureResource* src,
+ ResourceState srcState,
SubresourceRange srcSubresource,
ITextureResource::Offset3D srcOffset,
ITextureResource::Size extent) override
@@ -405,6 +410,7 @@ public:
SLANG_UNUSED(dstOffset);
SLANG_UNUSED(dstSize);
SLANG_UNUSED(src);
+ SLANG_UNUSED(srcState);
SLANG_UNUSED(srcSubresource);
SLANG_UNUSED(srcOffset);
SLANG_UNUSED(extent);
diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp
index 96e11eb27..9f5af2a1e 100644
--- a/tools/gfx/vulkan/render-vk.cpp
+++ b/tools/gfx/vulkan/render-vk.cpp
@@ -4502,23 +4502,54 @@ public:
m_commandBuffer = commandBuffer;
}
+ VkImageAspectFlags getAspectMask(TextureAspect aspect)
+ {
+ if (aspect == TextureAspect::Depth)
+ return VK_IMAGE_ASPECT_DEPTH_BIT;
+ if (aspect == TextureAspect::Stencil)
+ return VK_IMAGE_ASPECT_STENCIL_BIT;
+ return VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+
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::Size extent) override
{
- SLANG_UNUSED(dst);
- SLANG_UNUSED(dstSubresource);
- SLANG_UNUSED(dstOffset);
- SLANG_UNUSED(src);
- SLANG_UNUSED(srcSubresource);
- SLANG_UNUSED(srcOffset);
- SLANG_UNUSED(extent);
- SLANG_UNIMPLEMENTED_X("copyTexture");
+ auto srcImage = static_cast<TextureResourceImpl*>(src);
+ auto srcDesc = srcImage->getDesc();
+ auto srcImageLayout = VulkanUtil::getImageLayoutFromState(srcState);
+ auto dstImage = static_cast<TextureResourceImpl*>(dst);
+ auto dstDesc = dstImage->getDesc();
+ auto dstImageLayout = VulkanUtil::getImageLayoutFromState(dstState);
+
+ for (Int layer = 0; layer < srcSubresource.layerCount; ++layer)
+ {
+ for (Int mipId = 0; mipId < srcSubresource.mipLevelCount; ++mipId)
+ {
+ VkImageCopy region = {};
+ region.srcSubresource.aspectMask = getAspectMask(srcSubresource.aspectMask);
+ region.srcSubresource.baseArrayLayer = layer + srcSubresource.baseArrayLayer;
+ region.srcSubresource.mipLevel = mipId + srcSubresource.mipLevel;
+ region.srcSubresource.layerCount = 1;
+ region.srcOffset = { (int32_t)srcOffset.x, (int32_t)srcOffset.y, (int32_t)srcOffset.z };
+ region.dstSubresource.aspectMask = getAspectMask(dstSubresource.aspectMask);
+ region.dstSubresource.baseArrayLayer = layer + dstSubresource.baseArrayLayer;
+ region.dstSubresource.mipLevel = mipId + dstSubresource.mipLevel;
+ region.dstSubresource.layerCount = 1;
+ region.dstOffset = { (int32_t)dstOffset.x, (int32_t)dstOffset.y, (int32_t)dstOffset.z };
+ region.extent = { (uint32_t)extent.width, (uint32_t)extent.height, (uint32_t)extent.depth };
+
+ auto& vkApi = m_commandBuffer->m_renderer->m_api;
+ vkApi.vkCmdCopyImage(m_commandBuffer->m_commandBuffer, srcImage->m_image, srcImageLayout, dstImage->m_image, dstImageLayout, 1, &region);
+ }
+ }
}
virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData(
@@ -4765,18 +4796,31 @@ public:
size_t dstOffset,
size_t dstSize,
ITextureResource* src,
+ ResourceState srcState,
SubresourceRange srcSubresource,
ITextureResource::Offset3D srcOffset,
ITextureResource::Size extent) override
{
- SLANG_UNUSED(dst);
- SLANG_UNUSED(dstOffset);
- SLANG_UNUSED(dstSize);
- SLANG_UNUSED(src);
- SLANG_UNUSED(srcSubresource);
- SLANG_UNUSED(srcOffset);
- SLANG_UNUSED(extent);
- SLANG_UNIMPLEMENTED_X("copyTextureToBuffer");
+ assert(srcSubresource.mipLevelCount <= 1);
+
+ auto image = static_cast<TextureResourceImpl*>(src);
+ auto desc = image->getDesc();
+ auto buffer = static_cast<BufferResourceImpl*>(dst);
+ auto srcImageLayout = VulkanUtil::getImageLayoutFromState(srcState);
+
+ VkBufferImageCopy region = {};
+ region.bufferOffset = dstOffset;
+ region.bufferRowLength = 0;
+ region.bufferImageHeight = 0;
+ region.imageSubresource.aspectMask = getAspectMask(srcSubresource.aspectMask);
+ region.imageSubresource.mipLevel = srcSubresource.mipLevel;
+ region.imageSubresource.baseArrayLayer = srcSubresource.baseArrayLayer;
+ region.imageSubresource.layerCount = srcSubresource.layerCount;
+ region.imageOffset = { (int32_t)srcOffset.x, (int32_t)srcOffset.y, (int32_t)srcOffset.z };
+ region.imageExtent = { uint32_t(extent.width), uint32_t(extent.height), uint32_t(extent.depth) };
+
+ auto& vkApi = m_commandBuffer->m_renderer->m_api;
+ vkApi.vkCmdCopyImageToBuffer(m_commandBuffer->m_commandBuffer, image->m_image, srcImageLayout, buffer->m_buffer.m_buffer, 1, &region);
}
virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier(
@@ -4785,11 +4829,39 @@ public:
ResourceState src,
ResourceState dst) override
{
- SLANG_UNUSED(texture);
- SLANG_UNUSED(subresourceRange);
- SLANG_UNUSED(src);
- SLANG_UNUSED(dst);
- SLANG_UNIMPLEMENTED_X("textureSubresourceBarrier");
+ ShortList<VkImageMemoryBarrier> barriers;
+ auto image = static_cast<TextureResourceImpl*>(texture);
+ auto desc = image->getDesc();
+
+ VkImageMemoryBarrier barrier = {};
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.image = image->m_image;
+ barrier.oldLayout = translateImageLayout(src);
+ barrier.newLayout = translateImageLayout(dst);
+ barrier.subresourceRange.aspectMask = getAspectMask(subresourceRange.aspectMask);
+ barrier.subresourceRange.baseArrayLayer = subresourceRange.baseArrayLayer;
+ barrier.subresourceRange.baseMipLevel = subresourceRange.mipLevel;
+ barrier.subresourceRange.layerCount = subresourceRange.layerCount;
+ barrier.subresourceRange.levelCount = subresourceRange.mipLevelCount;
+ barrier.srcAccessMask = calcAccessFlags(src);
+ barrier.dstAccessMask = calcAccessFlags(dst);
+ barriers.add(barrier);
+
+ VkPipelineStageFlagBits srcStage = calcPipelineStageFlags(src, true);
+ VkPipelineStageFlagBits dstStage = calcPipelineStageFlags(dst, false);
+
+ auto& vkApi = m_commandBuffer->m_renderer->m_api;
+ vkApi.vkCmdPipelineBarrier(
+ m_commandBuffer->m_commandBuffer,
+ srcStage,
+ dstStage,
+ 0,
+ 0,
+ nullptr,
+ 0,
+ nullptr,
+ (uint32_t)barriers.getCount(),
+ barriers.getArrayView().getBuffer());
}
};
@@ -7061,6 +7133,9 @@ void VKDevice::_transitionImageLayout(
VkImageLayout oldLayout,
VkImageLayout newLayout)
{
+ if (oldLayout == newLayout)
+ return;
+
VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout;
diff --git a/tools/gfx/vulkan/vk-api.h b/tools/gfx/vulkan/vk-api.h
index 1d8cd66f6..72a6e73c8 100644
--- a/tools/gfx/vulkan/vk-api.h
+++ b/tools/gfx/vulkan/vk-api.h
@@ -96,6 +96,7 @@ namespace gfx {
x(vkCmdEndRenderPass) \
x(vkCmdPipelineBarrier) \
x(vkCmdCopyBufferToImage)\
+ x(vkCmdCopyImage) \
x(vkCmdCopyImageToBuffer) \
x(vkCmdPushConstants) \
x(vkCmdSetStencilReference) \