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)
}
TextureVk *textureVk = vk::GetImpl(texture);
ASSERT(textureVk != nullptr);
SamplerVk *samplerVk;
vk::SamplerSerial samplerSerial;
if (sampler == nullptr)
{
samplerVk = nullptr;
samplerSerial = vk::kInvalidSamplerSerial;
}
else
{
samplerVk = vk::GetImpl(sampler);
samplerSerial = samplerVk->getSamplerSerial();
}
const vk::SamplerHelper &samplerVk =
sampler ? vk::GetImpl(sampler)->getSampler() : textureVk->getSampler();
mActiveTextures[textureUnit].texture = textureVk;
mActiveTextures[textureUnit].sampler = &samplerVk;
mActiveTexturesDesc.update(textureUnit, textureVk->getSerial(),
samplerVk.getSamplerSerial());
if (textureVk->getImage().hasImmutableSampler())
{
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)
......
......@@ -539,7 +539,7 @@ void ProgramExecutableVk::addTextureDescriptorSetDesc(
// Always take the texture's sampler, that's only way to get to yuv conversion for
// externalFormat
const vk::Sampler &immutableSampler =
(*activeTextures)[textureUnit].texture->getSampler();
(*activeTextures)[textureUnit].texture->getSampler().get();
descOut->update(info.binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize,
activeStages, &immutableSampler);
}
......@@ -1335,17 +1335,13 @@ angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(ContextVk *contex
VkWriteDescriptorSet *writeInfos = contextVk->allocWriteDescriptorSets(arraySize);
for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
{
GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
TextureVk *textureVk = activeTextures[textureUnit].texture;
SamplerVk *samplerVk = activeTextures[textureUnit].sampler;
GLuint textureUnit = samplerBinding.boundTextureUnits[arrayElement];
TextureVk *textureVk = activeTextures[textureUnit].texture;
const vk::SamplerHelper &samplerVk = *activeTextures[textureUnit].sampler;
vk::ImageHelper &image = textureVk->getImage();
// Use bound sampler object if one present, otherwise use texture's sampler
const vk::Sampler &sampler =
(samplerVk != nullptr) ? samplerVk->getSampler() : textureVk->getSampler();
imageInfos[arrayElement].sampler = sampler.getHandle();
imageInfos[arrayElement].sampler = samplerVk.get().getHandle();
imageInfos[arrayElement].imageLayout = image.getCurrentLayout();
if (emulateSeamfulCubeMapSampling)
......@@ -1364,7 +1360,7 @@ angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(ContextVk *contex
if (textureVk->getImage().hasImmutableSampler())
{
imageInfos[arrayElement].sampler = textureVk->getSampler().getHandle();
imageInfos[arrayElement].sampler = textureVk->getSampler().get().getHandle();
}
ShaderInterfaceVariableInfoMap &variableInfoMap = mVariableInfoMap[shaderType];
const std::string samplerName =
......
......@@ -42,8 +42,6 @@ angle::Result SamplerVk::syncState(const gl::Context *context, const bool dirty)
vk::SamplerDesc desc(mState, false, 0);
ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, desc, &mSampler));
// Regenerate the serial on a sampler change.
mSamplerSerial = renderer->getResourceSerialFactory().generateSamplerSerial();
return angle::Result::Continue;
}
......
......@@ -26,18 +26,14 @@ class SamplerVk : public SamplerImpl
void onDestroy(const gl::Context *context) 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());
return mSampler.get();
}
vk::SamplerSerial getSamplerSerial() const { return mSamplerSerial; }
private:
vk::BindingPointer<vk::Sampler> mSampler;
// The serial is used for cache indexing.
vk::SamplerSerial mSamplerSerial;
vk::SamplerBinding mSampler;
};
} // namespace rx
......
......@@ -1463,7 +1463,7 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk)
samplerState.setWrapT(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);
ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler));
......@@ -1516,8 +1516,8 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk)
params.srcLevel = srcLevel;
params.destLevelCount = destLevelCount;
ANGLE_TRY(contextVk->getUtils().generateMipmap(contextVk, mImage, srcView, mImage,
destLevelViews, sampler.get(), params));
ANGLE_TRY(contextVk->getUtils().generateMipmap(
contextVk, mImage, srcView, mImage, destLevelViews, sampler.get().get(), params));
}
}
......
......@@ -182,7 +182,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
const gl::ImageUnit &binding,
const vk::ImageView **imageViewOut);
const vk::Sampler &getSampler() const
const vk::SamplerHelper &getSampler() const
{
ASSERT(mSampler.valid());
return mSampler.get();
......@@ -429,7 +429,7 @@ class TextureVk : public TextureImpl, public angle::ObserverInterface
// |mSampler| contains the relevant Vulkan sampler states representing the OpenGL Texture
// sampling states for the Texture.
vk::BindingPointer<vk::Sampler> mSampler;
vk::SamplerBinding mSampler;
// Render targets stored as vector of vectors
// Level is first dimension, layer is second
......
......@@ -2017,6 +2017,25 @@ bool SamplerDesc::operator==(const SamplerDesc &other) const
{
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
// RenderPassCache implementation.
......@@ -2412,7 +2431,7 @@ void SamplerCache::destroy(RendererVk *renderer)
{
vk::RefCountedSampler &sampler = iter.second;
ASSERT(!sampler.isReferenced());
sampler.get().destroy(device);
sampler.get().get().destroy(device);
renderer->getActiveHandleCounts().onDeallocate(vk::HandleType::Sampler);
}
......@@ -2422,7 +2441,7 @@ void SamplerCache::destroy(RendererVk *renderer)
angle::Result SamplerCache::getSampler(ContextVk *contextVk,
const vk::SamplerDesc &desc,
vk::BindingPointer<vk::Sampler> *samplerOut)
vk::SamplerBinding *samplerOut)
{
auto iter = mPayload.find(desc);
if (iter != mPayload.end())
......@@ -2432,10 +2451,11 @@ angle::Result SamplerCache::getSampler(ContextVk *contextVk,
return angle::Result::Continue;
}
vk::Sampler sampler;
ANGLE_TRY(desc.init(contextVk, &sampler));
vk::SamplerHelper samplerHelper(contextVk);
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;
samplerOut->set(&insertedSampler);
......
......@@ -28,7 +28,6 @@ using PipelineAndSerial = ObjectAndSerial<Pipeline>;
using RefCountedDescriptorSetLayout = RefCounted<DescriptorSetLayout>;
using RefCountedPipelineLayout = RefCounted<PipelineLayout>;
using RefCountedSampler = RefCounted<Sampler>;
using RefCountedSamplerYcbcrConversion = RefCounted<SamplerYcbcrConversion>;
// Helper macro that casts to a bitfield type then verifies no bits were dropped.
......@@ -896,6 +895,30 @@ class FramebufferDesc
uint32_t mMaxIndex;
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 rx
......@@ -1121,7 +1144,7 @@ class SamplerCache final : angle::NonCopyable
angle::Result getSampler(ContextVk *contextVk,
const vk::SamplerDesc &desc,
vk::BindingPointer<vk::Sampler> *samplerOut);
vk::SamplerBinding *samplerOut);
private:
std::unordered_map<vk::SamplerDesc, vk::RefCountedSampler> mPayload;
......
......@@ -5342,30 +5342,6 @@ ImageViewSubresourceSerial ImageViewHelper::getSubresourceSerial(uint32_t levelG
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::ShaderProgramHelper() = default;
......
......@@ -43,7 +43,7 @@ using StagingBufferOffsetArray = std::array<VkDeviceSize, 2>;
struct TextureUnit final
{
TextureVk *texture;
SamplerVk *sampler;
const vk::SamplerHelper *sampler;
};
// A dynamic buffer is conceptually an infinitely long buffer. Each time you write to the buffer,
......@@ -1810,26 +1810,6 @@ class ImageViewHelper : angle::NonCopyable
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
{
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