Add D3D12 buffer/buffer buffer/texture and texture/buffer copies

Right now, this only works if textures are 256-byte aligned
This commit is contained in:
Austin Eng 2017-06-28 12:35:07 -04:00 committed by Austin Eng
parent 6774bce06e
commit 8fa550c015
3 changed files with 71 additions and 0 deletions

View File

@ -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<CopyBufferToBufferCmd>();
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<CopyBufferToTextureCmd>();
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<CopyTextureToBufferCmd>();
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;

View File

@ -100,6 +100,10 @@ namespace d3d12 {
device->GetResourceAllocator()->Release(resource);
}
DXGI_FORMAT Texture::GetD3D12Format() const {
return D3D12TextureFormat(GetFormat());
}
ComPtr<ID3D12Resource> Texture::GetD3D12Resource() {
return resource;
}

View File

@ -29,6 +29,7 @@ namespace d3d12 {
Texture(Device* device, TextureBuilder* builder);
~Texture();
DXGI_FORMAT GetD3D12Format() const;
ComPtr<ID3D12Resource> GetD3D12Resource();
bool GetResourceTransitionBarrier(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage, D3D12_RESOURCE_BARRIER* barrier);