Commit 22695bf5 by Luc Ferron Committed by Commit Bot

Vulkan: Support cube mimaps generation

Bug: angleproject:2502 Change-Id: I953d99d04608cec04aad824b8b38f388ed1e4c2b Reviewed-on: https://chromium-review.googlesource.com/1069544 Commit-Queue: Luc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent c5181706
......@@ -316,6 +316,7 @@ gl::Error PixelBuffer::stageSubresourceUpdateAndGetData(RendererVk *renderer,
gl::Error TextureVk::generateMipmapLevels(ContextVk *contextVk,
const angle::Format &sourceFormat,
GLuint layer,
GLuint firstMipLevel,
GLuint maxMipLevel,
const size_t sourceWidth,
......@@ -345,7 +346,7 @@ gl::Error TextureVk::generateMipmapLevels(ContextVk *contextVk,
ANGLE_TRY(mPixelBuffer.stageSubresourceUpdateAndGetData(
renderer, mipAllocationSize,
gl::ImageIndex::MakeFromType(mState.getType(), currentMipLevel, 0, 1), mipLevelExtents,
gl::ImageIndex::MakeFromType(mState.getType(), currentMipLevel, layer), mipLevelExtents,
gl::Offset(), &destData));
// Generate the mipmap into that new buffer
......@@ -591,10 +592,8 @@ gl::Error TextureVk::setImageExternal(const gl::Context *context,
gl::Error TextureVk::generateMipmap(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(context);
vk::CommandBuffer *commandBuffer = nullptr;
RendererVk *renderer = contextVk->getRenderer();
getCommandBufferForWrite(renderer, &commandBuffer);
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
// Some data is pending, or the image has not been defined at all yet
if (!mImage.valid())
......@@ -614,22 +613,36 @@ gl::Error TextureVk::generateMipmap(const gl::Context *context)
// Before we loop to generate all the next levels, we can get the source level and copy it to a
// buffer.
const angle::Format &angleFormat = mImage.getFormat().textureFormat();
VkBuffer baseLevelBufferHandle = VK_NULL_HANDLE;
uint8_t *baseLevelBuffer = nullptr;
const angle::Format &angleFormat = mImage.getFormat().textureFormat();
uint32_t imageLayerCount = GetImageLayerCount(mState.getType());
bool newBufferAllocated = false;
uint32_t baseLevelBufferOffset = 0;
const gl::Extents baseLevelExtents = mImage.getExtents();
GLuint sourceRowPitch = baseLevelExtents.width * angleFormat.pixelBytes;
size_t baseLevelAllocationSize = sourceRowPitch * baseLevelExtents.height;
ANGLE_TRY(mPixelBuffer.allocate(renderer, baseLevelAllocationSize, &baseLevelBuffer,
&baseLevelBufferHandle, &baseLevelBufferOffset,
&newBufferAllocated));
vk::CommandBuffer *commandBuffer = nullptr;
getCommandBufferForWrite(renderer, &commandBuffer);
// Requirement of the copyImageToBuffer, the source image must be in SRC_OPTIMAL layout.
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, commandBuffer);
size_t totalAllocationSize = baseLevelAllocationSize * imageLayerCount;
VkBuffer copyBufferHandle;
uint8_t *baseLevelBuffers;
uint32_t copyBaseOffset;
// Allocate enough memory to copy every level 0 image (one for each layer of the texture).
ANGLE_TRY(mPixelBuffer.allocate(renderer, totalAllocationSize, &baseLevelBuffers,
&copyBufferHandle, &copyBaseOffset, &newBufferAllocated));
// Do only one copy for all layers at once.
VkBufferImageCopy region;
region.bufferImageHeight = baseLevelExtents.height;
region.bufferOffset = static_cast<VkDeviceSize>(baseLevelBufferOffset);
region.bufferOffset = static_cast<VkDeviceSize>(copyBaseOffset);
region.bufferRowLength = baseLevelExtents.width;
region.imageExtent.width = baseLevelExtents.width;
region.imageExtent.height = baseLevelExtents.height;
......@@ -639,15 +652,11 @@ gl::Error TextureVk::generateMipmap(const gl::Context *context)
region.imageOffset.z = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageSubresource.layerCount = imageLayerCount;
region.imageSubresource.mipLevel = mState.getEffectiveBaseLevel();
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, commandBuffer);
commandBuffer->copyImageToBuffer(mImage.getImage(), mImage.getCurrentLayout(),
baseLevelBufferHandle, 1, &region);
commandBuffer->copyImageToBuffer(mImage.getImage(), mImage.getCurrentLayout(), copyBufferHandle,
1, &region);
ANGLE_TRY(renderer->finish(context));
......@@ -657,9 +666,15 @@ gl::Error TextureVk::generateMipmap(const gl::Context *context)
// We now have the base level available to be manipulated in the baseLevelBuffer pointer.
// Generate all the missing mipmaps with the slow path. We can optimize with vkCmdBlitImage
// later.
ANGLE_TRY(generateMipmapLevels(contextVk, angleFormat, mState.getEffectiveBaseLevel() + 1,
mState.getMipmapMaxLevel(), baseLevelExtents.width,
baseLevelExtents.height, sourceRowPitch, baseLevelBuffer));
// For each layer, use the copied data to generate all the mips.
for (GLuint layer = 0; layer < imageLayerCount; layer++)
{
size_t bufferOffset = layer * baseLevelAllocationSize;
ANGLE_TRY(generateMipmapLevels(
contextVk, angleFormat, layer, mState.getEffectiveBaseLevel() + 1,
mState.getMipmapMaxLevel(), baseLevelExtents.width, baseLevelExtents.height,
sourceRowPitch, baseLevelBuffers + bufferOffset));
}
return gl::NoError();
}
......
......@@ -177,6 +177,7 @@ class TextureVk : public TextureImpl, public vk::CommandGraphResource
private:
gl::Error generateMipmapLevels(ContextVk *contextVk,
const angle::Format &sourceFormat,
GLuint layer,
GLuint firstMipLevel,
GLuint maxMipLevel,
size_t sourceWidth,
......
......@@ -80,17 +80,6 @@ VkImageCreateFlags GetImageCreateFlags(gl::TextureType textureType)
}
}
uint32_t GetImageLayerCount(gl::TextureType textureType)
{
if (textureType == gl::TextureType::CubeMap)
{
return gl::CUBE_FACE_COUNT;
}
else
{
return 1;
}
}
} // anonymous namespace
// DynamicBuffer implementation.
......
......@@ -149,6 +149,18 @@ vk::Error AllocateBufferOrImageMemory(VkDevice device,
}
} // anonymous namespace
uint32_t GetImageLayerCount(gl::TextureType textureType)
{
if (textureType == gl::TextureType::CubeMap)
{
return gl::CUBE_FACE_COUNT;
}
else
{
return 1;
}
}
const char *g_VkLoaderLayersPathEnv = "VK_LAYER_PATH";
const char *g_VkICDPathEnv = "VK_ICD_FILENAMES";
......
......@@ -69,6 +69,8 @@ bool GetAvailableValidationLayers(const std::vector<VkLayerProperties> &layerPro
const char *const **enabledLayerNames,
uint32_t *enabledLayerCount);
uint32_t GetImageLayerCount(gl::TextureType textureType);
extern const char *g_VkLoaderLayersPathEnv;
extern const char *g_VkICDPathEnv;
......
......@@ -237,7 +237,6 @@
2593 VULKAN : dEQP-GLES2.functional.shaders.invariance.mediump.loop_4 = SKIP
2594 VULKAN : dEQP-GLES2.functional.shaders.fragdata.valid_static_index = SKIP
2595 VULKAN : dEQP-GLES2.functional.shaders.random.all_features.fragment* = SKIP
2161 VULKAN : dEQP-GLES2.functional.texture.mipmap.cube.generate.* = SKIP
2596 VULKAN : dEQP-GLES2.functional.texture.completeness.2d.extra_level = SKIP
2596 VULKAN : dEQP-GLES2.functional.texture.completeness.cube.extra_level = SKIP
2597 VULKAN : dEQP-GLES2.functional.fbo.render.color_clear.* = SKIP
......
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