Commit 34ca1ac7 by Tobin Ehlis Committed by Commit Bot

Vulkan: Fix FramebufferVk cache

Migrate Serial from Image to ImageView. Imageviews are what are utimately used in FramebufferVk, so move the Serials into the ImageViewHelper class. Since that class also knows the level/layer of the imageView, we can revert to using a single Serial per ImageView instead of the AttachmentSerial that included the layer and level. ImageViewHelper caches Serials per layer/level combo. Bug: angleproject:4651 Change-Id: I3741d7d03523eada84295cb712c1cc1e6e3c3867 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2248203 Commit-Queue: Tobin Ehlis <tobine@google.com> Reviewed-by: 's avatarMohan Maiya <m.maiya@samsung.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent fe902f4b
...@@ -422,7 +422,10 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -422,7 +422,10 @@ class ContextVk : public ContextImpl, public vk::Context
// avoid calling vkAllocateDesctiporSets each texture update. // avoid calling vkAllocateDesctiporSets each texture update.
Serial generateTextureSerial() { return mTextureSerialFactory.generate(); } Serial generateTextureSerial() { return mTextureSerialFactory.generate(); }
const vk::TextureDescriptorDesc &getActiveTexturesDesc() const { return mActiveTexturesDesc; } const vk::TextureDescriptorDesc &getActiveTexturesDesc() const { return mActiveTexturesDesc; }
Serial generateAttachmentImageSerial() { return mAttachmentImageSerialFactory.generate(); } Serial generateAttachmentImageViewSerial()
{
return mAttachmentImageViewSerialFactory.generate();
}
angle::Result updateScissor(const gl::State &glState); angle::Result updateScissor(const gl::State &glState);
...@@ -965,7 +968,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -965,7 +968,7 @@ class ContextVk : public ContextImpl, public vk::Context
// Generators for texture & framebuffer serials. // Generators for texture & framebuffer serials.
SerialFactory mTextureSerialFactory; SerialFactory mTextureSerialFactory;
SerialFactory mAttachmentImageSerialFactory; SerialFactory mAttachmentImageViewSerialFactory;
gl::State::DirtyBits mPipelineDirtyBitsMask; gl::State::DirtyBits mPipelineDirtyBitsMask;
......
...@@ -1094,11 +1094,12 @@ angle::Result FramebufferVk::updateColorAttachment(const gl::Context *context, ...@@ -1094,11 +1094,12 @@ angle::Result FramebufferVk::updateColorAttachment(const gl::Context *context,
if (renderTarget && mState.getEnabledDrawBuffers()[colorIndexGL]) if (renderTarget && mState.getEnabledDrawBuffers()[colorIndexGL])
{ {
mCurrentFramebufferDesc.update(colorIndexGL, renderTarget->getAssignSerial(contextVk)); mCurrentFramebufferDesc.update(colorIndexGL,
renderTarget->getAssignImageViewSerial(contextVk));
} }
else else
{ {
mCurrentFramebufferDesc.update(colorIndexGL, vk::kZeroAttachmentSerial); mCurrentFramebufferDesc.update(colorIndexGL, kZeroSerial);
} }
return angle::Result::Continue; return angle::Result::Continue;
...@@ -1136,12 +1137,11 @@ void FramebufferVk::updateDepthStencilAttachmentSerial(ContextVk *contextVk) ...@@ -1136,12 +1137,11 @@ void FramebufferVk::updateDepthStencilAttachmentSerial(ContextVk *contextVk)
if (depthStencilRT != nullptr) if (depthStencilRT != nullptr)
{ {
mCurrentFramebufferDesc.update(vk::kFramebufferDescDepthStencilIndex, mCurrentFramebufferDesc.update(vk::kFramebufferDescDepthStencilIndex,
depthStencilRT->getAssignSerial(contextVk)); depthStencilRT->getAssignImageViewSerial(contextVk));
} }
else else
{ {
mCurrentFramebufferDesc.update(vk::kFramebufferDescDepthStencilIndex, mCurrentFramebufferDesc.update(vk::kFramebufferDescDepthStencilIndex, kZeroSerial);
vk::kZeroAttachmentSerial);
} }
} }
...@@ -1181,7 +1181,8 @@ angle::Result FramebufferVk::syncState(const gl::Context *context, ...@@ -1181,7 +1181,8 @@ angle::Result FramebufferVk::syncState(const gl::Context *context,
{ {
mCurrentFramebufferDesc.update( mCurrentFramebufferDesc.update(
static_cast<uint32_t>(colorIndexGL), static_cast<uint32_t>(colorIndexGL),
mRenderTargetCache.getColors()[colorIndexGL]->getAssignSerial(contextVk)); mRenderTargetCache.getColors()[colorIndexGL]->getAssignImageViewSerial(
contextVk));
} }
updateDepthStencilAttachmentSerial(contextVk); updateDepthStencilAttachmentSerial(contextVk);
break; break;
......
...@@ -58,18 +58,15 @@ void RenderTargetVk::reset() ...@@ -58,18 +58,15 @@ void RenderTargetVk::reset()
mContentDefined = false; mContentDefined = false;
} }
vk::AttachmentSerial RenderTargetVk::getAssignSerial(ContextVk *contextVk) Serial RenderTargetVk::getAssignImageViewSerial(ContextVk *contextVk)
{ {
ASSERT(mImage && mImage->valid()); ASSERT(mImageViews);
vk::AttachmentSerial attachmentSerial;
ASSERT(mLayerIndex < std::numeric_limits<uint16_t>::max()); ASSERT(mLayerIndex < std::numeric_limits<uint16_t>::max());
ASSERT(mLevelIndex < std::numeric_limits<uint16_t>::max()); ASSERT(mLevelIndex < std::numeric_limits<uint16_t>::max());
Serial imageSerial = mImage->getAssignSerial(contextVk);
ASSERT(imageSerial.getValue() < std::numeric_limits<uint32_t>::max()); Serial imageViewSerial = mImageViews->getAssignSerial(contextVk, mLevelIndex, mLayerIndex);
SetBitField(attachmentSerial.layer, mLayerIndex); ASSERT(imageViewSerial.getValue() < std::numeric_limits<uint32_t>::max());
SetBitField(attachmentSerial.level, mLevelIndex); return imageViewSerial;
SetBitField(attachmentSerial.imageSerial, imageSerial.getValue());
return attachmentSerial;
} }
angle::Result RenderTargetVk::onColorDraw(ContextVk *contextVk) angle::Result RenderTargetVk::onColorDraw(ContextVk *contextVk)
......
...@@ -47,8 +47,8 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -47,8 +47,8 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
uint32_t levelIndex, uint32_t levelIndex,
uint32_t layerIndex); uint32_t layerIndex);
void reset(); void reset();
// This returns the serial from underlying ImageHelper, first assigning one if required // This returns the serial from underlying ImageViewHelper, first assigning one if required
vk::AttachmentSerial getAssignSerial(ContextVk *contextVk); Serial getAssignImageViewSerial(ContextVk *contextVk);
// Note: RenderTargets should be called in order, with the depth/stencil onRender last. // Note: RenderTargets should be called in order, with the depth/stencil onRender last.
angle::Result onColorDraw(ContextVk *contextVk); angle::Result onColorDraw(ContextVk *contextVk);
......
...@@ -1667,7 +1667,7 @@ FramebufferDesc::~FramebufferDesc() = default; ...@@ -1667,7 +1667,7 @@ FramebufferDesc::~FramebufferDesc() = default;
FramebufferDesc::FramebufferDesc(const FramebufferDesc &other) = default; FramebufferDesc::FramebufferDesc(const FramebufferDesc &other) = default;
FramebufferDesc &FramebufferDesc::operator=(const FramebufferDesc &other) = default; FramebufferDesc &FramebufferDesc::operator=(const FramebufferDesc &other) = default;
void FramebufferDesc::update(uint32_t index, AttachmentSerial serial) void FramebufferDesc::update(uint32_t index, Serial serial)
{ {
ASSERT(index < kMaxFramebufferAttachments); ASSERT(index < kMaxFramebufferAttachments);
mSerials[index] = serial; mSerials[index] = serial;
...@@ -1675,13 +1675,12 @@ void FramebufferDesc::update(uint32_t index, AttachmentSerial serial) ...@@ -1675,13 +1675,12 @@ void FramebufferDesc::update(uint32_t index, AttachmentSerial serial)
size_t FramebufferDesc::hash() const size_t FramebufferDesc::hash() const
{ {
return angle::ComputeGenericHash(&mSerials, return angle::ComputeGenericHash(&mSerials, sizeof(Serial) * kMaxFramebufferAttachments);
sizeof(AttachmentSerial) * kMaxFramebufferAttachments);
} }
void FramebufferDesc::reset() void FramebufferDesc::reset()
{ {
memset(&mSerials, 0, sizeof(AttachmentSerial) * kMaxFramebufferAttachments); memset(&mSerials, 0, sizeof(Serial) * kMaxFramebufferAttachments);
} }
bool FramebufferDesc::operator==(const FramebufferDesc &other) const bool FramebufferDesc::operator==(const FramebufferDesc &other) const
...@@ -1692,9 +1691,9 @@ bool FramebufferDesc::operator==(const FramebufferDesc &other) const ...@@ -1692,9 +1691,9 @@ bool FramebufferDesc::operator==(const FramebufferDesc &other) const
uint32_t FramebufferDesc::attachmentCount() const uint32_t FramebufferDesc::attachmentCount() const
{ {
uint32_t count = 0; uint32_t count = 0;
for (const AttachmentSerial &serial : mSerials) for (const Serial &serial : mSerials)
{ {
if (serial.imageSerial != 0) if (serial.valid())
{ {
count++; count++;
} }
......
...@@ -782,15 +782,7 @@ constexpr size_t kMaxFramebufferAttachments = gl::IMPLEMENTATION_MAX_FRAMEBUFFER ...@@ -782,15 +782,7 @@ constexpr size_t kMaxFramebufferAttachments = gl::IMPLEMENTATION_MAX_FRAMEBUFFER
// Color serials are at index [0:gl::IMPLEMENTATION_MAX_DRAW_BUFFERS-1] // Color serials are at index [0:gl::IMPLEMENTATION_MAX_DRAW_BUFFERS-1]
// Depth/stencil index is at gl::IMPLEMENTATION_MAX_DRAW_BUFFERS // Depth/stencil index is at gl::IMPLEMENTATION_MAX_DRAW_BUFFERS
constexpr size_t kFramebufferDescDepthStencilIndex = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; constexpr size_t kFramebufferDescDepthStencilIndex = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
// Struct for AttachmentSerial cache signatures. Includes level/layer for imageView as
// well as a unique Serial value for the underlying image
struct AttachmentSerial
{
uint16_t level;
uint16_t layer;
uint32_t imageSerial;
};
constexpr AttachmentSerial kZeroAttachmentSerial = {0, 0, 0};
class FramebufferDesc class FramebufferDesc
{ {
public: public:
...@@ -800,7 +792,7 @@ class FramebufferDesc ...@@ -800,7 +792,7 @@ class FramebufferDesc
FramebufferDesc(const FramebufferDesc &other); FramebufferDesc(const FramebufferDesc &other);
FramebufferDesc &operator=(const FramebufferDesc &other); FramebufferDesc &operator=(const FramebufferDesc &other);
void update(uint32_t index, AttachmentSerial serial); void update(uint32_t index, Serial serial);
size_t hash() const; size_t hash() const;
void reset(); void reset();
...@@ -809,7 +801,19 @@ class FramebufferDesc ...@@ -809,7 +801,19 @@ class FramebufferDesc
uint32_t attachmentCount() const; uint32_t attachmentCount() const;
private: private:
gl::AttachmentArray<AttachmentSerial> mSerials; gl::AttachmentArray<Serial> mSerials;
};
// Layer/level pair type used to index into Serial Cache in ImageViewHelper
struct LayerLevel
{
uint32_t layer;
uint32_t level;
bool operator==(const LayerLevel &other) const
{
return layer == other.layer && level == other.level;
}
}; };
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
...@@ -864,6 +868,18 @@ struct hash<rx::vk::SamplerDesc> ...@@ -864,6 +868,18 @@ struct hash<rx::vk::SamplerDesc>
{ {
size_t operator()(const rx::vk::SamplerDesc &key) const { return key.hash(); } size_t operator()(const rx::vk::SamplerDesc &key) const { return key.hash(); }
}; };
template <>
struct hash<rx::vk::LayerLevel>
{
size_t operator()(const rx::vk::LayerLevel &layerLevel) const
{
// The left-shift by 11 was found to produce unique hash values
// in a 256x256 space for layer/level
return std::hash<uint32_t>()(layerLevel.layer) ^
(std::hash<uint32_t>()(layerLevel.level) << 11);
}
};
} // namespace std } // namespace std
namespace rx namespace rx
......
...@@ -3210,15 +3210,6 @@ void ImageHelper::clear(VkImageAspectFlags aspectFlags, ...@@ -3210,15 +3210,6 @@ void ImageHelper::clear(VkImageAspectFlags aspectFlags,
} }
} }
Serial ImageHelper::getAssignSerial(ContextVk *contextVk)
{
if (mSerial.getValue() == 0)
{
mSerial = contextVk->generateAttachmentImageSerial();
}
return mSerial;
}
// static // static
void ImageHelper::Copy(ImageHelper *srcImage, void ImageHelper::Copy(ImageHelper *srcImage,
ImageHelper *dstImage, ImageHelper *dstImage,
...@@ -4686,6 +4677,7 @@ ImageViewHelper::ImageViewHelper(ImageViewHelper &&other) ...@@ -4686,6 +4677,7 @@ ImageViewHelper::ImageViewHelper(ImageViewHelper &&other)
std::swap(mStencilReadImageView, other.mStencilReadImageView); std::swap(mStencilReadImageView, other.mStencilReadImageView);
std::swap(mLevelDrawImageViews, other.mLevelDrawImageViews); std::swap(mLevelDrawImageViews, other.mLevelDrawImageViews);
std::swap(mLayerLevelDrawImageViews, other.mLayerLevelDrawImageViews); std::swap(mLayerLevelDrawImageViews, other.mLayerLevelDrawImageViews);
std::swap(mSerialCache, other.mSerialCache);
} }
ImageViewHelper::~ImageViewHelper() ImageViewHelper::~ImageViewHelper()
...@@ -4754,6 +4746,8 @@ void ImageViewHelper::release(RendererVk *renderer) ...@@ -4754,6 +4746,8 @@ void ImageViewHelper::release(RendererVk *renderer)
// Ensure the resource use is always valid. // Ensure the resource use is always valid.
mUse.init(); mUse.init();
} }
mSerialCache.clear();
} }
void ImageViewHelper::destroy(VkDevice device) void ImageViewHelper::destroy(VkDevice device)
...@@ -4780,6 +4774,8 @@ void ImageViewHelper::destroy(VkDevice device) ...@@ -4780,6 +4774,8 @@ void ImageViewHelper::destroy(VkDevice device)
} }
} }
mLayerLevelDrawImageViews.clear(); mLayerLevelDrawImageViews.clear();
mSerialCache.clear();
} }
angle::Result ImageViewHelper::initReadViews(ContextVk *contextVk, angle::Result ImageViewHelper::initReadViews(ContextVk *contextVk,
...@@ -4965,6 +4961,16 @@ angle::Result ImageViewHelper::getLevelLayerDrawImageView(ContextVk *contextVk, ...@@ -4965,6 +4961,16 @@ angle::Result ImageViewHelper::getLevelLayerDrawImageView(ContextVk *contextVk,
imageView, level, 1, layer, 1); imageView, level, 1, layer, 1);
} }
Serial ImageViewHelper::getAssignSerial(ContextVk *contextVk, uint32_t level, uint32_t layer)
{
LayerLevel layerLevelPair = {layer, level};
if (mSerialCache.find(layerLevelPair) == mSerialCache.end())
{
mSerialCache[layerLevelPair] = contextVk->generateAttachmentImageViewSerial();
}
return mSerialCache[layerLevelPair];
}
// SamplerHelper implementation. // SamplerHelper implementation.
SamplerHelper::SamplerHelper() SamplerHelper::SamplerHelper()
{ {
......
...@@ -1152,8 +1152,6 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1152,8 +1152,6 @@ class ImageHelper final : public Resource, public angle::Subject
uint32_t layerCount, uint32_t layerCount,
CommandBuffer *commandBuffer); CommandBuffer *commandBuffer);
// Return unique Serial for underlying image, first assigning it if it hasn't been set yet
Serial getAssignSerial(ContextVk *contextVk);
void resetSerial() { mSerial = rx::kZeroSerial; } void resetSerial() { mSerial = rx::kZeroSerial; }
static void Copy(ImageHelper *srcImage, static void Copy(ImageHelper *srcImage,
...@@ -1605,6 +1603,9 @@ class ImageViewHelper : angle::NonCopyable ...@@ -1605,6 +1603,9 @@ class ImageViewHelper : angle::NonCopyable
uint32_t layer, uint32_t layer,
const ImageView **imageViewOut); const ImageView **imageViewOut);
// Return unique Serial for this imageView, first assigning it if it hasn't yet been set
Serial getAssignSerial(ContextVk *contextVk, uint32_t level, uint32_t layer);
private: private:
ImageView &getReadImageView() ImageView &getReadImageView()
{ {
...@@ -1636,6 +1637,9 @@ class ImageViewHelper : angle::NonCopyable ...@@ -1636,6 +1637,9 @@ class ImageViewHelper : angle::NonCopyable
// Draw views. // Draw views.
ImageViewVector mLevelDrawImageViews; ImageViewVector mLevelDrawImageViews;
LayerLevelImageViewVector mLayerLevelDrawImageViews; LayerLevelImageViewVector mLayerLevelDrawImageViews;
// Store Serials per layer/level of imageView
std::unordered_map<LayerLevel, Serial> mSerialCache;
}; };
// The SamplerHelper allows a Sampler to be coupled with a resource lifetime. // The SamplerHelper allows a Sampler to be coupled with a resource lifetime.
......
...@@ -4953,9 +4953,6 @@ void main() ...@@ -4953,9 +4953,6 @@ void main()
// Verify that a swizzle on an active sampler is handled appropriately // Verify that a swizzle on an active sampler is handled appropriately
TEST_P(ImageRespecificationTest, Swizzle) TEST_P(ImageRespecificationTest, Swizzle)
{ {
// TODO: Fix FramebufferVk caching logic (http://anglebug.com/4651)
ANGLE_SKIP_TEST_IF(isVulkanRenderer());
GLubyte data[] = {1, 64, 128, 200}; GLubyte data[] = {1, 64, 128, 200};
GLColor expectedData(data[0], data[1], data[2], data[3]); GLColor expectedData(data[0], data[1], data[2], data[3]);
...@@ -5006,9 +5003,6 @@ TEST_P(ImageRespecificationTest, Swizzle) ...@@ -5006,9 +5003,6 @@ TEST_P(ImageRespecificationTest, Swizzle)
// the Framebuffer that has the texture as a color attachment is recreated before next use. // the Framebuffer that has the texture as a color attachment is recreated before next use.
TEST_P(ImageRespecificationTest, ImageTarget2DOESSwitch) TEST_P(ImageRespecificationTest, ImageTarget2DOESSwitch)
{ {
// TODO: Fix FramebufferVk caching logic (http://anglebug.com/4651)
ANGLE_SKIP_TEST_IF(isVulkanRenderer());
// This is the specific problem on the Vulkan backend and needs some extensions // This is the specific problem on the Vulkan backend and needs some extensions
ANGLE_SKIP_TEST_IF( ANGLE_SKIP_TEST_IF(
!IsGLExtensionEnabled("GL_OES_EGL_image_external") || !IsGLExtensionEnabled("GL_OES_EGL_image_external") ||
......
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