// luma.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors import type {Device} from '../device'; import type {PrimitiveTopology, RenderPipelineParameters} from '../types/parameters'; import type {ShaderLayout, Bindings, BindingsByGroup} from '../types/shader-layout'; import type {BufferLayout} from '../types/buffer-layout'; import type { TextureFormatColor, TextureFormatDepthStencil } from '@luma.gl/core/shadertypes/texture-types/texture-formats'; import type {Shader} from './shader'; import type {SharedRenderPipeline} from './shared-render-pipeline'; import type {RenderPass} from './render-pass'; import {Resource, ResourceProps} from './resource'; import {VertexArray} from './vertex-array'; import {TransformFeedback} from './transform-feedback'; export type RenderPipelineProps = ResourceProps & { // Shaders and shader layout /** Compiled vertex shader */ vs?: Shader | null; /** Name of vertex shader stage main function (defaults to 'main'). WGSL only */ vertexEntryPoint?: string; // /** Constant values to apply to compiled vertex shader. Do not require re-compilation. (WGSL only) */ vsConstants?: Record; // WGSL only /** Compiled fragment shader */ fs?: Shader | null; /** Name of fragment shader stage main function (defaults to 'main'). WGSL only */ fragmentEntryPoint?: string; // WGSL only /** Constant values to apply to compiled fragment shader. Do not require re-compilation. (WGSL only) */ fsConstants?: Record; /** Describes the attributes and bindings exposed by the pipeline shader(s). */ shaderLayout?: ShaderLayout | null; /** Describes the buffers accepted by this pipeline and how they are mapped to shader attributes. */ bufferLayout?: BufferLayout[]; // Record /** Determines how vertices are read from the 'vertex' attributes */ topology?: PrimitiveTopology; // color attachment information (needed on WebGPU) /** Color attachments expected by this pipeline. Defaults to [device.preferredColorFormat]. Array needs not be contiguous. */ colorAttachmentFormats?: (TextureFormatColor | null)[]; /** Depth attachment expected by this pipeline. Defaults to device.preferredDepthFormat, if depthWriteEnables parameter is set */ depthStencilAttachmentFormat?: TextureFormatDepthStencil; /** Parameters that are controlled by pipeline */ parameters?: RenderPipelineParameters; /** Transform feedback varyings captured when linking a WebGL render pipeline. WebGL only. */ varyings?: string[]; /** Transform feedback buffer mode used when linking a WebGL render pipeline. WebGL only. */ bufferMode?: number; /** Some applications intentionally supply unused attributes and bindings, and want to disable warnings */ disableWarnings?: boolean; /** Internal hook for backend-specific shared pipeline implementations. */ _sharedRenderPipeline?: SharedRenderPipeline; // Dynamic bindings (TODO - pipelines should be immutable, move to RenderPass) /** Buffers, Textures, Samplers for the shader bindings */ bindings?: Bindings; /** Bindings grouped by bind-group index */ bindGroups?: BindingsByGroup; }; /** * A compiled and linked shader program */ export abstract class RenderPipeline extends Resource { override get [Symbol.toStringTag](): string { return 'RenderPipeline'; } abstract readonly vs: Shader; abstract readonly fs: Shader | null; /** The merged layout */ shaderLayout: ShaderLayout; /** Buffer map describing buffer interleaving etc */ readonly bufferLayout: BufferLayout[]; /** The linking status of the pipeline. 'pending' if linking is asynchronous, and on production */ linkStatus: 'pending' | 'success' | 'error' = 'pending'; /** The hash of the pipeline */ hash: string = ''; /** Optional shared backend implementation */ sharedRenderPipeline: SharedRenderPipeline | null = null; /** Whether shader or pipeline compilation/linking is still in progress */ get isPending(): boolean { return ( this.linkStatus === 'pending' || this.vs.compilationStatus === 'pending' || this.fs?.compilationStatus === 'pending' ); } /** Whether shader or pipeline compilation/linking has failed */ get isErrored(): boolean { return ( this.linkStatus === 'error' || this.vs.compilationStatus === 'error' || this.fs?.compilationStatus === 'error' ); } constructor(device: Device, props: RenderPipelineProps) { super(device, props, RenderPipeline.defaultProps); this.shaderLayout = this.props.shaderLayout!; this.bufferLayout = this.props.bufferLayout || []; this.sharedRenderPipeline = this.props._sharedRenderPipeline || null; } /** Draw call. Returns false if the draw call was aborted (due to resources still initializing) */ abstract draw(options: { /** Render pass to draw into (targeting screen or framebuffer) */ renderPass?: RenderPass; /** Parameters to be set during draw call. Note that most parameters can only be overridden in WebGL. */ parameters?: RenderPipelineParameters; /** Topology. Note can only be overridden in WebGL. */ topology?: PrimitiveTopology; /** vertex attributes */ vertexArray: VertexArray; /** Use instanced rendering? */ isInstanced?: boolean; /** Number of "rows" in 'instance' buffers */ instanceCount?: number; /** Number of "rows" in 'vertex' buffers */ vertexCount?: number; /** Number of "rows" in index buffer */ indexCount?: number; /** First vertex to draw from */ firstVertex?: number; /** First index to draw from */ firstIndex?: number; /** First instance to draw from */ firstInstance?: number; baseVertex?: number; /** Transform feedback. WebGL only. */ transformFeedback?: TransformFeedback; /** Bindings applied for this draw (textures, samplers, uniform buffers) */ bindings?: Bindings; /** Bindings grouped by bind-group index */ bindGroups?: BindingsByGroup; /** Optional stable cache keys for backend bind-group reuse */ _bindGroupCacheKeys?: Partial>; /** WebGL-only uniforms */ uniforms?: Record; }): boolean; static override defaultProps: Required = { ...Resource.defaultProps, vs: null, vertexEntryPoint: 'vertexMain', vsConstants: {}, fs: null, fragmentEntryPoint: 'fragmentMain', fsConstants: {}, shaderLayout: null, bufferLayout: [], topology: 'triangle-list', colorAttachmentFormats: undefined!, depthStencilAttachmentFormat: undefined!, parameters: {}, varyings: undefined!, bufferMode: undefined!, disableWarnings: false, _sharedRenderPipeline: undefined!, bindings: undefined!, bindGroups: undefined! }; }