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/GrD3DPipelineState.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h" 11cb93a386Sopenharmony_ci#include "src/gpu/GrFragmentProcessor.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrGeometryProcessor.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrProgramInfo.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrStencilSettings.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrXferProcessor.h" 16cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DBuffer.h" 17cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DGpu.h" 18cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DPipeline.h" 19cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DRootSignature.h" 20cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DTexture.h" 21cb93a386Sopenharmony_ci#include "src/gpu/effects/GrTextureEffect.h" 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ciGrD3DPipelineState::GrD3DPipelineState( 24cb93a386Sopenharmony_ci sk_sp<GrD3DPipeline> pipeline, 25cb93a386Sopenharmony_ci sk_sp<GrD3DRootSignature> rootSignature, 26cb93a386Sopenharmony_ci const GrGLSLBuiltinUniformHandles& builtinUniformHandles, 27cb93a386Sopenharmony_ci const UniformInfoArray& uniforms, 28cb93a386Sopenharmony_ci uint32_t uniformSize, 29cb93a386Sopenharmony_ci uint32_t numSamplers, 30cb93a386Sopenharmony_ci std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl, 31cb93a386Sopenharmony_ci std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl, 32cb93a386Sopenharmony_ci std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls, 33cb93a386Sopenharmony_ci size_t vertexStride, 34cb93a386Sopenharmony_ci size_t instanceStride) 35cb93a386Sopenharmony_ci : fPipeline(std::move(pipeline)) 36cb93a386Sopenharmony_ci , fRootSignature(std::move(rootSignature)) 37cb93a386Sopenharmony_ci , fBuiltinUniformHandles(builtinUniformHandles) 38cb93a386Sopenharmony_ci , fGPImpl(std::move(gpImpl)) 39cb93a386Sopenharmony_ci , fXPImpl(std::move(xpImpl)) 40cb93a386Sopenharmony_ci , fFPImpls(std::move(fpImpls)) 41cb93a386Sopenharmony_ci , fDataManager(uniforms, uniformSize) 42cb93a386Sopenharmony_ci , fNumSamplers(numSamplers) 43cb93a386Sopenharmony_ci , fVertexStride(vertexStride) 44cb93a386Sopenharmony_ci , fInstanceStride(instanceStride) {} 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_civoid GrD3DPipelineState::setAndBindConstants(GrD3DGpu* gpu, 47cb93a386Sopenharmony_ci const GrRenderTarget* renderTarget, 48cb93a386Sopenharmony_ci const GrProgramInfo& programInfo) { 49cb93a386Sopenharmony_ci this->setRenderTargetState(renderTarget, programInfo.origin()); 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci fGPImpl->setData(fDataManager, *gpu->caps()->shaderCaps(), programInfo.geomProc()); 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) { 54cb93a386Sopenharmony_ci const auto& fp = programInfo.pipeline().getFragmentProcessor(i); 55cb93a386Sopenharmony_ci fp.visitWithImpls([&](const GrFragmentProcessor& fp, 56cb93a386Sopenharmony_ci GrFragmentProcessor::ProgramImpl& impl) { 57cb93a386Sopenharmony_ci impl.setData(fDataManager, fp); 58cb93a386Sopenharmony_ci }, *fFPImpls[i]); 59cb93a386Sopenharmony_ci } 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci programInfo.pipeline().setDstTextureUniforms(fDataManager, &fBuiltinUniformHandles); 62cb93a386Sopenharmony_ci fXPImpl->setData(fDataManager, programInfo.pipeline().getXferProcessor()); 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci D3D12_GPU_VIRTUAL_ADDRESS constantsAddress = fDataManager.uploadConstants(gpu); 65cb93a386Sopenharmony_ci gpu->currentCommandList()->setGraphicsRootConstantBufferView( 66cb93a386Sopenharmony_ci (unsigned int)(GrD3DRootSignature::ParamIndex::kConstantBufferView), 67cb93a386Sopenharmony_ci constantsAddress); 68cb93a386Sopenharmony_ci} 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_civoid GrD3DPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) { 71cb93a386Sopenharmony_ci // Set RT adjustment and RT flip 72cb93a386Sopenharmony_ci SkISize dimensions = rt->dimensions(); 73cb93a386Sopenharmony_ci SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid()); 74cb93a386Sopenharmony_ci if (fRenderTargetState.fRenderTargetOrigin != origin || 75cb93a386Sopenharmony_ci fRenderTargetState.fRenderTargetSize != dimensions) { 76cb93a386Sopenharmony_ci fRenderTargetState.fRenderTargetSize = dimensions; 77cb93a386Sopenharmony_ci fRenderTargetState.fRenderTargetOrigin = origin; 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci // The client will mark a swap buffer as kTopLeft when making a SkSurface because 80cb93a386Sopenharmony_ci // D3D's framebuffer space has (0, 0) at the top left. This agrees with Skia's device 81cb93a386Sopenharmony_ci // coords. However, in NDC (-1, -1) is the bottom left. So we flip when origin is kTopLeft. 82cb93a386Sopenharmony_ci bool flip = (origin == kTopLeft_GrSurfaceOrigin); 83cb93a386Sopenharmony_ci std::array<float, 4> v = SkSL::Compiler::GetRTAdjustVector(dimensions, flip); 84cb93a386Sopenharmony_ci fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data()); 85cb93a386Sopenharmony_ci if (fBuiltinUniformHandles.fRTFlipUni.isValid()) { 86cb93a386Sopenharmony_ci // Note above that framebuffer space has origin top left. So we need !flip here. 87cb93a386Sopenharmony_ci std::array<float, 2> d = SkSL::Compiler::GetRTFlipVector(rt->height(), !flip); 88cb93a386Sopenharmony_ci fDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data()); 89cb93a386Sopenharmony_ci } 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci} 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_civoid GrD3DPipelineState::setAndBindTextures(GrD3DGpu* gpu, 94cb93a386Sopenharmony_ci const GrGeometryProcessor& geomProc, 95cb93a386Sopenharmony_ci const GrSurfaceProxy* const geomProcTextures[], 96cb93a386Sopenharmony_ci const GrPipeline& pipeline) { 97cb93a386Sopenharmony_ci SkASSERT(geomProcTextures || !geomProc.numTextureSamplers()); 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> shaderResourceViews(fNumSamplers); 100cb93a386Sopenharmony_ci std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> samplers(fNumSamplers); 101cb93a386Sopenharmony_ci unsigned int currTextureBinding = 0; 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci for (int i = 0; i < geomProc.numTextureSamplers(); ++i) { 104cb93a386Sopenharmony_ci SkASSERT(geomProcTextures[i]->asTextureProxy()); 105cb93a386Sopenharmony_ci const auto& sampler = geomProc.textureSampler(i); 106cb93a386Sopenharmony_ci auto texture = static_cast<GrD3DTexture*>(geomProcTextures[i]->peekTexture()); 107cb93a386Sopenharmony_ci shaderResourceViews[currTextureBinding] = texture->shaderResourceView(); 108cb93a386Sopenharmony_ci samplers[currTextureBinding++] = 109cb93a386Sopenharmony_ci gpu->resourceProvider().findOrCreateCompatibleSampler(sampler.samplerState()); 110cb93a386Sopenharmony_ci gpu->currentCommandList()->addSampledTextureRef(texture); 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci if (GrTexture* dstTexture = pipeline.peekDstTexture()) { 114cb93a386Sopenharmony_ci auto texture = static_cast<GrD3DTexture*>(dstTexture); 115cb93a386Sopenharmony_ci shaderResourceViews[currTextureBinding] = texture->shaderResourceView(); 116cb93a386Sopenharmony_ci samplers[currTextureBinding++] = gpu->resourceProvider().findOrCreateCompatibleSampler( 117cb93a386Sopenharmony_ci GrSamplerState::Filter::kNearest); 118cb93a386Sopenharmony_ci gpu->currentCommandList()->addSampledTextureRef(texture); 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci pipeline.visitTextureEffects([&](const GrTextureEffect& te) { 122cb93a386Sopenharmony_ci GrSamplerState samplerState = te.samplerState(); 123cb93a386Sopenharmony_ci auto* texture = static_cast<GrD3DTexture*>(te.texture()); 124cb93a386Sopenharmony_ci shaderResourceViews[currTextureBinding] = texture->shaderResourceView(); 125cb93a386Sopenharmony_ci samplers[currTextureBinding++] = 126cb93a386Sopenharmony_ci gpu->resourceProvider().findOrCreateCompatibleSampler(samplerState); 127cb93a386Sopenharmony_ci gpu->currentCommandList()->addSampledTextureRef(texture); 128cb93a386Sopenharmony_ci }); 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci SkASSERT(fNumSamplers == currTextureBinding); 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ci // fill in descriptor tables and bind to root signature 133cb93a386Sopenharmony_ci if (fNumSamplers > 0) { 134cb93a386Sopenharmony_ci // set up descriptor tables and bind heaps 135cb93a386Sopenharmony_ci sk_sp<GrD3DDescriptorTable> srvTable = 136cb93a386Sopenharmony_ci gpu->resourceProvider().findOrCreateShaderViewTable(shaderResourceViews); 137cb93a386Sopenharmony_ci sk_sp<GrD3DDescriptorTable> samplerTable = 138cb93a386Sopenharmony_ci gpu->resourceProvider().findOrCreateSamplerTable(samplers); 139cb93a386Sopenharmony_ci gpu->currentCommandList()->setDescriptorHeaps(srvTable->heap(), samplerTable->heap()); 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci // bind shader resource view table 142cb93a386Sopenharmony_ci gpu->currentCommandList()->setGraphicsRootDescriptorTable( 143cb93a386Sopenharmony_ci (unsigned int)GrD3DRootSignature::ParamIndex::kShaderViewDescriptorTable, 144cb93a386Sopenharmony_ci srvTable->baseGpuDescriptor()); 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci // bind sampler table 147cb93a386Sopenharmony_ci gpu->currentCommandList()->setGraphicsRootDescriptorTable( 148cb93a386Sopenharmony_ci (unsigned int)GrD3DRootSignature::ParamIndex::kSamplerDescriptorTable, 149cb93a386Sopenharmony_ci samplerTable->baseGpuDescriptor()); 150cb93a386Sopenharmony_ci } 151cb93a386Sopenharmony_ci} 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_civoid GrD3DPipelineState::bindBuffers(GrD3DGpu* gpu, sk_sp<const GrBuffer> indexBuffer, 154cb93a386Sopenharmony_ci sk_sp<const GrBuffer> instanceBuffer, 155cb93a386Sopenharmony_ci sk_sp<const GrBuffer> vertexBuffer, 156cb93a386Sopenharmony_ci GrD3DDirectCommandList* commandList) { 157cb93a386Sopenharmony_ci // Here our vertex and instance inputs need to match the same 0-based bindings they were 158cb93a386Sopenharmony_ci // assigned in the PipelineState. That is, vertex first (if any) followed by instance. 159cb93a386Sopenharmony_ci if (vertexBuffer) { 160cb93a386Sopenharmony_ci auto* d3dVertexBuffer = static_cast<const GrD3DBuffer*>(vertexBuffer.get()); 161cb93a386Sopenharmony_ci SkASSERT(!d3dVertexBuffer->isCpuBuffer()); 162cb93a386Sopenharmony_ci SkASSERT(!d3dVertexBuffer->isMapped()); 163cb93a386Sopenharmony_ci const_cast<GrD3DBuffer*>(d3dVertexBuffer)->setResourceState( 164cb93a386Sopenharmony_ci gpu, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); 165cb93a386Sopenharmony_ci } 166cb93a386Sopenharmony_ci if (instanceBuffer) { 167cb93a386Sopenharmony_ci auto* d3dInstanceBuffer = static_cast<const GrD3DBuffer*>(instanceBuffer.get()); 168cb93a386Sopenharmony_ci SkASSERT(!d3dInstanceBuffer->isCpuBuffer()); 169cb93a386Sopenharmony_ci SkASSERT(!d3dInstanceBuffer->isMapped()); 170cb93a386Sopenharmony_ci const_cast<GrD3DBuffer*>(d3dInstanceBuffer)->setResourceState( 171cb93a386Sopenharmony_ci gpu, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); 172cb93a386Sopenharmony_ci } 173cb93a386Sopenharmony_ci commandList->setVertexBuffers(0, std::move(vertexBuffer), fVertexStride, 174cb93a386Sopenharmony_ci std::move(instanceBuffer), fInstanceStride); 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci if (auto* d3dIndexBuffer = static_cast<const GrD3DBuffer*>(indexBuffer.get())) { 177cb93a386Sopenharmony_ci SkASSERT(!d3dIndexBuffer->isCpuBuffer()); 178cb93a386Sopenharmony_ci SkASSERT(!d3dIndexBuffer->isMapped()); 179cb93a386Sopenharmony_ci const_cast<GrD3DBuffer*>(d3dIndexBuffer)->setResourceState( 180cb93a386Sopenharmony_ci gpu, D3D12_RESOURCE_STATE_INDEX_BUFFER); 181cb93a386Sopenharmony_ci commandList->setIndexBuffer(std::move(indexBuffer)); 182cb93a386Sopenharmony_ci } 183cb93a386Sopenharmony_ci} 184