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:
parent
6774bce06e
commit
8fa550c015
|
@ -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;
|
||||
|
||||
|
|
|
@ -100,6 +100,10 @@ namespace d3d12 {
|
|||
device->GetResourceAllocator()->Release(resource);
|
||||
}
|
||||
|
||||
DXGI_FORMAT Texture::GetD3D12Format() const {
|
||||
return D3D12TextureFormat(GetFormat());
|
||||
}
|
||||
|
||||
ComPtr<ID3D12Resource> Texture::GetD3D12Resource() {
|
||||
return resource;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue