Commit 052167bc by Xinyi He Committed by Commit Bot

Vulkan: Mipmap is unconditionally enabled in ANGLE

ANGLE always enables the Mipmap. The fix does redefining the image with mipmaps and replace the origin one only when it is necessary. Bug: angleproject:3737 Change-Id: Ia33a16fd7feae303fb114988059c4eec58c4232d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1750627 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com>
parent 88a99e43
...@@ -163,3 +163,4 @@ Samsung Electronics, Inc. ...@@ -163,3 +163,4 @@ Samsung Electronics, Inc.
Arm Ltd. Arm Ltd.
Fei Yang Fei Yang
Xinyi He
...@@ -496,6 +496,28 @@ TextureTarget TextureState::getBaseImageTarget() const ...@@ -496,6 +496,28 @@ TextureTarget TextureState::getBaseImageTarget() const
: NonCubeTextureTypeToTarget(mType); : NonCubeTextureTypeToTarget(mType);
} }
GLuint TextureState::getEnabledLevelCount() const
{
GLuint levelCount = 0;
const GLuint baseLevel = getEffectiveBaseLevel();
const GLuint maxLevel = std::min(getEffectiveMaxLevel(), getMipmapMaxLevel());
// The mip chain will have either one or more sequential levels, or max levels,
// but not a sparse one.
for (size_t descIndex = baseLevel; descIndex < mImageDescs.size();)
{
if (!mImageDescs[descIndex].size.empty())
{
levelCount++;
}
descIndex = (mType == TextureType::CubeMap) ? descIndex + 6 : descIndex + 1;
}
// The original image already takes account into the levelCount.
levelCount = std::min(maxLevel - baseLevel + 1, levelCount);
return levelCount;
}
ImageDesc::ImageDesc() ImageDesc::ImageDesc()
: ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::Initialized) : ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::Initialized)
{} {}
......
...@@ -147,6 +147,9 @@ class TextureState final : private angle::NonCopyable ...@@ -147,6 +147,9 @@ class TextureState final : private angle::NonCopyable
void setGenerateMipmapHint(GLenum hint); void setGenerateMipmapHint(GLenum hint);
GLenum getGenerateMipmapHint() const; GLenum getGenerateMipmapHint() const;
// Return the enabled mipmap level count.
GLuint getEnabledLevelCount() const;
private: private:
// Texture needs access to the ImageDesc functions. // Texture needs access to the ImageDesc functions.
friend class Texture; friend class Texture;
......
...@@ -3003,7 +3003,7 @@ angle::Result ContextVk::updateActiveImages(const gl::Context *context, ...@@ -3003,7 +3003,7 @@ angle::Result ContextVk::updateActiveImages(const gl::Context *context,
// already notified of content change). // already notified of content change).
// Test: SimpleStateChangeTestES31.DispatchWithImageTextureTexSubImageThenDispatchAgain // Test: SimpleStateChangeTestES31.DispatchWithImageTextureTexSubImageThenDispatchAgain
// http://anglebug.com/3539 // http://anglebug.com/3539
ANGLE_TRY(textureVk->ensureImageInitialized(this)); ANGLE_TRY(textureVk->ensureImageInitialized(this, ImageMipLevels::EnabledLevels));
vk::ImageLayout imageLayout = vk::ImageLayout::AllGraphicsShadersWrite; vk::ImageLayout imageLayout = vk::ImageLayout::AllGraphicsShadersWrite;
if (program->isCompute()) if (program->isCompute())
......
...@@ -57,7 +57,8 @@ egl::Error ImageVk::initialize(const egl::Display *display) ...@@ -57,7 +57,8 @@ egl::Error ImageVk::initialize(const egl::Display *display)
// Make sure the texture has created its backing storage // Make sure the texture has created its backing storage
ASSERT(mContext != nullptr); ASSERT(mContext != nullptr);
ContextVk *contextVk = vk::GetImpl(mContext); ContextVk *contextVk = vk::GetImpl(mContext);
ANGLE_TRY(ResultToEGL(textureVk->ensureImageInitialized(contextVk))); ANGLE_TRY(ResultToEGL(
textureVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)));
mImage = &textureVk->getImage(); mImage = &textureVk->getImage();
......
...@@ -19,6 +19,14 @@ ...@@ -19,6 +19,14 @@
namespace rx namespace rx
{ {
enum class ImageMipLevels
{
EnabledLevels = 0,
FullMipChain = 1,
InvalidEnum = 2,
};
class TextureVk : public TextureImpl class TextureVk : public TextureImpl
{ {
public: public:
...@@ -180,7 +188,8 @@ class TextureVk : public TextureImpl ...@@ -180,7 +188,8 @@ class TextureVk : public TextureImpl
return mSampler.get(); return mSampler.get();
} }
angle::Result ensureImageInitialized(ContextVk *contextVk); // Normally, initialize the image with enabled mipmap level counts.
angle::Result ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels);
Serial getSerial() const { return mSerial; } Serial getSerial() const { return mSerial; }
...@@ -235,15 +244,6 @@ class TextureVk : public TextureImpl ...@@ -235,15 +244,6 @@ class TextureVk : public TextureImpl
const gl::Rectangle &sourceArea, const gl::Rectangle &sourceArea,
uint8_t **outDataPtr); uint8_t **outDataPtr);
angle::Result copyImageDataToBuffer(ContextVk *contextVk,
size_t sourceLevel,
uint32_t layerCount,
uint32_t baseLayer,
const gl::Box &sourceArea,
vk::BufferHelper **bufferOut,
VkDeviceSize *bufferOffsetOut,
uint8_t **outDataPtr);
angle::Result generateMipmapsWithCPU(const gl::Context *context); angle::Result generateMipmapsWithCPU(const gl::Context *context);
angle::Result generateMipmapLevelsWithCPU(ContextVk *contextVk, angle::Result generateMipmapLevelsWithCPU(ContextVk *contextVk,
...@@ -303,7 +303,14 @@ class TextureVk : public TextureImpl ...@@ -303,7 +303,14 @@ class TextureVk : public TextureImpl
const uint32_t levelCount); const uint32_t levelCount);
void releaseImage(ContextVk *contextVk); void releaseImage(ContextVk *contextVk);
void releaseStagingBuffer(ContextVk *contextVk); void releaseStagingBuffer(ContextVk *contextVk);
uint32_t getLevelCount() const; uint32_t getMipLevelCount(ImageMipLevels mipLevels) const;
uint32_t getMaxLevelCount() const;
angle::Result copyImageDataToStagingBuffer(ContextVk *contextVk,
const gl::ImageDesc &desc,
bool ignoreLayerCount,
uint32_t currentLayer,
uint32_t sourceLevel,
uint32_t stagingDstMipLevel);
angle::Result initImageViews(ContextVk *contextVk, angle::Result initImageViews(ContextVk *contextVk,
const vk::Format &format, const vk::Format &format,
const bool sized, const bool sized,
......
...@@ -2850,6 +2850,81 @@ bool ImageHelper::isUpdateStaged(uint32_t level, uint32_t layer) ...@@ -2850,6 +2850,81 @@ bool ImageHelper::isUpdateStaged(uint32_t level, uint32_t layer)
return false; return false;
} }
angle::Result ImageHelper::copyImageDataToBuffer(ContextVk *contextVk,
size_t sourceLevel,
uint32_t layerCount,
uint32_t baseLayer,
const gl::Box &sourceArea,
vk::BufferHelper **bufferOut,
VkDeviceSize *bufferOffsetOut,
uint8_t **outDataPtr)
{
ANGLE_TRACE_EVENT0("gpu.angle", "TextureVk::copyImageDataToBuffer");
const angle::Format &imageFormat = mFormat->actualImageFormat();
size_t sourceCopyAllocationSize = sourceArea.width * sourceArea.height * sourceArea.depth *
imageFormat.pixelBytes * layerCount;
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(recordCommands(contextVk, &commandBuffer));
// http://anglebug.com/3949: Need to handle DS combined aspect, will require copying D & S
// separately. See ImageHelper::stageSubresourceUpdate for DS copy buff->image example.
ASSERT(getAspectFlags() == VK_IMAGE_ASPECT_COLOR_BIT ||
getAspectFlags() == VK_IMAGE_ASPECT_DEPTH_BIT ||
getAspectFlags() == VK_IMAGE_ASPECT_STENCIL_BIT);
// Transition the image to readable layout
changeLayout(getAspectFlags(), vk::ImageLayout::TransferSrc, commandBuffer);
VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.image = mImage.getHandle();
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.subresourceRange.aspectMask = getAspectFlags();
barrier.subresourceRange.baseArrayLayer = baseLayer;
barrier.subresourceRange.layerCount = layerCount;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseMipLevel = static_cast<uint32_t>(sourceLevel);
barrier.oldLayout = getCurrentLayout();
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
&barrier);
// Allocate staging buffer data
ANGLE_TRY(allocateStagingMemory(contextVk, sourceCopyAllocationSize, outDataPtr, bufferOut,
bufferOffsetOut, nullptr));
VkBufferImageCopy region = {};
region.bufferOffset = *bufferOffsetOut;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageExtent.width = sourceArea.width;
region.imageExtent.height = sourceArea.height;
region.imageExtent.depth = sourceArea.depth;
region.imageOffset.x = sourceArea.x;
region.imageOffset.y = sourceArea.y;
region.imageOffset.z = sourceArea.z;
region.imageSubresource.aspectMask = getAspectFlags();
region.imageSubresource.baseArrayLayer = baseLayer;
region.imageSubresource.layerCount = layerCount;
region.imageSubresource.mipLevel = static_cast<uint32_t>(sourceLevel);
commandBuffer->copyImageToBuffer(mImage, getCurrentLayout(),
(*bufferOut)->getBuffer().getHandle(), 1, &region);
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
commandBuffer->imageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
&barrier);
return angle::Result::Continue;
}
// ImageHelper::SubresourceUpdate implementation // ImageHelper::SubresourceUpdate implementation
ImageHelper::SubresourceUpdate::SubresourceUpdate() ImageHelper::SubresourceUpdate::SubresourceUpdate()
: updateSource(UpdateSource::Buffer), buffer{VK_NULL_HANDLE} : updateSource(UpdateSource::Buffer), buffer{VK_NULL_HANDLE}
......
...@@ -882,6 +882,15 @@ class ImageHelper final : public CommandGraphResource ...@@ -882,6 +882,15 @@ class ImageHelper final : public CommandGraphResource
uint32_t getBaseLevel(); uint32_t getBaseLevel();
void setBaseAndMaxLevels(uint32_t baseLevel, uint32_t maxLevel); void setBaseAndMaxLevels(uint32_t baseLevel, uint32_t maxLevel);
angle::Result copyImageDataToBuffer(ContextVk *contextVk,
size_t sourceLevel,
uint32_t layerCount,
uint32_t baseLayer,
const gl::Box &sourceArea,
vk::BufferHelper **bufferOut,
VkDeviceSize *bufferOffsetOut,
uint8_t **outDataPtr);
private: private:
void forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask, void forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
ImageLayout newLayout, ImageLayout newLayout,
......
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