diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gfx-unit-test/copy-texture-tests.cpp | 365 | ||||
| -rw-r--r-- | tools/gfx-unit-test/gfx-test-util.cpp | 9 | ||||
| -rw-r--r-- | tools/gfx-unit-test/gfx-test-util.h | 23 | ||||
| -rw-r--r-- | tools/gfx/cuda/render-cuda.cpp | 6 | ||||
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 138 | ||||
| -rw-r--r-- | tools/gfx/debug-layer.cpp | 7 | ||||
| -rw-r--r-- | tools/gfx/debug-layer.h | 3 | ||||
| -rw-r--r-- | tools/gfx/immediate-renderer-base.cpp | 6 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 117 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-api.h | 1 |
10 files changed, 562 insertions, 113 deletions
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, ®ion); + } + } } 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, ®ion); } 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) \ |
