Add d3d pipeline state cache

Change-Id: Iab9d4288a54d0743dfbf94f078b206e5df3b5f87
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/287378
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2020-05-04 10:17:22 -04:00 committed by Skia Commit-Bot
parent 8842b37fc7
commit b698ad3f2b
5 changed files with 125 additions and 7 deletions

View File

@ -139,9 +139,8 @@ bool GrD3DOpsRenderPass::onBindPipeline(const GrProgramInfo& info, const SkRect&
fCurrentPipelineBounds.setEmpty();
}
GrProgramDesc desc = fGpu->caps()->makeDesc(fRenderTarget, info);
sk_sp<GrD3DPipelineState> pipelineState =
GrD3DPipelineStateBuilder::CreatePipelineState(fGpu, fRenderTarget, desc, info);
fGpu->resourceProvider().findOrCreateCompatiblePipelineState(fRenderTarget, info);
if (!pipelineState) {
return false;
}

View File

@ -26,7 +26,7 @@
typedef size_t shader_size;
sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::CreatePipelineState(
sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::MakePipelineState(
GrD3DGpu* gpu,
GrRenderTarget* renderTarget,
const GrProgramDesc& desc,

View File

@ -29,9 +29,9 @@ public:
* available to be used.
* @return the created pipeline if generation was successful; nullptr otherwise
*/
static sk_sp<GrD3DPipelineState> CreatePipelineState(GrD3DGpu*, GrRenderTarget*,
const GrProgramDesc&,
const GrProgramInfo&);
static sk_sp<GrD3DPipelineState> MakePipelineState(GrD3DGpu*, GrRenderTarget*,
const GrProgramDesc&,
const GrProgramInfo&);
const GrCaps* caps() const override;

View File

@ -7,10 +7,16 @@
#include "src/gpu/d3d/GrD3DResourceProvider.h"
#include "include/gpu/GrContextOptions.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/d3d/GrD3DCommandList.h"
#include "src/gpu/d3d/GrD3DGpu.h"
#include "src/gpu/d3d/GrD3DPipelineState.h"
#include "src/gpu/d3d/GrD3DPipelineStateBuilder.h"
GrD3DResourceProvider::GrD3DResourceProvider(GrD3DGpu* gpu) : fGpu(gpu) {
GrD3DResourceProvider::GrD3DResourceProvider(GrD3DGpu* gpu)
: fGpu(gpu)
, fPipelineStateCache(new PipelineStateCache(gpu)) {
// TODO: Change to handle growing the heap rather than a fixed size
const int kMaxRenderTargetViews = 256;
@ -61,3 +67,78 @@ D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::createRenderTargetView(
void GrD3DResourceProvider::recycleRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE* rtvDescriptor) {
fRTVDescriptorHeap->freeCPUHandle(rtvDescriptor);
}
sk_sp<GrD3DPipelineState> GrD3DResourceProvider::findOrCreateCompatiblePipelineState(
GrRenderTarget* rt, const GrProgramInfo& info) {
return fPipelineStateCache->refPipelineState(rt, info);
}
////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef GR_PIPELINE_STATE_CACHE_STATS
// Display pipeline state cache usage
static const bool c_DisplayMtlPipelineCache{false};
#endif
struct GrD3DResourceProvider::PipelineStateCache::Entry {
Entry(GrD3DGpu* gpu, sk_sp<GrD3DPipelineState> pipelineState)
: fGpu(gpu), fPipelineState(std::move(pipelineState)) {}
GrD3DGpu* fGpu;
sk_sp<GrD3DPipelineState> fPipelineState;
};
GrD3DResourceProvider::PipelineStateCache::PipelineStateCache(GrD3DGpu* gpu)
: fMap(gpu->getContext()->priv().options().fRuntimeProgramCacheSize)
, fGpu(gpu)
#ifdef GR_PIPELINE_STATE_CACHE_STATS
, fTotalRequests(0)
, fCacheMisses(0)
#endif
{
}
GrD3DResourceProvider::PipelineStateCache::~PipelineStateCache() {
// dump stats
#ifdef GR_PIPELINE_STATE_CACHE_STATS
if (c_DisplayMtlPipelineCache) {
SkDebugf("--- Pipeline State Cache ---\n");
SkDebugf("Total requests: %d\n", fTotalRequests);
SkDebugf("Cache misses: %d\n", fCacheMisses);
SkDebugf("Cache miss %%: %f\n",
(fTotalRequests > 0) ? 100.f * fCacheMisses / fTotalRequests : 0.f);
SkDebugf("---------------------\n");
}
#endif
}
sk_sp<GrD3DPipelineState> GrD3DResourceProvider::PipelineStateCache::refPipelineState(
GrRenderTarget* renderTarget, const GrProgramInfo& programInfo) {
#ifdef GR_PIPELINE_STATE_CACHE_STATS
++fTotalRequests;
#endif
const GrCaps* caps = fGpu->caps();
GrProgramDesc desc = caps->makeDesc(renderTarget, programInfo);
if (!desc.isValid()) {
GrCapsDebugf(fGpu->caps(), "Failed to build mtl program descriptor!\n");
return nullptr;
}
std::unique_ptr<Entry>* entry = fMap.find(desc);
if (!entry) {
#ifdef GR_PIPELINE_STATE_CACHE_STATS
++fCacheMisses;
#endif
sk_sp<GrD3DPipelineState> pipelineState = GrD3DPipelineStateBuilder::MakePipelineState(
fGpu, renderTarget, desc, programInfo);
if (!pipelineState) {
return nullptr;
}
entry = fMap.insert(desc, std::unique_ptr<Entry>(
new Entry(fGpu, std::move(pipelineState))));
return (*entry)->fPipelineState;
}
return (*entry)->fPipelineState;
}

View File

@ -10,6 +10,8 @@
#include "include/gpu/d3d/GrD3DTypes.h"
#include "include/private/SkTArray.h"
#include "src/core/SkLRUCache.h"
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/d3d/GrD3DDescriptorHeap.h"
#include "src/gpu/d3d/GrD3DRootSignature.h"
@ -17,6 +19,7 @@
class GrD3DDirectCommandList;
class GrD3DGpu;
class GrD3DPipelineState;
class GrD3DResourceProvider {
public:
@ -31,13 +34,48 @@ public:
D3D12_CPU_DESCRIPTOR_HANDLE createRenderTargetView(ID3D12Resource* textureResource);
void recycleRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE*);
sk_sp<GrD3DPipelineState> findOrCreateCompatiblePipelineState(GrRenderTarget*,
const GrProgramInfo&);
private:
#ifdef SK_DEBUG
#define GR_PIPELINE_STATE_CACHE_STATS
#endif
class PipelineStateCache : public ::SkNoncopyable {
public:
PipelineStateCache(GrD3DGpu* gpu);
~PipelineStateCache();
sk_sp<GrD3DPipelineState> refPipelineState(GrRenderTarget*, const GrProgramInfo&);
private:
struct Entry;
struct DescHash {
uint32_t operator()(const GrProgramDesc& desc) const {
return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
}
};
SkLRUCache<const GrProgramDesc, std::unique_ptr<Entry>, DescHash> fMap;
GrD3DGpu* fGpu;
#ifdef GR_PIPELINE_STATE_CACHE_STATS
int fTotalRequests;
int fCacheMisses;
#endif
};
GrD3DGpu* fGpu;
SkSTArray<4, std::unique_ptr<GrD3DDirectCommandList>> fAvailableDirectCommandLists;
SkSTArray<4, sk_sp<GrD3DRootSignature>> fRootSignatures;
sk_sp<GrD3DDescriptorHeap> fRTVDescriptorHeap;
std::unique_ptr<PipelineStateCache> fPipelineStateCache;
};
#endif