| /* | |
| * Copyright 2025 Rive | |
| */ | |
| #include "rive/renderer/d3d12/d3d12_pipeline_manager.hpp" | |
| #include "rive/renderer/d3d/d3d_constants.hpp" | |
| #include "generated/shaders/tessellate.glsl.exports.h" | |
| // offline shaders | |
| namespace shader | |
| { | |
| namespace tess::vert | |
| { | |
| #include "generated/shaders/d3d/tessellate.vert.h" | |
| } | |
| namespace tess::frag | |
| { | |
| #include "generated/shaders/d3d/tessellate.frag.h" | |
| } | |
| namespace grad::vert | |
| { | |
| #include "generated/shaders/d3d/color_ramp.vert.h" | |
| } | |
| namespace grad::frag | |
| { | |
| #include "generated/shaders/d3d/color_ramp.frag.h" | |
| } | |
| namespace atlas::vert | |
| { | |
| #include "generated/shaders/d3d/render_atlas.vert.h" | |
| } | |
| namespace atlas::fill | |
| { | |
| #include "generated/shaders/d3d/render_atlas_fill.frag.h" | |
| } | |
| namespace atlas::stroke | |
| { | |
| #include "generated/shaders/d3d/render_atlas_stroke.frag.h" | |
| } | |
| } // namespace shader | |
| // offline sigs | |
| namespace sig | |
| { | |
| #include "generated/shaders/d3d/root.sig.h" | |
| } // namespace sig | |
| namespace rive::gpu | |
| { | |
| D3D12PipelineManager::D3D12PipelineManager( | |
| ComPtr<ID3D12Device> device, | |
| const D3DCapabilities& capabilities, | |
| ShaderCompilationMode shaderCompilationMode) | |
| : Super(device, capabilities, shaderCompilationMode, "vs_5_1", "ps_5_1") | |
| { | |
| VERIFY_OK(this->device()->CreateRootSignature( | |
| 0, | |
| sig::g_ROOT_SIG, | |
| std::size(sig::g_ROOT_SIG), | |
| IID_PPV_ARGS(&m_rootSignature))); | |
| } | |
| inline DXGI_FORMAT getDXGIFormat(VertexElementFormat format) | |
| { | |
| switch (format) | |
| { | |
| case VertexElementFormat::float1: | |
| return DXGI_FORMAT_R32_FLOAT; | |
| case VertexElementFormat::float2: | |
| return DXGI_FORMAT_R32G32_FLOAT; | |
| case VertexElementFormat::float3: | |
| return DXGI_FORMAT_R32G32B32_FLOAT; | |
| case VertexElementFormat::float4: | |
| return DXGI_FORMAT_R32G32B32A32_FLOAT; | |
| case VertexElementFormat::uint8x4: | |
| return DXGI_FORMAT_R8G8B8A8_UINT; | |
| case VertexElementFormat::sint8x4: | |
| return DXGI_FORMAT_R8G8B8A8_SINT; | |
| case VertexElementFormat::unorm8x4: | |
| return DXGI_FORMAT_R8G8B8A8_UNORM; | |
| case VertexElementFormat::snorm8x4: | |
| return DXGI_FORMAT_R8G8B8A8_SNORM; | |
| case VertexElementFormat::uint16x2: | |
| return DXGI_FORMAT_R16G16_UINT; | |
| case VertexElementFormat::sint16x2: | |
| return DXGI_FORMAT_R16G16_SINT; | |
| case VertexElementFormat::unorm16x2: | |
| return DXGI_FORMAT_R16G16_UNORM; | |
| case VertexElementFormat::snorm16x2: | |
| return DXGI_FORMAT_R16G16_SNORM; | |
| case VertexElementFormat::uint16x4: | |
| return DXGI_FORMAT_R16G16B16A16_UINT; | |
| case VertexElementFormat::sint16x4: | |
| return DXGI_FORMAT_R16G16B16A16_SINT; | |
| case VertexElementFormat::float16x2: | |
| return DXGI_FORMAT_R16G16_FLOAT; | |
| case VertexElementFormat::float16x4: | |
| return DXGI_FORMAT_R16G16B16A16_FLOAT; | |
| case VertexElementFormat::uint32: | |
| return DXGI_FORMAT_R32_UINT; | |
| } | |
| RIVE_UNREACHABLE(); | |
| } | |
| template <typename ImageDrawInstance, uint32_t N> | |
| void addInstanceElements(StackVector<D3D12_INPUT_ELEMENT_DESC, N>& layoutDesc) | |
| { | |
| for (auto& attribute : ImageDrawInstance::getAttributes()) | |
| { | |
| layoutDesc.push_back({ | |
| .SemanticName = attribute.semanticName, | |
| .SemanticIndex = 0, | |
| .Format = getDXGIFormat(attribute.format), | |
| .InputSlot = IMAGE_DRAW_INSTANCE_DATA_SLOT, | |
| .AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT, | |
| .InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, | |
| .InstanceDataStepRate = 1, | |
| }); | |
| } | |
| } | |
| std::unique_ptr<D3D12DrawVertexShader> D3D12PipelineManager:: | |
| compileVertexShaderBlobToFinalType(DrawType drawType, ComPtr<ID3DBlob> blob) | |
| { | |
| auto result = std::make_unique<D3D12DrawVertexShader>(); | |
| switch (drawType) | |
| { | |
| case DrawType::midpointFanPatches: | |
| case DrawType::midpointFanCenterAAPatches: | |
| case DrawType::outerCurvePatches: | |
| result->m_layoutDesc.push_back({ | |
| GLSL_a_patchVertexData, | |
| 0, | |
| DXGI_FORMAT_R32G32B32A32_FLOAT, | |
| PATCH_VERTEX_DATA_SLOT, | |
| D3D12_APPEND_ALIGNED_ELEMENT, | |
| D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, | |
| 0, | |
| }); | |
| result->m_layoutDesc.push_back({ | |
| GLSL_a_mirroredVertexData, | |
| 0, | |
| DXGI_FORMAT_R32G32B32A32_FLOAT, | |
| PATCH_VERTEX_DATA_SLOT, | |
| D3D12_APPEND_ALIGNED_ELEMENT, | |
| D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, | |
| 0, | |
| }); | |
| break; | |
| case DrawType::interiorTriangulation: | |
| case DrawType::featherAtlasBlit: | |
| case DrawType::clipReset: | |
| result->m_layoutDesc.push_back({ | |
| GLSL_a_triangleVertex, | |
| 0, | |
| DXGI_FORMAT_R32G32B32_FLOAT, | |
| TRIANGLE_VERTEX_DATA_SLOT, | |
| 0, | |
| D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, | |
| 0, | |
| }); | |
| break; | |
| case DrawType::imageRect: | |
| result->m_layoutDesc.push_back({ | |
| GLSL_a_imageRectVertex, | |
| 0, | |
| DXGI_FORMAT_R32G32B32A32_FLOAT, | |
| IMAGE_RECT_VERTEX_DATA_SLOT, | |
| 0, | |
| D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, | |
| 0, | |
| }); | |
| addInstanceElements<ImageRectInstance>(result->m_layoutDesc); | |
| break; | |
| case DrawType::imageMesh: | |
| result->m_layoutDesc.push_back({ | |
| GLSL_a_position, | |
| 0, | |
| DXGI_FORMAT_R32G32_FLOAT, | |
| IMAGE_MESH_VERTEX_DATA_SLOT, | |
| D3D12_APPEND_ALIGNED_ELEMENT, | |
| D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, | |
| 0, | |
| }); | |
| result->m_layoutDesc.push_back({ | |
| GLSL_a_texCoord, | |
| 0, | |
| DXGI_FORMAT_R32G32_FLOAT, | |
| IMAGE_MESH_UV_DATA_SLOT, | |
| D3D12_APPEND_ALIGNED_ELEMENT, | |
| D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, | |
| 0, | |
| }); | |
| addInstanceElements<ImageMeshInstance>(result->m_layoutDesc); | |
| break; | |
| // depthStencil path draws derive everything from the vertex index, so | |
| // they bind no attributes at all. | |
| case DrawType::renderPassResolve: | |
| case DrawType::stencilMidpointFanBorrowedCoverage: | |
| case DrawType::stencilDynamicMidpointFans: | |
| case DrawType::stencilDynamicOuterCubics: | |
| case DrawType::stencilMidpointFans: | |
| case DrawType::stencilMidpointFanReset: | |
| case DrawType::stencilMidpointFanWinding: | |
| case DrawType::stencilMidpointFanCover: | |
| case DrawType::stencilOuterCubicBorrowedCoverage: | |
| case DrawType::stencilOuterCubicReset: | |
| case DrawType::stencilOuterCubicWinding: | |
| case DrawType::stencilOuterCubicCover: | |
| case DrawType::stencilOuterCubics: | |
| case DrawType::depthStrokes: | |
| case DrawType::depthAAStrokes: | |
| case DrawType::depthAAOuterHairline: | |
| break; | |
| case DrawType::renderPassInitialize: | |
| RIVE_UNREACHABLE(); | |
| } | |
| result->m_shader = blob; | |
| return result; | |
| } | |
| std::unique_ptr<D3D12DrawPixelShader> D3D12PipelineManager:: | |
| compilePixelShaderBlobToFinalType(ComPtr<ID3DBlob> blob) | |
| { | |
| auto result = std::make_unique<D3D12DrawPixelShader>(); | |
| result->m_shader = std::move(blob); | |
| return result; | |
| } | |
| static D3D12_STENCIL_OP d3d12_stencil_op(gpu::StencilOp op) | |
| { | |
| switch (op) | |
| { | |
| case gpu::StencilOp::keep: | |
| return D3D12_STENCIL_OP_KEEP; | |
| case gpu::StencilOp::replace: | |
| return D3D12_STENCIL_OP_REPLACE; | |
| case gpu::StencilOp::zero: | |
| return D3D12_STENCIL_OP_ZERO; | |
| case gpu::StencilOp::decrClamp: | |
| return D3D12_STENCIL_OP_DECR_SAT; | |
| case gpu::StencilOp::incrWrap: | |
| return D3D12_STENCIL_OP_INCR; | |
| case gpu::StencilOp::decrWrap: | |
| return D3D12_STENCIL_OP_DECR; | |
| } | |
| RIVE_UNREACHABLE(); | |
| } | |
| static D3D12_COMPARISON_FUNC d3d12_stencil_compare(gpu::StencilCompareOp op) | |
| { | |
| switch (op) | |
| { | |
| case gpu::StencilCompareOp::less: | |
| return D3D12_COMPARISON_FUNC_LESS; | |
| case gpu::StencilCompareOp::equal: | |
| return D3D12_COMPARISON_FUNC_EQUAL; | |
| case gpu::StencilCompareOp::lessOrEqual: | |
| return D3D12_COMPARISON_FUNC_LESS_EQUAL; | |
| case gpu::StencilCompareOp::notEqual: | |
| return D3D12_COMPARISON_FUNC_NOT_EQUAL; | |
| case gpu::StencilCompareOp::always: | |
| return D3D12_COMPARISON_FUNC_ALWAYS; | |
| } | |
| RIVE_UNREACHABLE(); | |
| } | |
| static void fill_stencil_face( | |
| const gpu::StencilFaceOps& ops, | |
| D3D12_DEPTH_STENCILOP_DESC* out) | |
| { | |
| out->StencilFailOp = d3d12_stencil_op(ops.stencilFailOp); | |
| out->StencilDepthFailOp = d3d12_stencil_op(ops.depthFailOp); | |
| out->StencilPassOp = d3d12_stencil_op(ops.depthStencilPassOp); | |
| out->StencilFunc = d3d12_stencil_compare(ops.compareOp); | |
| } | |
| // D3D's front face is rive's clockwise front (FrontCounterClockwise=FALSE), so | |
| // the faces map straight across with no swap. | |
| static D3D12_CULL_MODE d3d12_cull_mode(gpu::CullFace cull) | |
| { | |
| switch (cull) | |
| { | |
| case gpu::CullFace::none: | |
| return D3D12_CULL_MODE_NONE; | |
| case gpu::CullFace::clockwise: | |
| return D3D12_CULL_MODE_FRONT; | |
| case gpu::CullFace::counterclockwise: | |
| return D3D12_CULL_MODE_BACK; | |
| } | |
| RIVE_UNREACHABLE(); | |
| } | |
| std::unique_ptr<D3D12Pipeline> D3D12PipelineManager::linkPipeline( | |
| const PipelineProps& props, | |
| const D3D12DrawVertexShader& vs, | |
| const D3D12DrawPixelShader& ps, | |
| const PlatformFeatures& platformFeatures) | |
| { | |
| ComPtr<ID3D12PipelineState> pipelineState; | |
| D3D12_RASTERIZER_DESC rasterDesc = {}; | |
| // Wireframe is a debugging aid. The resolve is a fullscreen operation, so | |
| // leave it solid even in wireframe mode. | |
| rasterDesc.FillMode = (props.wireframe && | |
| props.drawType != DrawType::renderPassResolve) | |
| ? D3D12_FILL_MODE_WIREFRAME | |
| : D3D12_FILL_MODE_SOLID; | |
| rasterDesc.FrontCounterClockwise = FALSE; | |
| rasterDesc.DepthBias = 0; | |
| rasterDesc.SlopeScaledDepthBias = 0; | |
| rasterDesc.DepthBiasClamp = 0; | |
| rasterDesc.DepthClipEnable = TRUE; | |
| rasterDesc.MultisampleEnable = FALSE; | |
| rasterDesc.AntialiasedLineEnable = FALSE; | |
| switch (props.drawType) | |
| { | |
| case DrawType::midpointFanPatches: | |
| case DrawType::midpointFanCenterAAPatches: | |
| case DrawType::outerCurvePatches: | |
| case DrawType::interiorTriangulation: | |
| case DrawType::featherAtlasBlit: | |
| rasterDesc.CullMode = D3D12_CULL_MODE_BACK; | |
| break; | |
| case DrawType::imageRect: | |
| case DrawType::imageMesh: | |
| case DrawType::renderPassResolve: | |
| rasterDesc.CullMode = D3D12_CULL_MODE_NONE; | |
| break; | |
| case DrawType::stencilMidpointFanBorrowedCoverage: | |
| case DrawType::stencilDynamicMidpointFans: | |
| case DrawType::stencilDynamicOuterCubics: | |
| case DrawType::stencilMidpointFans: | |
| case DrawType::stencilMidpointFanReset: | |
| case DrawType::stencilMidpointFanWinding: | |
| case DrawType::stencilMidpointFanCover: | |
| case DrawType::stencilOuterCubicBorrowedCoverage: | |
| case DrawType::stencilOuterCubicReset: | |
| case DrawType::stencilOuterCubicWinding: | |
| case DrawType::stencilOuterCubicCover: | |
| case DrawType::stencilOuterCubics: | |
| case DrawType::clipReset: | |
| case DrawType::renderPassInitialize: | |
| case DrawType::depthStrokes: | |
| case DrawType::depthAAStrokes: | |
| case DrawType::depthAAOuterHairline: | |
| break; | |
| } | |
| D3D12_BLEND_DESC blendDesc{}; | |
| blendDesc.RenderTarget[0].BlendEnable = enums::is_flag_set( | |
| props.shaderMiscFlags, | |
| ShaderMiscFlags::fixedFunctionColorOutput); | |
| blendDesc.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; | |
| blendDesc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; | |
| blendDesc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; | |
| blendDesc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; | |
| blendDesc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; | |
| blendDesc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; | |
| blendDesc.RenderTarget[0] | |
| .RenderTargetWriteMask = enums::any_flag_set( | |
| props.shaderMiscFlags, | |
| ShaderMiscFlags::fixedFunctionColorOutput | | |
| ShaderMiscFlags:: | |
| coalescedResolveAndTransfer) | |
| ? D3D12_COLOR_WRITE_ENABLE_ALL | |
| : 0; | |
| D3D12_DEPTH_STENCIL_DESC depthStencilDesc = {}; | |
| const bool isDepthStencil = props.interlockMode == | |
| InterlockMode::depthStencil; | |
| if (isDepthStencil) | |
| { | |
| const gpu::PipelineState pipelineState = gpu::get_pipeline_state( | |
| props.drawType, | |
| props.interlockMode, | |
| props.shaderMiscFlags, | |
| props.drawContents, | |
| props.fixedFunctionColorOutput, | |
| props.blendMode, | |
| platformFeatures); | |
| rasterDesc.CullMode = d3d12_cull_mode(pipelineState.cullFace); | |
| depthStencilDesc.DepthEnable = pipelineState.depthTestEnabled || | |
| pipelineState.depthWriteEnabled; | |
| depthStencilDesc.DepthWriteMask = pipelineState.depthWriteEnabled | |
| ? D3D12_DEPTH_WRITE_MASK_ALL | |
| : D3D12_DEPTH_WRITE_MASK_ZERO; | |
| depthStencilDesc.DepthFunc = pipelineState.depthTestEnabled | |
| ? D3D12_COMPARISON_FUNC_GREATER | |
| : D3D12_COMPARISON_FUNC_ALWAYS; | |
| depthStencilDesc.StencilEnable = pipelineState.stencilTestEnabled; | |
| depthStencilDesc.StencilReadMask = pipelineState.stencilCompareMask; | |
| depthStencilDesc.StencilWriteMask = pipelineState.stencilWriteMask; | |
| fill_stencil_face( | |
| pipelineState.stencilFrontOps, | |
| &depthStencilDesc.FrontFace); | |
| fill_stencil_face( | |
| pipelineState.stencilDoubleSided ? pipelineState.stencilBackOps | |
| : pipelineState.stencilFrontOps, | |
| &depthStencilDesc.BackFace); | |
| // Advanced blend draws composite into the UAV and bind no render | |
| // target. Everything else blends src-over into the attachment. | |
| const bool rendersToUAV = enums::is_flag_set( | |
| props.shaderFeatures, | |
| ShaderFeatures::ENABLE_ADVANCED_BLEND) && | |
| !enums::is_flag_set( | |
| props.shaderMiscFlags, | |
| ShaderMiscFlags::fixedFunctionColorOutput); | |
| blendDesc.RenderTarget[0].BlendEnable = !rendersToUAV; | |
| blendDesc.RenderTarget[0] | |
| .RenderTargetWriteMask = !rendersToUAV && | |
| pipelineState.colorWriteEnabled | |
| ? D3D12_COLOR_WRITE_ENABLE_ALL | |
| : 0; | |
| } | |
| D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; | |
| psoDesc.InputLayout = {vs.m_layoutDesc.data(), vs.m_layoutDesc.size()}; | |
| psoDesc.pRootSignature = m_rootSignature.Get(); | |
| psoDesc.VS = CD3DX12_SHADER_BYTECODE(vs.m_shader.Get()); | |
| psoDesc.PS = CD3DX12_SHADER_BYTECODE(ps.m_shader.Get()); | |
| psoDesc.RasterizerState = rasterDesc; | |
| psoDesc.BlendState = blendDesc; | |
| psoDesc.DepthStencilState = depthStencilDesc; | |
| psoDesc.SampleMask = UINT_MAX; | |
| psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; | |
| psoDesc.NumRenderTargets = 1; | |
| psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; | |
| psoDesc.DSVFormat = isDepthStencil ? DXGI_FORMAT_D24_UNORM_S8_UINT | |
| : DXGI_FORMAT_UNKNOWN; | |
| psoDesc.SampleDesc.Count = 1; | |
| auto result = std::make_unique<D3D12Pipeline>(); | |
| #ifdef WITH_RIVE_TOOLS | |
| if (props.synthesizedFailureType == | |
| SynthesizedFailureType::pipelineCreation || | |
| props.synthesizedFailureType == SynthesizedFailureType::shaderCompilation) | |
| { | |
| // An empty result is what counts as "failed" | |
| return result; | |
| } | |
| #endif | |
| VERIFY_OK(device()->CreateGraphicsPipelineState( | |
| &psoDesc, | |
| IID_PPV_ARGS(&result->m_d3dPipelineState))); | |
| return result; | |
| } | |
| void D3D12PipelineManager::compileTesselationPipeline() | |
| { | |
| D3D12_INPUT_ELEMENT_DESC layoutDesc[] = { | |
| {GLSL_a_p0p1_, | |
| 0, | |
| DXGI_FORMAT_R32G32B32A32_FLOAT, | |
| 0, | |
| D3D12_APPEND_ALIGNED_ELEMENT, | |
| D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, | |
| 1}, | |
| {GLSL_a_p2p3_, | |
| 0, | |
| DXGI_FORMAT_R32G32B32A32_FLOAT, | |
| 0, | |
| D3D12_APPEND_ALIGNED_ELEMENT, | |
| D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, | |
| 1}, | |
| {GLSL_a_joinTan_and_ys, | |
| 0, | |
| DXGI_FORMAT_R32G32B32A32_FLOAT, | |
| 0, | |
| D3D12_APPEND_ALIGNED_ELEMENT, | |
| D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, | |
| 1}, | |
| {GLSL_a_args, | |
| 0, | |
| DXGI_FORMAT_R32G32B32A32_UINT, | |
| 0, | |
| D3D12_APPEND_ALIGNED_ELEMENT, | |
| D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, | |
| 1}}; | |
| D3D12_RASTERIZER_DESC rasterDesc = {}; | |
| rasterDesc.FillMode = D3D12_FILL_MODE_SOLID; | |
| rasterDesc.CullMode = D3D12_CULL_MODE_BACK; | |
| rasterDesc.FrontCounterClockwise = FALSE; | |
| rasterDesc.DepthBias = 0; | |
| rasterDesc.SlopeScaledDepthBias = 0; | |
| rasterDesc.DepthBiasClamp = 0; | |
| rasterDesc.DepthClipEnable = FALSE; | |
| rasterDesc.MultisampleEnable = FALSE; | |
| rasterDesc.AntialiasedLineEnable = FALSE; | |
| D3D12_BLEND_DESC blendDesc{}; | |
| blendDesc.RenderTarget[0].BlendEnable = FALSE; | |
| blendDesc.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; | |
| blendDesc.RenderTarget[0].DestBlend = D3D12_BLEND_ZERO; | |
| blendDesc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; | |
| blendDesc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; | |
| blendDesc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; | |
| blendDesc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; | |
| blendDesc.RenderTarget[0] | |
| .RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; | |
| D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; | |
| psoDesc.InputLayout = {layoutDesc, _countof(layoutDesc)}; | |
| psoDesc.pRootSignature = m_rootSignature.Get(); | |
| psoDesc.VS = { | |
| shader::tess::vert::g_main, | |
| std::size(shader::tess::vert::g_main)}; | |
| psoDesc.PS = { | |
| shader::tess::frag::g_main, | |
| std::size(shader::tess::frag::g_main)}; | |
| psoDesc.RasterizerState = rasterDesc; | |
| psoDesc.BlendState = blendDesc; | |
| 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_R32G32B32A32_UINT; | |
| psoDesc.SampleDesc.Count = 1; | |
| VERIFY_OK(device()->CreateGraphicsPipelineState( | |
| &psoDesc, | |
| IID_PPV_ARGS(&m_tesselationPipeline))); | |
| } | |
| void D3D12PipelineManager::compileGradientPipeline() | |
| { | |
| D3D12_INPUT_ELEMENT_DESC layoutDesc = { | |
| GLSL_a_span, | |
| 0, | |
| DXGI_FORMAT_R32G32B32A32_UINT, | |
| 0, | |
| 0, | |
| D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, | |
| 1}; | |
| D3D12_RASTERIZER_DESC rasterDesc = {}; | |
| rasterDesc.FillMode = D3D12_FILL_MODE_SOLID; | |
| rasterDesc.CullMode = D3D12_CULL_MODE_BACK; | |
| rasterDesc.FrontCounterClockwise = FALSE; | |
| rasterDesc.DepthBias = 0; | |
| rasterDesc.SlopeScaledDepthBias = 0; | |
| rasterDesc.DepthBiasClamp = 0; | |
| rasterDesc.DepthClipEnable = FALSE; | |
| rasterDesc.MultisampleEnable = FALSE; | |
| rasterDesc.AntialiasedLineEnable = FALSE; | |
| D3D12_BLEND_DESC blendDesc{}; | |
| blendDesc.RenderTarget[0].BlendEnable = FALSE; | |
| blendDesc.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; | |
| blendDesc.RenderTarget[0].DestBlend = D3D12_BLEND_ZERO; | |
| blendDesc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; | |
| blendDesc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; | |
| blendDesc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; | |
| blendDesc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; | |
| blendDesc.RenderTarget[0] | |
| .RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; | |
| D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; | |
| psoDesc.InputLayout = {&layoutDesc, 1}; | |
| psoDesc.pRootSignature = m_rootSignature.Get(); | |
| psoDesc.VS = { | |
| shader::grad::vert::g_main, | |
| std::size(shader::grad::vert::g_main)}; | |
| psoDesc.PS = { | |
| shader::grad::frag::g_main, | |
| std::size(shader::grad::frag::g_main)}; | |
| psoDesc.RasterizerState = rasterDesc; | |
| psoDesc.BlendState = blendDesc; | |
| 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; | |
| VERIFY_OK(device()->CreateGraphicsPipelineState( | |
| &psoDesc, | |
| IID_PPV_ARGS(&m_gradientPipeline))); | |
| } | |
| void D3D12PipelineManager::compileFeatherAtlasPipeline() | |
| { | |
| D3D12_INPUT_ELEMENT_DESC layoutDesc[2]; | |
| layoutDesc[0] = { | |
| GLSL_a_patchVertexData, | |
| 0, | |
| DXGI_FORMAT_R32G32B32A32_FLOAT, | |
| PATCH_VERTEX_DATA_SLOT, | |
| D3D12_APPEND_ALIGNED_ELEMENT, | |
| D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, | |
| 0}; | |
| layoutDesc[1] = { | |
| GLSL_a_mirroredVertexData, | |
| 0, | |
| DXGI_FORMAT_R32G32B32A32_FLOAT, | |
| PATCH_VERTEX_DATA_SLOT, | |
| D3D12_APPEND_ALIGNED_ELEMENT, | |
| D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, | |
| 0}; | |
| D3D12_RASTERIZER_DESC rasterDesc = {}; | |
| rasterDesc.FillMode = D3D12_FILL_MODE_SOLID; | |
| rasterDesc.CullMode = D3D12_CULL_MODE_BACK; | |
| rasterDesc.FrontCounterClockwise = FALSE; | |
| rasterDesc.DepthBias = 0; | |
| rasterDesc.SlopeScaledDepthBias = 0; | |
| rasterDesc.DepthBiasClamp = 0; | |
| rasterDesc.DepthClipEnable = FALSE; | |
| rasterDesc.MultisampleEnable = FALSE; | |
| rasterDesc.AntialiasedLineEnable = FALSE; | |
| D3D12_BLEND_DESC blendDesc{}; | |
| blendDesc.RenderTarget[0].BlendEnable = TRUE; | |
| blendDesc.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; | |
| blendDesc.RenderTarget[0].DestBlend = D3D12_BLEND_ONE; | |
| blendDesc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_MAX; | |
| blendDesc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; | |
| blendDesc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ONE; | |
| blendDesc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_MAX; | |
| blendDesc.RenderTarget[0] | |
| .RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; | |
| D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; | |
| psoDesc.InputLayout = {layoutDesc, 2}; | |
| psoDesc.pRootSignature = m_rootSignature.Get(); | |
| psoDesc.VS = { | |
| shader::atlas::vert::g_main, | |
| std::size(shader::atlas::vert::g_main)}; | |
| psoDesc.PS = { | |
| shader::atlas::stroke::g_main, | |
| std::size(shader::atlas::stroke::g_main)}; | |
| psoDesc.RasterizerState = rasterDesc; | |
| psoDesc.BlendState = blendDesc; | |
| 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_R16_FLOAT; | |
| psoDesc.SampleDesc.Count = 1; | |
| VERIFY_OK(device()->CreateGraphicsPipelineState( | |
| &psoDesc, | |
| IID_PPV_ARGS(&m_featherAtlasStrokePipeline))); | |
| psoDesc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; | |
| psoDesc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; | |
| psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; | |
| psoDesc.PS = { | |
| shader::atlas::fill::g_main, | |
| std::size(shader::atlas::fill::g_main)}; | |
| VERIFY_OK(device()->CreateGraphicsPipelineState( | |
| &psoDesc, | |
| IID_PPV_ARGS(&m_featherAtlasFillPipeline))); | |
| } | |
| } // namespace rive::gpu |