Implement backend texture->buffer and buffer->texture copies with row pitch

This commit is contained in:
Austin Eng 2017-07-13 15:28:58 -04:00 committed by Austin Eng
parent 51ff013ee2
commit 33560ef015
3 changed files with 14 additions and 19 deletions

View File

@ -202,7 +202,7 @@ namespace d3d12 {
} }
} }
D3D12_TEXTURE_COPY_LOCATION D3D12PlacedTextureCopyLocation(BufferCopyLocation& bufferLocation, Texture* texture, const TextureCopyLocation& textureLocation) { D3D12_TEXTURE_COPY_LOCATION D3D12PlacedTextureCopyLocation(BufferCopyLocation& bufferLocation, Texture* texture, const TextureCopyLocation& textureLocation, uint32_t rowPitch) {
D3D12_TEXTURE_COPY_LOCATION d3d12Location; D3D12_TEXTURE_COPY_LOCATION d3d12Location;
d3d12Location.pResource = ToBackend(bufferLocation.buffer.Get())->GetD3D12Resource().Get(); d3d12Location.pResource = ToBackend(bufferLocation.buffer.Get())->GetD3D12Resource().Get();
d3d12Location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; d3d12Location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
@ -211,10 +211,7 @@ namespace d3d12 {
d3d12Location.PlacedFootprint.Footprint.Width = textureLocation.width; d3d12Location.PlacedFootprint.Footprint.Width = textureLocation.width;
d3d12Location.PlacedFootprint.Footprint.Height = textureLocation.height; d3d12Location.PlacedFootprint.Footprint.Height = textureLocation.height;
d3d12Location.PlacedFootprint.Footprint.Depth = textureLocation.depth; d3d12Location.PlacedFootprint.Footprint.Depth = textureLocation.depth;
d3d12Location.PlacedFootprint.Footprint.RowPitch = rowPitch;
size_t texelSize = TextureFormatPixelSize(texture->GetFormat());
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; return d3d12Location;
} }
@ -320,12 +317,10 @@ namespace d3d12 {
Buffer* buffer = ToBackend(copy->source.buffer.Get()); Buffer* buffer = ToBackend(copy->source.buffer.Get());
Texture* texture = ToBackend(copy->destination.texture.Get()); Texture* texture = ToBackend(copy->destination.texture.Get());
D3D12_TEXTURE_COPY_LOCATION srcLocation = D3D12PlacedTextureCopyLocation(copy->source, texture, copy->destination); D3D12_TEXTURE_COPY_LOCATION srcLocation = D3D12PlacedTextureCopyLocation(copy->source, texture, copy->destination, copy->rowPitch);
D3D12_TEXTURE_COPY_LOCATION dstLocation = D3D12TextureCopyLocation(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 uint64_t totalBytes = (copy->rowPitch * (copy->destination.height - 1) + copy->destination.width) * copy->destination.depth;
// 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()); ASSERT(totalBytes <= buffer->GetD3D12Size());
commandList->CopyTextureRegion(&dstLocation, copy->destination.x, copy->destination.y, copy->destination.z, &srcLocation, nullptr); commandList->CopyTextureRegion(&dstLocation, copy->destination.x, copy->destination.y, copy->destination.z, &srcLocation, nullptr);
@ -339,11 +334,9 @@ namespace d3d12 {
Buffer* buffer = ToBackend(copy->destination.buffer.Get()); Buffer* buffer = ToBackend(copy->destination.buffer.Get());
D3D12_TEXTURE_COPY_LOCATION srcLocation = D3D12TextureCopyLocation(copy->source); D3D12_TEXTURE_COPY_LOCATION srcLocation = D3D12TextureCopyLocation(copy->source);
D3D12_TEXTURE_COPY_LOCATION dstLocation = D3D12PlacedTextureCopyLocation(copy->destination, texture, copy->source); D3D12_TEXTURE_COPY_LOCATION dstLocation = D3D12PlacedTextureCopyLocation(copy->destination, texture, copy->source, copy->rowPitch);
// 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 uint64_t totalBytes = (copy->rowPitch * (copy->source.height - 1) + copy->source.width) * copy->source.depth;
// 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()); ASSERT(totalBytes <= buffer->GetD3D12Size());
D3D12_BOX sourceRegion; D3D12_BOX sourceRegion;

View File

@ -207,7 +207,6 @@ namespace metal {
Buffer* buffer = ToBackend(src.buffer.Get()); Buffer* buffer = ToBackend(src.buffer.Get());
Texture* texture = ToBackend(dst.texture.Get()); Texture* texture = ToBackend(dst.texture.Get());
unsigned rowSize = dst.width * TextureFormatPixelSize(texture->GetFormat());
MTLOrigin origin; MTLOrigin origin;
origin.x = dst.x; origin.x = dst.x;
origin.y = dst.y; origin.y = dst.y;
@ -222,8 +221,8 @@ namespace metal {
[encoders.blit [encoders.blit
copyFromBuffer:buffer->GetMTLBuffer() copyFromBuffer:buffer->GetMTLBuffer()
sourceOffset:src.offset sourceOffset:src.offset
sourceBytesPerRow:rowSize sourceBytesPerRow:copy->rowPitch
sourceBytesPerImage:(rowSize * dst.height) sourceBytesPerImage:(copy->rowPitch * dst.height)
sourceSize:size sourceSize:size
toTexture:texture->GetMTLTexture() toTexture:texture->GetMTLTexture()
destinationSlice:0 destinationSlice:0
@ -240,7 +239,6 @@ namespace metal {
Texture* texture = ToBackend(src.texture.Get()); Texture* texture = ToBackend(src.texture.Get());
Buffer* buffer = ToBackend(dst.buffer.Get()); Buffer* buffer = ToBackend(dst.buffer.Get());
unsigned rowSize = src.width * TextureFormatPixelSize(texture->GetFormat());
MTLOrigin origin; MTLOrigin origin;
origin.x = src.x; origin.x = src.x;
origin.y = src.y; origin.y = src.y;
@ -260,8 +258,8 @@ namespace metal {
sourceSize:size sourceSize:size
toBuffer:buffer->GetMTLBuffer() toBuffer:buffer->GetMTLBuffer()
destinationOffset:dst.offset destinationOffset:dst.offset
destinationBytesPerRow:rowSize destinationBytesPerRow:copy->rowPitch
destinationBytesPerImage:rowSize * src.height]; destinationBytesPerImage:copy->rowPitch * src.height];
} }
break; break;

View File

@ -181,9 +181,11 @@ namespace opengl {
glBindTexture(target, texture->GetHandle()); glBindTexture(target, texture->GetHandle());
ASSERT(texture->GetDimension() == nxt::TextureDimension::e2D); ASSERT(texture->GetDimension() == nxt::TextureDimension::e2D);
glPixelStorei(GL_UNPACK_ROW_LENGTH, copy->rowPitch / static_cast<uint32_t>(TextureFormatPixelSize(texture->GetFormat())));
glTexSubImage2D(target, dst.level, dst.x, dst.y, dst.width, dst.height, glTexSubImage2D(target, dst.level, dst.x, dst.y, dst.width, dst.height,
format.format, format.type, format.format, format.type,
reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset))); reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
} }
break; break;
@ -210,9 +212,11 @@ namespace opengl {
texture->GetHandle(), src.level); texture->GetHandle(), src.level);
glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle()); glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
glPixelStorei(GL_PACK_ROW_LENGTH, copy->rowPitch / static_cast<uint32_t>(TextureFormatPixelSize(texture->GetFormat())));
ASSERT(src.depth == 1 && src.z == 0); ASSERT(src.depth == 1 && src.z == 0);
void* offset = reinterpret_cast<void*>(static_cast<uintptr_t>(dst.offset)); void* offset = reinterpret_cast<void*>(static_cast<uintptr_t>(dst.offset));
glReadPixels(src.x, src.y, src.width, src.height, format.format, format.type, offset); glReadPixels(src.x, src.y, src.width, src.height, format.format, format.type, offset);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glDeleteFramebuffers(1, &readFBO); glDeleteFramebuffers(1, &readFBO);