diff --git a/src/backend/d3d12/CommandBufferD3D12.cpp b/src/backend/d3d12/CommandBufferD3D12.cpp index da1ce4f6b8..ba233d1ef6 100644 --- a/src/backend/d3d12/CommandBufferD3D12.cpp +++ b/src/backend/d3d12/CommandBufferD3D12.cpp @@ -26,6 +26,8 @@ #include "SamplerD3D12.h" #include "TextureD3D12.h" +#include "ResourceAllocator.h" + namespace backend { namespace d3d12 { @@ -188,6 +190,36 @@ namespace d3d12 { D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); } } + + D3D12_TEXTURE_COPY_LOCATION D3D12PlacedTextureCopyLocation(BufferCopyLocation& bufferLocation, Texture* texture, const TextureCopyLocation& textureLocation) { + D3D12_TEXTURE_COPY_LOCATION d3d12Location; + d3d12Location.pResource = ToBackend(bufferLocation.buffer.Get())->GetD3D12Resource().Get(); + d3d12Location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + d3d12Location.PlacedFootprint.Offset = bufferLocation.offset; + d3d12Location.PlacedFootprint.Footprint.Format = texture->GetD3D12Format(); + d3d12Location.PlacedFootprint.Footprint.Width = textureLocation.width; + d3d12Location.PlacedFootprint.Footprint.Height = textureLocation.height; + d3d12Location.PlacedFootprint.Footprint.Depth = textureLocation.depth; + + uint32_t texelSize = 0; + switch (texture->GetFormat()) { + case nxt::TextureFormat::R8G8B8A8Unorm: + texelSize = 4; + break; + } + uint32_t rowSize = textureLocation.width * texelSize; + d3d12Location.PlacedFootprint.Footprint.RowPitch = ((rowSize - 1) / D3D12_TEXTURE_DATA_PITCH_ALIGNMENT + 1) * D3D12_TEXTURE_DATA_PITCH_ALIGNMENT; + + return d3d12Location; + } + + D3D12_TEXTURE_COPY_LOCATION D3D12TextureCopyLocation(TextureCopyLocation& textureLocation) { + D3D12_TEXTURE_COPY_LOCATION d3d12Location; + d3d12Location.pResource = ToBackend(textureLocation.texture.Get())->GetD3D12Resource().Get(); + d3d12Location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + d3d12Location.SubresourceIndex = textureLocation.level; + return d3d12Location; + } } CommandBuffer::CommandBuffer(Device* device, CommandBufferBuilder* builder) @@ -246,18 +278,52 @@ namespace d3d12 { case Command::CopyBufferToBuffer: { CopyBufferToBufferCmd* copy = commands.NextCommand(); + auto src = ToBackend(copy->source.buffer.Get())->GetD3D12Resource(); + auto dst = ToBackend(copy->destination.buffer.Get())->GetD3D12Resource(); + commandList->CopyBufferRegion(dst.Get(), copy->destination.offset, src.Get(), copy->source.offset, copy->size); } break; case Command::CopyBufferToTexture: { CopyBufferToTextureCmd* copy = commands.NextCommand(); + Buffer* buffer = ToBackend(copy->source.buffer.Get()); + Texture* texture = ToBackend(copy->destination.texture.Get()); + + D3D12_TEXTURE_COPY_LOCATION srcLocation = D3D12PlacedTextureCopyLocation(copy->source, texture, copy->destination); + D3D12_TEXTURE_COPY_LOCATION dstLocation = D3D12TextureCopyLocation(copy->destination); + + // TODO(enga@google.com): This assertion will not be true if the number of bytes in each row of the texture is not a multiple of 256 + // To resolve this we would need to create an intermediate resource or force all textures to be 256-byte aligned + uint64_t totalBytes = srcLocation.PlacedFootprint.Footprint.RowPitch * copy->destination.height * copy->destination.depth; + ASSERT(totalBytes <= buffer->GetD3D12Size()); + + commandList->CopyTextureRegion(&dstLocation, copy->destination.x, copy->destination.y, copy->destination.z, &srcLocation, nullptr); } break; case Command::CopyTextureToBuffer: { CopyTextureToBufferCmd* copy = commands.NextCommand(); + Texture* texture = ToBackend(copy->source.texture.Get()); + Buffer* buffer = ToBackend(copy->destination.buffer.Get()); + + D3D12_TEXTURE_COPY_LOCATION srcLocation = D3D12TextureCopyLocation(copy->source); + D3D12_TEXTURE_COPY_LOCATION dstLocation = D3D12PlacedTextureCopyLocation(copy->destination, texture, copy->source); + + // TODO(enga@google.com): This assertion will not be true if the number of bytes in each row of the texture is not a multiple of 256 + // To resolve this we would need to create an intermediate resource or force all textures to be 256-byte aligned + uint64_t totalBytes = dstLocation.PlacedFootprint.Footprint.RowPitch * copy->source.height * copy->source.depth; + ASSERT(totalBytes <= buffer->GetD3D12Size()); + + D3D12_BOX sourceRegion; + sourceRegion.left = copy->source.x; + sourceRegion.top = copy->source.y; + sourceRegion.front = copy->source.z; + sourceRegion.right = copy->source.x + copy->source.width; + sourceRegion.bottom = copy->source.y + copy->source.height; + sourceRegion.back = copy->source.z + copy->source.depth; + commandList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, &sourceRegion); } break; diff --git a/src/backend/d3d12/TextureD3D12.cpp b/src/backend/d3d12/TextureD3D12.cpp index cb06a05f7c..a4b94aff33 100644 --- a/src/backend/d3d12/TextureD3D12.cpp +++ b/src/backend/d3d12/TextureD3D12.cpp @@ -100,6 +100,10 @@ namespace d3d12 { device->GetResourceAllocator()->Release(resource); } + DXGI_FORMAT Texture::GetD3D12Format() const { + return D3D12TextureFormat(GetFormat()); + } + ComPtr Texture::GetD3D12Resource() { return resource; } diff --git a/src/backend/d3d12/TextureD3D12.h b/src/backend/d3d12/TextureD3D12.h index aa85c9ba6b..26f45d89d4 100644 --- a/src/backend/d3d12/TextureD3D12.h +++ b/src/backend/d3d12/TextureD3D12.h @@ -29,6 +29,7 @@ namespace d3d12 { Texture(Device* device, TextureBuilder* builder); ~Texture(); + DXGI_FORMAT GetD3D12Format() const; ComPtr GetD3D12Resource(); bool GetResourceTransitionBarrier(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage, D3D12_RESOURCE_BARRIER* barrier);