1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DResourceProvider.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/gpu/GrContextOptions.h" 11cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 12cb93a386Sopenharmony_ci#include "include/private/SkOpts_spi.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 14cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DBuffer.h" 15cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DCommandList.h" 16cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DGpu.h" 17cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DPipelineState.h" 18cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DPipelineStateBuilder.h" 19cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DRenderTarget.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ciGrD3DResourceProvider::GrD3DResourceProvider(GrD3DGpu* gpu) 22cb93a386Sopenharmony_ci : fGpu(gpu) 23cb93a386Sopenharmony_ci , fCpuDescriptorManager(gpu) 24cb93a386Sopenharmony_ci , fDescriptorTableManager(gpu) 25cb93a386Sopenharmony_ci , fPipelineStateCache(new PipelineStateCache(gpu)) 26cb93a386Sopenharmony_ci , fShaderResourceDescriptorTableCache(gpu) 27cb93a386Sopenharmony_ci , fSamplerDescriptorTableCache(gpu) { 28cb93a386Sopenharmony_ci} 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_civoid GrD3DResourceProvider::destroyResources() { 31cb93a386Sopenharmony_ci fSamplers.reset(); 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci fPipelineStateCache->release(); 34cb93a386Sopenharmony_ci} 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_cistd::unique_ptr<GrD3DDirectCommandList> GrD3DResourceProvider::findOrCreateDirectCommandList() { 37cb93a386Sopenharmony_ci if (fAvailableDirectCommandLists.count()) { 38cb93a386Sopenharmony_ci std::unique_ptr<GrD3DDirectCommandList> list = 39cb93a386Sopenharmony_ci std::move(fAvailableDirectCommandLists.back()); 40cb93a386Sopenharmony_ci fAvailableDirectCommandLists.pop_back(); 41cb93a386Sopenharmony_ci return list; 42cb93a386Sopenharmony_ci } 43cb93a386Sopenharmony_ci return GrD3DDirectCommandList::Make(fGpu); 44cb93a386Sopenharmony_ci} 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_civoid GrD3DResourceProvider::recycleDirectCommandList( 47cb93a386Sopenharmony_ci std::unique_ptr<GrD3DDirectCommandList> commandList) { 48cb93a386Sopenharmony_ci commandList->reset(); 49cb93a386Sopenharmony_ci fAvailableDirectCommandLists.push_back(std::move(commandList)); 50cb93a386Sopenharmony_ci} 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_cisk_sp<GrD3DRootSignature> GrD3DResourceProvider::findOrCreateRootSignature(int numTextureSamplers, 53cb93a386Sopenharmony_ci int numUAVs) { 54cb93a386Sopenharmony_ci for (int i = 0; i < fRootSignatures.count(); ++i) { 55cb93a386Sopenharmony_ci if (fRootSignatures[i]->isCompatible(numTextureSamplers, numUAVs)) { 56cb93a386Sopenharmony_ci return fRootSignatures[i]; 57cb93a386Sopenharmony_ci } 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci auto rootSig = GrD3DRootSignature::Make(fGpu, numTextureSamplers, numUAVs); 61cb93a386Sopenharmony_ci if (!rootSig) { 62cb93a386Sopenharmony_ci return nullptr; 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci fRootSignatures.push_back(rootSig); 65cb93a386Sopenharmony_ci return rootSig; 66cb93a386Sopenharmony_ci} 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_cisk_sp<GrD3DCommandSignature> GrD3DResourceProvider::findOrCreateCommandSignature( 69cb93a386Sopenharmony_ci GrD3DCommandSignature::ForIndexed indexed, unsigned int slot) { 70cb93a386Sopenharmony_ci for (int i = 0; i < fCommandSignatures.count(); ++i) { 71cb93a386Sopenharmony_ci if (fCommandSignatures[i]->isCompatible(indexed, slot)) { 72cb93a386Sopenharmony_ci return fCommandSignatures[i]; 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci auto commandSig = GrD3DCommandSignature::Make(fGpu, indexed, slot); 77cb93a386Sopenharmony_ci if (!commandSig) { 78cb93a386Sopenharmony_ci return nullptr; 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci fCommandSignatures.push_back(commandSig); 81cb93a386Sopenharmony_ci return commandSig; 82cb93a386Sopenharmony_ci} 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ciGrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createRenderTargetView( 85cb93a386Sopenharmony_ci ID3D12Resource* textureResource) { 86cb93a386Sopenharmony_ci return fCpuDescriptorManager.createRenderTargetView(fGpu, textureResource); 87cb93a386Sopenharmony_ci} 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_civoid GrD3DResourceProvider::recycleRenderTargetView( 90cb93a386Sopenharmony_ci const GrD3DDescriptorHeap::CPUHandle& rtvDescriptor) { 91cb93a386Sopenharmony_ci fCpuDescriptorManager.recycleRenderTargetView(rtvDescriptor); 92cb93a386Sopenharmony_ci} 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ciGrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createDepthStencilView( 95cb93a386Sopenharmony_ci ID3D12Resource* textureResource) { 96cb93a386Sopenharmony_ci return fCpuDescriptorManager.createDepthStencilView(fGpu, textureResource); 97cb93a386Sopenharmony_ci} 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_civoid GrD3DResourceProvider::recycleDepthStencilView( 100cb93a386Sopenharmony_ci const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) { 101cb93a386Sopenharmony_ci fCpuDescriptorManager.recycleDepthStencilView(dsvDescriptor); 102cb93a386Sopenharmony_ci} 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ciGrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createConstantBufferView( 105cb93a386Sopenharmony_ci ID3D12Resource* bufferResource, size_t offset, size_t size) { 106cb93a386Sopenharmony_ci return fCpuDescriptorManager.createConstantBufferView(fGpu, bufferResource, offset, size); 107cb93a386Sopenharmony_ci} 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ciGrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createShaderResourceView( 110cb93a386Sopenharmony_ci ID3D12Resource* resource, unsigned int highestMip, unsigned int mipLevels) { 111cb93a386Sopenharmony_ci return fCpuDescriptorManager.createShaderResourceView(fGpu, resource, highestMip, mipLevels); 112cb93a386Sopenharmony_ci} 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ciGrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createUnorderedAccessView( 115cb93a386Sopenharmony_ci ID3D12Resource* resource, unsigned int mipSlice) { 116cb93a386Sopenharmony_ci return fCpuDescriptorManager.createUnorderedAccessView(fGpu, resource, mipSlice); 117cb93a386Sopenharmony_ci} 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_civoid GrD3DResourceProvider::recycleShaderView( 120cb93a386Sopenharmony_ci const GrD3DDescriptorHeap::CPUHandle& view) { 121cb93a386Sopenharmony_ci fCpuDescriptorManager.recycleShaderView(view); 122cb93a386Sopenharmony_ci} 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_cistatic D3D12_TEXTURE_ADDRESS_MODE wrap_mode_to_d3d_address_mode(GrSamplerState::WrapMode wrapMode) { 125cb93a386Sopenharmony_ci switch (wrapMode) { 126cb93a386Sopenharmony_ci case GrSamplerState::WrapMode::kClamp: 127cb93a386Sopenharmony_ci return D3D12_TEXTURE_ADDRESS_MODE_CLAMP; 128cb93a386Sopenharmony_ci case GrSamplerState::WrapMode::kRepeat: 129cb93a386Sopenharmony_ci return D3D12_TEXTURE_ADDRESS_MODE_WRAP; 130cb93a386Sopenharmony_ci case GrSamplerState::WrapMode::kMirrorRepeat: 131cb93a386Sopenharmony_ci return D3D12_TEXTURE_ADDRESS_MODE_MIRROR; 132cb93a386Sopenharmony_ci case GrSamplerState::WrapMode::kClampToBorder: 133cb93a386Sopenharmony_ci return D3D12_TEXTURE_ADDRESS_MODE_BORDER; 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci SK_ABORT("Unknown wrap mode."); 136cb93a386Sopenharmony_ci} 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_cistatic D3D12_FILTER d3d_filter(GrSamplerState sampler) { 139cb93a386Sopenharmony_ci switch (sampler.mipmapMode()) { 140cb93a386Sopenharmony_ci // When the mode is kNone we disable filtering using maxLOD. 141cb93a386Sopenharmony_ci case GrSamplerState::MipmapMode::kNone: 142cb93a386Sopenharmony_ci case GrSamplerState::MipmapMode::kNearest: 143cb93a386Sopenharmony_ci switch (sampler.filter()) { 144cb93a386Sopenharmony_ci case GrSamplerState::Filter::kNearest: return D3D12_FILTER_MIN_MAG_MIP_POINT; 145cb93a386Sopenharmony_ci case GrSamplerState::Filter::kLinear: return D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; 146cb93a386Sopenharmony_ci } 147cb93a386Sopenharmony_ci SkUNREACHABLE; 148cb93a386Sopenharmony_ci case GrSamplerState::MipmapMode::kLinear: 149cb93a386Sopenharmony_ci switch (sampler.filter()) { 150cb93a386Sopenharmony_ci case GrSamplerState::Filter::kNearest: return D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR; 151cb93a386Sopenharmony_ci case GrSamplerState::Filter::kLinear: return D3D12_FILTER_MIN_MAG_MIP_LINEAR; 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci SkUNREACHABLE; 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci SkUNREACHABLE; 156cb93a386Sopenharmony_ci} 157cb93a386Sopenharmony_ci 158cb93a386Sopenharmony_ciD3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::findOrCreateCompatibleSampler( 159cb93a386Sopenharmony_ci const GrSamplerState& params) { 160cb93a386Sopenharmony_ci uint32_t key = params.asIndex(); 161cb93a386Sopenharmony_ci D3D12_CPU_DESCRIPTOR_HANDLE* samplerPtr = fSamplers.find(key); 162cb93a386Sopenharmony_ci if (samplerPtr) { 163cb93a386Sopenharmony_ci return *samplerPtr; 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci D3D12_FILTER filter = d3d_filter(params); 167cb93a386Sopenharmony_ci // We disable MIP filtering using maxLOD. Otherwise, we want the max LOD to be unbounded. 168cb93a386Sopenharmony_ci float maxLOD = params.mipmapped() == GrMipmapped::kYes ? std::numeric_limits<float>::max() 169cb93a386Sopenharmony_ci : 0.f; 170cb93a386Sopenharmony_ci D3D12_TEXTURE_ADDRESS_MODE addressModeU = wrap_mode_to_d3d_address_mode(params.wrapModeX()); 171cb93a386Sopenharmony_ci D3D12_TEXTURE_ADDRESS_MODE addressModeV = wrap_mode_to_d3d_address_mode(params.wrapModeY()); 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci D3D12_CPU_DESCRIPTOR_HANDLE sampler = 174cb93a386Sopenharmony_ci fCpuDescriptorManager.createSampler( 175cb93a386Sopenharmony_ci fGpu, filter, maxLOD, addressModeU, addressModeV).fHandle; 176cb93a386Sopenharmony_ci fSamplers.set(key, sampler); 177cb93a386Sopenharmony_ci return sampler; 178cb93a386Sopenharmony_ci} 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_cisk_sp<GrD3DDescriptorTable> GrD3DResourceProvider::findOrCreateShaderViewTable( 181cb93a386Sopenharmony_ci const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE>& shaderViews) { 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci auto createFunc = [this](GrD3DGpu* gpu, unsigned int numDesc) { 184cb93a386Sopenharmony_ci return this->fDescriptorTableManager.createShaderViewTable(gpu, numDesc); 185cb93a386Sopenharmony_ci }; 186cb93a386Sopenharmony_ci return fShaderResourceDescriptorTableCache.findOrCreateDescTable(shaderViews, createFunc); 187cb93a386Sopenharmony_ci} 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_cisk_sp<GrD3DDescriptorTable> GrD3DResourceProvider::findOrCreateSamplerTable( 190cb93a386Sopenharmony_ci const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE>& samplers) { 191cb93a386Sopenharmony_ci auto createFunc = [this](GrD3DGpu* gpu, unsigned int numDesc) { 192cb93a386Sopenharmony_ci return this->fDescriptorTableManager.createSamplerTable(gpu, numDesc); 193cb93a386Sopenharmony_ci }; 194cb93a386Sopenharmony_ci return fShaderResourceDescriptorTableCache.findOrCreateDescTable(samplers, createFunc); 195cb93a386Sopenharmony_ci} 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_ciGrD3DPipelineState* GrD3DResourceProvider::findOrCreateCompatiblePipelineState( 198cb93a386Sopenharmony_ci GrD3DRenderTarget* rt, const GrProgramInfo& info) { 199cb93a386Sopenharmony_ci return fPipelineStateCache->refPipelineState(rt, info); 200cb93a386Sopenharmony_ci} 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_cisk_sp<GrD3DPipeline> GrD3DResourceProvider::findOrCreateMipmapPipeline() { 203cb93a386Sopenharmony_ci if (!fMipmapPipeline) { 204cb93a386Sopenharmony_ci // Note: filtering for non-even widths and heights samples at the 0.25 and 0.75 205cb93a386Sopenharmony_ci // locations and averages the result. As the initial samples are bilerped this is 206cb93a386Sopenharmony_ci // approximately a triangle filter. We should look into doing a better kernel but 207cb93a386Sopenharmony_ci // this should hold us for now. 208cb93a386Sopenharmony_ci const char* shader = 209cb93a386Sopenharmony_ci "SamplerState textureSampler : register(s0, space1);\n" 210cb93a386Sopenharmony_ci "Texture2D<float4> inputTexture : register(t1, space1);\n" 211cb93a386Sopenharmony_ci "RWTexture2D<float4> outUAV : register(u2, space1);\n" 212cb93a386Sopenharmony_ci "\n" 213cb93a386Sopenharmony_ci "cbuffer UniformBuffer : register(b0, space0) {\n" 214cb93a386Sopenharmony_ci " float2 inverseDims;\n" 215cb93a386Sopenharmony_ci " uint mipLevel;\n" 216cb93a386Sopenharmony_ci " uint sampleMode;\n" 217cb93a386Sopenharmony_ci "}\n" 218cb93a386Sopenharmony_ci "\n" 219cb93a386Sopenharmony_ci "[numthreads(8, 8, 1)]\n" 220cb93a386Sopenharmony_ci "void main(uint groupIndex : SV_GroupIndex, uint3 threadID : SV_DispatchThreadID) {\n" 221cb93a386Sopenharmony_ci " float2 uv = inverseDims * (threadID.xy + 0.5);\n" 222cb93a386Sopenharmony_ci " float4 mipVal;\n" 223cb93a386Sopenharmony_ci " switch (sampleMode) {\n" 224cb93a386Sopenharmony_ci " case 0: {\n" 225cb93a386Sopenharmony_ci " mipVal = inputTexture.SampleLevel(textureSampler, uv, mipLevel);\n" 226cb93a386Sopenharmony_ci " break;\n" 227cb93a386Sopenharmony_ci " }\n" 228cb93a386Sopenharmony_ci " case 1: {\n" 229cb93a386Sopenharmony_ci " float2 uvdiff = inverseDims * 0.25;\n" 230cb93a386Sopenharmony_ci " mipVal = inputTexture.SampleLevel(textureSampler, uv-uvdiff, mipLevel);\n" 231cb93a386Sopenharmony_ci " mipVal += inputTexture.SampleLevel(textureSampler, uv+uvdiff, mipLevel);\n" 232cb93a386Sopenharmony_ci " uvdiff.y = -uvdiff.y;\n" 233cb93a386Sopenharmony_ci " mipVal += inputTexture.SampleLevel(textureSampler, uv-uvdiff, mipLevel);\n" 234cb93a386Sopenharmony_ci " mipVal += inputTexture.SampleLevel(textureSampler, uv+uvdiff, mipLevel);\n" 235cb93a386Sopenharmony_ci " mipVal *= 0.25;\n" 236cb93a386Sopenharmony_ci " break;\n" 237cb93a386Sopenharmony_ci " }\n" 238cb93a386Sopenharmony_ci " case 2: {\n" 239cb93a386Sopenharmony_ci " float2 uvdiff = float2(inverseDims.x * 0.25, 0);\n" 240cb93a386Sopenharmony_ci " mipVal = inputTexture.SampleLevel(textureSampler, uv-uvdiff, mipLevel);\n" 241cb93a386Sopenharmony_ci " mipVal += inputTexture.SampleLevel(textureSampler, uv+uvdiff, mipLevel);\n" 242cb93a386Sopenharmony_ci " mipVal *= 0.5;\n" 243cb93a386Sopenharmony_ci " break;\n" 244cb93a386Sopenharmony_ci " }\n" 245cb93a386Sopenharmony_ci " case 3: {\n" 246cb93a386Sopenharmony_ci " float2 uvdiff = float2(0, inverseDims.y * 0.25);\n" 247cb93a386Sopenharmony_ci " mipVal = inputTexture.SampleLevel(textureSampler, uv-uvdiff, mipLevel);\n" 248cb93a386Sopenharmony_ci " mipVal += inputTexture.SampleLevel(textureSampler, uv+uvdiff, mipLevel);\n" 249cb93a386Sopenharmony_ci " mipVal *= 0.5;\n" 250cb93a386Sopenharmony_ci " break;\n" 251cb93a386Sopenharmony_ci " }\n" 252cb93a386Sopenharmony_ci " }\n" 253cb93a386Sopenharmony_ci "\n" 254cb93a386Sopenharmony_ci " outUAV[threadID.xy] = mipVal;\n" 255cb93a386Sopenharmony_ci "}\n"; 256cb93a386Sopenharmony_ci 257cb93a386Sopenharmony_ci sk_sp<GrD3DRootSignature> rootSig = this->findOrCreateRootSignature(1, 1); 258cb93a386Sopenharmony_ci 259cb93a386Sopenharmony_ci fMipmapPipeline = 260cb93a386Sopenharmony_ci GrD3DPipelineStateBuilder::MakeComputePipeline(fGpu, rootSig.get(), shader); 261cb93a386Sopenharmony_ci } 262cb93a386Sopenharmony_ci 263cb93a386Sopenharmony_ci return fMipmapPipeline; 264cb93a386Sopenharmony_ci} 265cb93a386Sopenharmony_ci 266cb93a386Sopenharmony_ciD3D12_GPU_VIRTUAL_ADDRESS GrD3DResourceProvider::uploadConstantData(void* data, size_t size) { 267cb93a386Sopenharmony_ci // constant size has to be aligned to 256 268cb93a386Sopenharmony_ci constexpr int kConstantAlignment = 256; 269cb93a386Sopenharmony_ci 270cb93a386Sopenharmony_ci // upload the data 271cb93a386Sopenharmony_ci size_t paddedSize = SkAlignTo(size, kConstantAlignment); 272cb93a386Sopenharmony_ci GrRingBuffer::Slice slice = fGpu->uniformsRingBuffer()->suballocate(paddedSize); 273cb93a386Sopenharmony_ci char* destPtr = static_cast<char*>(slice.fBuffer->map()) + slice.fOffset; 274cb93a386Sopenharmony_ci memcpy(destPtr, data, size); 275cb93a386Sopenharmony_ci 276cb93a386Sopenharmony_ci // create the associated constant buffer view descriptor 277cb93a386Sopenharmony_ci GrD3DBuffer* d3dBuffer = static_cast<GrD3DBuffer*>(slice.fBuffer); 278cb93a386Sopenharmony_ci D3D12_GPU_VIRTUAL_ADDRESS gpuAddress = d3dBuffer->d3dResource()->GetGPUVirtualAddress(); 279cb93a386Sopenharmony_ci return gpuAddress + slice.fOffset; 280cb93a386Sopenharmony_ci} 281cb93a386Sopenharmony_ci 282cb93a386Sopenharmony_civoid GrD3DResourceProvider::prepForSubmit() { 283cb93a386Sopenharmony_ci fDescriptorTableManager.prepForSubmit(fGpu); 284cb93a386Sopenharmony_ci // Any heap memory used for these will be returned when the command buffer finishes, 285cb93a386Sopenharmony_ci // so we have to invalidate all entries. 286cb93a386Sopenharmony_ci fShaderResourceDescriptorTableCache.release(); 287cb93a386Sopenharmony_ci fSamplerDescriptorTableCache.release(); 288cb93a386Sopenharmony_ci} 289cb93a386Sopenharmony_ci 290cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////////////////// 291cb93a386Sopenharmony_ci 292cb93a386Sopenharmony_ci#ifdef GR_PIPELINE_STATE_CACHE_STATS 293cb93a386Sopenharmony_ci// Display pipeline state cache usage 294cb93a386Sopenharmony_cistatic const bool c_DisplayMtlPipelineCache{false}; 295cb93a386Sopenharmony_ci#endif 296cb93a386Sopenharmony_ci 297cb93a386Sopenharmony_cistruct GrD3DResourceProvider::PipelineStateCache::Entry { 298cb93a386Sopenharmony_ci Entry(GrD3DGpu* gpu, std::unique_ptr<GrD3DPipelineState> pipelineState) 299cb93a386Sopenharmony_ci : fGpu(gpu), fPipelineState(std::move(pipelineState)) {} 300cb93a386Sopenharmony_ci 301cb93a386Sopenharmony_ci GrD3DGpu* fGpu; 302cb93a386Sopenharmony_ci std::unique_ptr<GrD3DPipelineState> fPipelineState; 303cb93a386Sopenharmony_ci}; 304cb93a386Sopenharmony_ci 305cb93a386Sopenharmony_ciGrD3DResourceProvider::PipelineStateCache::PipelineStateCache(GrD3DGpu* gpu) 306cb93a386Sopenharmony_ci : fMap(gpu->getContext()->priv().options().fRuntimeProgramCacheSize) 307cb93a386Sopenharmony_ci , fGpu(gpu) 308cb93a386Sopenharmony_ci#ifdef GR_PIPELINE_STATE_CACHE_STATS 309cb93a386Sopenharmony_ci , fTotalRequests(0) 310cb93a386Sopenharmony_ci , fCacheMisses(0) 311cb93a386Sopenharmony_ci#endif 312cb93a386Sopenharmony_ci{ 313cb93a386Sopenharmony_ci} 314cb93a386Sopenharmony_ci 315cb93a386Sopenharmony_ciGrD3DResourceProvider::PipelineStateCache::~PipelineStateCache() { 316cb93a386Sopenharmony_ci // dump stats 317cb93a386Sopenharmony_ci#ifdef GR_PIPELINE_STATE_CACHE_STATS 318cb93a386Sopenharmony_ci if (c_DisplayMtlPipelineCache) { 319cb93a386Sopenharmony_ci SkDebugf("--- Pipeline State Cache ---\n"); 320cb93a386Sopenharmony_ci SkDebugf("Total requests: %d\n", fTotalRequests); 321cb93a386Sopenharmony_ci SkDebugf("Cache misses: %d\n", fCacheMisses); 322cb93a386Sopenharmony_ci SkDebugf("Cache miss %%: %f\n", 323cb93a386Sopenharmony_ci (fTotalRequests > 0) ? 100.f * fCacheMisses / fTotalRequests : 0.f); 324cb93a386Sopenharmony_ci SkDebugf("---------------------\n"); 325cb93a386Sopenharmony_ci } 326cb93a386Sopenharmony_ci#endif 327cb93a386Sopenharmony_ci} 328cb93a386Sopenharmony_ci 329cb93a386Sopenharmony_civoid GrD3DResourceProvider::PipelineStateCache::release() { 330cb93a386Sopenharmony_ci fMap.reset(); 331cb93a386Sopenharmony_ci} 332cb93a386Sopenharmony_ci 333cb93a386Sopenharmony_ciGrD3DPipelineState* GrD3DResourceProvider::PipelineStateCache::refPipelineState( 334cb93a386Sopenharmony_ci GrD3DRenderTarget* renderTarget, const GrProgramInfo& programInfo) { 335cb93a386Sopenharmony_ci#ifdef GR_PIPELINE_STATE_CACHE_STATS 336cb93a386Sopenharmony_ci ++fTotalRequests; 337cb93a386Sopenharmony_ci#endif 338cb93a386Sopenharmony_ci 339cb93a386Sopenharmony_ci const GrCaps* caps = fGpu->caps(); 340cb93a386Sopenharmony_ci 341cb93a386Sopenharmony_ci GrProgramDesc desc = caps->makeDesc(renderTarget, programInfo); 342cb93a386Sopenharmony_ci if (!desc.isValid()) { 343cb93a386Sopenharmony_ci GrCapsDebugf(fGpu->caps(), "Failed to build mtl program descriptor!\n"); 344cb93a386Sopenharmony_ci return nullptr; 345cb93a386Sopenharmony_ci } 346cb93a386Sopenharmony_ci 347cb93a386Sopenharmony_ci std::unique_ptr<Entry>* entry = fMap.find(desc); 348cb93a386Sopenharmony_ci if (!entry) { 349cb93a386Sopenharmony_ci#ifdef GR_PIPELINE_STATE_CACHE_STATS 350cb93a386Sopenharmony_ci ++fCacheMisses; 351cb93a386Sopenharmony_ci#endif 352cb93a386Sopenharmony_ci std::unique_ptr<GrD3DPipelineState> pipelineState = 353cb93a386Sopenharmony_ci GrD3DPipelineStateBuilder::MakePipelineState(fGpu, renderTarget, desc, programInfo); 354cb93a386Sopenharmony_ci if (!pipelineState) { 355cb93a386Sopenharmony_ci return nullptr; 356cb93a386Sopenharmony_ci } 357cb93a386Sopenharmony_ci entry = fMap.insert(desc, std::unique_ptr<Entry>( 358cb93a386Sopenharmony_ci new Entry(fGpu, std::move(pipelineState)))); 359cb93a386Sopenharmony_ci return ((*entry)->fPipelineState).get(); 360cb93a386Sopenharmony_ci } 361cb93a386Sopenharmony_ci return ((*entry)->fPipelineState).get(); 362cb93a386Sopenharmony_ci} 363cb93a386Sopenharmony_ci 364cb93a386Sopenharmony_civoid GrD3DResourceProvider::PipelineStateCache::markPipelineStateUniformsDirty() { 365cb93a386Sopenharmony_ci fMap.foreach ([](const GrProgramDesc*, std::unique_ptr<Entry>* entry) { 366cb93a386Sopenharmony_ci (*entry)->fPipelineState->markUniformsDirty(); 367cb93a386Sopenharmony_ci }); 368cb93a386Sopenharmony_ci} 369cb93a386Sopenharmony_ci 370cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////////////////// 371cb93a386Sopenharmony_ci 372cb93a386Sopenharmony_civoid GrD3DResourceProvider::DescriptorTableCache::release() { 373cb93a386Sopenharmony_ci fMap.reset(); 374cb93a386Sopenharmony_ci} 375cb93a386Sopenharmony_ci 376cb93a386Sopenharmony_cisk_sp<GrD3DDescriptorTable> GrD3DResourceProvider::DescriptorTableCache::findOrCreateDescTable( 377cb93a386Sopenharmony_ci const std::vector<D3D12_CPU_DESCRIPTOR_HANDLE>& cpuDescriptors, 378cb93a386Sopenharmony_ci std::function<sk_sp<GrD3DDescriptorTable>(GrD3DGpu*, unsigned int numDesc)> createFunc) { 379cb93a386Sopenharmony_ci sk_sp<GrD3DDescriptorTable>* entry = fMap.find(cpuDescriptors); 380cb93a386Sopenharmony_ci if (entry) { 381cb93a386Sopenharmony_ci return *entry; 382cb93a386Sopenharmony_ci } 383cb93a386Sopenharmony_ci 384cb93a386Sopenharmony_ci unsigned int numDescriptors = cpuDescriptors.size(); 385cb93a386Sopenharmony_ci SkASSERT(numDescriptors <= kRangeSizesCount); 386cb93a386Sopenharmony_ci sk_sp<GrD3DDescriptorTable> descTable = createFunc(fGpu, numDescriptors); 387cb93a386Sopenharmony_ci fGpu->device()->CopyDescriptors(1, descTable->baseCpuDescriptorPtr(), &numDescriptors, 388cb93a386Sopenharmony_ci numDescriptors, cpuDescriptors.data(), fRangeSizes, 389cb93a386Sopenharmony_ci descTable->type()); 390cb93a386Sopenharmony_ci entry = fMap.insert(cpuDescriptors, std::move(descTable)); 391cb93a386Sopenharmony_ci return *entry; 392cb93a386Sopenharmony_ci} 393