Commit b9b5fa55 by Jamie Madill Committed by Commit Bot

Vulkan: Redo Sampler Serials.

Instead of refreshing sampler serials every time the SamplerVk or TextureVk has a state change we can give a VkSampler a unique serial. The serial is unique to this VkSampler and repeated state changes will fetch the same Serial from the SamplerCache. This allows for more cache hits. We store the the new Serial together with the VkSampler in a SamplerHelper class and store references to a SamplerHelper in SamplerVk and TextureVk instead of the VkSampler directly. In a follow-up change we will improve image view caching by also improving how we store serials for ImageViews. Bug: angleproject:4911 Change-Id: I9168c2700e383bca796cca925b38cfd30132d982 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2333988 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent adc250c3
...@@ -3868,30 +3868,20 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -3868,30 +3868,20 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
} }
TextureVk *textureVk = vk::GetImpl(texture); TextureVk *textureVk = vk::GetImpl(texture);
ASSERT(textureVk != nullptr);
SamplerVk *samplerVk; const vk::SamplerHelper &samplerVk =
vk::SamplerSerial samplerSerial; sampler ? vk::GetImpl(sampler)->getSampler() : textureVk->getSampler();
if (sampler == nullptr)
{ mActiveTextures[textureUnit].texture = textureVk;
samplerVk = nullptr; mActiveTextures[textureUnit].sampler = &samplerVk;
samplerSerial = vk::kInvalidSamplerSerial; mActiveTexturesDesc.update(textureUnit, textureVk->getSerial(),
} samplerVk.getSamplerSerial());
else
{
samplerVk = vk::GetImpl(sampler);
samplerSerial = samplerVk->getSamplerSerial();
}
if (textureVk->getImage().hasImmutableSampler()) if (textureVk->getImage().hasImmutableSampler())
{ {
haveImmutableSampler = true; haveImmutableSampler = true;
} }
mActiveTextures[textureUnit].texture = textureVk;
mActiveTextures[textureUnit].sampler = samplerVk;
// Cache serials from sampler and texture, but re-use texture if no sampler bound
ASSERT(textureVk != nullptr);
mActiveTexturesDesc.update(textureUnit, textureVk->getSerial(), samplerSerial);
} }
if (haveImmutableSampler) if (haveImmutableSampler)
......
...@@ -539,7 +539,7 @@ void ProgramExecutableVk::addTextureDescriptorSetDesc( ...@@ -539,7 +539,7 @@ void ProgramExecutableVk::addTextureDescriptorSetDesc(
// Always take the texture's sampler, that's only way to get to yuv conversion for // Always take the texture's sampler, that's only way to get to yuv conversion for
// externalFormat // externalFormat
const vk::Sampler &immutableSampler = const vk::Sampler &immutableSampler =
(*activeTextures)[textureUnit].texture->getSampler(); (*activeTextures)[textureUnit].texture->getSampler().get();
descOut->update(info.binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize, descOut->update(info.binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize,
activeStages, &immutableSampler); activeStages, &immutableSampler);
} }
...@@ -1335,17 +1335,13 @@ angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(ContextVk *contex ...@@ -1335,17 +1335,13 @@ angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(ContextVk *contex
VkWriteDescriptorSet *writeInfos = contextVk->allocWriteDescriptorSets(arraySize); VkWriteDescriptorSet *writeInfos = contextVk->allocWriteDescriptorSets(arraySize);
for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement) for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
{ {
GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement]; GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
TextureVk *textureVk = activeTextures[textureUnit].texture; TextureVk *textureVk = activeTextures[textureUnit].texture;
SamplerVk *samplerVk = activeTextures[textureUnit].sampler; const vk::SamplerHelper &samplerVk = *activeTextures[textureUnit].sampler;
vk::ImageHelper &image = textureVk->getImage(); vk::ImageHelper &image = textureVk->getImage();
// Use bound sampler object if one present, otherwise use texture's sampler imageInfos[arrayElement].sampler = samplerVk.get().getHandle();
const vk::Sampler &sampler =
(samplerVk != nullptr) ? samplerVk->getSampler() : textureVk->getSampler();
imageInfos[arrayElement].sampler = sampler.getHandle();
imageInfos[arrayElement].imageLayout = image.getCurrentLayout(); imageInfos[arrayElement].imageLayout = image.getCurrentLayout();
if (emulateSeamfulCubeMapSampling) if (emulateSeamfulCubeMapSampling)
...@@ -1364,7 +1360,7 @@ angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(ContextVk *contex ...@@ -1364,7 +1360,7 @@ angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(ContextVk *contex
if (textureVk->getImage().hasImmutableSampler()) if (textureVk->getImage().hasImmutableSampler())
{ {
imageInfos[arrayElement].sampler = textureVk->getSampler().getHandle(); imageInfos[arrayElement].sampler = textureVk->getSampler().get().getHandle();
} }
ShaderInterfaceVariableInfoMap &variableInfoMap = mVariableInfoMap[shaderType]; ShaderInterfaceVariableInfoMap &variableInfoMap = mVariableInfoMap[shaderType];
const std::string samplerName = const std::string samplerName =
......
...@@ -42,8 +42,6 @@ angle::Result SamplerVk::syncState(const gl::Context *context, const bool dirty) ...@@ -42,8 +42,6 @@ angle::Result SamplerVk::syncState(const gl::Context *context, const bool dirty)
vk::SamplerDesc desc(mState, false, 0); vk::SamplerDesc desc(mState, false, 0);
ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, desc, &mSampler)); ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, desc, &mSampler));
// Regenerate the serial on a sampler change.
mSamplerSerial = renderer->getResourceSerialFactory().generateSamplerSerial();
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -26,18 +26,14 @@ class SamplerVk : public SamplerImpl ...@@ -26,18 +26,14 @@ class SamplerVk : public SamplerImpl
void onDestroy(const gl::Context *context) override; void onDestroy(const gl::Context *context) override;
angle::Result syncState(const gl::Context *context, const bool dirty) override; angle::Result syncState(const gl::Context *context, const bool dirty) override;
const vk::Sampler &getSampler() const const vk::SamplerHelper &getSampler() const
{ {
ASSERT(mSampler.valid()); ASSERT(mSampler.valid());
return mSampler.get(); return mSampler.get();
} }
vk::SamplerSerial getSamplerSerial() const { return mSamplerSerial; }
private: private:
vk::BindingPointer<vk::Sampler> mSampler; vk::SamplerBinding mSampler;
// The serial is used for cache indexing.
vk::SamplerSerial mSamplerSerial;
}; };
} // namespace rx } // namespace rx
......
...@@ -1463,7 +1463,7 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk) ...@@ -1463,7 +1463,7 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk)
samplerState.setWrapT(GL_CLAMP_TO_EDGE); samplerState.setWrapT(GL_CLAMP_TO_EDGE);
samplerState.setWrapR(GL_CLAMP_TO_EDGE); samplerState.setWrapR(GL_CLAMP_TO_EDGE);
vk::BindingPointer<vk::Sampler> sampler; vk::BindingPointer<vk::SamplerHelper> sampler;
vk::SamplerDesc samplerDesc(samplerState, false, 0); vk::SamplerDesc samplerDesc(samplerState, false, 0);
ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler)); ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler));
...@@ -1516,8 +1516,8 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk) ...@@ -1516,8 +1516,8 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk)
params.srcLevel = srcLevel; params.srcLevel = srcLevel;
params.destLevelCount = destLevelCount; params.destLevelCount = destLevelCount;
ANGLE_TRY(contextVk->getUtils().generateMipmap(contextVk, mImage, srcView, mImage, ANGLE_TRY(contextVk->getUtils().generateMipmap(
destLevelViews, sampler.get(), params)); contextVk, mImage, srcView, mImage, destLevelViews, sampler.get().get(), params));
} }
} }
......
...@@ -182,7 +182,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -182,7 +182,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
const gl::ImageUnit &binding, const gl::ImageUnit &binding,
const vk::ImageView **imageViewOut); const vk::ImageView **imageViewOut);
const vk::Sampler &getSampler() const const vk::SamplerHelper &getSampler() const
{ {
ASSERT(mSampler.valid()); ASSERT(mSampler.valid());
return mSampler.get(); return mSampler.get();
...@@ -429,7 +429,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface ...@@ -429,7 +429,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
// |mSampler| contains the relevant Vulkan sampler states representing the OpenGL Texture // |mSampler| contains the relevant Vulkan sampler states representing the OpenGL Texture
// sampling states for the Texture. // sampling states for the Texture.
vk::BindingPointer<vk::Sampler> mSampler; vk::SamplerBinding mSampler;
// Render targets stored as vector of vectors // Render targets stored as vector of vectors
// Level is first dimension, layer is second // Level is first dimension, layer is second
......
...@@ -2017,6 +2017,25 @@ bool SamplerDesc::operator==(const SamplerDesc &other) const ...@@ -2017,6 +2017,25 @@ bool SamplerDesc::operator==(const SamplerDesc &other) const
{ {
return (memcmp(this, &other, sizeof(SamplerDesc)) == 0); return (memcmp(this, &other, sizeof(SamplerDesc)) == 0);
} }
// SamplerHelper implementation.
SamplerHelper::SamplerHelper(ContextVk *contextVk)
: mSamplerSerial(contextVk->getRenderer()->getResourceSerialFactory().generateSamplerSerial())
{}
SamplerHelper::~SamplerHelper() {}
SamplerHelper::SamplerHelper(SamplerHelper &&samplerHelper)
{
*this = std::move(samplerHelper);
}
SamplerHelper &SamplerHelper::operator=(SamplerHelper &&rhs)
{
std::swap(mSampler, rhs.mSampler);
std::swap(mSamplerSerial, rhs.mSamplerSerial);
return *this;
}
} // namespace vk } // namespace vk
// RenderPassCache implementation. // RenderPassCache implementation.
...@@ -2412,7 +2431,7 @@ void SamplerCache::destroy(RendererVk *renderer) ...@@ -2412,7 +2431,7 @@ void SamplerCache::destroy(RendererVk *renderer)
{ {
vk::RefCountedSampler &sampler = iter.second; vk::RefCountedSampler &sampler = iter.second;
ASSERT(!sampler.isReferenced()); ASSERT(!sampler.isReferenced());
sampler.get().destroy(device); sampler.get().get().destroy(device);
renderer->getActiveHandleCounts().onDeallocate(vk::HandleType::Sampler); renderer->getActiveHandleCounts().onDeallocate(vk::HandleType::Sampler);
} }
...@@ -2422,7 +2441,7 @@ void SamplerCache::destroy(RendererVk *renderer) ...@@ -2422,7 +2441,7 @@ void SamplerCache::destroy(RendererVk *renderer)
angle::Result SamplerCache::getSampler(ContextVk *contextVk, angle::Result SamplerCache::getSampler(ContextVk *contextVk,
const vk::SamplerDesc &desc, const vk::SamplerDesc &desc,
vk::BindingPointer<vk::Sampler> *samplerOut) vk::SamplerBinding *samplerOut)
{ {
auto iter = mPayload.find(desc); auto iter = mPayload.find(desc);
if (iter != mPayload.end()) if (iter != mPayload.end())
...@@ -2432,10 +2451,11 @@ angle::Result SamplerCache::getSampler(ContextVk *contextVk, ...@@ -2432,10 +2451,11 @@ angle::Result SamplerCache::getSampler(ContextVk *contextVk,
return angle::Result::Continue; return angle::Result::Continue;
} }
vk::Sampler sampler; vk::SamplerHelper samplerHelper(contextVk);
ANGLE_TRY(desc.init(contextVk, &sampler)); ANGLE_TRY(desc.init(contextVk, &samplerHelper.get()));
auto insertedItem = mPayload.emplace(desc, vk::RefCountedSampler(std::move(sampler))); vk::RefCountedSampler newSampler(std::move(samplerHelper));
auto insertedItem = mPayload.emplace(desc, std::move(newSampler));
vk::RefCountedSampler &insertedSampler = insertedItem.first->second; vk::RefCountedSampler &insertedSampler = insertedItem.first->second;
samplerOut->set(&insertedSampler); samplerOut->set(&insertedSampler);
......
...@@ -28,7 +28,6 @@ using PipelineAndSerial = ObjectAndSerial<Pipeline>; ...@@ -28,7 +28,6 @@ using PipelineAndSerial = ObjectAndSerial<Pipeline>;
using RefCountedDescriptorSetLayout = RefCounted<DescriptorSetLayout>; using RefCountedDescriptorSetLayout = RefCounted<DescriptorSetLayout>;
using RefCountedPipelineLayout = RefCounted<PipelineLayout>; using RefCountedPipelineLayout = RefCounted<PipelineLayout>;
using RefCountedSampler = RefCounted<Sampler>;
using RefCountedSamplerYcbcrConversion = RefCounted<SamplerYcbcrConversion>; using RefCountedSamplerYcbcrConversion = RefCounted<SamplerYcbcrConversion>;
// Helper macro that casts to a bitfield type then verifies no bits were dropped. // Helper macro that casts to a bitfield type then verifies no bits were dropped.
...@@ -896,6 +895,30 @@ class FramebufferDesc ...@@ -896,6 +895,30 @@ class FramebufferDesc
uint32_t mMaxIndex; uint32_t mMaxIndex;
FramebufferAttachmentArray<ImageViewSubresourceSerial> mSerials; FramebufferAttachmentArray<ImageViewSubresourceSerial> mSerials;
}; };
// The SamplerHelper allows a Sampler to be coupled with a serial.
// Must be included before we declare SamplerCache.
class SamplerHelper final : angle::NonCopyable
{
public:
SamplerHelper(ContextVk *contextVk);
~SamplerHelper();
explicit SamplerHelper(SamplerHelper &&samplerHelper);
SamplerHelper &operator=(SamplerHelper &&rhs);
bool valid() const { return mSampler.valid(); }
const Sampler &get() const { return mSampler; }
Sampler &get() { return mSampler; }
SamplerSerial getSamplerSerial() const { return mSamplerSerial; }
private:
Sampler mSampler;
SamplerSerial mSamplerSerial;
};
using RefCountedSampler = RefCounted<SamplerHelper>;
using SamplerBinding = BindingPointer<SamplerHelper>;
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
...@@ -1121,7 +1144,7 @@ class SamplerCache final : angle::NonCopyable ...@@ -1121,7 +1144,7 @@ class SamplerCache final : angle::NonCopyable
angle::Result getSampler(ContextVk *contextVk, angle::Result getSampler(ContextVk *contextVk,
const vk::SamplerDesc &desc, const vk::SamplerDesc &desc,
vk::BindingPointer<vk::Sampler> *samplerOut); vk::SamplerBinding *samplerOut);
private: private:
std::unordered_map<vk::SamplerDesc, vk::RefCountedSampler> mPayload; std::unordered_map<vk::SamplerDesc, vk::RefCountedSampler> mPayload;
......
...@@ -5342,30 +5342,6 @@ ImageViewSubresourceSerial ImageViewHelper::getSubresourceSerial(uint32_t levelG ...@@ -5342,30 +5342,6 @@ ImageViewSubresourceSerial ImageViewHelper::getSubresourceSerial(uint32_t levelG
return serial; return serial;
} }
// SamplerHelper implementation.
SamplerHelper::SamplerHelper()
{
mUse.init();
}
SamplerHelper::~SamplerHelper()
{
mUse.release();
}
void SamplerHelper::release(RendererVk *renderer)
{
renderer->collectGarbageAndReinit(&mUse, &mSampler);
}
angle::Result SamplerHelper::init(Context *context, const VkSamplerCreateInfo &createInfo)
{
RendererVk *renderer = context->getRenderer();
ANGLE_VK_TRY(context, mSampler.init(renderer->getDevice(), createInfo));
renderer->getActiveHandleCounts().onAllocate(HandleType::Sampler);
return angle::Result::Continue;
}
// ShaderProgramHelper implementation. // ShaderProgramHelper implementation.
ShaderProgramHelper::ShaderProgramHelper() = default; ShaderProgramHelper::ShaderProgramHelper() = default;
......
...@@ -43,7 +43,7 @@ using StagingBufferOffsetArray = std::array<VkDeviceSize, 2>; ...@@ -43,7 +43,7 @@ using StagingBufferOffsetArray = std::array<VkDeviceSize, 2>;
struct TextureUnit final struct TextureUnit final
{ {
TextureVk *texture; TextureVk *texture;
SamplerVk *sampler; const vk::SamplerHelper *sampler;
}; };
// A dynamic buffer is conceptually an infinitely long buffer. Each time you write to the buffer, // A dynamic buffer is conceptually an infinitely long buffer. Each time you write to the buffer,
...@@ -1810,26 +1810,6 @@ class ImageViewHelper : angle::NonCopyable ...@@ -1810,26 +1810,6 @@ class ImageViewHelper : angle::NonCopyable
ImageViewSerial mImageViewSerial; ImageViewSerial mImageViewSerial;
}; };
// The SamplerHelper allows a Sampler to be coupled with a resource lifetime.
class SamplerHelper final : angle::NonCopyable
{
public:
SamplerHelper();
~SamplerHelper();
angle::Result init(Context *context, const VkSamplerCreateInfo &createInfo);
void release(RendererVk *renderer);
bool valid() const { return mSampler.valid(); }
const Sampler &get() const { return mSampler; }
void retain(ResourceUseList *resourceUseList) { resourceUseList->add(mUse); }
private:
SharedResourceUse mUse;
Sampler mSampler;
};
class FramebufferHelper : public Resource class FramebufferHelper : public Resource
{ {
public: public:
......
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