blob: f0682055ad82533d01e8d991d6f49ad1f191a2f9 [file] [log] [blame]
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/d3d/GrD3DPipelineState.h"
#include "include/private/SkTemplates.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/d3d/GrD3DGpu.h"
static DXGI_FORMAT attrib_type_to_format(GrVertexAttribType type) {
switch (type) {
case kFloat_GrVertexAttribType:
return DXGI_FORMAT_R32_FLOAT;
case kFloat2_GrVertexAttribType:
return DXGI_FORMAT_R32G32_FLOAT;
case kFloat3_GrVertexAttribType:
return DXGI_FORMAT_R32G32B32_FLOAT;
case kFloat4_GrVertexAttribType:
return DXGI_FORMAT_R32G32B32A32_FLOAT;
case kHalf_GrVertexAttribType:
return DXGI_FORMAT_R16_FLOAT;
case kHalf2_GrVertexAttribType:
return DXGI_FORMAT_R16G16_FLOAT;
case kHalf4_GrVertexAttribType:
return DXGI_FORMAT_R16G16B16A16_FLOAT;
case kInt2_GrVertexAttribType:
return DXGI_FORMAT_R32G32_SINT;
case kInt3_GrVertexAttribType:
return DXGI_FORMAT_R32G32B32_SINT;
case kInt4_GrVertexAttribType:
return DXGI_FORMAT_R32G32B32A32_SINT;
case kByte_GrVertexAttribType:
return DXGI_FORMAT_R8_SINT;
case kByte2_GrVertexAttribType:
return DXGI_FORMAT_R8G8_SINT;
case kByte4_GrVertexAttribType:
return DXGI_FORMAT_R8G8B8A8_SINT;
case kUByte_GrVertexAttribType:
return DXGI_FORMAT_R8_UINT;
case kUByte2_GrVertexAttribType:
return DXGI_FORMAT_R8G8_UINT;
case kUByte4_GrVertexAttribType:
return DXGI_FORMAT_R8G8B8A8_UINT;
case kUByte_norm_GrVertexAttribType:
return DXGI_FORMAT_R8_UNORM;
case kUByte4_norm_GrVertexAttribType:
return DXGI_FORMAT_R8G8B8A8_UNORM;
case kShort2_GrVertexAttribType:
return DXGI_FORMAT_R16G16_SINT;
case kShort4_GrVertexAttribType:
return DXGI_FORMAT_R16G16B16A16_SINT;
case kUShort2_GrVertexAttribType:
return DXGI_FORMAT_R16G16_UINT;
case kUShort2_norm_GrVertexAttribType:
return DXGI_FORMAT_R16G16_UNORM;
case kInt_GrVertexAttribType:
return DXGI_FORMAT_R32_SINT;
case kUint_GrVertexAttribType:
return DXGI_FORMAT_R32_UINT;
case kUShort_norm_GrVertexAttribType:
return DXGI_FORMAT_R16_UNORM;
case kUShort4_norm_GrVertexAttribType:
return DXGI_FORMAT_R16G16B16A16_UNORM;
}
SK_ABORT("Unknown vertex attrib type");
}
static void setup_vertex_input_layout(const GrPrimitiveProcessor& primProc,
D3D12_INPUT_ELEMENT_DESC* inputElements) {
unsigned int slotNumber = 0;
unsigned int vertexSlot = 0;
unsigned int instanceSlot = 0;
if (primProc.hasVertexAttributes()) {
vertexSlot = slotNumber++;
}
if (primProc.hasInstanceAttributes()) {
instanceSlot = slotNumber++;
}
unsigned int currentAttrib = 0;
unsigned int vertexAttributeOffset = 0;
for (const auto& attrib : primProc.vertexAttributes()) {
// When using SPIRV-Cross it converts the location modifier in SPIRV to be
// TEXCOORD<N> where N is the location value for eveery vertext attribute
inputElements[currentAttrib] = {"TEXCOORD", currentAttrib,
attrib_type_to_format(attrib.cpuType()),
vertexSlot, vertexAttributeOffset,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0};
vertexAttributeOffset += attrib.sizeAlign4();
}
SkASSERT(vertexAttributeOffset == primProc.vertexStride());
unsigned int instanceAttributeOffset = 0;
for (const auto& attrib : primProc.vertexAttributes()) {
// When using SPIRV-Cross it converts the location modifier in SPIRV to be
// TEXCOORD<N> where N is the location value for eveery vertext attribute
inputElements[currentAttrib] = {"TEXCOORD", currentAttrib,
attrib_type_to_format(attrib.cpuType()),
instanceSlot, instanceAttributeOffset,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0};
instanceAttributeOffset += attrib.sizeAlign4();
}
SkASSERT(instanceAttributeOffset == primProc.vertexStride());
}
static D3D12_BLEND blend_coeff_to_d3d_blend(GrBlendCoeff coeff) {
switch (coeff) {
case kZero_GrBlendCoeff:
return D3D12_BLEND_ZERO;
case kOne_GrBlendCoeff:
return D3D12_BLEND_ONE;
case kSC_GrBlendCoeff:
return D3D12_BLEND_SRC_COLOR;
case kISC_GrBlendCoeff:
return D3D12_BLEND_INV_SRC_COLOR;
case kDC_GrBlendCoeff:
return D3D12_BLEND_DEST_COLOR;
case kIDC_GrBlendCoeff:
return D3D12_BLEND_INV_DEST_COLOR;
case kSA_GrBlendCoeff:
return D3D12_BLEND_SRC_ALPHA;
case kISA_GrBlendCoeff:
return D3D12_BLEND_INV_SRC_ALPHA;
case kDA_GrBlendCoeff:
return D3D12_BLEND_DEST_ALPHA;
case kIDA_GrBlendCoeff:
return D3D12_BLEND_INV_DEST_ALPHA;
case kConstC_GrBlendCoeff:
return D3D12_BLEND_BLEND_FACTOR;
case kIConstC_GrBlendCoeff:
return D3D12_BLEND_INV_BLEND_FACTOR;
case kS2C_GrBlendCoeff:
return D3D12_BLEND_SRC1_COLOR;
case kIS2C_GrBlendCoeff:
return D3D12_BLEND_INV_SRC1_COLOR;
case kS2A_GrBlendCoeff:
return D3D12_BLEND_SRC1_ALPHA;
case kIS2A_GrBlendCoeff:
return D3D12_BLEND_INV_SRC1_ALPHA;
case kIllegal_GrBlendCoeff:
return D3D12_BLEND_ZERO;
}
SkUNREACHABLE;
}
static D3D12_BLEND_OP blend_equation_to_d3d_op(GrBlendEquation equation) {
switch (equation) {
case kAdd_GrBlendEquation:
return D3D12_BLEND_OP_ADD;
case kSubtract_GrBlendEquation:
return D3D12_BLEND_OP_SUBTRACT;
case kReverseSubtract_GrBlendEquation:
return D3D12_BLEND_OP_REV_SUBTRACT;
default:
SkUNREACHABLE;
}
}
static void fill_in_blend_state(const GrPipeline& pipeline, D3D12_BLEND_DESC* blendDesc) {
blendDesc->AlphaToCoverageEnable = false;
blendDesc->IndependentBlendEnable = false;
const GrXferProcessor::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo();
GrBlendEquation equation = blendInfo.fEquation;
GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
bool blendOff = GrBlendShouldDisable(equation, srcCoeff, dstCoeff);
auto& rtBlend = blendDesc->RenderTarget[0];
rtBlend.BlendEnable = !blendOff;
if (!blendOff) {
rtBlend.SrcBlend = blend_coeff_to_d3d_blend(srcCoeff);
rtBlend.DestBlend = blend_coeff_to_d3d_blend(dstCoeff);
rtBlend.BlendOp = blend_equation_to_d3d_op(equation);
rtBlend.SrcBlendAlpha = blend_coeff_to_d3d_blend(srcCoeff);
rtBlend.DestBlendAlpha = blend_coeff_to_d3d_blend(dstCoeff);
rtBlend.BlendOpAlpha = blend_equation_to_d3d_op(equation);
}
if (!blendInfo.fWriteColor) {
rtBlend.RenderTargetWriteMask = 0;
} else {
rtBlend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
}
}
static void fill_in_rasterizer_state(const GrPipeline& pipeline, const GrCaps* caps,
D3D12_RASTERIZER_DESC* rasterizer) {
rasterizer->FillMode = (caps->wireframeMode() || pipeline.isWireframe()) ?
D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID;
rasterizer->CullMode = D3D12_CULL_MODE_NONE;
rasterizer->FrontCounterClockwise = true;
rasterizer->DepthBias = 0;
rasterizer->DepthBiasClamp = 0.0f;
rasterizer->SlopeScaledDepthBias = 0.0f;
rasterizer->DepthClipEnable = false;
rasterizer->MultisampleEnable = pipeline.isHWAntialiasState();
rasterizer->AntialiasedLineEnable = false;
rasterizer->ForcedSampleCount = 0;
rasterizer->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
}
std::unique_ptr<GrD3DPipelineState> GrD3DPipelineState::Make(GrD3DGpu* gpu,
const GrProgramInfo& programInfo) {
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
unsigned int totalAttributeCnt = programInfo.primProc().numVertexAttributes() +
programInfo.primProc().numInstanceAttributes();
SkAutoSTArray<4, D3D12_INPUT_ELEMENT_DESC> inputElements(totalAttributeCnt);
setup_vertex_input_layout(programInfo.primProc(), inputElements.get());
psoDesc.InputLayout = { inputElements.get(), totalAttributeCnt };
fill_in_blend_state(programInfo.pipeline(), &psoDesc.BlendState);
fill_in_rasterizer_state(programInfo.pipeline(), gpu->caps(), &psoDesc.RasterizerState);
// TODO: fill in the rest of the descriptor.
#if 0
psoDesc.pRootSignature = m_rootSignature.Get();
psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), vertexShader->GetBufferSize() };
psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), pixelShader->GetBufferSize() };
psoDesc.DepthStencilState.DepthEnable = FALSE;
psoDesc.DepthStencilState.StencilEnable = FALSE;
psoDesc.SampleMask = UINT_MAX;
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
psoDesc.NumRenderTargets = 1;
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
psoDesc.SampleDesc.Count = 1;
ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState)));
#endif
return nullptr;
}
GrD3DPipelineState::GrD3DPipelineState(gr_cp<ID3D12PipelineState> pipelineState)
: fPipelineState(std::move(pipelineState)) {}