From 8b6394c24f755db39936e4e5111a3f251cc56857 Mon Sep 17 00:00:00 2001 From: egdaniel Date: Fri, 4 Mar 2016 07:35:10 -0800 Subject: Add a cache of GrVkSamplers in GrVkResourceProvider. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1765523002 Review URL: https://codereview.chromium.org/1765523002 --- src/gpu/vk/GrVkProgram.cpp | 7 ++++--- src/gpu/vk/GrVkProgram.h | 4 ++-- src/gpu/vk/GrVkResourceProvider.cpp | 27 +++++++++++++++++++++++++++ src/gpu/vk/GrVkResourceProvider.h | 11 +++++++++++ src/gpu/vk/GrVkSampler.cpp | 20 ++++++++++++++++---- src/gpu/vk/GrVkSampler.h | 14 +++++++++++--- 6 files changed, 71 insertions(+), 12 deletions(-) (limited to 'src/gpu') diff --git a/src/gpu/vk/GrVkProgram.cpp b/src/gpu/vk/GrVkProgram.cpp index 0e1e201c2b..92adde86a9 100644 --- a/src/gpu/vk/GrVkProgram.cpp +++ b/src/gpu/vk/GrVkProgram.cpp @@ -163,7 +163,7 @@ static void append_texture_bindings(const GrProcessor& processor, } } -void GrVkProgram::setData(const GrVkGpu* gpu, +void GrVkProgram::setData(GrVkGpu* gpu, const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { // This is here to protect against someone calling setData multiple times in a row without @@ -255,12 +255,13 @@ void GrVkProgram::writeUniformBuffers(const GrVkGpu* gpu) { } } -void GrVkProgram::writeSamplers(const GrVkGpu* gpu, +void GrVkProgram::writeSamplers(GrVkGpu* gpu, const SkTArray& textureBindings) { SkASSERT(fNumSamplers == textureBindings.count()); for (int i = 0; i < textureBindings.count(); ++i) { - fSamplers.push(GrVkSampler::Create(gpu, *textureBindings[i])); + const GrTextureParams& params = textureBindings[i]->getParams(); + fSamplers.push(gpu->resourceProvider().findOrCreateCompatibleSampler(params)); GrVkTexture* texture = static_cast(textureBindings[i]->getTexture()); diff --git a/src/gpu/vk/GrVkProgram.h b/src/gpu/vk/GrVkProgram.h index e0477260e9..9b4eeb1e93 100644 --- a/src/gpu/vk/GrVkProgram.h +++ b/src/gpu/vk/GrVkProgram.h @@ -33,7 +33,7 @@ public: GrVkPipeline* vkPipeline() const { return fPipeline; } - void setData(const GrVkGpu*, const GrPrimitiveProcessor&, const GrPipeline&); + void setData(GrVkGpu*, const GrPrimitiveProcessor&, const GrPipeline&); void bind(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer); @@ -68,7 +68,7 @@ private: void writeUniformBuffers(const GrVkGpu* gpu); - void writeSamplers(const GrVkGpu* gpu, const SkTArray& textureBindings); + void writeSamplers(GrVkGpu* gpu, const SkTArray& textureBindings); /** diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp index 19bda41525..b273e3b65d 100644 --- a/src/gpu/vk/GrVkResourceProvider.cpp +++ b/src/gpu/vk/GrVkResourceProvider.cpp @@ -7,9 +7,11 @@ #include "GrVkResourceProvider.h" +#include "GrTextureParams.h" #include "GrVkCommandBuffer.h" #include "GrVkPipeline.h" #include "GrVkRenderPass.h" +#include "GrVkSampler.h" #include "GrVkUtil.h" #ifdef SK_TRACE_VK_RESOURCES @@ -81,6 +83,17 @@ GrVkDescriptorPool* GrVkResourceProvider::findOrCreateCompatibleDescriptorPool( return new GrVkDescriptorPool(fGpu, typeCounts); } +GrVkSampler* GrVkResourceProvider::findOrCreateCompatibleSampler(const GrTextureParams& params) { + GrVkSampler* sampler = fSamplers.find(GrVkSampler::GenerateKey(params)); + if (!sampler) { + sampler = GrVkSampler::Create(fGpu, params); + fSamplers.add(sampler); + } + SkASSERT(sampler); + sampler->ref(); + return sampler; +} + GrVkCommandBuffer* GrVkResourceProvider::createCommandBuffer() { GrVkCommandBuffer* cmdBuffer = GrVkCommandBuffer::Create(fGpu, fGpu->cmdPool()); fActiveCommandBuffers.push_back(cmdBuffer); @@ -112,6 +125,13 @@ void GrVkResourceProvider::destroyResources() { } fSimpleRenderPasses.reset(); + // Iterate through all store GrVkSamplers and unref them before resetting the hash. + SkTDynamicHash::Iter iter(&fSamplers); + for (; !iter.done(); ++iter) { + (*iter).unref(fGpu); + } + fSamplers.reset(); + #ifdef SK_TRACE_VK_RESOURCES SkASSERT(0 == GrVkResource::fTrace.count()); #endif @@ -133,6 +153,13 @@ void GrVkResourceProvider::abandonResources() { } fSimpleRenderPasses.reset(); + // Iterate through all store GrVkSamplers and unrefAndAbandon them before resetting the hash. + SkTDynamicHash::Iter iter(&fSamplers); + for (; !iter.done(); ++iter) { + (*iter).unrefAndAbandon(); + } + fSamplers.reset(); + #ifdef SK_TRACE_VK_RESOURCES SkASSERT(0 == GrVkResource::fTrace.count()); #endif diff --git a/src/gpu/vk/GrVkResourceProvider.h b/src/gpu/vk/GrVkResourceProvider.h index 38d6c40187..a769a652d4 100644 --- a/src/gpu/vk/GrVkResourceProvider.h +++ b/src/gpu/vk/GrVkResourceProvider.h @@ -12,16 +12,19 @@ #include "GrVkResource.h" #include "GrVkUtil.h" #include "SkTArray.h" +#include "SkTDynamicHash.h" #include "vulkan/vulkan.h" class GrPipeline; class GrPrimitiveProcessor; +class GrTextureParams; class GrVkCommandBuffer; class GrVkGpu; class GrVkPipeline; class GrVkRenderPass; class GrVkRenderTarget; +class GrVkSampler; class GrVkResourceProvider { public: @@ -55,6 +58,10 @@ public: GrVkDescriptorPool* findOrCreateCompatibleDescriptorPool( const GrVkDescriptorPool::DescriptorTypeCounts& typeCounts); + // Finds or creates a compatible GrVkSampler based on the GrTextureParams. + // The refcount is incremented and a pointer returned. + GrVkSampler* findOrCreateCompatibleSampler(const GrTextureParams&); + // Destroy any cached resources. To be called before destroying the VkDevice. // The assumption is that all queues are idle and all command buffers are finished. // For resource tracing to work properly, this should be called after unrefing all other @@ -78,6 +85,10 @@ private: // Array of CommandBuffers that are currently in flight SkSTArray<4, GrVkCommandBuffer*> fActiveCommandBuffers; + + // Stores GrVkSampler objects that we've already created so we can reuse them across multiple + // programs + SkTDynamicHash fSamplers; }; #endif diff --git a/src/gpu/vk/GrVkSampler.cpp b/src/gpu/vk/GrVkSampler.cpp index 4bba66268b..9938340a84 100644 --- a/src/gpu/vk/GrVkSampler.cpp +++ b/src/gpu/vk/GrVkSampler.cpp @@ -23,7 +23,7 @@ static inline VkSamplerAddressMode tile_to_vk_sampler_address(SkShader::TileMode return gWrapModes[tm]; } -GrVkSampler* GrVkSampler::Create(const GrVkGpu* gpu, const GrTextureAccess& textureAccess) { +GrVkSampler* GrVkSampler::Create(const GrVkGpu* gpu, const GrTextureParams& params) { static VkFilter vkMinFilterModes[] = { VK_FILTER_NEAREST, @@ -36,8 +36,6 @@ GrVkSampler* GrVkSampler::Create(const GrVkGpu* gpu, const GrTextureAccess& text VK_FILTER_LINEAR }; - const GrTextureParams& params = textureAccess.getParams(); - VkSamplerCreateInfo createInfo; memset(&createInfo, 0, sizeof(VkSamplerCreateInfo)); createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; @@ -65,10 +63,24 @@ GrVkSampler* GrVkSampler::Create(const GrVkGpu* gpu, const GrTextureAccess& text nullptr, &sampler)); - return new GrVkSampler(sampler); + return new GrVkSampler(sampler, GenerateKey(params)); } void GrVkSampler::freeGPUData(const GrVkGpu* gpu) const { SkASSERT(fSampler); GR_VK_CALL(gpu->vkInterface(), DestroySampler(gpu->device(), fSampler, nullptr)); } + +uint8_t GrVkSampler::GenerateKey(const GrTextureParams& params) { + + uint8_t key = params.filterMode(); + + SkASSERT(params.filterMode() <= 3); + key |= (params.getTileModeX() << 2); + + GR_STATIC_ASSERT(SkShader::kTileModeCount <= 4); + key |= (params.getTileModeY() << 4); + + return key; +} + diff --git a/src/gpu/vk/GrVkSampler.h b/src/gpu/vk/GrVkSampler.h index d3212cbc53..72181354eb 100644 --- a/src/gpu/vk/GrVkSampler.h +++ b/src/gpu/vk/GrVkSampler.h @@ -13,23 +13,31 @@ #include "vulkan/vulkan.h" class GrTextureAccess; +class GrTextureParams; class GrVkGpu; class GrVkSampler : public GrVkResource { public: - static GrVkSampler* Create(const GrVkGpu* gpu, const GrTextureAccess& textureAccess); + static GrVkSampler* Create(const GrVkGpu* gpu, const GrTextureParams&); VkSampler sampler() const { return fSampler; } + // Helpers for hashing GrVkSampler + static uint8_t GenerateKey(const GrTextureParams&); + + static const uint8_t& GetKey(const GrVkSampler& sampler) { return sampler.fKey; } + static uint32_t Hash(const uint8_t& key) { return key; } private: - GrVkSampler(VkSampler sampler) : INHERITED(), fSampler(sampler) {} + GrVkSampler(VkSampler sampler, uint8_t key) : INHERITED(), fSampler(sampler), fKey(key) {} void freeGPUData(const GrVkGpu* gpu) const override; VkSampler fSampler; + uint8_t fKey; typedef GrVkResource INHERITED; }; -#endif \ No newline at end of file +#endif + -- cgit v1.2.3