Commit 9d597f8a by Jamie Madill Committed by Commit Bot

Vulkan: Use copyImageDataToBuffer in Texture mipmap gen.

There were two code paths using nearly identical code. Fix this by generalizing the helper method slightly. Refactoring change only. Bug: angleproject:2828 Change-Id: I39caccfaad4880e566e995483b8e8fb46d67d3da Reviewed-on: https://chromium-review.googlesource.com/1249563Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 996628a4
...@@ -643,11 +643,15 @@ gl::Error TextureVk::copySubTextureImpl(ContextVk *contextVk, ...@@ -643,11 +643,15 @@ gl::Error TextureVk::copySubTextureImpl(ContextVk *contextVk,
{ {
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
if (sourceLevel != 0)
{
WARN() << "glCopyTextureCHROMIUM with sourceLevel != 0 not implemented.";
return angle::Result::Stop();
}
// Read back the requested region of the source texture // Read back the requested region of the source texture
uint8_t *sourceData = nullptr; uint8_t *sourceData = nullptr;
ANGLE_TRY(source->copyImageDataToBuffer(contextVk, sourceLevel, sourceArea, &sourceData)); ANGLE_TRY(source->copyImageDataToBuffer(contextVk, sourceLevel, 1, sourceArea, &sourceData));
ANGLE_TRY(renderer->finish(contextVk));
// Using the front-end ANGLE format for the colorRead and colorWrite functions. Otherwise // Using the front-end ANGLE format for the colorRead and colorWrite functions. Otherwise
// emulated formats like luminance-alpha would not know how to interpret the data. // emulated formats like luminance-alpha would not know how to interpret the data.
...@@ -755,33 +759,28 @@ angle::Result TextureVk::redefineImage(const gl::Context *context, ...@@ -755,33 +759,28 @@ angle::Result TextureVk::redefineImage(const gl::Context *context,
angle::Result TextureVk::copyImageDataToBuffer(ContextVk *contextVk, angle::Result TextureVk::copyImageDataToBuffer(ContextVk *contextVk,
size_t sourceLevel, size_t sourceLevel,
uint32_t layerCount,
const gl::Rectangle &sourceArea, const gl::Rectangle &sourceArea,
uint8_t **outDataPtr) uint8_t **outDataPtr)
{ {
if (sourceLevel != 0)
{
WARN() << "glCopyTextureCHROMIUM with sourceLevel != 0 not implemented.";
return angle::Result::Stop();
}
// Make sure the source is initialized and it's images are flushed. // Make sure the source is initialized and it's images are flushed.
ANGLE_TRY(ensureImageInitialized(contextVk)); ANGLE_TRY(ensureImageInitialized(contextVk));
const angle::Format &angleFormat = getImage().getFormat().textureFormat(); const angle::Format &imageFormat = getImage().getFormat().textureFormat();
size_t sourceCopyAllocationSize = sourceArea.width * sourceArea.height * angleFormat.pixelBytes; size_t sourceCopyAllocationSize = sourceArea.width * sourceArea.height * imageFormat.pixelBytes;
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(getCommandBufferForWrite(contextVk, &commandBuffer)); ANGLE_TRY(getCommandBufferForWrite(contextVk, &commandBuffer));
// Requirement of the copyImageToBuffer, the source image must be in SRC_OPTIMAL layout. // Requirement of the copyImageToBuffer, the source image must be in SRC_OPTIMAL layout.
bool newBufferAllocated = false;
mImage.changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, mImage.changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, commandBuffer); VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, commandBuffer);
// Allocate enough memory to copy the sourceArea region of the source texture into its pixel // Allocate enough memory to copy the sourceArea region of the source texture into its pixel
// buffer. // buffer.
VkBuffer copyBufferHandle; bool newBufferAllocated = false;
VkBuffer copyBufferHandle = VK_NULL_HANDLE;
VkDeviceSize sourceCopyOffset = 0; VkDeviceSize sourceCopyOffset = 0;
ANGLE_TRY(mPixelBuffer.allocate(contextVk, sourceCopyAllocationSize, outDataPtr, ANGLE_TRY(mPixelBuffer.allocate(contextVk, sourceCopyAllocationSize, outDataPtr,
&copyBufferHandle, &sourceCopyOffset, &newBufferAllocated)); &copyBufferHandle, &sourceCopyOffset, &newBufferAllocated));
...@@ -798,12 +797,15 @@ angle::Result TextureVk::copyImageDataToBuffer(ContextVk *contextVk, ...@@ -798,12 +797,15 @@ angle::Result TextureVk::copyImageDataToBuffer(ContextVk *contextVk,
region.imageOffset.z = 0; region.imageOffset.z = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.baseArrayLayer = 0; region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1; region.imageSubresource.layerCount = layerCount;
region.imageSubresource.mipLevel = static_cast<uint32_t>(sourceLevel); region.imageSubresource.mipLevel = static_cast<uint32_t>(sourceLevel);
commandBuffer->copyImageToBuffer(mImage.getImage(), mImage.getCurrentLayout(), copyBufferHandle, commandBuffer->copyImageToBuffer(mImage.getImage(), mImage.getCurrentLayout(), copyBufferHandle,
1, &region); 1, &region);
// Explicitly finish. If new use cases arise where we don't want to block we can change this.
ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
return angle::Result::Continue(); return angle::Result::Continue();
} }
...@@ -895,60 +897,22 @@ angle::Result TextureVk::generateMipmapWithBlit(ContextVk *contextVk) ...@@ -895,60 +897,22 @@ angle::Result TextureVk::generateMipmapWithBlit(ContextVk *contextVk)
angle::Result TextureVk::generateMipmapWithCPU(const gl::Context *context) angle::Result TextureVk::generateMipmapWithCPU(const gl::Context *context)
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
bool newBufferAllocated = false;
const gl::Extents baseLevelExtents = mImage.getExtents(); const gl::Extents baseLevelExtents = mImage.getExtents();
uint32_t imageLayerCount = GetImageLayerCount(mState.getType()); uint32_t imageLayerCount = GetImageLayerCount(mState.getType());
const angle::Format &angleFormat = mImage.getFormat().textureFormat();
GLuint sourceRowPitch = baseLevelExtents.width * angleFormat.pixelBytes;
size_t baseLevelAllocationSize = sourceRowPitch * baseLevelExtents.height;
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(getCommandBufferForWrite(contextVk, &commandBuffer));
// Requirement of the copyImageToBuffer, the source image must be in SRC_OPTIMAL layout. uint8_t *imageData = nullptr;
mImage.changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, gl::Rectangle imageArea(0, 0, baseLevelExtents.width, baseLevelExtents.height);
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, ANGLE_TRY(copyImageDataToBuffer(contextVk, mState.getEffectiveBaseLevel(), imageLayerCount,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, commandBuffer); imageArea, &imageData));
size_t totalAllocationSize = baseLevelAllocationSize * imageLayerCount;
VkBuffer copyBufferHandle;
uint8_t *baseLevelBuffers;
VkDeviceSize copyBaseOffset;
// Allocate enough memory to copy every level 0 image (one for each layer of the texture).
ANGLE_TRY(mPixelBuffer.allocate(contextVk, totalAllocationSize, &baseLevelBuffers,
&copyBufferHandle, &copyBaseOffset, &newBufferAllocated));
// Do only one copy for all layers at once.
VkBufferImageCopy region;
region.bufferImageHeight = baseLevelExtents.height;
region.bufferOffset = copyBaseOffset;
region.bufferRowLength = baseLevelExtents.width;
region.imageExtent.width = baseLevelExtents.width;
region.imageExtent.height = baseLevelExtents.height;
region.imageExtent.depth = 1;
region.imageOffset.x = 0;
region.imageOffset.y = 0;
region.imageOffset.z = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = imageLayerCount;
region.imageSubresource.mipLevel = mState.getEffectiveBaseLevel();
commandBuffer->copyImageToBuffer(mImage.getImage(), mImage.getCurrentLayout(), copyBufferHandle, const angle::Format &angleFormat = mImage.getFormat().textureFormat();
1, &region); GLuint sourceRowPitch = baseLevelExtents.width * angleFormat.pixelBytes;
size_t baseLevelAllocationSize = sourceRowPitch * baseLevelExtents.height;
ANGLE_TRY(renderer->finish(contextVk));
const uint32_t levelCount = getLevelCount(); // We now have the base level available to be manipulated in the imageData pointer. Generate all
// the missing mipmaps with the slow path. For each layer, use the copied data to generate all
// We now have the base level available to be manipulated in the baseLevelBuffer pointer. // the mips.
// Generate all the missing mipmaps with the slow path. We can optimize with vkCmdBlitImage
// later.
// For each layer, use the copied data to generate all the mips.
for (GLuint layer = 0; layer < imageLayerCount; layer++) for (GLuint layer = 0; layer < imageLayerCount; layer++)
{ {
size_t bufferOffset = layer * baseLevelAllocationSize; size_t bufferOffset = layer * baseLevelAllocationSize;
...@@ -956,10 +920,12 @@ angle::Result TextureVk::generateMipmapWithCPU(const gl::Context *context) ...@@ -956,10 +920,12 @@ angle::Result TextureVk::generateMipmapWithCPU(const gl::Context *context)
ANGLE_TRY(generateMipmapLevelsWithCPU( ANGLE_TRY(generateMipmapLevelsWithCPU(
contextVk, angleFormat, layer, mState.getEffectiveBaseLevel() + 1, contextVk, angleFormat, layer, mState.getEffectiveBaseLevel() + 1,
mState.getMipmapMaxLevel(), baseLevelExtents.width, baseLevelExtents.height, mState.getMipmapMaxLevel(), baseLevelExtents.width, baseLevelExtents.height,
sourceRowPitch, baseLevelBuffers + bufferOffset)); sourceRowPitch, imageData + bufferOffset));
} }
return mPixelBuffer.flushUpdatesToImage(contextVk, levelCount, &mImage, commandBuffer); vk::CommandBuffer *commandBuffer;
ANGLE_TRY(mImage.recordCommands(contextVk, &commandBuffer));
return mPixelBuffer.flushUpdatesToImage(contextVk, getLevelCount(), &mImage, commandBuffer);
} }
gl::Error TextureVk::generateMipmap(const gl::Context *context) gl::Error TextureVk::generateMipmap(const gl::Context *context)
......
...@@ -217,6 +217,7 @@ class TextureVk : public TextureImpl ...@@ -217,6 +217,7 @@ class TextureVk : public TextureImpl
angle::Result copyImageDataToBuffer(ContextVk *contextVk, angle::Result copyImageDataToBuffer(ContextVk *contextVk,
size_t sourceLevel, size_t sourceLevel,
uint32_t layerCount,
const gl::Rectangle &sourceArea, const gl::Rectangle &sourceArea,
uint8_t **outDataPtr); uint8_t **outDataPtr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment