Graphics rendering pipeline for ossia score. More...
Detailed Description
Graphics rendering pipeline for ossia score.
Compile-time detection and dispatch for the QRhi indirect APIs that are newer than this project's Qt floor:
Qt 6.12: QRhi::DrawIndirect / DrawIndirectMulti, QRhiCommandBuffer::drawIndirect / drawIndexedIndirect Qt 6.13: QRhi::DispatchIndirect / DrawIndirectCount, QRhiCommandBuffer::dispatchIndirect, drawIndirectCount / drawIndexedIndirectCount
Detection is by member/enumerator rather than QT_VERSION_CHECK(6, 13, 0): the ossia SDK pins the Qt 6.12 branch and cherry-picks the dev (6.13) indirect changes on top (sdk common/clone-qt.sh: refs/changes/11/738611, 12/738612, 69/761469). On those builds QT_VERSION says 6.12 while the 6.13 API is present, so a version gate would silently compile the features out of the reference builds. A stock 6.12 lacks the API entirely, and CI's floor is 6.4. Member/enumerator detection is right on all three tiers; version macros are right on only two.
SCORE_GFX_SIMULATE_QT612: this compile flag forces every 6.13-era detection below to false even when the API exists, so the "Qt 6.12: multi-draw indirect but no count, no indirect dispatch" tier can be built and run against a newer Qt when no stock 6.12 build is reachable. The runtime equivalents are the SCORE_GFX_NO_GPU_INDIRECT* environment kill switches in RenderList.cpp.
This namespace provides a rendering pipeline for GPU visuals, by the way of a rendering graph. The implementation uses the Qt RHI:
https://www.qt.io/blog/graphics-in-qt-6.0-qrhi-qt-quick-qt-quick-3d
It is mainly designed for rendering a succession of visual effects, not rendering arbitrary 3D. Shaders are written in the usual glslang -> spirv-cross fashion, with GLSL version 450. They are then translated automatically to SPIRV, Metal, GLSL or D3D11 shaders.
The overall design is as follows :
- Elements to render are represented as nodes to a graph: score::gfx::Node
- Input ports are the uniforms and input textures & audio data.
- Output ports generally are just the texture we are rendering to.
- score::gfx::Graph contains all the nodes, and relationships between these nodes.
- For each output sink (a window surface, an NDI or Spout output...), a score::gfx::RenderList is created. It contains all the nodes to render for a given output.
- For each score::gfx::Node, the score::gfx::RenderList creates a score::gfx::NodeRenderer which contains the actual GPU resource handles for the sink.
Given the following graph :
Two render lists are created, the first being
and the second being
Rendering for these two RenderList is entirely independent - they can render at different sizes and potentially use different graphic APIs, e.g. one OpenGL and the other Vulkan. This is also done to enable threaded rendering for each of these.
We provide the most essential nodes for building interesting visual effects:
- A window output node (score::gfx::ScreenNode).
- Shader filters using Interactive Shader Format (https://isf.video).
- Video (score::gfx::VideoNode) and image (score::gfx::ImagesNode) renderers.
- The video renderer tries to do as much of the decoding as possible on the GPU: for instance YUV420, HAP, ... are decoded on the GPU. Otherwises it falls back on libavcodec to guarantee compatibility with a wide range of video formats.
Other plug-ins may provide other useful things, such as NDI I/O or particle effects.
See GfxPlugins for information on how to create your custom nodes, visual effects and video decoders.
Namespaces | |
| namespace | RhiClearBuffer |
| Fill (a sub-range of) a QRhiBuffer with a 4-byte pattern. | |
Classes | |
| struct | ArrayParseResult |
| struct | AudioTexture |
| Data model for audio data being sent to the GPU. More... | |
| struct | AudioTextureUpload |
| struct | BackgroundNode |
| struct | BasicMesh |
| struct | BayerDecoder |
| Demosaics a single-channel colour-filter-array frame into RGB. More... | |
| struct | BayerExternalOESDecoder |
| struct | BGRAComputeEncoder |
| Compute-shader RGBA -> BGRA (NTV2_FBF_ARGB byte order) encoder targeting an external SSBO. More... | |
| struct | BGRAEncoder |
| Cross-backend RGBA -> BGRA byte-order encoder. More... | |
| struct | BitField |
| One channel's placement inside the packed container. More... | |
| struct | BufferCopyRegion |
| Region-based GPU buffer copy for strided / gather patterns. More... | |
| struct | BufferView |
| struct | CameraUBOData |
| struct | CaptureAdjust |
| Sensor-side corrections, in the order the shader applies them. More... | |
| class | CaptureAdjustSlot |
| Cross-thread handoff for CaptureAdjust. More... | |
| struct | CaptureMaterialUBO |
| The capture path's material block: the shared one, plus corrections. More... | |
| struct | ComputeEncoder |
| Base interface for compute-shader RGBA -> AJA-format encoders. More... | |
| struct | CudaFunctions |
| Runtime-loaded CUDA driver-API table. Owns the libcuda handle. More... | |
| class | CustomMesh |
| struct | DecodedImage |
| struct | DefaultShaderMaterial |
| Utility to represent a shader material following score conventions. More... | |
| class | DirectVideoNodeRenderer |
| Renderer for intra-only video codecs with instant seeking. More... | |
| struct | DirectVideoOutputBackend |
Vendor playout backend. Constructed with its vendor-specific settings (video format, pixel format, channel, link, HDR, ...); open() then brings the device up. The node queries geometry/format/planes and drives playout through the registrar + GPU-direct candidates + pacing hooks. More... | |
| class | DirectVideoOutputNode |
| class | DisplayVSyncClock |
| Wraps ScreenNode's swap-chain vsync callback path (clock #1, push). More... | |
| struct | DMACaptureBackend |
| Vendor seam for a DMA capture card's input path. More... | |
| struct | DMACaptureInputNode |
ProcessNode base for DMA capture-card inputs. One Image output port; its renderer is the generic DMACaptureRenderer. More... | |
| struct | DrawCall |
| struct | DummyMesh |
| struct | DXVDecoder |
| Decodes DXV DXT1/DXT5 (Resolume) format to GPU. More... | |
| struct | DXVYCoCgDecoder |
| Decodes DXV YCG6/YG10 (YCoCg) format to GPU. More... | |
| struct | Edge |
| Connection between two score::gfx::Port. More... | |
| struct | EmptyDecoder |
| Default decoder when we do not know what to render. More... | |
| struct | EnvParamsUBO |
| class | ExternalGenlockClock |
| Hardware-genlock render clock (opt-in): a card's output VBI. More... | |
| struct | FallbackBindingPlan |
| struct | FlatScene |
| class | FlattenedSceneFilterNode |
| Per-pass filter on a flattened scene: geometry_spec → geometry_spec. More... | |
| struct | FlattenVisitor |
| struct | FullScreenImageNode |
| struct | GaussianSplatNode |
| Gaussian Splat rendering node. More... | |
| class | GaussianSplatRenderer |
| Renderer for GaussianSplatNode. More... | |
| class | GenericNodeRenderer |
| Generic renderer. More... | |
| struct | geometry |
| struct | geometry_input_port_vis |
| class | GeometryFilterNode |
| Data model for geometry filters. More... | |
| struct | GeometryFilterNodeRenderer |
| class | GPUBufferScatter |
| GPU-side buffer format conversion (scatter). More... | |
| class | GpuResourceRegistry |
| Per-RenderList arena store for GPU-resident scene data. More... | |
| class | GpuTimings |
| Named-bucket GPU timing collector. More... | |
| class | GPUVideoDecoder |
| Processes and renders a video frame on the GPU. More... | |
| struct | GPUVideoEncoder |
| Base class for GPU-side video format conversion (RGBA to YUV). More... | |
| struct | Graph |
| Represents a graph of renderers. More... | |
| struct | GraphicsSSBO |
| One SSBO attached to a graphics pipeline. More... | |
| struct | GraphicsStorageImage |
| One storage image attached to a graphics pipeline. More... | |
| struct | GraphicsStorageResources |
| Aggregate of all graphics-visible storage resources for a node. More... | |
| struct | GraphicsUBO |
| One UBO sourced from an upstream Buffer port (uniform_input). More... | |
| struct | HAPDecoder |
| Base class for HAP ((c) Vidvox) decoding. More... | |
| struct | HAPDefaultDecoder |
| Decodes HAP basic format. More... | |
| struct | HAPMDecoder |
| Decodes HAP-M (HAP + alpha channel) More... | |
| struct | HWTransferDecoder |
| Fallback hardware decoder that transfers HW frames to CPU via av_hwframe_transfer_data(), then delegates to a software GPU decoder. More... | |
| struct | I420Encoder |
| GPU RGBA->I420 encoder (planar 4:2:0). More... | |
| struct | Image |
| Image data and metadata. More... | |
| struct | image |
| struct | ImagesNode |
| A node that renders an image to screen. More... | |
| struct | InstanceKey |
| struct | InstanceKeyHash |
| struct | is_output |
| struct | isf_input_port_count_vis |
| struct | isf_input_port_vis |
| struct | isf_input_size_vis |
| class | ISFNode |
| Data model for Interactive Shader Format filters. More... | |
| class | KmsOutputNode |
| OutputNode scanning out directly through DRM/KMS. More... | |
| struct | KmsOutputSettings |
| struct | LayoutResult |
| struct | MaterialExtensionsGPU |
| struct | MaterialGPU |
| struct | MatrixShape |
| class | MergeGeometriesNode |
| Concatenates up to N upstream geometry_specs into one. More... | |
| struct | Mesh |
| Data model for meshes. More... | |
| struct | MeshBuffers |
| struct | MeshUBO |
| struct | Message |
| struct | ModelCameraUBO |
| UBO shared across all entities shown with the same camera. More... | |
| struct | ModelDisplayNode |
| A node that renders a model to screen. More... | |
| struct | MultiWindowNode |
| class | MultiWindowRenderer |
| struct | no_delay_edges |
| class | Node |
| Root data model for visual nodes. More... | |
| class | NodeModel |
| Common base class for most single-pass, simple nodes. More... | |
| class | NodeRenderer |
| Renderer for a given node. More... | |
| struct | NV12Decoder |
| Decodes NV12 videos. More... | |
| struct | NV12Encoder |
| GPU RGBA->NV12 encoder (semi-planar 4:2:0). More... | |
| struct | NV12ExternalOESDecoder |
| struct | NV16Decoder |
| Decodes NV16 semi-planar 4:2:2 8-bit videos. More... | |
| struct | NV24Decoder |
| Decodes NV24 / NV42 semi-planar 4:4:4 8-bit videos. More... | |
| struct | OutputConfiguration |
| class | OutputNode |
| Base class for sink nodes (QWindow, spout, syphon, NDI output, ...) More... | |
| class | OutputNodeRenderer |
| struct | OutputUBO |
| UBO shared across all entities shown on the same output. More... | |
| struct | P010Decoder |
| Decodes P010 videos. More... | |
| struct | P010Encoder |
| GPU RGBA -> p010le encoder (semi-planar 4:2:0, 10-bit). More... | |
| struct | P016Decoder |
| Decodes P016 videos. More... | |
| struct | P210Decoder |
| Decodes P210 semi-planar 4:2:2 10-bit videos. More... | |
| struct | P410Decoder |
| Decodes P410 semi-planar 4:4:4 10-bit videos. More... | |
| struct | PackedBitfieldLayout |
| struct | PackedBitfieldYUVDecoder |
| struct | PackedBitfieldYUVLayout |
| struct | PackedDecoder |
| struct | PackedRectDecoder |
| struct | PackedRGBEncoder |
| Generic packed-pixel RGB/byte encoder for AJA framebuffer formats. More... | |
| struct | Pass |
| struct | PersistSampler |
| struct | Pipeline |
| Useful abstraction for storing a graphics pipeline and associated resource bindings. More... | |
| struct | PixelFormatInfo |
| struct | PlainMesh |
| A mesh with only position attributes. More... | |
| struct | PlainTriangle |
| A triangle mesh with only positions. More... | |
| struct | PlanarDecoder |
| struct | Port |
| Port of a score::gfx::Node. More... | |
| struct | port_counts |
| struct | port_indices |
| class | PreviewNode |
| class | PreviewRenderer |
| class | PreviewRendererInvertY |
| class | ProcessNode |
| Common base class for nodes that map to score processes. More... | |
| struct | ProcessUBO |
| UBO specific to individual processes / nodes. More... | |
| struct | R210Decoder |
| Decodes 10-bit RGB packed in r210 (DeckLink bmdFormat10BitRGB). More... | |
| struct | RawCameraData |
| struct | RawLightData |
| struct | RawLocalTransform |
| struct | ReadbackTarget |
| struct | RefcountedFrame |
| class | RenderClock |
| Abstract render clock. More... | |
| struct | RenderedCSFNode |
| struct | RenderedFlattenedSceneFilterNode |
| struct | RenderedISFNode |
| struct | RenderedMergeGeometriesNode |
| struct | RenderedRawRasterPipelineNode |
| struct | RenderedSceneFilterNode |
| struct | RenderedScenePreprocessorNode |
| class | RenderList |
| List of nodes to be rendered to an output. More... | |
| struct | RenderState |
| Global state associated to a rendering context. More... | |
| struct | RenderTargetSpecs |
| struct | RGB24Decoder |
| struct | RGB48Decoder |
| struct | RGBA64Decoder |
| struct | Sampler |
| Stores a sampler and the texture currently associated with it. More... | |
| class | SceneFilterNode |
| Tree-level filter on a scene_spec. More... | |
| class | ScenePreprocessorNode |
Bridge from scene_spec (hierarchical, CPU) to geometry_spec (flat, GPU-resident). More... | |
| struct | SceneUBO |
| class | ScopedGpuTimer |
| RAII helper that brackets a named pass region for GPU frame-debug. More... | |
| struct | ScreenNode |
| This node is used for rendering to a score::gfx::Window. More... | |
| struct | ShaderCache |
| Cache of baked QShader instances. More... | |
| struct | ShadowCascadesUBO |
| struct | SimpleRenderedISFNode |
| struct | SimpleRenderedVSANode |
| struct | SkeletonGPU |
| struct | Std430TypeInfo |
| struct | TexgenNode |
| struct | TextNode |
| A node that renders text to screen. More... | |
| class | TextureCache |
| struct | TexturedMesh |
| A mesh with positions and texture coordinates. More... | |
| struct | TexturedQuad |
| A quad mesh with positions and texture coordinates. More... | |
| struct | TexturedTriangle |
| A triangle mesh with positions and texture coordinates. More... | |
| struct | TextureRenderTarget |
| Useful abstraction for storing all the data related to a render target. More... | |
| class | TextureShare |
| GPU-only triple-buffered texture sharing between two QRhi instances in different threads. More... | |
| class | TextureShareBackend |
| Backend-specific implementation interface for GPU-only texture sharing. More... | |
| class | TextureShareBackendBase |
| class | TimerClock |
| Wraps GfxContext's shared wall-timer (clock #2, the default). More... | |
| struct | Timings |
| Messages sent from the execution thread to the rendering thread. More... | |
| class | TripleBufferIndex |
| struct | UYVY422Decoder |
| Decodes UYVY422 video, mostly used for NDI. More... | |
| struct | UYVYComputeEncoder |
| Compute-shader RGBA -> UYVY (2vuy) encoder targeting an external SSBO. More... | |
| struct | UYVYEncoder |
| GPU RGBA->UYVY encoder (packed 4:2:2). More... | |
| struct | V210ComputeEncoder |
| Compute-shader RGBA -> v210 encoder targeting an external SSBO. More... | |
| struct | V210Decoder |
| Decodes 10-bit 4:2:2 YCbCr packed in v210 (SMPTE ST 2110-20 / SDI native). More... | |
| struct | V210Encoder |
| Cross-backend RGBA -> v210 encoder. More... | |
| class | VertexFallbackPool |
| struct | VertexFallbackSpec |
| struct | VideoFrameReader |
| struct | VideoFrameShare |
| struct | VideoMaterialUBO |
| UBO shared across all video objects. More... | |
| class | VideoNode |
| Model for rendering a video. More... | |
| class | VideoNodeBase |
| class | VideoNodeRenderer |
| struct | VUYADecoder |
| Decodes VUYA / VUYX packed 4:4:4 8-bit videos. More... | |
| class | Window |
| A platform window in which the content is going to be rendered. More... | |
| struct | WorldTransformEmit |
| struct | WorldTransformMat4 |
| struct | XV30Decoder |
| Decodes XV30 packed 4:4:4 10-bit videos. More... | |
| struct | Y210Decoder |
| Decodes Y210 packed 4:2:2 10-bit videos. More... | |
| struct | YUV420Decoder |
| Decodes YUV420 videos. More... | |
| struct | YUV420P10Decoder |
| Decodes YUV420 videos. More... | |
| struct | YUV420P12Decoder |
| Decodes YUV420 videos. More... | |
| struct | YUV422Decoder |
| Decodes YUV422 videos. More... | |
| struct | YUV422P10Decoder |
| Decodes YUV422 videos. More... | |
| struct | YUV422P10Encoder |
| GPU RGBA -> yuv422p10le encoder (planar 4:2:2, 10-bit). More... | |
| struct | YUV422P12Decoder |
| Decodes YUV422 videos. More... | |
| struct | YUV440Decoder |
| Decodes YUV440P planar 4:4:0 8-bit videos. More... | |
| struct | YUV444Decoder |
| Decodes YUV444P videos. More... | |
| struct | YUV444P10Decoder |
| Decodes YUV444P10 videos. More... | |
| struct | YUV444P12Decoder |
| Decodes YUV444P12 videos. More... | |
| struct | YUVA420Decoder |
| Decodes YUVA420P videos. More... | |
| struct | YUVA444Decoder |
| Decodes YUVA444P videos. More... | |
| struct | YUVA444P10Decoder |
| Decodes YUVA444P10 videos. More... | |
| struct | YUVA444P12Decoder |
| Decodes YUVA444P12 videos. More... | |
| struct | YUVPlanarEncoder |
| Generic 3-plane planar YCbCr encoder (8 or 10 bit, 4:2:2 or 4:2:0). More... | |
| struct | YUY2Encoder |
| GPU RGBA->YUY2 encoder (packed 4:2:2, NTV2_FBF_8BIT_YCBCR_YUY2). More... | |
| struct | YUYV422Decoder |
| Decodes YUYV422 video. More... | |
Typedefs | |
| using | Vertex = score::gfx::Node * |
| using | GraphImpl = boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS, Vertex, Process::CableType > |
| using | VertexMap = ossia::hash_map< score::gfx::Node *, GraphImpl::vertex_descriptor > |
| using | FunctionMessage = std::function< void(score::gfx::Node &)> |
| using | gfx_input = ossia::variant< ossia::monostate, ossia::value, ossia::audio_vector, ossia::render_target_spec, ossia::transform3d, FunctionMessage, ossia::buffer_spec > |
| using | PassMap = ossia::small_vector< std::pair< Edge *, Pass >, 2 > |
| using | PassOutput = ossia::variant< PersistSampler, TextureRenderTarget > |
Enumerations | |
| enum class | CameraProjectionMode : int { Perspective = 0 , Orthographic = 1 , Fulldome = 2 } |
| enum | ImageMode { Single , Clamped , Tiled , Mirrored } |
| enum | GraphicsApi { Null , OpenGL , Vulkan , D3D11 , Metal , D3D12 } |
| Available graphics APIs to use. | |
| enum class | SharedDeviceMode { Owned , Cached } |
| Who owns the imported Vulkan device behind a RenderState. More... | |
| enum class | BufferCopyBarrier { Auto , None } |
| Copy the contents of one GPU buffer to another. More... | |
| enum class | ReadbackPath { Unsupported , HostCopy , Import } |
| enum | ScaleMode { Original , BlackBars , Fill , Stretch } |
| How to resize a texture to adapt it to a viewport. | |
| enum | PlaybackMode { AutoPlayback , Direct , FrameQueue } |
| How to choose the video renderer. | |
| enum class | Types : int8_t { Empty , Int , Float , Vec2 , Vec3 , Vec4 , Image , Audio , Camera , Geometry , Buffer , Scene } |
| enum class | Flag : uint32_t { GrabsFromSource = (1 << 0) , SamplableDepth = (1 << 1) , TextureArray = (1 << 2) , StorageImage = (1 << 3) , IndirectDraw = (1 << 4) , MultiView = (1 << 5) , DepthOnly = (1 << 6) , UniformBuffer = (1 << 7) , ThreeDimensional = (1 << 8) , Cubemap = (1 << 9) } |
Functions | |
| void | packCameraUBO (CameraUBOData &out, const ossia::camera_component &cam, const QMatrix4x4 &worldTransform, QSize renderSize, float timeSeconds, float aspectOverride) |
| constexpr int64_t | cameraAuxByteSize (std::size_t cameraCount) noexcept |
| void | writeMat4 (float dst[16], const QMatrix4x4 &src) |
| void | setReverseZPerspective (QMatrix4x4 &out, float fovYDeg, float aspect, float nearPlane, float farPlane) |
| void | setReverseZOrthographic (QMatrix4x4 &out, float halfWidth, float halfHeight, float nearPlane, float farPlane) |
| void | applyTo (const CaptureAdjust &a, CaptureMaterialUBO &ubo) noexcept |
Fills the correction half of ubo. The geometry half is the caller's. | |
| void | adjustCaptureReference (const CaptureAdjust &a, float rgb[3]) noexcept |
| The corrections, on the CPU, in the same order the shader applies them. | |
| bool | buftrace_enabled () |
| std::unique_ptr< GPUVideoDecoder > | createGPUVideoDecoder (Video::ImageFormat &format, const std::string &filter={}) |
| Creates the appropriate GPUVideoDecoder for a given pixel format. | |
| bool | nv12ExternalOesUsable (QRhi::Implementation backend) noexcept |
| QByteArray | toExternalSamplerEssl (QByteArray glsl) |
| QString | packedBitfieldFilter (const PackedBitfieldLayout &l) |
| std::unique_ptr< GPUVideoDecoder > | makePackedBitfieldDecoder (const PackedBitfieldLayout &l, Video::ImageFormat &d) |
| Convenience: the decoder for a packed-bitfield format. | |
| std::unique_ptr< GPUVideoDecoder > | makeWireDecoder (score::gfx::interop::VideoPixelFormat fmt, Video::ImageFormat &d) |
| std::unique_ptr< GPUVideoEncoder > | makeWireEncoder (score::gfx::interop::VideoPixelFormat fmt) |
| std::unique_ptr< ComputeEncoder > | makeWireComputeEncoder (score::gfx::interop::VideoPixelFormat fmt) |
| bool | wireComputeSupports (score::gfx::interop::VideoPixelFormat fmt, int width) |
| template<typename Graph_T , typename IO > | |
| void | print_graph (Graph_T &g, IO &stream) |
| std::string | hwCodecName (const char *codec_name, AVHWDeviceType device) |
| Delegates to Video::hwCodecName (score-plugin-gfx wrapper) | |
| bool | codecSupportsHWPixelFormat (AVCodecID codec_id, AVPixelFormat pix_fmt) |
| Delegates to Video::codecSupportsHWPixelFormat (score-plugin-gfx wrapper) | |
| AVPixelFormat | selectHardwareAcceleration (score::gfx::GraphicsApi api, AVCodecID codec_id, QRhi *rhi=nullptr) |
| Picks the best HW accel for the given API/codec, using QRhi for vendor detection. | |
| std::unique_ptr< TextureShareBackend > | createTextureShareBackend (QRhi *producer, QRhi *consumer) |
| int64_t | glslTypeSizeBytes (std::string_view type) noexcept |
| Byte size of a single GLSL primitive type as used for SSBO element strides in this codebase. | |
| int64_t | std430ArrayStride (std::string_view type) noexcept |
std430 array stride for a GLSL primitive type when laid out as T array[] inside a shader storage block. | |
| int64_t | std430LayoutSize (const std::vector< isf::storage_input::layout_field > &layout) noexcept |
Compute the std430 element size of a layout (vector of {name,type} field entries), each field rounded up to 16 bytes per the array-of-struct alignment rule. Used by AUXILIARY blocks and by the user-defined struct lookup in glslTypeSizeBytes. | |
| int64_t | glslTypeSizeBytes (std::string_view type, const isf::descriptor &d) noexcept |
Same as glslTypeSizeBytes, but resolves user-defined types from the descriptor's TYPES section. Falls back to the built-in size table for primitives, then to descriptor.types lookup for struct names. The std430 size of a struct is the sum of its fields' sizes, each rounded up to a 16-byte boundary (matching the array-of-struct alignment rule already used by std430LayoutSize for AUXILIARY blocks). Returns 16 (the lenient default) for unresolved names. | |
| int64_t | std430ArrayStride (std::string_view type, const isf::descriptor &d) noexcept |
Same as std430ArrayStride, but resolves user-defined struct names against the descriptor's TYPES section. Falls back to glslTypeSizeBytes(type, d) for non-vec3 primitives and structs. | |
| QRhiShaderResourceBinding::StageFlags | visibilityToStages (std::string_view visibility) noexcept |
| Decode an isf::storage_input::visibility string to Qt RHI stage flags. | |
| void | collectGraphicsStorageResources (const isf::descriptor &desc, int firstBinding, GraphicsStorageResources &out) |
Walk desc.inputs once and populate out with the storage buffers and images declared by the shader. | |
| void | ensureStorageResources (QRhi &rhi, QRhiResourceUpdateBatch &res, const RenderList &renderer, const isf::descriptor &desc, GraphicsStorageResources &store, QSize renderSize) |
| Create missing buffers and textures. | |
| QVarLengthArray< QRhiShaderResourceBinding, 8 > | buildExtraBindings (const GraphicsStorageResources &store) |
| Produce the QRhiShaderResourceBinding list for the graphics pipeline. | |
| void | bindUpstreamBuffers (RenderList &renderer, const std::vector< Port * > &inputPorts, GraphicsStorageResources &store, QRhiShaderResourceBindings *srb=nullptr) |
| Wire read-only SSBOs to upstream geometry buffers. | |
| void | bindUpstreamImagesFromGeometry (GraphicsStorageResources &store, const ossia::geometry &geometry, QRhiShaderResourceBindings *srb=nullptr) |
| Wire read-only csf_image_input storage images to an upstream geometry's published auxiliary_textures. | |
| void | bindUpstreamBuffersFromGeometry (QRhi &rhi, QRhiResourceUpdateBatch &res, GraphicsStorageResources &store, const ossia::geometry &geometry, QRhiShaderResourceBindings *srb=nullptr) |
| Wire INPUTS storage_input / uniform_input bindings to upstream geometry's published auxiliary_buffers list (name-match). | |
| void | swapPersistentSSBOsState (GraphicsStorageResources &store) |
Swap current/prev pointers in store without touching any SRB. | |
| void | reapplyStorageBindings (const GraphicsStorageResources &store, QRhiShaderResourceBindings &srb) |
| Re-apply the current persistent-storage state to a single SRB. | |
| void | swapPersistentSSBOs (GraphicsStorageResources &store, QRhiShaderResourceBindings &srb) |
| Swap current/prev for all persistent SSBOs and storage images, then update the SRB. | |
| template<typename F > | |
| void | walk_descriptor_inputs (const isf::descriptor &desc, port_counts start, F &&fn) |
| template<typename F > | |
| void | walk_descriptor_inputs (const isf::descriptor &desc, F &&fn) |
| void | noteZeroCountSlotsSkipped (int skipped) noexcept |
| uint64_t | zeroCountSlotsSkippedTotal () noexcept |
| void | drawMeshWithOptionalIndirect (const Mesh &mesh, const MeshBuffers &bufs, QRhiCommandBuffer &cb) noexcept |
| Draw a mesh, using indirect multi-draw when available in MeshBuffers. | |
| bool | bufferSizeIsExpressible (int64_t byte_size) noexcept |
| bool | drawCommandPaints (const ossia::geometry::draw_command &cmd) noexcept |
| Q_DECLARE_OPERATORS_FOR_FLAGS (Mesh::Flags) | |
| void | defaultPassesInit (PassMap &passes, const std::vector< Edge * > &edges, RenderList &renderer, const Mesh &mesh, const QShader &v, const QShader &f, QRhiBuffer *processUBO, QRhiBuffer *matUBO, std::span< const Sampler > samplers, std::span< QRhiShaderResourceBinding > additionalBindings) |
| void | defaultRenderPass (RenderList &renderer, const Mesh &mesh, const MeshBuffers &bufs, QRhiCommandBuffer &cb, Edge &edge, PassMap &passes) |
| void | quadRenderPass (RenderList &renderer, const MeshBuffers &bufs, QRhiCommandBuffer &cb, Edge &edge, PassMap &passes) |
| QRhiGraphicsPipeline::CompareOp | toCompareOp (std::string_view s) noexcept |
| float | depthClearForCompare (QRhiGraphicsPipeline::CompareOp compare) noexcept |
| float | depthClearForState (const isf::pipeline_state &state) noexcept |
| QRhiGraphicsPipeline::CullMode | toCullMode (std::string_view s) noexcept |
| QRhiGraphicsPipeline::FrontFace | toFrontFace (std::string_view s) noexcept |
| QRhiGraphicsPipeline::PolygonMode | toPolygonMode (std::string_view s) noexcept |
| QRhiGraphicsPipeline::Topology | toTopology (std::string_view s) noexcept |
| QRhiGraphicsPipeline::BlendFactor | toBlendFactor (std::string_view s) noexcept |
| QRhiGraphicsPipeline::BlendOp | toBlendOp (std::string_view s) noexcept |
| QRhiGraphicsPipeline::StencilOp | toStencilOp (std::string_view s) noexcept |
| QRhiGraphicsPipeline::ColorMask | toColorMask (std::string_view s) noexcept |
| QRhiGraphicsPipeline::TargetBlend | toTargetBlend (const isf::blend_attachment &b) noexcept |
| QRhiGraphicsPipeline::StencilOpState | toStencilOpState (const isf::stencil_op_state &s) noexcept |
| isf::pipeline_state | mergeState (isf::pipeline_state base, const isf::pipeline_state &over) |
| bool | stateAffectsPipeline (const isf::pipeline_state &s) noexcept |
| void | applyPipelineState (QRhiGraphicsPipeline &pip, const isf::pipeline_state &state, int colorAttachmentCount, bool depthAttachmentAvailable, bool wantsDepthByDefault) noexcept |
| std::shared_ptr< RenderState > | importRenderState (QSize sz, QRhi *rhi) |
| std::vector< Sampler > | initAudioTextures (RenderList &renderer, std::list< AudioTexture > &textures) |
| QRhiTexture::Format | imageTextureFormat (const QRhi &rhi) noexcept |
| Texture format to use for images uploaded from the CPU. | |
| QImage | adaptImageFormat (QImage img, QRhiTexture::Format fmt) |
| Put an image in the byte order imageTextureFormat() asks for. | |
| std::shared_ptr< RenderState > | createRenderState (GraphicsApi graphicsApi, QSize sz, QWindow *window, SharedDeviceMode deviceMode=SharedDeviceMode::Owned) |
| QRhiBuffer::UsageFlags | compatibleBufferUsage (QRhi &rhi, QRhiBuffer::UsageFlags usage) noexcept |
| Drop a StorageBuffer usage the backend cannot actually honour. | |
| bool | indirectDrawBreaksMultiView (GraphicsApi api, int multiViewCount) noexcept |
| Whether a GPU indirect draw silently loses multiview on this backend. | |
| bool | drawIndirectCountUsable (GraphicsApi api, int multiViewCount) noexcept |
| Whether the GPU-count draw path (drawIndexedIndirectCount) is usable. | |
| bool | viewIndexNeedsPassIndexFallback (GraphicsApi api, const QShaderVersion &version, int multiViewCount) noexcept |
| Whether MULTIVIEW must be emulated with one pass per view. | |
| bool | clearBufferMetal (QRhi &, QRhiCommandBuffer &, QRhiBuffer *, quint32, quint32, quint32) |
| void | copyBufferMetal (QRhi &, QRhiCommandBuffer &, QRhiBuffer *, QRhiBuffer *, int, int, int) |
| void | copyBufferRegionsMetal (QRhi &, QRhiCommandBuffer &, QRhiBuffer *, QRhiBuffer *, const BufferCopyRegion *, int) |
| void | insertComputeBarrier (QRhi &rhi, QRhiCommandBuffer &cb) |
| Insert a compute-to-compute memory barrier. | |
| bool | dispatchComputeLayeredImages (QRhi &rhi, QRhiCommandBuffer &cb, QRhiShaderResourceBindings &srb, int x, int y, int z) |
| Dispatch a compute pass, working around Qt's non-layered bind of layered (3D / cube / array) storage images on the OpenGL backend. | |
| void | beginBufferCopyBarrier (QRhi &rhi, QRhiCommandBuffer &cb) |
| void | endBufferCopyBarrier (QRhi &rhi, QRhiCommandBuffer &cb) |
| void | copyBuffer (QRhi &rhi, QRhiCommandBuffer &cb, QRhiBuffer *src, QRhiBuffer *dst, int size, int srcOffset, int dstOffset, BufferCopyBarrier barrier) |
| void | copyBufferRegions (QRhi &rhi, QRhiCommandBuffer &cb, QRhiBuffer *src, QRhiBuffer *dst, const BufferCopyRegion *regions, int count, BufferCopyBarrier barrier) |
| template<typename R = QRhi> | |
| bool | rhiSupportsDrawIndirectCount (R &rhi) noexcept |
| template<typename R = QRhi> | |
| bool | rhiSupportsDispatchIndirect (R &rhi) noexcept |
| QRhi::DispatchIndirect reported by the device; same convention as above. | |
| template<typename CB = QRhiCommandBuffer> | |
| bool | drawIndirectCountCompat (CB &cb, bool indexed, QRhiBuffer *indirectBuffer, quint32 indirectOffset, QRhiBuffer *countBuffer, quint32 countOffset, quint32 maxDrawCount, quint32 stride) noexcept |
| template<typename CB = QRhiCommandBuffer> | |
| bool | dispatchIndirectCompat (CB &cb, QRhiBuffer *argsBuffer, quint32 argsOffset) noexcept |
| ReadbackPath | readbackPath (QRhi &rhi) noexcept |
| bool | canReadbackToHostMemory (QRhi &rhi) noexcept |
| std::size_t | readbackHostMemoryAlignment (QRhi &rhi) noexcept |
| bool | readbackTextureSupported (QRhi &rhi, QRhiTexture &src, std::size_t dstBytes) noexcept |
| ReadbackTarget * | createReadbackTarget (QRhi &rhi, void *dst, std::size_t bytes) |
| void | destroyReadbackTarget (ReadbackTarget *t) |
| std::size_t | readbackDstOffsetAlignment (QRhi &rhi, QRhiTexture &src) noexcept |
| bool | readbackTextureToHost (QRhi &rhi, QRhiCommandBuffer &cb, QRhiTexture &src, ReadbackTarget &t, std::size_t dstOffset) |
| bool | finishReadbackToHost (QRhi &rhi, ReadbackTarget &t) |
| std::shared_ptr< ossia::geometry > | primitiveToGeometry (const ossia::mesh_primitive &prim) |
| MaterialGPU | packMaterial (const ossia::material_component &mc) |
| MaterialExtensionsGPU | packMaterialExtensions (const ossia::material_component &mc) |
| void | flattenScene (const ossia::scene_spec &scene, FlatScene &out, float aspectRatio) |
| constexpr uint32_t | tex_ref_none () |
| constexpr uint32_t | tex_ref_static (uint32_t bucket, uint32_t layer) |
| constexpr uint32_t | tex_ref_dynamic (uint32_t slot) |
| QByteArray | hlslIntrinsicCollision (const QByteArray &raw) noexcept |
| The identifier a shader declares that collides with an HLSL intrinsic. | |
| std::optional< DecodedImage > | decodeImageFromPath (const QString &path) |
| std::optional< DecodedImage > | decodeImageFromMemory (const QByteArray &bytes, const QString &mime_hint) |
| QRhiTexture * | uploadImageToTexture (QRhi &rhi, QRhiResourceUpdateBatch &batch, const QImage &img, bool srgb, const QString &debug_name) |
| QRhiTexture * | loadAndUploadTexture (QRhi &rhi, QRhiResourceUpdateBatch &batch, const QString &path, bool srgb) |
| QRhiTexture * | loadAndUploadTexture (QRhi &rhi, QRhiResourceUpdateBatch &batch, const QByteArray &bytes, const QString &mime_hint, bool srgb) |
| TextureRenderTarget | createRenderTarget (const RenderState &state, QRhiTexture *tex, int samples, bool depth, bool samplableDepth=false) |
| Create a render target from a texture. | |
| TextureRenderTarget | createRenderTarget (const RenderState &state, QRhiTexture::Format fmt, QSize sz, int samples, bool depth, bool samplableDepth=false, QRhiTexture::Flags flags={}) |
| Create a render target from a texture format and size. | |
| TextureRenderTarget | createRenderTarget (const RenderState &state, std::span< QRhiTexture *const > colorTextures, QRhiTexture *depthTexture, int samples) |
| Create a render target with multiple color attachments and optional sampleable depth. | |
| void | replaceBuffer (std::vector< QRhiShaderResourceBinding > &tmp, int binding, QRhiBuffer *newBuffer) |
| void | replaceSampler (std::vector< QRhiShaderResourceBinding > &tmp, int binding, QRhiSampler *newSampler) |
| void | replaceTexture (std::vector< QRhiShaderResourceBinding > &tmp, int binding, QRhiTexture *newTexture) |
| void | replaceBuffer (QRhiShaderResourceBindings &srb, int binding, QRhiBuffer *newBuffer) |
| void | replaceSampler (QRhiShaderResourceBindings &srb, int binding, QRhiSampler *newSampler) |
| void | replaceTexture (QRhiShaderResourceBindings &srb, int binding, QRhiTexture *newTexture) |
| void | replaceSampler (QRhiShaderResourceBindings &, QRhiSampler *oldSampler, QRhiSampler *newSampler) |
| Replace a sampler. | |
| void | replaceSamplerAndTexture (QRhiShaderResourceBindings &, QRhiSampler *oldSampler, QRhiSampler *newSampler, QRhiTexture *newTexture) |
| Replace both sampler and texture in a SRC. | |
| void | replaceTexture (QRhiShaderResourceBindings &, QRhiSampler *sampler, QRhiTexture *newTexture) |
| Replace the texture currently bound to a sampler. | |
| void | replaceTexture (QRhiShaderResourceBindings &srb, QRhiTexture *old_tex, QRhiTexture *new_tex) |
| Replace a texture by another in a set of bindings. | |
| const ossia::geometry::attribute * | findGeometryAttribute (const ossia::geometry &geom, std::string_view name, std::string_view semantic_key) |
| Match a (name, semantic) request to an upstream geometry attribute. | |
| bool | remapPipelineVertexInputs (QRhiGraphicsPipeline &pip, const QShader &vertexShader, const ossia::geometry &geom) |
| Remap a pipeline's vertex input layout using semantic matching. | |
| bool | remapPipelineVertexInputs (QRhiGraphicsPipeline &pip, const QShader &vertexShader, const ossia::geometry &geom, const isf::descriptor &desc) |
| Same as above, but honours explicit SEMANTIC on each VERTEX_INPUTS entry from the isf descriptor when present. | |
| bool | remapPipelineVertexInputs (QRhiGraphicsPipeline &pip, const QShader &vertexShader, const ossia::geometry &geom, const isf::descriptor &desc, QRhi &rhi, VertexFallbackPool &pool, QRhiResourceUpdateBatch &batch, FallbackBindingPlan &outPlan) |
| Fallback-aware overload: the strict-matching behaviour of the overload above, extended so VERTEX_INPUTS entries with "REQUIRED": false silently resolve to a shared identity buffer from the pool when their semantic is absent upstream. | |
| Pipeline | buildPipeline (const RenderList &renderer, const Mesh &mesh, const QShader &vertexS, const QShader &fragmentS, const TextureRenderTarget &rt, QRhiShaderResourceBindings *srb) |
| Lower-level buildPipeline variant: bring your own SRB. | |
| QRhiShaderResourceBindings * | createDefaultBindings (const RenderList &renderer, const TextureRenderTarget &rt, QRhiBuffer *processUBO, QRhiBuffer *materialUBO, std::span< const Sampler > samplers, std::span< QRhiShaderResourceBinding > additionalBindings={}) |
| Create bindings following the score conventions for shaders and materials. | |
| Pipeline | buildPipeline (const RenderList &renderer, const Mesh &mesh, const QShader &vertexS, const QShader &fragmentS, const TextureRenderTarget &rt, QRhiBuffer *processUBO, QRhiBuffer *materialUBO, std::span< const Sampler > samplers, std::span< QRhiShaderResourceBinding > additionalBindings={}) |
| Create a render pipeline following the score conventions for shaders and materials. | |
| Pipeline | buildPipelineWithState (const RenderList &renderer, const Mesh &mesh, const QShader &vertexS, const QShader &fragmentS, const TextureRenderTarget &rt, QRhiBuffer *processUBO, QRhiBuffer *materialUBO, std::span< const Sampler > samplers, std::span< QRhiShaderResourceBinding > extraBindings, const isf::pipeline_state &state, int multiViewCount=0, bool useShadingRate=false) |
| Create a render pipeline applying pipeline_state from an ISF descriptor. | |
| std::pair< QShader, QShader > | makeShaders (const RenderState &v, QString vert, QString frag, int multiViewCount=0) |
| Get a pair of compiled vertex / fragment shaders from GLSL 4.5 sources. | |
| QShader | makeCompute (const RenderState &v, QString compt) |
| Compile a compute shader. | |
| QSize | resizeTextureSize (QSize img, int min, int max) noexcept |
| Resize the size of a texture to fit within GPU limits. | |
| QImage | resizeTexture (const QImage &img, int min, int max) noexcept |
| Resize a texture to fit within GPU limits. | |
| QSizeF | computeScaleForMeshSizing (score::gfx::ScaleMode mode, QSizeF viewport, QSizeF texture) |
| Compute the scale to apply to a texture so that it fits in a GL viewport. | |
| QSizeF | computeScaleForTexcoordSizing (score::gfx::ScaleMode mode, QSizeF viewport, QSizeF texture) |
| Compute the scale to apply to a texture rendered to a quad the size of viewport. | |
| std::vector< Sampler > | initInputSamplers (const score::gfx::Node &node, RenderList &renderer, const std::vector< Port * > &ports, const isf::descriptor *desc) |
| TextureRenderTarget | createDepthOnlyRenderTarget (const RenderState &state, QSize sz, int samples, bool samplableDepth=true, QRhiTexture::Format depthFmt=QRhiTexture::D32F) |
| Create a depth-only render target. | |
| TextureRenderTarget | createLayeredRenderTarget (const RenderState &state, QRhiTexture *colorTextureArray, int renderLayer, QRhiTexture *depthTexture, int samples) |
| Create a render target that targets a single layer of a texture array. | |
| TextureRenderTarget | createMultiViewRenderTarget (const RenderState &state, QRhiTexture *colorTextureArray, int multiViewCount, QRhiTexture *depthTextureArray, int samples) |
| Create a multiview render target (single RT drawing N views at once). | |
| TextureRenderTarget | createDepthOnlyRenderTarget (const RenderState &state, QRhiTexture *externalDepthTexture, int samples, bool samplableDepth=true) |
| Create a depth-only render target around an EXTERNAL depth texture. | |
| TextureRenderTarget | createLayeredRenderTarget (const RenderState &state, std::span< QRhiTexture *const > colorTextures, int renderLayer, QRhiTexture *depthTexture, int samples) |
| Multi-attachment (MRT) layered render target. | |
| TextureRenderTarget | createMultiViewRenderTarget (const RenderState &state, std::span< QRhiTexture *const > colorTextures, int multiViewCount, QRhiTexture *depthTextureArray, int samples) |
| Multi-attachment (MRT) multiview render target. | |
| QRhiTexture::Format | parseOutputFormat (const std::string &fmt, QRhiTexture::Format fallback) noexcept |
| Map an ISF/CSF FORMAT string to a QRhiTexture::Format. | |
| QRhiSampler * | makeSampler (QRhi &rhi, const isf::sampler_config &cfg) |
| Build a QRhiSampler from an isf::sampler_config. | |
| QRhiBuffer::Type | bufferTypeFor (QRhiBuffer::UsageFlags usage, QRhiBuffer::Type nonDynamic=QRhiBuffer::Immutable) noexcept |
| The QRhi buffer type a usage flag is allowed to be created with. | |
| void | copyMatrix (const QMatrix4x4 &mat, float *ptr) noexcept |
| void | copyMatrix (const QMatrix3x3 &mat, float *ptr) noexcept |
| void | updateDynamicBufferWithStoredData (QRhiResourceUpdateBatch *ub, QRhiBuffer *buf, int offset, int64_t bytesize, const char *data) |
| Schedule a Dynamic buffer update when we can guarantee the buffer outlives the frame. | |
| void | updateDynamicBufferWithStoredData (QRhiResourceUpdateBatch *ub, QRhiBuffer *buf, int offset, QByteArray b) |
| void | uploadStaticBufferWithStoredData (QRhiResourceUpdateBatch *ub, QRhiBuffer *buf, int offset, int64_t bytesize, const char *data) |
| Schedule a Static buffer update when we can guarantee the buffer outlives the frame. | |
| void | uploadStaticBufferWithStoredData (QRhiResourceUpdateBatch *ub, QRhiBuffer *buf, int offset, QByteArray b) |
| std::optional< VertexFallbackSpec > | resolveVertexFallback (ossia::attribute_semantic semantic, std::string_view decl_type, const std::vector< double > &user_default) noexcept |
| uint64_t | hashVertexFallback (const VertexFallbackSpec &spec) noexcept |
| uint64_t | hash_qstring (const QString &s) noexcept |
| uint64_t | hash_qbytearray (const QByteArray &b) noexcept |
Variables | |
| constexpr bool | rhiHasDrawIndirectCount = detail::rhi_has_indirect_count<QRhiCommandBuffer>::value |
| constexpr bool | rhiHasDispatchIndirect = detail::rhi_has_dispatch_indirect<QRhiCommandBuffer>::value |
Enumeration Type Documentation
◆ BufferCopyBarrier
|
strong |
Copy the contents of one GPU buffer to another.
Performs a GPU-side buffer-to-buffer copy of size bytes from src + srcOffset to dst + dstOffset. Both buffers must already be created and large enough to satisfy the requested region. Must be called between beginExternal() and endExternal().
The source and destination buffers must NOT overlap (the copy is unordered when src == dst).
Per-backend behaviour:
- Vulkan : vkCmdCopyBuffer
- OpenGL : glCopyBufferSubData
- D3D12 : CopyBufferRegion
- D3D11 : CopySubresourceRegion (offsets supported via D3D11_BOX)
- Metal : MTLBlitCommandEncoder copyFromBuffer
◆ ReadbackPath
|
strong |
How the backend reaches caller-owned memory. Vulkan and D3D12 import the pages and the GPU writes them directly; OpenGL and D3D11 have no import and must land in a driver buffer that is then memcpy'd, with the fence wait falling on the render thread.
This is a performance property, not a capability one, and it decides the default: against plain QRhi staging, Import is cheaper per frame, while HostCopy is a small regression.
| Enumerator | |
|---|---|
| HostCopy | driver buffer + memcpy + fence on the render thread |
| Import | caller pages imported; GPU writes them directly |
◆ SharedDeviceMode
|
strong |
Who owns the imported Vulkan device behind a RenderState.
Owned is the default: one vkCreateDevice per RenderState, one vkDestroyDevice when it goes away. Cached takes a reference on the process-wide SharedVulkanDeviceCache instead, so a create/destroy pair is not paid every time the state is rebuilt. Only the shader previews opt in — they are rebuilt on every selection, whereas outputs and encoders are long-lived.
Function Documentation
◆ adaptImageFormat()
| SCORE_PLUGIN_GFX_EXPORT QImage score::gfx::adaptImageFormat | ( | QImage | img, |
| QRhiTexture::Format | fmt | ||
| ) |
Put an image in the byte order imageTextureFormat() asks for.
QRhi uploads a QImage's bits as-is, so the two have to agree. Premultiplication is preserved: only the channel order changes.
◆ adjustCaptureReference()
|
inlinenoexcept |
The corrections, on the CPU, in the same order the shader applies them.
This is the specification: CaptureAdjustGLSL.hpp implements it on the GPU, and a test can only check the two agree if one of them is checkable. Keep them in step – a divergence shows up as the picture changing when the capture rung changes, which looks like a capture bug.
◆ beginBufferCopyBarrier()
| void score::gfx::beginBufferCopyBarrier | ( | QRhi & | rhi, |
| QRhiCommandBuffer & | cb | ||
| ) |
Emit the {compute,transfer}→transfer barrier that must precede a buffer copy. The compute half orders the copy after a compute shader that just produced the data; the transfer half orders it after the staging copies QRhi emits for a QRhiResourceUpdateBatch submitted earlier in the same command buffer. That second half is not optional: these helpers record through beginExternal(), so QRhi's own per-buffer barrier tracking never sees them and cannot order them against its own uploads. Pair with endBufferCopyBarrier(). No-op on backends that handle the transition implicitly (D3D11, Metal).
◆ bindUpstreamBuffers()
| void score::gfx::bindUpstreamBuffers | ( | RenderList & | renderer, |
| const std::vector< Port * > & | inputPorts, | ||
| GraphicsStorageResources & | store, | ||
| QRhiShaderResourceBindings * | srb = nullptr |
||
| ) |
Wire read-only SSBOs to upstream geometry buffers.
When a storage_input is declared as read_only AND the upstream node supplies a buffer on the port, the binding is rewired to point at the upstream's QRhiBuffer (no allocation needed). Called each frame to track port changes.
◆ bindUpstreamBuffersFromGeometry()
| void score::gfx::bindUpstreamBuffersFromGeometry | ( | QRhi & | rhi, |
| QRhiResourceUpdateBatch & | res, | ||
| GraphicsStorageResources & | store, | ||
| const ossia::geometry & | geometry, | ||
| QRhiShaderResourceBindings * | srb = nullptr |
||
| ) |
Wire INPUTS storage_input / uniform_input bindings to upstream geometry's published auxiliary_buffers list (name-match).
SSBO/UBO sibling of bindUpstreamImagesFromGeometry. ScenePreprocessor publishes scene_lights / world_transforms / per_draws / scene_materials / scene_counts / scene_light_indices / camera UBO / env UBO as named aux buffers travelling along the geometry edge — flattened-scene shaders (classic_pbr et al.) declare matching INPUTS storage_input/uniform_input blocks and the runtime resolves them by name.
Without this, INPUTS storage_input/uniform_input that go through the m_storage path stay at the 16-byte placeholder allocated by ensureStorageResources for owned SSBOs — vertices read a zero PerDraw, multiply by a zero world_transforms matrix, and collapse to origin. (Indirect-draw storage_inputs are skipped — they have no shader binding.)
For CPU-backed aux buffers a fresh QRhiBuffer is allocated and the data uploaded immediately into res; the entry's owned flag is updated so release() cleans up correctly. For GPU-backed aux buffers we just adopt the upstream handle (owned=false).
Patches the SRB in-place when a target SRB is provided; idempotent so multi-SRB callers can invoke once per SRB without re-running the lookup.
◆ bindUpstreamImagesFromGeometry()
| void score::gfx::bindUpstreamImagesFromGeometry | ( | GraphicsStorageResources & | store, |
| const ossia::geometry & | geometry, | ||
| QRhiShaderResourceBindings * | srb = nullptr |
||
| ) |
Wire read-only csf_image_input storage images to an upstream geometry's published auxiliary_textures.
Symmetric to bindUpstreamBuffers for SSBOs: when a csf_image_input is declared read_only AND the upstream geometry publishes a storage image with the same name (e.g. an upstream CSF wrote to it via image_input with write_only/read_write), this swaps the storage image's texture pointer to the upstream's published handle and frees the auto-allocated placeholder we created in ensureStorageResources.
Without this, every read_only csf_image_input INPUTS in a downstream RawRaster / ISF stage reads from its OWN zero-initialised texture instead of the upstream's actual contents — silently broken.
Called per-frame; idempotent. When srb is non-null, patches the binding in-place via replaceTexture. The lookup is purely by name match against geometry.auxiliary_textures (the same name-match pattern used by RawRaster's m_auxTextureSamplers rebind path).
◆ bufferTypeFor()
|
inlinenoexcept |
The QRhi buffer type a usage flag is allowed to be created with.
A uniform buffer must be Dynamic on D3D11: QD3D11Buffer::create() rejects anything else outright ("UniformBuffer must always be combined with Dynamic
on D3D11"), leaves its ID3D11Buffer null and returns false. OpenGL ES says the same thing through the NonDynamicUniformBuffers feature. Every UBO this plugin allocates from a literal is already Dynamic; this exists for the few places that pick the usage at RUNTIME from a shader's declaration, where an unconditional Immutable would silently give a null-backed buffer on D3D11 and bind it anyway. Everything else keeps nonDynamic, which for a storage or vertex buffer is what it wants (and Dynamic + StorageBuffer is itself rejected).
◆ buildExtraBindings()
| QVarLengthArray< QRhiShaderResourceBinding, 8 > score::gfx::buildExtraBindings | ( | const GraphicsStorageResources & | store | ) |
Produce the QRhiShaderResourceBinding list for the graphics pipeline.
Call this from inside addOutputPass() after buildPipeline() has been set up. The result is concatenated with the standard bindings (sampler, material, processUBO, etc.) via the additionalBindings span in createDefaultBindings.
◆ buildPipeline()
| Pipeline score::gfx::buildPipeline | ( | const RenderList & | renderer, |
| const Mesh & | mesh, | ||
| const QShader & | vertexS, | ||
| const QShader & | fragmentS, | ||
| const TextureRenderTarget & | rt, | ||
| QRhiShaderResourceBindings * | srb | ||
| ) |
Lower-level buildPipeline variant: bring your own SRB.
The returned Pipeline::srb equals the srb you passed — no ownership transfer. Useful when the caller wants to share a pipeline across multiple Passes that each have their own SRB (layout-compatible with this one per QRhi contract); the pipeline's stored SRB is only used for layout extraction at create() time and never dereferenced at draw time.
◆ buildPipelineWithState()
| Pipeline score::gfx::buildPipelineWithState | ( | const RenderList & | renderer, |
| const Mesh & | mesh, | ||
| const QShader & | vertexS, | ||
| const QShader & | fragmentS, | ||
| const TextureRenderTarget & | rt, | ||
| QRhiBuffer * | processUBO, | ||
| QRhiBuffer * | materialUBO, | ||
| std::span< const Sampler > | samplers, | ||
| std::span< QRhiShaderResourceBinding > | extraBindings, | ||
| const isf::pipeline_state & | state, | ||
| int | multiViewCount = 0, |
||
| bool | useShadingRate = false |
||
| ) |
Create a render pipeline applying pipeline_state from an ISF descriptor.
Depth test / depth write and the anyNodeRequiresDepth() fallback are all driven by state here. When state is empty (all fields nullopt), behaviour matches the variant above exactly.
extraBindings is typically the result of IsfBindingsBuilder::buildExtraBindings(). multiViewCount >= 2 activates multiview rendering (requires state.caps.multiview).
When useShadingRate == true AND renderer.state.caps.variableRateShading == true, the pipeline gets QRhiGraphicsPipeline::UsesShadingRate. The shading-rate texture / per-draw rate itself is supplied elsewhere (via the render-target attachment's setShadingRateMap or the command- buffer's setShadingRate). Presets opt in; silent no-op when the backend doesn't support VRS.
◆ canReadbackToHostMemory()
|
noexcept |
Whether this backend can read a texture straight into caller-owned host memory. Stable per QRhi; query once.
◆ collectGraphicsStorageResources()
| void score::gfx::collectGraphicsStorageResources | ( | const isf::descriptor & | desc, |
| int | firstBinding, | ||
| GraphicsStorageResources & | out | ||
| ) |
Walk desc.inputs once and populate out with the storage buffers and images declared by the shader.
Bindings are assigned sequentially starting from firstBinding. Persistent SSBOs consume TWO consecutive bindings.
No GPU resources are allocated here — call ensureStorageResources() later.
◆ compatibleBufferUsage()
|
inlinenoexcept |
Drop a StorageBuffer usage the backend cannot actually honour.
QGles2Buffer::create() picks the target it will run every glBufferData / glBufferSubData through from the usage flags, and StorageBuffer outranks both VertexBuffer and IndirectBuffer (qrhigles2.cpp):
targetForDataOps = GL_ARRAY_BUFFER; if (usage & IndexBuffer) targetForDataOps = GL_ELEMENT_ARRAY_BUFFER; else if (usage & StorageBuffer) targetForDataOps = GL_SHADER_STORAGE_BUFFER; else if (usage & IndirectBuffer) targetForDataOps = GL_DRAW_INDIRECT_BUFFER;
GL_SHADER_STORAGE_BUFFER arrived with GL 4.3 / GLES 3.1. macOS caps desktop OpenGL at 4.1, so on Apple's driver the bind and every upload against that target raise GL_INVALID_ENUM and do nothing: glGenBuffers still hands out a name, create() still returns true, and the object never receives a data store or a single byte of content. Nothing in score can see that, because the only thing it can check – create() – succeeded.
The damage lands at draw time and looks like two unrelated bugs:
- bound as a VERTEX buffer, Apple's GL walks the storeless object and faults inside gleRunVertexSubmitImmediate, EXC_BAD_ACCESS at the attribute's own byte offset (0x0, 0x40, ...);
- bound as an INDIRECT buffer, the draw reads zeros and rasterises nothing, silently and with an empty error string. Mesa and the NVIDIA driver expose 4.6, so the same code is correct on Linux/OpenGL, which is what makes this look platform-specific rather than backend-specific.
A buffer a shader genuinely reads as an SSBO cannot be rescued here: below 4.3 there are no SSBOs to read. So a StorageBuffer-ONLY usage is returned untouched and fails honestly. This only demotes buffers whose storage role is an ADDITIONAL one alongside a vertex / index / indirect role the backend can still serve – the mesh arena, the geometry VBOs, the MDI command buffer.
◆ createDepthOnlyRenderTarget() [1/2]
| TextureRenderTarget score::gfx::createDepthOnlyRenderTarget | ( | const RenderState & | state, |
| QRhiTexture * | externalDepthTexture, | ||
| int | samples, | ||
| bool | samplableDepth = true |
||
| ) |
Create a depth-only render target around an EXTERNAL depth texture.
Builds the RT around externalDepthTexture (caller-allocated, already created) instead of allocating its own. Use this when the depth texture is named/owned by the node (so textureForOutput() can return it).
externalDepthTexture may be a plain 2D depth texture or a TextureArray (layered / shadow-cascade depth). It becomes ret.depthTexture and is released with the RT.
◆ createDepthOnlyRenderTarget() [2/2]
| TextureRenderTarget score::gfx::createDepthOnlyRenderTarget | ( | const RenderState & | state, |
| QSize | sz, | ||
| int | samples, | ||
| bool | samplableDepth = true, |
||
| QRhiTexture::Format | depthFmt = QRhiTexture::D32F |
||
| ) |
Create a depth-only render target.
Allocates a sampleable depth texture (samplableDepth=true) or a depth renderbuffer. If the backend rejects color-less render targets, a 1x1 RGBA8 dummy color texture is allocated and stored in the TextureRenderTarget::dummyColorTexture field (owned by the RT).
The resulting TextureRenderTarget has:
depthTextureordepthRenderBufferset (never both)texture== nullptr (depth-only semantics)dummyColorTexturemay be non-null on some backends
◆ createGPUVideoDecoder()
| SCORE_PLUGIN_GFX_EXPORT std::unique_ptr< GPUVideoDecoder > score::gfx::createGPUVideoDecoder | ( | Video::ImageFormat & | format, |
| const std::string & | filter = {} |
||
| ) |
Creates the appropriate GPUVideoDecoder for a given pixel format.
This factory centralizes the pixel-format-to-decoder switch statement that was previously duplicated in VideoNodeRenderer and DirectVideoNodeRenderer.
- Parameters
-
format The video frame format (width, height, pixel_format) filter Optional GLSL filter expression to apply in the fragment shader
- Returns
- A unique_ptr to the created decoder, or nullptr if format is unhandled
◆ createLayeredRenderTarget() [1/2]
| TextureRenderTarget score::gfx::createLayeredRenderTarget | ( | const RenderState & | state, |
| QRhiTexture * | colorTextureArray, | ||
| int | renderLayer, | ||
| QRhiTexture * | depthTexture, | ||
| int | samples | ||
| ) |
Create a render target that targets a single layer of a texture array.
colorTextureArray must have been created with QRhiTexture::TextureArray and at least (renderLayer + 1) layers.
depthTexture may be a regular 2D texture (shared across layers) or nullptr to skip depth (use a renderbuffer instead via createRenderTarget overloads).
◆ createLayeredRenderTarget() [2/2]
| TextureRenderTarget score::gfx::createLayeredRenderTarget | ( | const RenderState & | state, |
| std::span< QRhiTexture *const > | colorTextures, | ||
| int | renderLayer, | ||
| QRhiTexture * | depthTexture, | ||
| int | samples | ||
| ) |
Multi-attachment (MRT) layered render target.
Same as the single-texture overload but attaches ALL colorTextures to the render pass (locations 0..N-1), so the number of attachments matches the pipeline blend-state count (rt.colorAttachmentCount()). Each layered color texture renders to renderLayer; plain 2D textures keep layer 0.
◆ createMultiViewRenderTarget() [1/2]
| TextureRenderTarget score::gfx::createMultiViewRenderTarget | ( | const RenderState & | state, |
| QRhiTexture * | colorTextureArray, | ||
| int | multiViewCount, | ||
| QRhiTexture * | depthTextureArray, | ||
| int | samples | ||
| ) |
Create a multiview render target (single RT drawing N views at once).
colorTextureArray must be a TextureArray with at least multiViewCount layers. depthTextureArray may be nullptr for no depth, or a TextureArray with the same layer count.
Requires state.caps.multiview == true — caller must check.
◆ createMultiViewRenderTarget() [2/2]
| TextureRenderTarget score::gfx::createMultiViewRenderTarget | ( | const RenderState & | state, |
| std::span< QRhiTexture *const > | colorTextures, | ||
| int | multiViewCount, | ||
| QRhiTexture * | depthTextureArray, | ||
| int | samples | ||
| ) |
Multi-attachment (MRT) multiview render target.
Same as the single-texture overload but attaches ALL colorTextures (each a TextureArray with >= multiViewCount layers) with per-attachment multiview, so attachments == pipeline blend targets. Requires state.caps.multiview == true.
◆ createReadbackTarget()
| ReadbackTarget * score::gfx::createReadbackTarget | ( | QRhi & | rhi, |
| void * | dst, | ||
| std::size_t | bytes | ||
| ) |
Registers dst (alignment-aligned, bytes rounded up to the alignment and owned by the caller) once. Returns nullptr when the backend or the specific allocation cannot be wrapped — fall back to QRhi::readBackTexture. Never call per frame.
◆ createRenderTarget() [1/2]
| TextureRenderTarget score::gfx::createRenderTarget | ( | const RenderState & | state, |
| QRhiTexture::Format | fmt, | ||
| QSize | sz, | ||
| int | samples, | ||
| bool | depth, | ||
| bool | samplableDepth = false, |
||
| QRhiTexture::Flags | flags = {} |
||
| ) |
Create a render target from a texture format and size.
This function will also create a texture.
◆ createRenderTarget() [2/2]
| TextureRenderTarget score::gfx::createRenderTarget | ( | const RenderState & | state, |
| std::span< QRhiTexture *const > | colorTextures, | ||
| QRhiTexture * | depthTexture, | ||
| int | samples | ||
| ) |
Create a render target with multiple color attachments and optional sampleable depth.
- Parameters
-
colorTextures All color attachment textures (must be non-empty, first becomes primary) depthTexture Sampleable depth texture, or nullptr for no depth / renderbuffer depth
◆ dispatchComputeLayeredImages()
| bool score::gfx::dispatchComputeLayeredImages | ( | QRhi & | rhi, |
| QRhiCommandBuffer & | cb, | ||
| QRhiShaderResourceBindings & | srb, | ||
| int | x, | ||
| int | y, | ||
| int | z | ||
| ) |
Dispatch a compute pass, working around Qt's non-layered bind of layered (3D / cube / array) storage images on the OpenGL backend.
Qt's QRhi OpenGL backend (before the fix that shipped in 6.10) binds a 3D, cube-map OR 2D-texture-array storage image with glBindImageTexture(..., layered=GL_FALSE, layer=0). That exposes only slice/face/layer 0 to the shader, so an imageStore into an image3D, imageCube or image2DArray writes ONLY that single slice and every other slice/face/layer stays uninitialised — the classic "layered compute output
reads back black on GL, fine on Vulkan" symptom. (Fixed upstream in Qt 6.10: qrhigles2.cpp binds layered = CubeMap || ThreeDimensional || TextureArray; there this call is a harmless identical re-bind.)
When srb contains at least one layered storage-image binding (3D, cube or array) AND the backend is OpenGL, this issues the dispatch itself: it flushes QRhi's own (mis-)binding via beginExternal(), re-binds each layered storage image LAYERED (all slices/faces/layers writable), dispatches, emits a full memory barrier, and returns true. The predicate is kept EXACTLY in sync with qrhigles2's own layered determination.
Returns false when the caller should issue the ordinary QRhi dispatch (non-OpenGL backend, or no layered storage image in the SRB) — every other backend and the 2D image path are left completely untouched.
Must be called inside an active compute pass, after setComputePipeline() and setShaderResources().
◆ dispatchIndirectCompat()
|
inlinenoexcept |
dispatchIndirect when the API exists; returns false when it does not, so the caller can fall back to a CPU worst-case dispatch.
◆ drawIndirectCountCompat()
|
inlinenoexcept |
drawIndirectCount / drawIndexedIndirectCount when the API exists; returns false (recorded nothing) when it does not, so the caller can fall back to the plain multi-draw / CPU rungs.
◆ drawIndirectCountUsable()
|
inlinenoexcept |
Whether the GPU-count draw path (drawIndexedIndirectCount) is usable.
Ask this WITH caps.drawIndirectCount at every site that selects the count rung; QRhi's feature flag alone is not enough:
- Metal implements the count draw exclusively through Indirect Command Buffers, which demand things the flag cannot express: the graphics pipeline must be created with QRhiGraphicsPipeline::UsesIndirectDraws (qrhimetal.mm icbUnavailableReason — the draw is SKIPPED with a warning otherwise), the pipeline may not sample textures at all, and the pass is interrupted/restarted so a transient DepthStencil renderbuffer loses its contents unless created with NoTransientBacking. None of those three are plumbed yet, so the count rung is declined on Metal wholesale; the plain multi-draw rung there stays correct because producers zero dead command slots. Lift this once the three prerequisites land together.
- The multiview-on-Metal indirect break applies to the count entry points exactly as it does to drawIndexedIndirect (they share the encoder path), so the existing predicate is folded in.
◆ drawMeshWithOptionalIndirect()
|
noexcept |
Draw a mesh, using indirect multi-draw when available in MeshBuffers.
When bufs.useIndirectDraw is true (and Qt >= 6.12), dispatches to cb.drawIndexedIndirect / cb.drawIndirect with the offset/count/stride stored in bufs. Otherwise falls back to the mesh's standard draw().
This is the main draw entry point for ISF / RawRaster / Scene renderers so that they can transparently support multi-draw indirect just by wiring an indirect buffer into MeshBuffers.
◆ endBufferCopyBarrier()
| void score::gfx::endBufferCopyBarrier | ( | QRhi & | rhi, |
| QRhiCommandBuffer & | cb | ||
| ) |
Emit the transfer→compute barrier after a batch of buffer copies so downstream compute/graphics reads observe the writes.
◆ ensureStorageResources()
| void score::gfx::ensureStorageResources | ( | QRhi & | rhi, |
| QRhiResourceUpdateBatch & | res, | ||
| const RenderList & | renderer, | ||
| const isf::descriptor & | desc, | ||
| GraphicsStorageResources & | store, | ||
| QSize | renderSize | ||
| ) |
Create missing buffers and textures.
Safe to call every frame — idempotent. Resizes buffers when they don't match the current layout. For persistent SSBOs, allocates both the current and prev buffers. For indirect-draw buffers, adds the IndirectBuffer usage flag.
◆ findGeometryAttribute()
| const ossia::geometry::attribute * score::gfx::findGeometryAttribute | ( | const ossia::geometry & | geom, |
| std::string_view | name, | ||
| std::string_view | semantic_key | ||
| ) |
Match a (name, semantic) request to an upstream geometry attribute.
Three-stage cascade shared by all shader modes:
- semantic_key → name_to_semantic → if known, geom.find(semantic).
- Custom-attribute lookup by
name. - display_name == name fallback (so { NAME: "position", SEMANTIC: "custom" } still finds the real position attribute when no custom one shadows it). If
semantic_keyis empty,nameis used as the semantic key.
◆ finishReadbackToHost()
| bool score::gfx::finishReadbackToHost | ( | QRhi & | rhi, |
| ReadbackTarget & | dst | ||
| ) |
Makes the last recorded readback's bytes visible in dst. On the GL paths this waits on a fence (and memcpys from the PBO when not pinned); on D3D11 it maps the staging texture and copies it into dst; on Vulkan/D3D12 it is a no-op — the caller's frame synchronization suffices. Must be called after every recorded readback, on every backend.
◆ glslTypeSizeBytes()
|
noexcept |
Byte size of a single GLSL primitive type as used for SSBO element strides in this codebase.
Coverage: scalars (float, int, uint, bool), vectors (vec[234], ivec[234], uvec[234]), and matrices (mat2, mat3, mat4). Sampler / image / opaque types are not covered (return the fallback). Returns 16 as a fallback for unknown / unsupported types.
Conventions:
- Returns 12 for
vec3/ivec3/uvec3(the bare component size). Consumers that need std140 / std430 array stride must align to 16 themselves; for that case preferstd430ArrayStridebelow, which encapsulates the rule and keeps the two domains (bare type size vs. stride-in-SSBO) from drifting at call sites. ISF auxiliary layouts continue to align at the field level viastd430LayoutSize. mat2is reported as 16 (twovec2columns, no per-column padding).mat3is reported as 48 (threevec4-padded columns); this matches both std140 and std430 column-major layout format3in storage blocks.mat4is reported as 64.
This is the single source of truth for GLSL type → element size in score-plugin-gfx; do not introduce private copies.
The vertex-attribute format → byte-size mapping (ossia::geometry::attribute enum) is a different domain – binary attribute formats, not GLSL type strings – and lives in its own helper inside RenderedCSFNode.cpp.
◆ hlslIntrinsicCollision()
|
noexcept |
The identifier a shader declares that collides with an HLSL intrinsic.
The identifier a shader declares that collides with an HLSL intrinsic, or empty if there is none.
Empty when there is none. Only the names SPIRV-Cross actually emits when translating a GLSL builtin are listed: an identifier is only dangerous because the generated HLSL will also contain a CALL by that name. A wider list – every HLSL intrinsic in existence – would reject shaders that compile perfectly well, which is worse than the bug.
SPIRV-Cross rewrites GLSL builtins to their HLSL spellings but leaves the user's variable names alone, so float frac becomes float frac = frac(...) and only Direct3D rejects it. Checked before baking for D3D so the author is told which name to change, instead of getting an fxc error about a line that looks correct.
◆ imageTextureFormat()
|
noexcept |
Texture format to use for images uploaded from the CPU.
BGRA8 where the backend has it, RGBA8 otherwise. QRhiGles2 asks for GL_BGRA whenever a texture is BGRA8, and WebGL has no such format at all, so uploading one there is an INVALID_ENUM and the image never appears.
◆ indirectDrawBreaksMultiView()
|
inlinenoexcept |
Whether a GPU indirect draw silently loses multiview on this backend.
Qt's Metal backend derives gl_ViewIndex by multiplying the instance count and binding a view-mask buffer, and it does BOTH only in adjustForMultiViewDraw() – which qrhimetal.mm calls from draw() (:2499) and drawIndexed() (:2539) and from NEITHER drawIndirect() nor drawIndexedIndirect(). An indirect draw of a multiview shader therefore renders every amplified view into layer 0, with no qWarning: the warning inside adjustForMultiViewDraw cannot fire because the function is never entered. Metal's validation layer names it outright:
Vertex Function(main0): missing Buffer binding at index 24 for spvViewMask[0].
The CPU fallback in CustomMesh::drawSingleMesh issues one drawIndexed per command, which DOES go through adjustForMultiViewDraw, so declining GPU indirect restores correct multiview at the cost of N draw calls.
Scoped to Metal deliberately: Vulkan and D3D12 implement multiview in the render pass / view instancing, so the indirect entry points inherit it.
◆ insertComputeBarrier()
| void score::gfx::insertComputeBarrier | ( | QRhi & | rhi, |
| QRhiCommandBuffer & | cb | ||
| ) |
Insert a compute-to-compute memory barrier.
Ensures that SSBO writes from a preceding compute dispatch are visible to the next compute dispatch. Must be called between QRhiCommandBuffer::beginExternal() and endExternal(), inside a compute pass.
Per-backend behaviour:
- Vulkan : vkCmdPipelineBarrier (COMPUTE → COMPUTE, SHADER_WRITE → SHADER_READ|WRITE)
- OpenGL : glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT)
- D3D12 : UAV barrier on all resources
- D3D11 : no-op (implicit within device context)
- Metal : no-op (implicit between command encoders; each QRhi compute pass uses a separate MTLComputeCommandEncoder)
◆ makeCompute()
| QShader score::gfx::makeCompute | ( | const RenderState & | v, |
| QString | compt | ||
| ) |
Compile a compute shader.
Note: this function will throw if the shader is invalid.
◆ makeSampler()
| QRhiSampler * score::gfx::makeSampler | ( | QRhi & | rhi, |
| const isf::sampler_config & | cfg | ||
| ) |
Build a QRhiSampler from an isf::sampler_config.
Fields left empty/unset in the config are filled with ossia defaults (linear filtering, no mipmaps, clamp-to-edge). When the config sets a comparison op other than "never", the returned sampler is a shadow comparison sampler.
The returned sampler is created (create() was called) and has no name assigned; callers should setName() before or after create() as needed. Ownership follows the standard QRhi convention — callers delete it.
◆ makeShaders()
| std::pair< QShader, QShader > score::gfx::makeShaders | ( | const RenderState & | v, |
| QString | vert, | ||
| QString | frag, | ||
| int | multiViewCount = 0 |
||
| ) |
Get a pair of compiled vertex / fragment shaders from GLSL 4.5 sources.
Note: this function will throw if a shader is invalid.
◆ makeWireComputeEncoder()
|
inline |
Compute-shader encoder for the GPU-direct path (writes into an imported buffer). Only the formats with a compute variant are supported.
◆ makeWireEncoder()
|
inline |
Render (fragment-shader) encoder producing fmt's exact on-wire bytes. Returns nullptr when no GPU encoder exists for fmt.
◆ nv12ExternalOesUsable()
|
noexcept |
True when this decoder can be used at all: a GLES backend whose driver advertises the external-image extension. Checked before the backend commits to it, because an external texture the driver will not sample is worse than the CPU path.
◆ packedBitfieldFilter()
|
inline |
Builds the PackedDecoder filter that unpacks l.
The word is rebuilt from the sampled bytes, then each field is shifted, masked and normalised by its own maximum, so a 5-bit channel spans the full 0..1 range rather than topping out at 31/255.
◆ parseOutputFormat()
|
noexcept |
Map an ISF/CSF FORMAT string to a QRhiTexture::Format.
Supported: rgba8, bgra8, r8, rg8, r16, rg16, r16f, r32f, rgba16f, rgba32f, d16, d24, d24s8, d32f. Unknown / empty strings fall back to the caller's default. Lookup is case-insensitive.
◆ readbackDstOffsetAlignment()
|
noexcept |
Required alignment of the dstOffset passed to readbackTextureToHost for a texture of this format (0 = backend unsupported). D3D12: 512 (D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); Vulkan: the texel size and 4; OpenGL: 4; D3D11: 1.
◆ readbackHostMemoryAlignment()
|
noexcept |
Required alignment of dst and granularity of bytes for createReadbackTarget, or 0 when unsupported. Vulkan: the device's minImportedHostPointerAlignment (4096 on NVIDIA). OpenGL: 4096 (GL_AMD_pinned_memory page requirement; the PBO fallback ignores it). D3D12: 65536 (VirtualAlloc allocation granularity). D3D11: 1 (dst is only ever a memcpy destination).
◆ readbackTextureSupported()
|
noexcept |
Whether readbackTextureToHost can handle this texture on this backend (format/size/pitch constraints), for a target of dstBytes — the same checks the record path performs, without recording anything. Lets a caller decide at init time instead of discovering a permanent per-frame failure.
◆ readbackTextureToHost()
| bool score::gfx::readbackTextureToHost | ( | QRhi & | rhi, |
| QRhiCommandBuffer & | cb, | ||
| QRhiTexture & | src, | ||
| ReadbackTarget & | dst, | ||
| std::size_t | dstOffset = 0 |
||
| ) |
Records the texture→(dst + dstOffset) copy on cb. Must be called outside a render pass. The copy is tightly packed rows, texture storage order (top-left origin in score). dstOffset lets the copy land on an interior pointer of the registered region (device SDKs often hand out offset frame pointers inside their allocations); it must satisfy readbackDstOffsetAlignment and fit in the target. Returns false when the texture's format/size/offset cannot target this backend's path — nothing is recorded, fall back.
◆ reapplyStorageBindings()
| void score::gfx::reapplyStorageBindings | ( | const GraphicsStorageResources & | store, |
| QRhiShaderResourceBindings & | srb | ||
| ) |
Re-apply the current persistent-storage state to a single SRB.
Pairs with swapPersistentSSBOsState: after swapping store once, call this on every SRB that references the persistent bindings so the descriptor set matches the new pointers. Uses replaceBuffer's updateResources() fast path — no srb->create() rebuild — to avoid thrashing the SRB pool slot every frame on a static scene.
◆ remapPipelineVertexInputs() [1/2]
| bool score::gfx::remapPipelineVertexInputs | ( | QRhiGraphicsPipeline & | pip, |
| const QShader & | vertexShader, | ||
| const ossia::geometry & | geom | ||
| ) |
Remap a pipeline's vertex input layout using semantic matching.
Reflects the compiled vertex shader to find each in variable, then for each one runs findGeometryAttribute(name, name) — useful when no isf descriptor is around (legacy callers). Returns true on success, false if a required attribute can't be matched.
◆ remapPipelineVertexInputs() [2/2]
| bool score::gfx::remapPipelineVertexInputs | ( | QRhiGraphicsPipeline & | pip, |
| const QShader & | vertexShader, | ||
| const ossia::geometry & | geom, | ||
| const isf::descriptor & | desc, | ||
| QRhi & | rhi, | ||
| VertexFallbackPool & | pool, | ||
| QRhiResourceUpdateBatch & | batch, | ||
| FallbackBindingPlan & | outPlan | ||
| ) |
Fallback-aware overload: the strict-matching behaviour of the overload above, extended so VERTEX_INPUTS entries with "REQUIRED": false silently resolve to a shared identity buffer from the pool when their semantic is absent upstream.
pool per-RenderList shared fallback buffer pool batch any uploads for freshly-allocated fallback buffers are recorded here outPlan filled with the bindings the caller must merge into the draw's QRhiCommandBuffer::VertexInput array. Cleared on entry.
Returns false (and logs which input failed) if:
- a REQUIRED=true input has no matching upstream attribute, OR
- a REQUIRED=false input has no matching upstream attribute AND the declared GLSL TYPE is unsupported (mat4 / integer / sampler) OR the resolved semantic is not in the whitelist AND no explicit DEFAULT was supplied.
◆ rhiSupportsDrawIndirectCount()
|
inlinenoexcept |
QRhi::DrawIndirectCount reported by the device, false when the API does not exist in this Qt (or SCORE_GFX_SIMULATE_QT612 pretends it does not).
◆ std430ArrayStride()
|
noexcept |
std430 array stride for a GLSL primitive type when laid out as T array[] inside a shader storage block.
Differs from glslTypeSizeBytes only for vec3-shaped vectors: per the std430 layout rules, an array of vec3 (or ivec3 / uvec3) keeps the element's vec4-aligned base alignment, so the per-element stride is 16 bytes — the trailing 4 bytes are padding the GPU does not write but consumer reads must skip. For scalars, vec2, vec4 and matrices, the stride equals the bare type size, so this returns glslTypeSizeBytes(type) unchanged.
Use this — never glslTypeSizeBytes — when sizing a CSF SoA output SSBO buffer or setting a downstream vertex binding stride that mirrors the SSBO's std430 layout: mixing the two corrupts vec3 data silently.
◆ swapPersistentSSBOs()
| void score::gfx::swapPersistentSSBOs | ( | GraphicsStorageResources & | store, |
| QRhiShaderResourceBindings & | srb | ||
| ) |
Swap current/prev for all persistent SSBOs and storage images, then update the SRB.
Call at end of frame, after all passes have run. Symmetric to the existing texture ping-pong in RenderedISFNode (the swap(passes, altPasses) at RenderedISFNode.cpp:1094).
◆ swapPersistentSSBOsState()
| void score::gfx::swapPersistentSSBOsState | ( | GraphicsStorageResources & | store | ) |
Swap current/prev pointers in store without touching any SRB.
Used by multi-pass / multi-SRB renderers that need to apply the same post-swap state to many descriptor sets: call this once per frame, then call reapplyStorageBindings on every affected SRB. Calling swapPersistentSSBOs per-SRB would double-swap and cancel out.
◆ toExternalSamplerEssl()
| QByteArray score::gfx::toExternalSamplerEssl | ( | QByteArray | glsl | ) |
Turn the baked GLSL into the external-sampler variant.
Two surgical edits on the baked text rather than a reconstruction: the baked shader already carries exactly the uniform blocks, locations and precision qualifiers that QRhiGles2 will wire from the reflection, and rebuilding that by hand gets it wrong: the blocks end } renderer; rather than };, so slicing to the first }; produces malformed source and a compile error at token "renderer".
Rewrite baked GLSL so its sampler2D tex becomes samplerExternalOES tex, adding the required extension pragma. Shared because every external-image decoder needs exactly this edit: glslang rejects the external type, so the shader is baked with sampler2D and only the GL text is swapped. Returns an empty array when the input does not look like baked GLSL.
◆ viewIndexNeedsPassIndexFallback()
|
inlinenoexcept |
Whether MULTIVIEW must be emulated with one pass per view.
gl_ViewIndex becomes HLSL SV_ViewID, which requires shader model 6.1. D3D11 is pinned to SM 5.0 for good, and D3D12 drops to 5.0 whenever dxcompiler.dll is absent, so on those targets a multiview shader cannot be COMPILED at all:
Vertex shader error: View Index input is only supported in VS and PS 6.1 or higher.
ShaderCache answers this by rewriting gl_ViewIndex to the PASSINDEX uniform, which the N-pass path stamps per invocation.
That rewrite and the choice of render path MUST be driven by the same predicate. When they disagree the failure is silent and looks like a rasterizer bug: a D3D12 shader lowered to read PASSINDEX while QRhi still reports MultiView gets ONE amplified draw in which passIndex never advances past 0 – and all six cube faces come back carrying face 0's colour. Ask this function in both places.
◆ visibilityToStages()
|
noexcept |
Decode an isf::storage_input::visibility string to Qt RHI stage flags.
"fragment" → FragmentStage "vertex" → VertexStage "vertex+fragment" / "both" / "graphics" → Vertex | Fragment "compute" → ComputeStage "none" → 0
◆ wireComputeSupports()
|
inline |
Whether the compute encoder can handle (fmt, width): v210 needs width % 6, UYVY needs width % 2, BGRA is unconstrained.