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 <d3dcompiler.h> 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DPipelineStateBuilder.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 13cb93a386Sopenharmony_ci#include "include/gpu/d3d/GrD3DTypes.h" 14cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h" 15cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrAutoLocaleSetter.h" 17cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 18cb93a386Sopenharmony_ci#include "src/gpu/GrPersistentCacheUtils.h" 19cb93a386Sopenharmony_ci#include "src/gpu/GrShaderCaps.h" 20cb93a386Sopenharmony_ci#include "src/gpu/GrShaderUtils.h" 21cb93a386Sopenharmony_ci#include "src/gpu/GrStencilSettings.h" 22cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DGpu.h" 23cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DPipeline.h" 24cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DRenderTarget.h" 25cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DRootSignature.h" 26cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DUtil.h" 27cb93a386Sopenharmony_ci#include "src/sksl/SkSLCompiler.h" 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci#include <d3dcompiler.h> 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_cistd::unique_ptr<GrD3DPipelineState> GrD3DPipelineStateBuilder::MakePipelineState( 32cb93a386Sopenharmony_ci GrD3DGpu* gpu, 33cb93a386Sopenharmony_ci GrD3DRenderTarget* renderTarget, 34cb93a386Sopenharmony_ci const GrProgramDesc& desc, 35cb93a386Sopenharmony_ci const GrProgramInfo& programInfo) { 36cb93a386Sopenharmony_ci // ensure that we use "." as a decimal separator when creating SkSL code 37cb93a386Sopenharmony_ci GrAutoLocaleSetter als("C"); 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci // create a builder. This will be handed off to effects so they can use it to add 40cb93a386Sopenharmony_ci // uniforms, varyings, textures, etc 41cb93a386Sopenharmony_ci GrD3DPipelineStateBuilder builder(gpu, renderTarget, desc, programInfo); 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci if (!builder.emitAndInstallProcs()) { 44cb93a386Sopenharmony_ci return nullptr; 45cb93a386Sopenharmony_ci } 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci return builder.finalize(); 48cb93a386Sopenharmony_ci} 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ciGrD3DPipelineStateBuilder::GrD3DPipelineStateBuilder(GrD3DGpu* gpu, 51cb93a386Sopenharmony_ci GrD3DRenderTarget* renderTarget, 52cb93a386Sopenharmony_ci const GrProgramDesc& desc, 53cb93a386Sopenharmony_ci const GrProgramInfo& programInfo) 54cb93a386Sopenharmony_ci : INHERITED(desc, programInfo) 55cb93a386Sopenharmony_ci , fGpu(gpu) 56cb93a386Sopenharmony_ci , fVaryingHandler(this) 57cb93a386Sopenharmony_ci , fUniformHandler(this) 58cb93a386Sopenharmony_ci , fRenderTarget(renderTarget) {} 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ciconst GrCaps* GrD3DPipelineStateBuilder::caps() const { 61cb93a386Sopenharmony_ci return fGpu->caps(); 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ciSkSL::Compiler* GrD3DPipelineStateBuilder::shaderCompiler() const { 65cb93a386Sopenharmony_ci return fGpu->shaderCompiler(); 66cb93a386Sopenharmony_ci} 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_civoid GrD3DPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) { 69cb93a386Sopenharmony_ci outputColor.addLayoutQualifier("location = 0, index = 0"); 70cb93a386Sopenharmony_ci} 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_civoid GrD3DPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) { 73cb93a386Sopenharmony_ci outputColor.addLayoutQualifier("location = 0, index = 1"); 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci// Print the source code for all shaders generated. 77cb93a386Sopenharmony_cistatic const bool gPrintSKSL = false; 78cb93a386Sopenharmony_cistatic const bool gPrintHLSL = false; 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_cistatic gr_cp<ID3DBlob> GrCompileHLSLShader(GrD3DGpu* gpu, 81cb93a386Sopenharmony_ci const SkSL::String& hlsl, 82cb93a386Sopenharmony_ci SkSL::ProgramKind kind) { 83cb93a386Sopenharmony_ci TRACE_EVENT0("skia.shaders", "driver_compile_shader"); 84cb93a386Sopenharmony_ci const char* compileTarget = nullptr; 85cb93a386Sopenharmony_ci switch (kind) { 86cb93a386Sopenharmony_ci case SkSL::ProgramKind::kVertex: 87cb93a386Sopenharmony_ci compileTarget = "vs_5_1"; 88cb93a386Sopenharmony_ci break; 89cb93a386Sopenharmony_ci case SkSL::ProgramKind::kFragment: 90cb93a386Sopenharmony_ci compileTarget = "ps_5_1"; 91cb93a386Sopenharmony_ci break; 92cb93a386Sopenharmony_ci default: 93cb93a386Sopenharmony_ci SkUNREACHABLE; 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci uint32_t compileFlags = 0; 97cb93a386Sopenharmony_ci#ifdef SK_DEBUG 98cb93a386Sopenharmony_ci // Enable better shader debugging with the graphics debugging tools. 99cb93a386Sopenharmony_ci compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; 100cb93a386Sopenharmony_ci#endif 101cb93a386Sopenharmony_ci // SPRIV-cross does matrix multiplication expecting row major matrices 102cb93a386Sopenharmony_ci compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR; 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci gr_cp<ID3DBlob> shader; 105cb93a386Sopenharmony_ci gr_cp<ID3DBlob> errors; 106cb93a386Sopenharmony_ci HRESULT hr = D3DCompile(hlsl.c_str(), hlsl.length(), nullptr, nullptr, nullptr, "main", 107cb93a386Sopenharmony_ci compileTarget, compileFlags, 0, &shader, &errors); 108cb93a386Sopenharmony_ci if (!SUCCEEDED(hr)) { 109cb93a386Sopenharmony_ci gpu->getContext()->priv().getShaderErrorHandler()->compileError( 110cb93a386Sopenharmony_ci hlsl.c_str(), reinterpret_cast<char*>(errors->GetBufferPointer())); 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci return shader; 113cb93a386Sopenharmony_ci} 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_cibool GrD3DPipelineStateBuilder::loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID3DBlob> shaders[]) { 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci SkSL::String hlsl[kGrShaderTypeCount]; 118cb93a386Sopenharmony_ci SkSL::Program::Inputs inputs[kGrShaderTypeCount]; 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci if (!GrPersistentCacheUtils::UnpackCachedShaders(reader, hlsl, inputs, kGrShaderTypeCount)) { 121cb93a386Sopenharmony_ci return false; 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci auto compile = [&](SkSL::ProgramKind kind, GrShaderType shaderType) { 125cb93a386Sopenharmony_ci if (inputs[shaderType].fUseFlipRTUniform) { 126cb93a386Sopenharmony_ci this->addRTFlipUniform(SKSL_RTFLIP_NAME); 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci shaders[shaderType] = GrCompileHLSLShader(fGpu, hlsl[shaderType], kind); 129cb93a386Sopenharmony_ci return shaders[shaderType].get(); 130cb93a386Sopenharmony_ci }; 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ci return compile(SkSL::ProgramKind::kVertex, kVertex_GrShaderType) && 133cb93a386Sopenharmony_ci compile(SkSL::ProgramKind::kFragment, kFragment_GrShaderType); 134cb93a386Sopenharmony_ci} 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_cigr_cp<ID3DBlob> GrD3DPipelineStateBuilder::compileD3DProgram( 137cb93a386Sopenharmony_ci SkSL::ProgramKind kind, 138cb93a386Sopenharmony_ci const SkSL::String& sksl, 139cb93a386Sopenharmony_ci const SkSL::Program::Settings& settings, 140cb93a386Sopenharmony_ci SkSL::Program::Inputs* outInputs, 141cb93a386Sopenharmony_ci SkSL::String* outHLSL) { 142cb93a386Sopenharmony_ci#ifdef SK_DEBUG 143cb93a386Sopenharmony_ci SkSL::String src = GrShaderUtils::PrettyPrint(sksl); 144cb93a386Sopenharmony_ci#else 145cb93a386Sopenharmony_ci const SkSL::String& src = sksl; 146cb93a386Sopenharmony_ci#endif 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_ci std::unique_ptr<SkSL::Program> program = fGpu->shaderCompiler()->convertProgram( 149cb93a386Sopenharmony_ci kind, src, settings); 150cb93a386Sopenharmony_ci if (!program || !fGpu->shaderCompiler()->toHLSL(*program, outHLSL)) { 151cb93a386Sopenharmony_ci auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler(); 152cb93a386Sopenharmony_ci errorHandler->compileError(src.c_str(), 153cb93a386Sopenharmony_ci fGpu->shaderCompiler()->errorText().c_str()); 154cb93a386Sopenharmony_ci return gr_cp<ID3DBlob>(); 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci *outInputs = program->fInputs; 157cb93a386Sopenharmony_ci 158cb93a386Sopenharmony_ci if (gPrintSKSL || gPrintHLSL) { 159cb93a386Sopenharmony_ci GrShaderUtils::PrintShaderBanner(kind); 160cb93a386Sopenharmony_ci if (gPrintSKSL) { 161cb93a386Sopenharmony_ci SkDebugf("SKSL:\n"); 162cb93a386Sopenharmony_ci GrShaderUtils::PrintLineByLine(GrShaderUtils::PrettyPrint(sksl)); 163cb93a386Sopenharmony_ci } 164cb93a386Sopenharmony_ci if (gPrintHLSL) { 165cb93a386Sopenharmony_ci SkDebugf("HLSL:\n"); 166cb93a386Sopenharmony_ci GrShaderUtils::PrintLineByLine(GrShaderUtils::PrettyPrint(*outHLSL)); 167cb93a386Sopenharmony_ci } 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci if (program->fInputs.fUseFlipRTUniform) { 171cb93a386Sopenharmony_ci this->addRTFlipUniform(SKSL_RTFLIP_NAME); 172cb93a386Sopenharmony_ci } 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci return GrCompileHLSLShader(fGpu, *outHLSL, kind); 175cb93a386Sopenharmony_ci} 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_cistatic DXGI_FORMAT attrib_type_to_format(GrVertexAttribType type) { 178cb93a386Sopenharmony_ci switch (type) { 179cb93a386Sopenharmony_ci case kFloat_GrVertexAttribType: 180cb93a386Sopenharmony_ci return DXGI_FORMAT_R32_FLOAT; 181cb93a386Sopenharmony_ci case kFloat2_GrVertexAttribType: 182cb93a386Sopenharmony_ci return DXGI_FORMAT_R32G32_FLOAT; 183cb93a386Sopenharmony_ci case kFloat3_GrVertexAttribType: 184cb93a386Sopenharmony_ci return DXGI_FORMAT_R32G32B32_FLOAT; 185cb93a386Sopenharmony_ci case kFloat4_GrVertexAttribType: 186cb93a386Sopenharmony_ci return DXGI_FORMAT_R32G32B32A32_FLOAT; 187cb93a386Sopenharmony_ci case kHalf_GrVertexAttribType: 188cb93a386Sopenharmony_ci return DXGI_FORMAT_R16_FLOAT; 189cb93a386Sopenharmony_ci case kHalf2_GrVertexAttribType: 190cb93a386Sopenharmony_ci return DXGI_FORMAT_R16G16_FLOAT; 191cb93a386Sopenharmony_ci case kHalf4_GrVertexAttribType: 192cb93a386Sopenharmony_ci return DXGI_FORMAT_R16G16B16A16_FLOAT; 193cb93a386Sopenharmony_ci case kInt2_GrVertexAttribType: 194cb93a386Sopenharmony_ci return DXGI_FORMAT_R32G32_SINT; 195cb93a386Sopenharmony_ci case kInt3_GrVertexAttribType: 196cb93a386Sopenharmony_ci return DXGI_FORMAT_R32G32B32_SINT; 197cb93a386Sopenharmony_ci case kInt4_GrVertexAttribType: 198cb93a386Sopenharmony_ci return DXGI_FORMAT_R32G32B32A32_SINT; 199cb93a386Sopenharmony_ci case kByte_GrVertexAttribType: 200cb93a386Sopenharmony_ci return DXGI_FORMAT_R8_SINT; 201cb93a386Sopenharmony_ci case kByte2_GrVertexAttribType: 202cb93a386Sopenharmony_ci return DXGI_FORMAT_R8G8_SINT; 203cb93a386Sopenharmony_ci case kByte4_GrVertexAttribType: 204cb93a386Sopenharmony_ci return DXGI_FORMAT_R8G8B8A8_SINT; 205cb93a386Sopenharmony_ci case kUByte_GrVertexAttribType: 206cb93a386Sopenharmony_ci return DXGI_FORMAT_R8_UINT; 207cb93a386Sopenharmony_ci case kUByte2_GrVertexAttribType: 208cb93a386Sopenharmony_ci return DXGI_FORMAT_R8G8_UINT; 209cb93a386Sopenharmony_ci case kUByte4_GrVertexAttribType: 210cb93a386Sopenharmony_ci return DXGI_FORMAT_R8G8B8A8_UINT; 211cb93a386Sopenharmony_ci case kUByte_norm_GrVertexAttribType: 212cb93a386Sopenharmony_ci return DXGI_FORMAT_R8_UNORM; 213cb93a386Sopenharmony_ci case kUByte4_norm_GrVertexAttribType: 214cb93a386Sopenharmony_ci return DXGI_FORMAT_R8G8B8A8_UNORM; 215cb93a386Sopenharmony_ci case kShort2_GrVertexAttribType: 216cb93a386Sopenharmony_ci return DXGI_FORMAT_R16G16_SINT; 217cb93a386Sopenharmony_ci case kShort4_GrVertexAttribType: 218cb93a386Sopenharmony_ci return DXGI_FORMAT_R16G16B16A16_SINT; 219cb93a386Sopenharmony_ci case kUShort2_GrVertexAttribType: 220cb93a386Sopenharmony_ci return DXGI_FORMAT_R16G16_UINT; 221cb93a386Sopenharmony_ci case kUShort2_norm_GrVertexAttribType: 222cb93a386Sopenharmony_ci return DXGI_FORMAT_R16G16_UNORM; 223cb93a386Sopenharmony_ci case kInt_GrVertexAttribType: 224cb93a386Sopenharmony_ci return DXGI_FORMAT_R32_SINT; 225cb93a386Sopenharmony_ci case kUInt_GrVertexAttribType: 226cb93a386Sopenharmony_ci return DXGI_FORMAT_R32_UINT; 227cb93a386Sopenharmony_ci case kUShort_norm_GrVertexAttribType: 228cb93a386Sopenharmony_ci return DXGI_FORMAT_R16_UNORM; 229cb93a386Sopenharmony_ci case kUShort4_norm_GrVertexAttribType: 230cb93a386Sopenharmony_ci return DXGI_FORMAT_R16G16B16A16_UNORM; 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci SK_ABORT("Unknown vertex attrib type"); 233cb93a386Sopenharmony_ci} 234cb93a386Sopenharmony_ci 235cb93a386Sopenharmony_cistatic void setup_vertex_input_layout(const GrGeometryProcessor& geomProc, 236cb93a386Sopenharmony_ci D3D12_INPUT_ELEMENT_DESC* inputElements) { 237cb93a386Sopenharmony_ci unsigned int slotNumber = 0; 238cb93a386Sopenharmony_ci unsigned int vertexSlot = 0; 239cb93a386Sopenharmony_ci unsigned int instanceSlot = 0; 240cb93a386Sopenharmony_ci if (geomProc.hasVertexAttributes()) { 241cb93a386Sopenharmony_ci vertexSlot = slotNumber++; 242cb93a386Sopenharmony_ci } 243cb93a386Sopenharmony_ci if (geomProc.hasInstanceAttributes()) { 244cb93a386Sopenharmony_ci instanceSlot = slotNumber++; 245cb93a386Sopenharmony_ci } 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci unsigned int currentAttrib = 0; 248cb93a386Sopenharmony_ci unsigned int vertexAttributeOffset = 0; 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci for (const auto& attrib : geomProc.vertexAttributes()) { 251cb93a386Sopenharmony_ci // When using SPIRV-Cross it converts the location modifier in SPIRV to be 252cb93a386Sopenharmony_ci // TEXCOORD<N> where N is the location value for eveery vertext attribute 253cb93a386Sopenharmony_ci inputElements[currentAttrib] = { "TEXCOORD", currentAttrib, 254cb93a386Sopenharmony_ci attrib_type_to_format(attrib.cpuType()), 255cb93a386Sopenharmony_ci vertexSlot, vertexAttributeOffset, 256cb93a386Sopenharmony_ci D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }; 257cb93a386Sopenharmony_ci vertexAttributeOffset += attrib.sizeAlign4(); 258cb93a386Sopenharmony_ci currentAttrib++; 259cb93a386Sopenharmony_ci } 260cb93a386Sopenharmony_ci SkASSERT(vertexAttributeOffset == geomProc.vertexStride()); 261cb93a386Sopenharmony_ci 262cb93a386Sopenharmony_ci unsigned int instanceAttributeOffset = 0; 263cb93a386Sopenharmony_ci for (const auto& attrib : geomProc.instanceAttributes()) { 264cb93a386Sopenharmony_ci // When using SPIRV-Cross it converts the location modifier in SPIRV to be 265cb93a386Sopenharmony_ci // TEXCOORD<N> where N is the location value for eveery vertext attribute 266cb93a386Sopenharmony_ci inputElements[currentAttrib] = { "TEXCOORD", currentAttrib, 267cb93a386Sopenharmony_ci attrib_type_to_format(attrib.cpuType()), 268cb93a386Sopenharmony_ci instanceSlot, instanceAttributeOffset, 269cb93a386Sopenharmony_ci D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 }; 270cb93a386Sopenharmony_ci instanceAttributeOffset += attrib.sizeAlign4(); 271cb93a386Sopenharmony_ci currentAttrib++; 272cb93a386Sopenharmony_ci } 273cb93a386Sopenharmony_ci SkASSERT(instanceAttributeOffset == geomProc.instanceStride()); 274cb93a386Sopenharmony_ci} 275cb93a386Sopenharmony_ci 276cb93a386Sopenharmony_cistatic D3D12_BLEND blend_coeff_to_d3d_blend(GrBlendCoeff coeff) { 277cb93a386Sopenharmony_ci switch (coeff) { 278cb93a386Sopenharmony_ci case kZero_GrBlendCoeff: 279cb93a386Sopenharmony_ci return D3D12_BLEND_ZERO; 280cb93a386Sopenharmony_ci case kOne_GrBlendCoeff: 281cb93a386Sopenharmony_ci return D3D12_BLEND_ONE; 282cb93a386Sopenharmony_ci case kSC_GrBlendCoeff: 283cb93a386Sopenharmony_ci return D3D12_BLEND_SRC_COLOR; 284cb93a386Sopenharmony_ci case kISC_GrBlendCoeff: 285cb93a386Sopenharmony_ci return D3D12_BLEND_INV_SRC_COLOR; 286cb93a386Sopenharmony_ci case kDC_GrBlendCoeff: 287cb93a386Sopenharmony_ci return D3D12_BLEND_DEST_COLOR; 288cb93a386Sopenharmony_ci case kIDC_GrBlendCoeff: 289cb93a386Sopenharmony_ci return D3D12_BLEND_INV_DEST_COLOR; 290cb93a386Sopenharmony_ci case kSA_GrBlendCoeff: 291cb93a386Sopenharmony_ci return D3D12_BLEND_SRC_ALPHA; 292cb93a386Sopenharmony_ci case kISA_GrBlendCoeff: 293cb93a386Sopenharmony_ci return D3D12_BLEND_INV_SRC_ALPHA; 294cb93a386Sopenharmony_ci case kDA_GrBlendCoeff: 295cb93a386Sopenharmony_ci return D3D12_BLEND_DEST_ALPHA; 296cb93a386Sopenharmony_ci case kIDA_GrBlendCoeff: 297cb93a386Sopenharmony_ci return D3D12_BLEND_INV_DEST_ALPHA; 298cb93a386Sopenharmony_ci case kConstC_GrBlendCoeff: 299cb93a386Sopenharmony_ci return D3D12_BLEND_BLEND_FACTOR; 300cb93a386Sopenharmony_ci case kIConstC_GrBlendCoeff: 301cb93a386Sopenharmony_ci return D3D12_BLEND_INV_BLEND_FACTOR; 302cb93a386Sopenharmony_ci case kS2C_GrBlendCoeff: 303cb93a386Sopenharmony_ci return D3D12_BLEND_SRC1_COLOR; 304cb93a386Sopenharmony_ci case kIS2C_GrBlendCoeff: 305cb93a386Sopenharmony_ci return D3D12_BLEND_INV_SRC1_COLOR; 306cb93a386Sopenharmony_ci case kS2A_GrBlendCoeff: 307cb93a386Sopenharmony_ci return D3D12_BLEND_SRC1_ALPHA; 308cb93a386Sopenharmony_ci case kIS2A_GrBlendCoeff: 309cb93a386Sopenharmony_ci return D3D12_BLEND_INV_SRC1_ALPHA; 310cb93a386Sopenharmony_ci case kIllegal_GrBlendCoeff: 311cb93a386Sopenharmony_ci return D3D12_BLEND_ZERO; 312cb93a386Sopenharmony_ci } 313cb93a386Sopenharmony_ci SkUNREACHABLE; 314cb93a386Sopenharmony_ci} 315cb93a386Sopenharmony_ci 316cb93a386Sopenharmony_cistatic D3D12_BLEND blend_coeff_to_d3d_blend_for_alpha(GrBlendCoeff coeff) { 317cb93a386Sopenharmony_ci switch (coeff) { 318cb93a386Sopenharmony_ci // Force all srcColor used in alpha slot to alpha version. 319cb93a386Sopenharmony_ci case kSC_GrBlendCoeff: 320cb93a386Sopenharmony_ci return D3D12_BLEND_SRC_ALPHA; 321cb93a386Sopenharmony_ci case kISC_GrBlendCoeff: 322cb93a386Sopenharmony_ci return D3D12_BLEND_INV_SRC_ALPHA; 323cb93a386Sopenharmony_ci case kDC_GrBlendCoeff: 324cb93a386Sopenharmony_ci return D3D12_BLEND_DEST_ALPHA; 325cb93a386Sopenharmony_ci case kIDC_GrBlendCoeff: 326cb93a386Sopenharmony_ci return D3D12_BLEND_INV_DEST_ALPHA; 327cb93a386Sopenharmony_ci case kS2C_GrBlendCoeff: 328cb93a386Sopenharmony_ci return D3D12_BLEND_SRC1_ALPHA; 329cb93a386Sopenharmony_ci case kIS2C_GrBlendCoeff: 330cb93a386Sopenharmony_ci return D3D12_BLEND_INV_SRC1_ALPHA; 331cb93a386Sopenharmony_ci 332cb93a386Sopenharmony_ci default: 333cb93a386Sopenharmony_ci return blend_coeff_to_d3d_blend(coeff); 334cb93a386Sopenharmony_ci } 335cb93a386Sopenharmony_ci} 336cb93a386Sopenharmony_ci 337cb93a386Sopenharmony_ci 338cb93a386Sopenharmony_cistatic D3D12_BLEND_OP blend_equation_to_d3d_op(GrBlendEquation equation) { 339cb93a386Sopenharmony_ci switch (equation) { 340cb93a386Sopenharmony_ci case kAdd_GrBlendEquation: 341cb93a386Sopenharmony_ci return D3D12_BLEND_OP_ADD; 342cb93a386Sopenharmony_ci case kSubtract_GrBlendEquation: 343cb93a386Sopenharmony_ci return D3D12_BLEND_OP_SUBTRACT; 344cb93a386Sopenharmony_ci case kReverseSubtract_GrBlendEquation: 345cb93a386Sopenharmony_ci return D3D12_BLEND_OP_REV_SUBTRACT; 346cb93a386Sopenharmony_ci default: 347cb93a386Sopenharmony_ci SkUNREACHABLE; 348cb93a386Sopenharmony_ci } 349cb93a386Sopenharmony_ci} 350cb93a386Sopenharmony_ci 351cb93a386Sopenharmony_cistatic void fill_in_blend_state(const GrPipeline& pipeline, D3D12_BLEND_DESC* blendDesc) { 352cb93a386Sopenharmony_ci blendDesc->AlphaToCoverageEnable = false; 353cb93a386Sopenharmony_ci blendDesc->IndependentBlendEnable = false; 354cb93a386Sopenharmony_ci 355cb93a386Sopenharmony_ci const GrXferProcessor::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo(); 356cb93a386Sopenharmony_ci 357cb93a386Sopenharmony_ci GrBlendEquation equation = blendInfo.fEquation; 358cb93a386Sopenharmony_ci GrBlendCoeff srcCoeff = blendInfo.fSrcBlend; 359cb93a386Sopenharmony_ci GrBlendCoeff dstCoeff = blendInfo.fDstBlend; 360cb93a386Sopenharmony_ci bool blendOff = GrBlendShouldDisable(equation, srcCoeff, dstCoeff); 361cb93a386Sopenharmony_ci 362cb93a386Sopenharmony_ci auto& rtBlend = blendDesc->RenderTarget[0]; 363cb93a386Sopenharmony_ci rtBlend.BlendEnable = !blendOff; 364cb93a386Sopenharmony_ci if (!blendOff) { 365cb93a386Sopenharmony_ci rtBlend.SrcBlend = blend_coeff_to_d3d_blend(srcCoeff); 366cb93a386Sopenharmony_ci rtBlend.DestBlend = blend_coeff_to_d3d_blend(dstCoeff); 367cb93a386Sopenharmony_ci rtBlend.BlendOp = blend_equation_to_d3d_op(equation); 368cb93a386Sopenharmony_ci rtBlend.SrcBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(srcCoeff); 369cb93a386Sopenharmony_ci rtBlend.DestBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(dstCoeff); 370cb93a386Sopenharmony_ci rtBlend.BlendOpAlpha = blend_equation_to_d3d_op(equation); 371cb93a386Sopenharmony_ci } 372cb93a386Sopenharmony_ci 373cb93a386Sopenharmony_ci if (!blendInfo.fWriteColor) { 374cb93a386Sopenharmony_ci rtBlend.RenderTargetWriteMask = 0; 375cb93a386Sopenharmony_ci } else { 376cb93a386Sopenharmony_ci rtBlend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; 377cb93a386Sopenharmony_ci } 378cb93a386Sopenharmony_ci} 379cb93a386Sopenharmony_ci 380cb93a386Sopenharmony_cistatic void fill_in_rasterizer_state(const GrPipeline& pipeline, 381cb93a386Sopenharmony_ci bool multisampleEnable, 382cb93a386Sopenharmony_ci const GrCaps* caps, 383cb93a386Sopenharmony_ci D3D12_RASTERIZER_DESC* rasterizer) { 384cb93a386Sopenharmony_ci rasterizer->FillMode = (caps->wireframeMode() || pipeline.isWireframe()) ? 385cb93a386Sopenharmony_ci D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID; 386cb93a386Sopenharmony_ci rasterizer->CullMode = D3D12_CULL_MODE_NONE; 387cb93a386Sopenharmony_ci rasterizer->FrontCounterClockwise = true; 388cb93a386Sopenharmony_ci rasterizer->DepthBias = 0; 389cb93a386Sopenharmony_ci rasterizer->DepthBiasClamp = 0.0f; 390cb93a386Sopenharmony_ci rasterizer->SlopeScaledDepthBias = 0.0f; 391cb93a386Sopenharmony_ci rasterizer->DepthClipEnable = false; 392cb93a386Sopenharmony_ci rasterizer->MultisampleEnable = multisampleEnable; 393cb93a386Sopenharmony_ci rasterizer->AntialiasedLineEnable = false; 394cb93a386Sopenharmony_ci rasterizer->ForcedSampleCount = 0; 395cb93a386Sopenharmony_ci rasterizer->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; 396cb93a386Sopenharmony_ci} 397cb93a386Sopenharmony_ci 398cb93a386Sopenharmony_cistatic D3D12_STENCIL_OP stencil_op_to_d3d_op(GrStencilOp op) { 399cb93a386Sopenharmony_ci switch (op) { 400cb93a386Sopenharmony_ci case GrStencilOp::kKeep: 401cb93a386Sopenharmony_ci return D3D12_STENCIL_OP_KEEP; 402cb93a386Sopenharmony_ci case GrStencilOp::kZero: 403cb93a386Sopenharmony_ci return D3D12_STENCIL_OP_ZERO; 404cb93a386Sopenharmony_ci case GrStencilOp::kReplace: 405cb93a386Sopenharmony_ci return D3D12_STENCIL_OP_REPLACE; 406cb93a386Sopenharmony_ci case GrStencilOp::kInvert: 407cb93a386Sopenharmony_ci return D3D12_STENCIL_OP_INVERT; 408cb93a386Sopenharmony_ci case GrStencilOp::kIncWrap: 409cb93a386Sopenharmony_ci return D3D12_STENCIL_OP_INCR; 410cb93a386Sopenharmony_ci case GrStencilOp::kDecWrap: 411cb93a386Sopenharmony_ci return D3D12_STENCIL_OP_DECR; 412cb93a386Sopenharmony_ci case GrStencilOp::kIncClamp: 413cb93a386Sopenharmony_ci return D3D12_STENCIL_OP_INCR_SAT; 414cb93a386Sopenharmony_ci case GrStencilOp::kDecClamp: 415cb93a386Sopenharmony_ci return D3D12_STENCIL_OP_DECR_SAT; 416cb93a386Sopenharmony_ci } 417cb93a386Sopenharmony_ci SkUNREACHABLE; 418cb93a386Sopenharmony_ci} 419cb93a386Sopenharmony_ci 420cb93a386Sopenharmony_cistatic D3D12_COMPARISON_FUNC stencil_test_to_d3d_func(GrStencilTest test) { 421cb93a386Sopenharmony_ci switch (test) { 422cb93a386Sopenharmony_ci case GrStencilTest::kAlways: 423cb93a386Sopenharmony_ci return D3D12_COMPARISON_FUNC_ALWAYS; 424cb93a386Sopenharmony_ci case GrStencilTest::kNever: 425cb93a386Sopenharmony_ci return D3D12_COMPARISON_FUNC_NEVER; 426cb93a386Sopenharmony_ci case GrStencilTest::kGreater: 427cb93a386Sopenharmony_ci return D3D12_COMPARISON_FUNC_GREATER; 428cb93a386Sopenharmony_ci case GrStencilTest::kGEqual: 429cb93a386Sopenharmony_ci return D3D12_COMPARISON_FUNC_GREATER_EQUAL; 430cb93a386Sopenharmony_ci case GrStencilTest::kLess: 431cb93a386Sopenharmony_ci return D3D12_COMPARISON_FUNC_LESS; 432cb93a386Sopenharmony_ci case GrStencilTest::kLEqual: 433cb93a386Sopenharmony_ci return D3D12_COMPARISON_FUNC_LESS_EQUAL; 434cb93a386Sopenharmony_ci case GrStencilTest::kEqual: 435cb93a386Sopenharmony_ci return D3D12_COMPARISON_FUNC_EQUAL; 436cb93a386Sopenharmony_ci case GrStencilTest::kNotEqual: 437cb93a386Sopenharmony_ci return D3D12_COMPARISON_FUNC_NOT_EQUAL; 438cb93a386Sopenharmony_ci } 439cb93a386Sopenharmony_ci SkUNREACHABLE; 440cb93a386Sopenharmony_ci} 441cb93a386Sopenharmony_ci 442cb93a386Sopenharmony_cistatic void setup_stencilop_desc(D3D12_DEPTH_STENCILOP_DESC* desc, 443cb93a386Sopenharmony_ci const GrStencilSettings::Face& stencilFace) { 444cb93a386Sopenharmony_ci desc->StencilFailOp = stencil_op_to_d3d_op(stencilFace.fFailOp); 445cb93a386Sopenharmony_ci desc->StencilDepthFailOp = desc->StencilFailOp; 446cb93a386Sopenharmony_ci desc->StencilPassOp = stencil_op_to_d3d_op(stencilFace.fPassOp); 447cb93a386Sopenharmony_ci desc->StencilFunc = stencil_test_to_d3d_func(stencilFace.fTest); 448cb93a386Sopenharmony_ci} 449cb93a386Sopenharmony_ci 450cb93a386Sopenharmony_cistatic void fill_in_depth_stencil_state(const GrProgramInfo& programInfo, 451cb93a386Sopenharmony_ci D3D12_DEPTH_STENCIL_DESC* dsDesc) { 452cb93a386Sopenharmony_ci GrStencilSettings stencilSettings = programInfo.nonGLStencilSettings(); 453cb93a386Sopenharmony_ci GrSurfaceOrigin origin = programInfo.origin(); 454cb93a386Sopenharmony_ci 455cb93a386Sopenharmony_ci dsDesc->DepthEnable = false; 456cb93a386Sopenharmony_ci dsDesc->DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; 457cb93a386Sopenharmony_ci dsDesc->DepthFunc = D3D12_COMPARISON_FUNC_NEVER; 458cb93a386Sopenharmony_ci dsDesc->StencilEnable = !stencilSettings.isDisabled(); 459cb93a386Sopenharmony_ci if (!stencilSettings.isDisabled()) { 460cb93a386Sopenharmony_ci if (stencilSettings.isTwoSided()) { 461cb93a386Sopenharmony_ci const auto& frontFace = stencilSettings.postOriginCCWFace(origin); 462cb93a386Sopenharmony_ci const auto& backFace = stencilSettings.postOriginCWFace(origin); 463cb93a386Sopenharmony_ci 464cb93a386Sopenharmony_ci SkASSERT(frontFace.fTestMask == backFace.fTestMask); 465cb93a386Sopenharmony_ci SkASSERT(frontFace.fWriteMask == backFace.fWriteMask); 466cb93a386Sopenharmony_ci dsDesc->StencilReadMask = frontFace.fTestMask; 467cb93a386Sopenharmony_ci dsDesc->StencilWriteMask = frontFace.fWriteMask; 468cb93a386Sopenharmony_ci 469cb93a386Sopenharmony_ci setup_stencilop_desc(&dsDesc->FrontFace, frontFace); 470cb93a386Sopenharmony_ci setup_stencilop_desc(&dsDesc->BackFace, backFace); 471cb93a386Sopenharmony_ci } else { 472cb93a386Sopenharmony_ci dsDesc->StencilReadMask = stencilSettings.singleSidedFace().fTestMask; 473cb93a386Sopenharmony_ci dsDesc->StencilWriteMask = stencilSettings.singleSidedFace().fWriteMask; 474cb93a386Sopenharmony_ci setup_stencilop_desc(&dsDesc->FrontFace, stencilSettings.singleSidedFace()); 475cb93a386Sopenharmony_ci dsDesc->BackFace = dsDesc->FrontFace; 476cb93a386Sopenharmony_ci } 477cb93a386Sopenharmony_ci } 478cb93a386Sopenharmony_ci} 479cb93a386Sopenharmony_ci 480cb93a386Sopenharmony_cistatic D3D12_PRIMITIVE_TOPOLOGY_TYPE gr_primitive_type_to_d3d(GrPrimitiveType primitiveType) { 481cb93a386Sopenharmony_ci switch (primitiveType) { 482cb93a386Sopenharmony_ci case GrPrimitiveType::kTriangles: 483cb93a386Sopenharmony_ci case GrPrimitiveType::kTriangleStrip: //fall through 484cb93a386Sopenharmony_ci return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; 485cb93a386Sopenharmony_ci case GrPrimitiveType::kPoints: 486cb93a386Sopenharmony_ci return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; 487cb93a386Sopenharmony_ci case GrPrimitiveType::kLines: // fall through 488cb93a386Sopenharmony_ci case GrPrimitiveType::kLineStrip: 489cb93a386Sopenharmony_ci return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; 490cb93a386Sopenharmony_ci case GrPrimitiveType::kPatches: // fall through, unsupported 491cb93a386Sopenharmony_ci case GrPrimitiveType::kPath: // fall through, unsupported 492cb93a386Sopenharmony_ci default: 493cb93a386Sopenharmony_ci SkUNREACHABLE; 494cb93a386Sopenharmony_ci } 495cb93a386Sopenharmony_ci} 496cb93a386Sopenharmony_ci 497cb93a386Sopenharmony_cigr_cp<ID3D12PipelineState> create_pipeline_state( 498cb93a386Sopenharmony_ci GrD3DGpu* gpu, const GrProgramInfo& programInfo, const sk_sp<GrD3DRootSignature>& rootSig, 499cb93a386Sopenharmony_ci gr_cp<ID3DBlob> vertexShader, gr_cp<ID3DBlob> pixelShader, 500cb93a386Sopenharmony_ci DXGI_FORMAT renderTargetFormat, DXGI_FORMAT depthStencilFormat, 501cb93a386Sopenharmony_ci unsigned int sampleQualityPattern) { 502cb93a386Sopenharmony_ci D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; 503cb93a386Sopenharmony_ci 504cb93a386Sopenharmony_ci psoDesc.pRootSignature = rootSig->rootSignature(); 505cb93a386Sopenharmony_ci 506cb93a386Sopenharmony_ci psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), 507cb93a386Sopenharmony_ci vertexShader->GetBufferSize() }; 508cb93a386Sopenharmony_ci psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), 509cb93a386Sopenharmony_ci pixelShader->GetBufferSize() }; 510cb93a386Sopenharmony_ci 511cb93a386Sopenharmony_ci psoDesc.StreamOutput = { nullptr, 0, nullptr, 0, 0 }; 512cb93a386Sopenharmony_ci 513cb93a386Sopenharmony_ci fill_in_blend_state(programInfo.pipeline(), &psoDesc.BlendState); 514cb93a386Sopenharmony_ci psoDesc.SampleMask = UINT_MAX; 515cb93a386Sopenharmony_ci 516cb93a386Sopenharmony_ci fill_in_rasterizer_state(programInfo.pipeline(), programInfo.numSamples() > 1, gpu->caps(), 517cb93a386Sopenharmony_ci &psoDesc.RasterizerState); 518cb93a386Sopenharmony_ci 519cb93a386Sopenharmony_ci fill_in_depth_stencil_state(programInfo, &psoDesc.DepthStencilState); 520cb93a386Sopenharmony_ci 521cb93a386Sopenharmony_ci unsigned int totalAttributeCnt = programInfo.geomProc().numVertexAttributes() + 522cb93a386Sopenharmony_ci programInfo.geomProc().numInstanceAttributes(); 523cb93a386Sopenharmony_ci SkAutoSTArray<4, D3D12_INPUT_ELEMENT_DESC> inputElements(totalAttributeCnt); 524cb93a386Sopenharmony_ci setup_vertex_input_layout(programInfo.geomProc(), inputElements.get()); 525cb93a386Sopenharmony_ci 526cb93a386Sopenharmony_ci psoDesc.InputLayout = { inputElements.get(), totalAttributeCnt }; 527cb93a386Sopenharmony_ci 528cb93a386Sopenharmony_ci psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; 529cb93a386Sopenharmony_ci 530cb93a386Sopenharmony_ci // This is for geometry or hull shader primitives 531cb93a386Sopenharmony_ci psoDesc.PrimitiveTopologyType = gr_primitive_type_to_d3d(programInfo.primitiveType()); 532cb93a386Sopenharmony_ci 533cb93a386Sopenharmony_ci psoDesc.NumRenderTargets = 1; 534cb93a386Sopenharmony_ci 535cb93a386Sopenharmony_ci psoDesc.RTVFormats[0] = renderTargetFormat; 536cb93a386Sopenharmony_ci 537cb93a386Sopenharmony_ci psoDesc.DSVFormat = depthStencilFormat; 538cb93a386Sopenharmony_ci 539cb93a386Sopenharmony_ci unsigned int numSamples = programInfo.numSamples(); 540cb93a386Sopenharmony_ci psoDesc.SampleDesc = { numSamples, sampleQualityPattern }; 541cb93a386Sopenharmony_ci 542cb93a386Sopenharmony_ci // Only used for multi-adapter systems. 543cb93a386Sopenharmony_ci psoDesc.NodeMask = 0; 544cb93a386Sopenharmony_ci 545cb93a386Sopenharmony_ci psoDesc.CachedPSO = { nullptr, 0 }; 546cb93a386Sopenharmony_ci psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; 547cb93a386Sopenharmony_ci 548cb93a386Sopenharmony_ci gr_cp<ID3D12PipelineState> pipelineState; 549cb93a386Sopenharmony_ci { 550cb93a386Sopenharmony_ci TRACE_EVENT0("skia.shaders", "CreateGraphicsPipelineState"); 551cb93a386Sopenharmony_ci GR_D3D_CALL_ERRCHECK( 552cb93a386Sopenharmony_ci gpu->device()->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState))); 553cb93a386Sopenharmony_ci } 554cb93a386Sopenharmony_ci 555cb93a386Sopenharmony_ci return pipelineState; 556cb93a386Sopenharmony_ci} 557cb93a386Sopenharmony_ci 558cb93a386Sopenharmony_cistatic constexpr SkFourByteTag kHLSL_Tag = SkSetFourByteTag('H', 'L', 'S', 'L'); 559cb93a386Sopenharmony_cistatic constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L'); 560cb93a386Sopenharmony_ci 561cb93a386Sopenharmony_cistd::unique_ptr<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() { 562cb93a386Sopenharmony_ci TRACE_EVENT0("skia.shaders", TRACE_FUNC); 563cb93a386Sopenharmony_ci 564cb93a386Sopenharmony_ci this->finalizeShaders(); 565cb93a386Sopenharmony_ci 566cb93a386Sopenharmony_ci SkSL::Program::Settings settings; 567cb93a386Sopenharmony_ci settings.fSharpenTextures = 568cb93a386Sopenharmony_ci this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures; 569cb93a386Sopenharmony_ci settings.fRTFlipOffset = fUniformHandler.getRTFlipOffset(); 570cb93a386Sopenharmony_ci settings.fRTFlipBinding = 0; 571cb93a386Sopenharmony_ci settings.fRTFlipSet = 0; 572cb93a386Sopenharmony_ci 573cb93a386Sopenharmony_ci sk_sp<SkData> cached; 574cb93a386Sopenharmony_ci SkReadBuffer reader; 575cb93a386Sopenharmony_ci SkFourByteTag shaderType = 0; 576cb93a386Sopenharmony_ci auto persistentCache = fGpu->getContext()->priv().getPersistentCache(); 577cb93a386Sopenharmony_ci if (persistentCache) { 578cb93a386Sopenharmony_ci // Shear off the D3D-specific portion of the Desc to get the persistent key. We only cache 579cb93a386Sopenharmony_ci // shader code, not entire pipelines. 580cb93a386Sopenharmony_ci sk_sp<SkData> key = 581cb93a386Sopenharmony_ci SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength()); 582cb93a386Sopenharmony_ci cached = persistentCache->load(*key); 583cb93a386Sopenharmony_ci if (cached) { 584cb93a386Sopenharmony_ci reader.setMemory(cached->data(), cached->size()); 585cb93a386Sopenharmony_ci shaderType = GrPersistentCacheUtils::GetType(&reader); 586cb93a386Sopenharmony_ci } 587cb93a386Sopenharmony_ci } 588cb93a386Sopenharmony_ci 589cb93a386Sopenharmony_ci const GrGeometryProcessor& geomProc = this->geometryProcessor(); 590cb93a386Sopenharmony_ci gr_cp<ID3DBlob> shaders[kGrShaderTypeCount]; 591cb93a386Sopenharmony_ci 592cb93a386Sopenharmony_ci if (kHLSL_Tag == shaderType && this->loadHLSLFromCache(&reader, shaders)) { 593cb93a386Sopenharmony_ci // We successfully loaded and compiled HLSL 594cb93a386Sopenharmony_ci } else { 595cb93a386Sopenharmony_ci SkSL::Program::Inputs inputs[kGrShaderTypeCount]; 596cb93a386Sopenharmony_ci SkSL::String* sksl[kGrShaderTypeCount] = { 597cb93a386Sopenharmony_ci &fVS.fCompilerString, 598cb93a386Sopenharmony_ci &fFS.fCompilerString, 599cb93a386Sopenharmony_ci }; 600cb93a386Sopenharmony_ci SkSL::String cached_sksl[kGrShaderTypeCount]; 601cb93a386Sopenharmony_ci SkSL::String hlsl[kGrShaderTypeCount]; 602cb93a386Sopenharmony_ci 603cb93a386Sopenharmony_ci if (kSKSL_Tag == shaderType) { 604cb93a386Sopenharmony_ci if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs, 605cb93a386Sopenharmony_ci kGrShaderTypeCount)) { 606cb93a386Sopenharmony_ci for (int i = 0; i < kGrShaderTypeCount; ++i) { 607cb93a386Sopenharmony_ci sksl[i] = &cached_sksl[i]; 608cb93a386Sopenharmony_ci } 609cb93a386Sopenharmony_ci } 610cb93a386Sopenharmony_ci } 611cb93a386Sopenharmony_ci 612cb93a386Sopenharmony_ci auto compile = [&](SkSL::ProgramKind kind, GrShaderType shaderType) { 613cb93a386Sopenharmony_ci shaders[shaderType] = this->compileD3DProgram(kind, *sksl[shaderType], settings, 614cb93a386Sopenharmony_ci &inputs[shaderType], &hlsl[shaderType]); 615cb93a386Sopenharmony_ci return shaders[shaderType].get(); 616cb93a386Sopenharmony_ci }; 617cb93a386Sopenharmony_ci 618cb93a386Sopenharmony_ci if (!compile(SkSL::ProgramKind::kVertex, kVertex_GrShaderType) || 619cb93a386Sopenharmony_ci !compile(SkSL::ProgramKind::kFragment, kFragment_GrShaderType)) { 620cb93a386Sopenharmony_ci return nullptr; 621cb93a386Sopenharmony_ci } 622cb93a386Sopenharmony_ci 623cb93a386Sopenharmony_ci if (persistentCache && !cached) { 624cb93a386Sopenharmony_ci const bool cacheSkSL = fGpu->getContext()->priv().options().fShaderCacheStrategy == 625cb93a386Sopenharmony_ci GrContextOptions::ShaderCacheStrategy::kSkSL; 626cb93a386Sopenharmony_ci if (cacheSkSL) { 627cb93a386Sopenharmony_ci // Replace the HLSL with formatted SkSL to be cached. This looks odd, but this is 628cb93a386Sopenharmony_ci // the last time we're going to use these strings, so it's safe. 629cb93a386Sopenharmony_ci for (int i = 0; i < kGrShaderTypeCount; ++i) { 630cb93a386Sopenharmony_ci hlsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]); 631cb93a386Sopenharmony_ci } 632cb93a386Sopenharmony_ci } 633cb93a386Sopenharmony_ci sk_sp<SkData> key = 634cb93a386Sopenharmony_ci SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength()); 635cb93a386Sopenharmony_ci SkString description = GrProgramDesc::Describe(fProgramInfo, *this->caps()); 636cb93a386Sopenharmony_ci sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders( 637cb93a386Sopenharmony_ci cacheSkSL ? kSKSL_Tag : kHLSL_Tag, hlsl, inputs, kGrShaderTypeCount); 638cb93a386Sopenharmony_ci persistentCache->store(*key, *data, description); 639cb93a386Sopenharmony_ci } 640cb93a386Sopenharmony_ci } 641cb93a386Sopenharmony_ci 642cb93a386Sopenharmony_ci sk_sp<GrD3DRootSignature> rootSig = 643cb93a386Sopenharmony_ci fGpu->resourceProvider().findOrCreateRootSignature(fUniformHandler.fTextures.count()); 644cb93a386Sopenharmony_ci if (!rootSig) { 645cb93a386Sopenharmony_ci return nullptr; 646cb93a386Sopenharmony_ci } 647cb93a386Sopenharmony_ci 648cb93a386Sopenharmony_ci const GrD3DRenderTarget* rt = static_cast<const GrD3DRenderTarget*>(fRenderTarget); 649cb93a386Sopenharmony_ci gr_cp<ID3D12PipelineState> pipelineState = create_pipeline_state( 650cb93a386Sopenharmony_ci fGpu, fProgramInfo, rootSig, std::move(shaders[kVertex_GrShaderType]), 651cb93a386Sopenharmony_ci std::move(shaders[kFragment_GrShaderType]), 652cb93a386Sopenharmony_ci rt->dxgiFormat(), rt->stencilDxgiFormat(), rt->sampleQualityPattern()); 653cb93a386Sopenharmony_ci sk_sp<GrD3DPipeline> pipeline = GrD3DPipeline::Make(std::move(pipelineState)); 654cb93a386Sopenharmony_ci 655cb93a386Sopenharmony_ci return std::unique_ptr<GrD3DPipelineState>( 656cb93a386Sopenharmony_ci new GrD3DPipelineState(std::move(pipeline), 657cb93a386Sopenharmony_ci std::move(rootSig), 658cb93a386Sopenharmony_ci fUniformHandles, 659cb93a386Sopenharmony_ci fUniformHandler.fUniforms, 660cb93a386Sopenharmony_ci fUniformHandler.fCurrentUBOOffset, 661cb93a386Sopenharmony_ci fUniformHandler.fSamplers.count(), 662cb93a386Sopenharmony_ci std::move(fGPImpl), 663cb93a386Sopenharmony_ci std::move(fXPImpl), 664cb93a386Sopenharmony_ci std::move(fFPImpls), 665cb93a386Sopenharmony_ci geomProc.vertexStride(), 666cb93a386Sopenharmony_ci geomProc.instanceStride())); 667cb93a386Sopenharmony_ci} 668cb93a386Sopenharmony_ci 669cb93a386Sopenharmony_ci 670cb93a386Sopenharmony_cisk_sp<GrD3DPipeline> GrD3DPipelineStateBuilder::MakeComputePipeline(GrD3DGpu* gpu, 671cb93a386Sopenharmony_ci GrD3DRootSignature* rootSig, 672cb93a386Sopenharmony_ci const char* shader) { 673cb93a386Sopenharmony_ci D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {}; 674cb93a386Sopenharmony_ci psoDesc.pRootSignature = rootSig->rootSignature(); 675cb93a386Sopenharmony_ci 676cb93a386Sopenharmony_ci // compile shader 677cb93a386Sopenharmony_ci gr_cp<ID3DBlob> shaderBlob; 678cb93a386Sopenharmony_ci { 679cb93a386Sopenharmony_ci TRACE_EVENT0("skia.shaders", "driver_compile_shader"); 680cb93a386Sopenharmony_ci uint32_t compileFlags = 0; 681cb93a386Sopenharmony_ci#ifdef SK_DEBUG 682cb93a386Sopenharmony_ci // Enable better shader debugging with the graphics debugging tools. 683cb93a386Sopenharmony_ci compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; 684cb93a386Sopenharmony_ci#endif 685cb93a386Sopenharmony_ci 686cb93a386Sopenharmony_ci gr_cp<ID3DBlob> errors; 687cb93a386Sopenharmony_ci HRESULT hr = D3DCompile(shader, strlen(shader), nullptr, nullptr, nullptr, "main", 688cb93a386Sopenharmony_ci "cs_5_1", compileFlags, 0, &shaderBlob, &errors); 689cb93a386Sopenharmony_ci if (!SUCCEEDED(hr)) { 690cb93a386Sopenharmony_ci gpu->getContext()->priv().getShaderErrorHandler()->compileError( 691cb93a386Sopenharmony_ci shader, reinterpret_cast<char*>(errors->GetBufferPointer())); 692cb93a386Sopenharmony_ci return nullptr; 693cb93a386Sopenharmony_ci } 694cb93a386Sopenharmony_ci psoDesc.CS = { reinterpret_cast<UINT8*>(shaderBlob->GetBufferPointer()), 695cb93a386Sopenharmony_ci shaderBlob->GetBufferSize() }; 696cb93a386Sopenharmony_ci } 697cb93a386Sopenharmony_ci 698cb93a386Sopenharmony_ci // Only used for multi-adapter systems. 699cb93a386Sopenharmony_ci psoDesc.NodeMask = 0; 700cb93a386Sopenharmony_ci 701cb93a386Sopenharmony_ci psoDesc.CachedPSO = { nullptr, 0 }; 702cb93a386Sopenharmony_ci psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; 703cb93a386Sopenharmony_ci 704cb93a386Sopenharmony_ci gr_cp<ID3D12PipelineState> pipelineState; 705cb93a386Sopenharmony_ci { 706cb93a386Sopenharmony_ci TRACE_EVENT0("skia.shaders", "CreateComputePipelineState"); 707cb93a386Sopenharmony_ci GR_D3D_CALL_ERRCHECK( 708cb93a386Sopenharmony_ci gpu->device()->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState))); 709cb93a386Sopenharmony_ci } 710cb93a386Sopenharmony_ci 711cb93a386Sopenharmony_ci return GrD3DPipeline::Make(std::move(pipelineState)); 712cb93a386Sopenharmony_ci} 713cb93a386Sopenharmony_ci 714