GrMtlResourceProvider.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Copyright 2018 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #ifndef GrMtlResourceProvider_DEFINED
  8. #define GrMtlResourceProvider_DEFINED
  9. #include "include/private/SkSpinlock.h"
  10. #include "include/private/SkTArray.h"
  11. #include "src/core/SkLRUCache.h"
  12. #include "src/gpu/mtl/GrMtlDepthStencil.h"
  13. #include "src/gpu/mtl/GrMtlPipelineStateBuilder.h"
  14. #include "src/gpu/mtl/GrMtlSampler.h"
  15. #import <Metal/Metal.h>
  16. class GrMtlGpu;
  17. class GrMtlCommandBuffer;
  18. class GrMtlResourceProvider {
  19. public:
  20. GrMtlResourceProvider(GrMtlGpu* gpu);
  21. GrMtlPipelineState* findOrCreateCompatiblePipelineState(
  22. GrRenderTarget*, GrSurfaceOrigin,
  23. const GrPipeline&,
  24. const GrPrimitiveProcessor&,
  25. const GrTextureProxy* const primProcProxies[],
  26. GrPrimitiveType);
  27. // Finds or creates a compatible MTLDepthStencilState based on the GrStencilSettings.
  28. GrMtlDepthStencil* findOrCreateCompatibleDepthStencilState(const GrStencilSettings&,
  29. GrSurfaceOrigin);
  30. // Finds or creates a compatible MTLSamplerState based on the GrSamplerState.
  31. GrMtlSampler* findOrCreateCompatibleSampler(const GrSamplerState&, uint32_t maxMipLevel);
  32. id<MTLBuffer> getDynamicBuffer(size_t size, size_t* offset);
  33. void addBufferCompletionHandler(GrMtlCommandBuffer* cmdBuffer);
  34. // Destroy any cached resources. To be called before releasing the MtlDevice.
  35. void destroyResources();
  36. private:
  37. #ifdef SK_DEBUG
  38. #define GR_PIPELINE_STATE_CACHE_STATS
  39. #endif
  40. class PipelineStateCache : public ::SkNoncopyable {
  41. public:
  42. PipelineStateCache(GrMtlGpu* gpu);
  43. ~PipelineStateCache();
  44. void release();
  45. GrMtlPipelineState* refPipelineState(GrRenderTarget*, GrSurfaceOrigin,
  46. const GrPrimitiveProcessor&,
  47. const GrTextureProxy* const primProcProxies[],
  48. const GrPipeline&,
  49. GrPrimitiveType);
  50. private:
  51. enum {
  52. // We may actually have kMaxEntries+1 PipelineStates in context because we create a new
  53. // PipelineState before evicting from the cache.
  54. kMaxEntries = 128,
  55. };
  56. struct Entry;
  57. struct DescHash {
  58. uint32_t operator()(const GrProgramDesc& desc) const {
  59. return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
  60. }
  61. };
  62. SkLRUCache<const GrMtlPipelineStateBuilder::Desc, std::unique_ptr<Entry>, DescHash> fMap;
  63. GrMtlGpu* fGpu;
  64. #ifdef GR_PIPELINE_STATE_CACHE_STATS
  65. int fTotalRequests;
  66. int fCacheMisses;
  67. #endif
  68. };
  69. // Buffer allocator
  70. class BufferSuballocator : public SkRefCnt {
  71. public:
  72. BufferSuballocator(id<MTLDevice> device, size_t size);
  73. ~BufferSuballocator() {
  74. fBuffer = nil;
  75. fTotalSize = 0;
  76. }
  77. id<MTLBuffer> getAllocation(size_t size, size_t* offset);
  78. void addCompletionHandler(GrMtlCommandBuffer* cmdBuffer);
  79. size_t size() { return fTotalSize; }
  80. private:
  81. id<MTLBuffer> fBuffer;
  82. size_t fTotalSize;
  83. size_t fHead SK_GUARDED_BY(fMutex); // where we start allocating
  84. size_t fTail SK_GUARDED_BY(fMutex); // where we start deallocating
  85. SkSpinlock fMutex;
  86. };
  87. static constexpr size_t kBufferSuballocatorStartSize = 1024*1024;
  88. static constexpr size_t kBufferSuballocatorMaxSize = 8*1024*1024;
  89. GrMtlGpu* fGpu;
  90. // Cache of GrMtlPipelineStates
  91. std::unique_ptr<PipelineStateCache> fPipelineStateCache;
  92. SkTDynamicHash<GrMtlSampler, GrMtlSampler::Key> fSamplers;
  93. SkTDynamicHash<GrMtlDepthStencil, GrMtlDepthStencil::Key> fDepthStencilStates;
  94. // This is ref-counted because we might delete the GrContext before the command buffer
  95. // finishes. The completion handler will retain a reference to this so it won't get
  96. // deleted along with the GrContext.
  97. sk_sp<BufferSuballocator> fBufferSuballocator;
  98. };
  99. #endif