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: Cody Northrop <cnorthrop@google.com>
Reviewed-by: Ian Elliott <ianelliott@google.com>
This commit is contained in:
Xinyi He 2019-08-13 14:09:04 +08:00 коммит произвёл Commit Bot
Родитель 88a99e4382
Коммит 052167bc15
9 изменённых файлов: 237 добавлений и 104 удалений

Просмотреть файл

@ -163,3 +163,4 @@ Samsung Electronics, Inc.
Arm Ltd.
Fei Yang
Xinyi He

Просмотреть файл

@ -496,6 +496,28 @@ TextureTarget TextureState::getBaseImageTarget() const
: 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(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::Initialized)
{}

Просмотреть файл

@ -147,6 +147,9 @@ class TextureState final : private angle::NonCopyable
void setGenerateMipmapHint(GLenum hint);
GLenum getGenerateMipmapHint() const;
// Return the enabled mipmap level count.
GLuint getEnabledLevelCount() const;
private:
// Texture needs access to the ImageDesc functions.
friend class Texture;

Просмотреть файл

@ -3003,7 +3003,7 @@ angle::Result ContextVk::updateActiveImages(const gl::Context *context,
// already notified of content change).
// Test: SimpleStateChangeTestES31.DispatchWithImageTextureTexSubImageThenDispatchAgain
// http://anglebug.com/3539
ANGLE_TRY(textureVk->ensureImageInitialized(this));
ANGLE_TRY(textureVk->ensureImageInitialized(this, ImageMipLevels::EnabledLevels));
vk::ImageLayout imageLayout = vk::ImageLayout::AllGraphicsShadersWrite;
if (program->isCompute())

Просмотреть файл

@ -57,7 +57,8 @@ egl::Error ImageVk::initialize(const egl::Display *display)
// Make sure the texture has created its backing storage
ASSERT(mContext != nullptr);
ContextVk *contextVk = vk::GetImpl(mContext);
ANGLE_TRY(ResultToEGL(textureVk->ensureImageInitialized(contextVk)));
ANGLE_TRY(ResultToEGL(
textureVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels)));
mImage = &textureVk->getImage();

Просмотреть файл

@ -341,7 +341,7 @@ angle::Result TextureVk::copyCompressedTexture(const gl::Context *context,
ANGLE_TRY(redefineImage(context, destIndex, vkFormat, size));
ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk));
ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
return copySubImageImplWithTransfer(
contextVk, destIndex, gl::Offset(0, 0, 0), vkFormat, sourceLevel, 0,
@ -433,7 +433,7 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
{
RendererVk *renderer = contextVk->getRenderer();
ANGLE_TRY(source->ensureImageInitialized(contextVk));
ANGLE_TRY(source->ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
const vk::Format &sourceVkFormat = source->getImage().getFormat();
const vk::Format &destVkFormat = renderer->getFormat(destFormat.sizedInternalFormat);
@ -546,7 +546,7 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
if (mImage->valid())
{
// Make sure any updates to the image are already flushed.
ANGLE_TRY(ensureImageInitialized(contextVk));
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
@ -648,7 +648,7 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
if (mImage->valid())
{
// Make sure any updates to the image are already flushed.
ANGLE_TRY(ensureImageInitialized(contextVk));
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex)
{
@ -953,15 +953,15 @@ angle::Result TextureVk::copyImageDataToBufferAndGetData(ContextVk *contextVk,
ANGLE_TRACE_EVENT0("gpu.angle", "TextureVk::copyImageDataToBufferAndGetData");
// Make sure the source is initialized and it's images are flushed.
ANGLE_TRY(ensureImageInitialized(contextVk));
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
gl::Box area(0, 0, 0, sourceArea.width, sourceArea.height, 1);
vk::BufferHelper *copyBuffer = nullptr;
VkDeviceSize sourceCopyOffset = 0;
ANGLE_TRY(copyImageDataToBuffer(contextVk, sourceLevel, layerCount, 0, area, &copyBuffer,
&sourceCopyOffset, outDataPtr));
ANGLE_TRY(mImage->copyImageDataToBuffer(contextVk, sourceLevel, layerCount, 0, area,
&copyBuffer, &sourceCopyOffset, outDataPtr));
// Explicitly finish. If new use cases arise where we don't want to block we can change this.
ANGLE_TRY(contextVk->finishImpl());
@ -969,58 +969,6 @@ angle::Result TextureVk::copyImageDataToBufferAndGetData(ContextVk *contextVk,
return angle::Result::Continue;
}
angle::Result TextureVk::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 = getImage().getFormat().actualImageFormat();
size_t sourceCopyAllocationSize = sourceArea.width * sourceArea.height * sourceArea.depth *
imageFormat.pixelBytes * layerCount;
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mImage->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(mImage->getAspectFlags() == VK_IMAGE_ASPECT_COLOR_BIT ||
mImage->getAspectFlags() == VK_IMAGE_ASPECT_DEPTH_BIT ||
mImage->getAspectFlags() == VK_IMAGE_ASPECT_STENCIL_BIT);
// Transition the image to readable layout
mImage->changeLayout(mImage->getAspectFlags(), vk::ImageLayout::TransferSrc, commandBuffer);
// Allocate staging buffer data
ANGLE_TRY(mImage->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 = mImage->getAspectFlags();
region.imageSubresource.baseArrayLayer = baseLayer;
region.imageSubresource.layerCount = layerCount;
region.imageSubresource.mipLevel = static_cast<uint32_t>(sourceLevel);
commandBuffer->copyImageToBuffer(mImage->getImage(), mImage->getCurrentLayout(),
(*bufferOut)->getBuffer().getHandle(), 1, &region);
return angle::Result::Continue;
}
angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(context);
@ -1060,7 +1008,11 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
angle::Result TextureVk::generateMipmap(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(context);
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
bool needRedefineImage = true;
const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
// Some data is pending, or the image has not been defined at all yet
if (!mImage->valid())
@ -1068,8 +1020,9 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
// Let's initialize the image so we can generate the next levels.
if (mImage->hasStagedUpdates())
{
ANGLE_TRY(ensureImageInitialized(contextVk));
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::FullMipChain));
ASSERT(mImage->valid());
needRedefineImage = false;
}
else
{
@ -1078,13 +1031,41 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
}
}
RendererVk *renderer = contextVk->getRenderer();
// Check whether the image is already full mipmap
if (mImage->getLevelCount() == getMipLevelCount(ImageMipLevels::FullMipChain) &&
mImage->getBaseLevel() == mState.getEffectiveBaseLevel())
{
needRedefineImage = false;
}
if (needRedefineImage)
{
// Flush update if needed.
if (mImage->hasStagedUpdates())
{
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
ANGLE_TRY(mImage->flushStagedUpdates(contextVk, getNativeImageLevel(0),
mImage->getLevelCount(), getNativeImageLayer(0),
mImage->getLayerCount(), commandBuffer));
}
// Redefine the images with mipmaps.
// Copy image to the staging buffer and stage an update to the new one.
ANGLE_TRY(copyImageDataToStagingBuffer(contextVk, baseLevelDesc, false,
getNativeImageLayer(0), 0, mImage->getBaseLevel()));
onStagingBufferChange();
// Release the origin image and recreate it with new mipmap counts.
releaseImage(contextVk);
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::FullMipChain));
}
// Check if the image supports blit. If it does, we can do the mipmap generation on the gpu
// only.
if (renderer->hasImageFormatFeatureBits(mImage->getFormat().vkImageFormat, kBlitFeatureFlags))
{
ANGLE_TRY(ensureImageInitialized(contextVk));
ANGLE_TRY(mImage->generateMipmapsWithBlit(
contextVk, mState.getMipmapMaxLevel() - mState.getEffectiveBaseLevel()));
}
@ -1096,6 +1077,46 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
return angle::Result::Continue;
}
angle::Result TextureVk::copyImageDataToStagingBuffer(ContextVk *contextVk,
const gl::ImageDesc &desc,
bool ignoreLayerCount,
uint32_t currentLayer,
uint32_t sourceMipLevel,
uint32_t stagingDstMipLevel)
{
const gl::Extents &baseLevelExtents = desc.size;
const gl::InternalFormat &baseLevelFormat = *desc.format.info;
VkExtent3D updatedExtents;
VkOffset3D offset = {0};
uint32_t layerCount;
gl_vk::GetExtentsAndLayerCount(mState.getType(), baseLevelExtents, &updatedExtents,
&layerCount);
gl::Box area(offset.x, offset.y, offset.z, updatedExtents.width, updatedExtents.height,
updatedExtents.depth);
// TODO: Refactor TextureVk::changeLevels() to avoid this workaround.
if (ignoreLayerCount)
{
layerCount = 1;
}
// Copy from the base level image to the staging buffer
vk::BufferHelper *stagingBuffer = nullptr;
VkDeviceSize stagingBufferOffset = 0;
ANGLE_TRY(mImage->copyImageDataToBuffer(contextVk, sourceMipLevel, layerCount, currentLayer,
area, &stagingBuffer, &stagingBufferOffset, nullptr));
// Stage an update to the new image
size_t bufferSize = updatedExtents.width * updatedExtents.height * updatedExtents.depth *
baseLevelFormat.pixelBytes;
ANGLE_TRY(mImage->stageSubresourceUpdateFromBuffer(contextVk, bufferSize, stagingDstMipLevel,
currentLayer, layerCount, updatedExtents,
offset, stagingBuffer, stagingBufferOffset));
return angle::Result::Continue;
}
angle::Result TextureVk::setBaseLevel(const gl::Context *context, GLuint baseLevel)
{
return angle::Result::Continue;
@ -1171,35 +1192,14 @@ angle::Result TextureVk::changeLevels(ContextVk *contextVk, GLuint baseLevel, GL
// First we populate the staging buffer with current level data
const gl::ImageDesc &desc =
mState.getImageDesc(gl::TextureTypeToTarget(mState.getType(), layer), level);
const gl::Extents &glExtents = desc.size;
const gl::InternalFormat &info = *desc.format.info;
// We need to adjust the source Vulkan level to reflect the previous base level.
// vk level 0 previously aligned with whatever the base level was.
uint32_t srcLevelVK = baseLevelChanged ? level - previousBaseLevel : level;
ASSERT(srcLevelVK <= mImage->getLevelCount());
// Gather Vulkan dimensions based on our knowledge of image type here
VkOffset3D vkOffset = {0};
VkExtent3D vkExtent;
uint32_t layerCountDontCare;
gl_vk::GetExtentsAndLayerCount(mState.getType(), glExtents, &vkExtent,
&layerCountDontCare);
// Now copy from the image to the staging buffer
vk::BufferHelper *stagingBuffer = nullptr;
VkDeviceSize stagingBufferOffset = 0;
gl::Box area(vkOffset.x, vkOffset.y, vkOffset.z, vkExtent.width, vkExtent.height,
vkExtent.depth);
ANGLE_TRY(copyImageDataToBuffer(contextVk, srcLevelVK, 1, layer, area, &stagingBuffer,
&stagingBufferOffset, nullptr));
// Stage an update to the new image that we will populate with existing mip levels
// We're providing the buffer handle and offset to use, since we *just* populated it
size_t bufferSize = vkExtent.width * vkExtent.height * vkExtent.depth * info.pixelBytes;
ANGLE_TRY(mImage->stageSubresourceUpdateFromBuffer(contextVk, bufferSize, level, layer,
1, vkExtent, vkOffset, stagingBuffer,
stagingBufferOffset));
ANGLE_TRY(
copyImageDataToStagingBuffer(contextVk, desc, true, layer, srcLevelVK, level));
}
}
@ -1251,7 +1251,7 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
ASSERT(imageIndex.getLevelIndex() >= 0);
ContextVk *contextVk = vk::GetImpl(context);
ANGLE_TRY(ensureImageInitialized(contextVk));
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
GLuint layerIndex = 0, layerCount = 0;
GetRenderTargetLayerCountAndIndex(mImage, imageIndex, &layerCount, &layerIndex);
@ -1264,11 +1264,11 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
return angle::Result::Continue;
}
angle::Result TextureVk::ensureImageInitialized(ContextVk *contextVk)
angle::Result TextureVk::ensureImageInitialized(ContextVk *contextVk, ImageMipLevels mipLevels)
{
const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
const gl::Extents &baseLevelExtents = baseLevelDesc.size;
const uint32_t levelCount = getLevelCount() - mState.getEffectiveBaseLevel();
const uint32_t levelCount = getMipLevelCount(mipLevels);
const vk::Format &format =
contextVk->getRenderer()->getFormat(baseLevelDesc.format.info->sizedInternalFormat);
@ -1338,7 +1338,7 @@ angle::Result TextureVk::syncState(const gl::Context *context,
}
// Initialize the image storage and flush the pixel buffer.
ANGLE_TRY(ensureImageInitialized(contextVk));
ANGLE_TRY(ensureImageInitialized(contextVk, ImageMipLevels::EnabledLevels));
if (dirtyBits.none() && mSampler.valid())
{
@ -1635,7 +1635,22 @@ void TextureVk::releaseStagingBuffer(ContextVk *contextVk)
}
}
uint32_t TextureVk::getLevelCount() const
uint32_t TextureVk::getMipLevelCount(ImageMipLevels mipLevels) const
{
switch (mipLevels)
{
case ImageMipLevels::EnabledLevels:
return mState.getEnabledLevelCount();
case ImageMipLevels::FullMipChain:
return getMaxLevelCount() - mState.getEffectiveBaseLevel();
default:
UNREACHABLE();
return 0;
}
}
uint32_t TextureVk::getMaxLevelCount() const
{
// getMipmapMaxLevel will be 0 here if mipmaps are not used, so the levelCount is always +1.
return mState.getMipmapMaxLevel() + 1;

Просмотреть файл

@ -19,6 +19,14 @@
namespace rx
{
enum class ImageMipLevels
{
EnabledLevels = 0,
FullMipChain = 1,
InvalidEnum = 2,
};
class TextureVk : public TextureImpl
{
public:
@ -180,7 +188,8 @@ class TextureVk : public TextureImpl
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; }
@ -235,15 +244,6 @@ class TextureVk : public TextureImpl
const gl::Rectangle &sourceArea,
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 generateMipmapLevelsWithCPU(ContextVk *contextVk,
@ -303,7 +303,14 @@ class TextureVk : public TextureImpl
const uint32_t levelCount);
void releaseImage(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,
const vk::Format &format,
const bool sized,

Просмотреть файл

@ -2850,6 +2850,81 @@ bool ImageHelper::isUpdateStaged(uint32_t level, uint32_t layer)
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::SubresourceUpdate()
: updateSource(UpdateSource::Buffer), buffer{VK_NULL_HANDLE}

Просмотреть файл

@ -882,6 +882,15 @@ class ImageHelper final : public CommandGraphResource
uint32_t getBaseLevel();
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:
void forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
ImageLayout newLayout,