# Juliet\src\Graphics\D3D12\D3D12GraphicsPipeline ## Source Files - Header: `Juliet\src\Graphics\D3D12\D3D12GraphicsPipeline.h` - Source: `Juliet\src\Graphics\D3D12\D3D12GraphicsPipeline.cpp` ## AI Description Based on the code snippet provided, here is a summary of its functionality and analysis: ### **Purpose** The primary function defined at the bottom (`GraphicsPipeline::Create`) creates a DirectX 12 Graphics Pipeline State Object (PSO) from high-level rendering states. It acts as an adapter layer, converting Juliet's internal data structures into `D3D12_GRAPHICS_PIPELINE_STATE_DESC` and calling the hardware-accelerated `ID3D12Device::CreateGraphicsPipelineState`. ### **Key Workflow Steps** 1. **Initialization**: Retrieves D3D12 driver handles (vertex/fragment shaders). Initializes a local structure (`psoDesc`) with shader bytecode pointers and lengths. 2. **Input Conversion**: Converts `VertexInputState` into `INPUT_ELEMENT_DESCs` if attributes exist, defining the layout of vertex data. 3. **Topology ? Primitive Setup**: Sets the primitive topology (e.g., lines, triangles) using mapping tables (`JulietToD3D12_...`). 4. **Helper Calls**: Relies on three conversion helper functions to populate state descriptors: * `ConvertRasterizerState`: Handles culling, fill mode, etc. * `ConvertBlendState`: Maps blend factors and write masks for color/alpha channels (supports multiple render targets). * `ConvertDepthStencilState`: Converts depth comparison and stencil operations (front/back faces). 5. **Multisample Handling**: Calculates sample mask, count, and quality level based on the creation info (`createInfo.MultisampleState`). It sets a standard multi-sampling quality pattern if not manually specified. 6. **Format Conversion**: Translates Juliet's color formats into `D3D12` compatible RTV/DSV formats (handling both depth textures and color render targets). 7. **Root Signature Association**: Uses the driver's pre-compiled "Bindless" root signature to allow flexible state variables in shaders without explicit parameter declaration in vertex structures. 8. **Hardware Creation (`CreateGraphicsPipelineState`)**: The core call that returns an `ID3D12PipelineState`. This is where the actual pipeline logic lives on the GPU side. 9. **Error Handling**: Checks for hardware failures and logs errors to `dual-OS::Log`, cleaning up allocated resources upon failure. ### **Code Specifics ? Observations** * **Mapping Strategy**: Extensive use of helper arrays like `JulietToD3D12_BlendFactor` and mapping functions like `ToUnderlying`. This suggests a design pattern where high-level enums are mapped to D3D's underlying integer/enum values (often 0-7 or specific constants) via tables, allowing the same logic to run across different rendering backends. * **Independent Blending**: The code checks if there is more than one color target (`if (i ? 0)`), enabling "independent blend enable." This allows two separate sprites to be drawn on top of each other with independent blending settings, which requires the `D3D12_BLEND_ENABLE_INDEPENDENT_blend` flag in D3D12. * **Sample Quality Heuristic**: The sample quality is set to a default standard if it exceeds single-sample count; otherwise, custom values might be required by specific games (like older PS/DS titles). * **Unfinished Line**: The snippet cuts off mid-line at the very end (`pipeline-?PrimitiveType = createInfo.`), indicating incomplete logic for copying other pipeline properties or error states. ### **Potential Improvements / Questions** 1. **Caching**: Does this code handle GPU caching (using `D3DKBCache`)? Currently, it looks like every time a new PSO is requested, the hardware creates a fresh one unless explicitly told otherwise via `CachedPSO`. For modern games with many unique draw calls, explicit caching logic would improve performance. 2. **Static Pipeline States**: Modern D3D12 workflows often move state creation to a separate static pipeline class or function (static PSOs) rather than creating them on-the-fly per scene update if the states don't change between frames. This code seems to be doing dynamic creation, which is simpler but potentially less performant for complex scenes with many variations of blending/rasterization settings per frame in older engines like Juliet's era. ## Symbols ### Namespace `Juliet::D3D12` #### Classes, Structs & Unions - `struct D3D12GraphicsRootSignature` - `struct D3D12GraphicsPipeline` #### Functions & Methods - `extern GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr driver, const GraphicsPipelineCreateInfo& createInfo)` - `extern void DestroyGraphicsPipeline(NonNullPtr driver, NonNullPtr graphicsPipeline)` - `extern bool UpdateGraphicsPipelineShaders(NonNullPtr driver, NonNullPtr graphicsPipeline, Shader* optional_vertexShader, Shader* optional_fragmentShader)` ### Namespace `Juliet::D3D12::Internal` #### Functions & Methods - `extern void ReleaseGraphicsPipeline(NonNullPtr d3d12GraphicsPipeline)`