Commit db32bda4 by Jamie Madill Committed by Commit Bot

Vulkan: Observe staging buffer changes in TextureVk.

This switches where we notify the Texture class that the back-end has a dirty staging buffer. Previously we notified in every possible code site in TextureVk. Now we notify in a single centralized location in the staging buffer. This will allow us to stash clears in the staging buffer in the FramebufferVk class via RenderTargetVk. And ultimately let us defer clears to fix Manhattan's rendering feedback loop. Bug: angleproject:4517 Change-Id: I67760f133e2c58feddbba3d1062de0b966bac281 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2128546Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent dbb23ec3
......@@ -39,6 +39,8 @@ constexpr VkImageUsageFlags kTransferStagingImageFlags =
constexpr VkFormatFeatureFlags kBlitFeatureFlags =
VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
constexpr angle::SubjectIndex kStagingBufferSubjectIndex = 0;
bool CanCopyWithTransfer(RendererVk *renderer,
const vk::Format &srcFormat,
const vk::Format &destFormat)
......@@ -111,7 +113,8 @@ TextureVk::TextureVk(const gl::TextureState &state, RendererVk *renderer)
mImageLevelOffset(0),
mImage(nullptr),
mStagingBufferInitialSize(vk::kStagingBufferSize),
mImageUsageFlags(0)
mImageUsageFlags(0),
mStagingBufferObserverBinding(this, kStagingBufferSubjectIndex)
{}
TextureVk::~TextureVk() = default;
......@@ -280,7 +283,6 @@ angle::Result TextureVk::setSubImageImpl(const gl::Context *context,
inputRowPitch, inputDepthPitch, inputSkipBytes));
unpackBufferVk->unmapImpl(contextVk);
onStagingBufferChange();
}
}
else if (pixels)
......@@ -288,7 +290,6 @@ angle::Result TextureVk::setSubImageImpl(const gl::Context *context,
ANGLE_TRY(mImage->stageSubresourceUpdate(
contextVk, getNativeImageIndex(index), gl::Extents(area.width, area.height, area.depth),
gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, pixels, vkFormat));
onStagingBufferChange();
}
return angle::Result::Continue;
......@@ -460,7 +461,6 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
context, offsetImageIndex, clippedSourceArea, modifiedDestOffset,
gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1), internalFormat,
framebufferVk));
onStagingBufferChange();
return angle::Result::Continue;
}
......@@ -526,7 +526,6 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
contextVk, destinationAllocationSize, offsetImageIndex,
gl::Extents(sourceArea.width, sourceArea.height, 1), destOffset, &destData));
onStagingBufferChange();
// Source and dest data is tightly packed
GLuint sourceDataRowPitch = sourceArea.width * sourceTextureFormat.pixelBytes;
......@@ -635,7 +634,6 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
VkImageType imageType = gl_vk::GetImageType(mState.getType());
mImage->stageSubresourceUpdateFromImage(stagingImage.release(), index, destOffset, extents,
imageType);
onStagingBufferChange();
}
return angle::Result::Continue;
......@@ -731,7 +729,6 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
mImage->stageSubresourceUpdateFromImage(stagingImage.release(), index, destOffset,
gl::Extents(sourceArea.width, sourceArea.height, 1),
imageType);
onStagingBufferChange();
}
return angle::Result::Continue;
......@@ -877,6 +874,7 @@ void TextureVk::releaseAndDeleteImage(ContextVk *contextVk)
{
releaseImage(contextVk);
releaseStagingBuffer(contextVk);
mStagingBufferObserverBinding.bind(nullptr);
SafeDelete(mImage);
}
}
......@@ -921,6 +919,8 @@ void TextureVk::setImageHelper(ContextVk *contextVk,
{
ASSERT(mImage == nullptr);
mStagingBufferObserverBinding.bind(imageHelper);
mOwnsImage = selfOwned;
mImageNativeType = imageType;
mImageLevelOffset = imageLevelOffset;
......@@ -1151,7 +1151,6 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
ANGLE_TRY(copyAndStageImageSubresource(contextVk, baseLevelDesc, false,
getNativeImageLayer(0), 0, mImage->getBaseLevel()));
onStagingBufferChange();
// Release the origin image and recreate it with new mipmap counts.
releaseImage(contextVk);
......@@ -1312,8 +1311,6 @@ angle::Result TextureVk::changeLevels(ContextVk *contextVk,
}
}
// Inform the front end that we've updated the staging buffer
onStagingBufferChange();
// Now that we've staged all the updates, release the current image so that it will be
// recreated with the correct number of mip levels, base level, and max level.
releaseImage(contextVk);
......@@ -1552,7 +1549,6 @@ angle::Result TextureVk::initializeContents(const gl::Context *context,
vk::GetImpl(context)->getRenderer()->getFormat(desc.format.info->sizedInternalFormat);
mImage->stageSubresourceRobustClear(imageIndex, format);
onStagingBufferChange();
// Note that we cannot ensure the image is initialized because we might be calling subImage
// on a non-complete cube map.
......@@ -1658,7 +1654,6 @@ angle::Result TextureVk::initImage(ContextVk *contextVk,
{
gl::ImageIndex index = gl::ImageIndex::Make2DArrayRange(level, 0, layerCount);
mImage->stageSubresourceRobustClear(index, format);
onStagingBufferChange();
}
}
......@@ -1698,6 +1693,7 @@ void TextureVk::releaseImage(ContextVk *contextVk)
}
else
{
mStagingBufferObserverBinding.bind(nullptr);
mImage = nullptr;
}
}
......@@ -1712,7 +1708,7 @@ void TextureVk::releaseImage(ContextVk *contextVk)
// Then clear the levels
mRenderTargets.clear();
onStagingBufferChange();
onStateChange(angle::SubjectMessage::SubjectChanged);
}
void TextureVk::releaseStagingBuffer(ContextVk *contextVk)
......@@ -1783,7 +1779,6 @@ angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk,
contextVk, mipAllocationSize,
gl::ImageIndex::MakeFromType(mState.getType(), currentMipLevel, layer), mipLevelExtents,
gl::Offset(), &destData));
onStagingBufferChange();
// Generate the mipmap into that new buffer
sourceFormat.mipGenerationFunction(
......@@ -1861,4 +1856,12 @@ const vk::Format &TextureVk::getBaseLevelFormat(RendererVk *renderer) const
const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
return renderer->getFormat(baseLevelDesc.format.info->sizedInternalFormat);
}
void TextureVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
ASSERT(index == kStagingBufferSubjectIndex && message == angle::SubjectMessage::SubjectChanged);
// Forward the notification to vk::Texture that the staging buffer changed.
onStateChange(angle::SubjectMessage::SubjectChanged);
}
} // namespace rx
......@@ -30,7 +30,7 @@ enum class ImageMipLevels
// vkCmdCopyBufferToImage buffer offset multiple
constexpr VkDeviceSize kBufferOffsetMultiple = 4;
class TextureVk : public TextureImpl
class TextureVk : public TextureImpl, public angle::ObserverInterface
{
public:
TextureVk(const gl::TextureState &state, RendererVk *renderer);
......@@ -371,8 +371,6 @@ class TextureVk : public TextureImpl
uint32_t levelCount,
const vk::Format &format);
void onStagingBufferChange() { onStateChange(angle::SubjectMessage::SubjectChanged); }
const gl::InternalFormat &getImplementationSizedFormat(const gl::Context *context) const;
const vk::Format &getBaseLevelFormat(RendererVk *renderer) const;
// Re-create the image.
......@@ -384,6 +382,10 @@ class TextureVk : public TextureImpl
// Update base and max levels, and re-create image if needed.
angle::Result updateBaseMaxLevels(ContextVk *contextVk, GLuint baseLevel, GLuint maxLevel);
// We monitor the staging buffer and set dirty bits if the staging buffer changes. Note that we
// support changes in the staging buffer even outside the TextureVk class.
void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
bool mOwnsImage;
gl::TextureType mImageNativeType;
......@@ -422,6 +424,8 @@ class TextureVk : public TextureImpl
// The created vkImage usage flag.
VkImageUsageFlags mImageUsageFlags;
angle::ObserverBinding mStagingBufferObserverBinding;
};
} // namespace rx
......
......@@ -1736,7 +1736,8 @@ void BufferHelper::updateWriteBarrier(VkAccessFlags writeAccessType,
// ImageHelper implementation.
ImageHelper::ImageHelper()
: mFormat(nullptr),
: mExtents{},
mFormat(nullptr),
mSamples(1),
mSerial(rx::kZeroSerial),
mCurrentLayout(ImageLayout::Undefined),
......@@ -2594,7 +2595,7 @@ angle::Result ImageHelper::stageSubresourceUpdateImpl(ContextVk *contextVk,
stencilCopy.imageOffset = copy.imageOffset;
stencilCopy.imageExtent = copy.imageExtent;
stencilCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
mSubresourceUpdates.emplace_back(mStagingBuffer.getCurrentBuffer(), stencilCopy);
appendSubresourceUpdate(SubresourceUpdate(mStagingBuffer.getCurrentBuffer(), stencilCopy));
aspectFlags &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
}
......@@ -2618,7 +2619,7 @@ angle::Result ImageHelper::stageSubresourceUpdateImpl(ContextVk *contextVk,
if (aspectFlags)
{
copy.imageSubresource.aspectMask = aspectFlags;
mSubresourceUpdates.emplace_back(mStagingBuffer.getCurrentBuffer(), copy);
appendSubresourceUpdate(SubresourceUpdate(mStagingBuffer.getCurrentBuffer(), copy));
}
return angle::Result::Continue;
......@@ -2699,7 +2700,7 @@ angle::Result ImageHelper::stageSubresourceUpdateAndGetData(ContextVk *contextVk
gl_vk::GetOffset(offset, &copy.imageOffset);
gl_vk::GetExtent(glExtents, &copy.imageExtent);
mSubresourceUpdates.emplace_back(mStagingBuffer.getCurrentBuffer(), copy);
appendSubresourceUpdate(SubresourceUpdate(mStagingBuffer.getCurrentBuffer(), copy));
return angle::Result::Continue;
}
......@@ -2742,10 +2743,10 @@ angle::Result ImageHelper::stageSubresourceUpdateFromBuffer(ContextVk *contextVk
copy[1].imageSubresource.layerCount = layerCount;
copy[1].imageOffset = offset;
copy[1].imageExtent = extent;
mSubresourceUpdates.emplace_back(bufferHelper, copy[1]);
appendSubresourceUpdate(SubresourceUpdate(bufferHelper, copy[1]));
}
mSubresourceUpdates.emplace_back(bufferHelper, copy[0]);
appendSubresourceUpdate(SubresourceUpdate(bufferHelper, copy[0]));
return angle::Result::Continue;
}
......@@ -2845,7 +2846,7 @@ angle::Result ImageHelper::stageSubresourceUpdateFromFramebuffer(
gl_vk::GetExtent(dstExtent, &copyToImage.imageExtent);
// 3- enqueue the destination image subresource update
mSubresourceUpdates.emplace_back(mStagingBuffer.getCurrentBuffer(), copyToImage);
appendSubresourceUpdate(SubresourceUpdate(mStagingBuffer.getCurrentBuffer(), copyToImage));
return angle::Result::Continue;
}
......@@ -2882,7 +2883,7 @@ void ImageHelper::stageSubresourceUpdateFromImage(ImageHelper *image,
gl_vk::GetOffset(destOffset, &copyToImage.dstOffset);
gl_vk::GetExtent(glExtents, &copyToImage.extent);
mSubresourceUpdates.emplace_back(image, copyToImage);
appendSubresourceUpdate(SubresourceUpdate(image, copyToImage));
}
void ImageHelper::stageSubresourceRobustClear(const gl::ImageIndex &index, const Format &format)
......@@ -2926,6 +2927,7 @@ void ImageHelper::stageSubresourceClear(const gl::ImageIndex &index,
// Note that clears can arrive out of order from the front-end with respect to staged changes,
// but they are intended to be done first.
mSubresourceUpdates.emplace(mSubresourceUpdates.begin(), clearValue, index);
onStateChange(angle::SubjectMessage::SubjectChanged);
}
angle::Result ImageHelper::allocateStagingMemory(ContextVk *contextVk,
......@@ -3551,6 +3553,12 @@ bool ImageHelper::SubresourceUpdate::isUpdateToLayerLevel(uint32_t layerIndex,
return dst.baseArrayLayer == layerIndex && dst.mipLevel == levelIndex;
}
void ImageHelper::appendSubresourceUpdate(SubresourceUpdate &&update)
{
mSubresourceUpdates.emplace_back(std::move(update));
onStateChange(angle::SubjectMessage::SubjectChanged);
}
// FramebufferHelper implementation.
FramebufferHelper::FramebufferHelper() = default;
......
......@@ -627,7 +627,7 @@ enum class ImageLayout
EnumCount = 13,
};
class ImageHelper final : public Resource
class ImageHelper final : public Resource, public angle::Subject
{
public:
ImageHelper();
......@@ -937,36 +937,6 @@ class ImageHelper final : public Resource
GLuint *inputSkipBytes);
private:
// Generalized to accept both "primary" and "secondary" command buffers.
template <typename CommandBufferT>
void forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
ImageLayout newLayout,
uint32_t newQueueFamilyIndex,
CommandBufferT *commandBuffer);
void stageSubresourceClear(const gl::ImageIndex &index,
const angle::Format &format,
const VkClearColorValue &colorValue,
const VkClearDepthStencilValue &depthStencilValue);
void clearColor(const VkClearColorValue &color,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
CommandBuffer *commandBuffer);
void clearDepthStencil(VkImageAspectFlags imageAspectFlags,
VkImageAspectFlags clearAspectFlags,
const VkClearDepthStencilValue &depthStencil,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
CommandBuffer *commandBuffer);
angle::Result initializeNonZeroMemory(Context *context, VkDeviceSize size);
enum class UpdateSource
{
Clear,
......@@ -1018,6 +988,38 @@ class ImageHelper final : public Resource
};
};
// Generalized to accept both "primary" and "secondary" command buffers.
template <typename CommandBufferT>
void forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
ImageLayout newLayout,
uint32_t newQueueFamilyIndex,
CommandBufferT *commandBuffer);
void stageSubresourceClear(const gl::ImageIndex &index,
const angle::Format &format,
const VkClearColorValue &colorValue,
const VkClearDepthStencilValue &depthStencilValue);
void clearColor(const VkClearColorValue &color,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
CommandBuffer *commandBuffer);
void clearDepthStencil(VkImageAspectFlags imageAspectFlags,
VkImageAspectFlags clearAspectFlags,
const VkClearDepthStencilValue &depthStencil,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount,
CommandBuffer *commandBuffer);
angle::Result initializeNonZeroMemory(Context *context, VkDeviceSize size);
void appendSubresourceUpdate(SubresourceUpdate &&update);
// Vulkan objects.
Image mImage;
DeviceMemory mDeviceMemory;
......
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