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>
diff --git a/src/gpu/d3d/GrD3DResourceProvider.cpp b/src/gpu/d3d/GrD3DResourceProvider.cpp
index 67bc060..5cc2783 100644
--- a/src/gpu/d3d/GrD3DResourceProvider.cpp
+++ b/src/gpu/d3d/GrD3DResourceProvider.cpp
@@ -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 @@
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;
+}