[Feat] (MG_State, MG_Impl): give program pipelines their object and their state

Every program pipeline entry point was an export stub, and the stub macro's
`return (type)1` made glIsProgramPipeline answer GL_TRUE for anything - including
the names glGenProgramPipelines had never written. All four
direct_state_access.program_pipelines cases failed.

ProgramPipelineObject holds what GL 4.6 core 7.4 says a pipeline is: a program
reference per shader stage, the active program glProgramUniform* addresses, a
validate status and an info log. Its validate status starts false, unlike
ProgramObject's, because a pipeline that has never been validated must report
GL_VALIDATE_STATUS as 0.

The name rules follow the shape queries and transform feedbacks already use, and
which the CTS checks first: glGenProgramPipelines only RESERVES a name and
glIsProgramPipeline answers GL_FALSE for it; the object appears on first bind, or
immediately from glCreateProgramPipelines. Map membership is object existence -
a pipeline, unlike a transform feedback, has no stateful default object zero, so
no everBound flag is needed.

glGet(GL_PROGRAM_PIPELINE_BINDING) reports the real binding now instead of a
hardcoded zero whose comment said the entry points were stubbed.

This is the state half only. program_pipelines_functional needs mixed-stage
rendering - a vertex-only and a fragment-only program drawn together - and stays
failing; glCreateShaderProgramv is deliberately left stubbed until that lands, so
nothing can half-work in between.

Takes program_pipelines_creation, _defaults and _errors from failing to passing
on both backends.
This commit is contained in:
BZLZHH
2026-08-05 05:43:13 -04:00
parent 1f1a331a44
commit 300b458132
8 changed files with 385 additions and 11 deletions
+19
View File
@@ -14,6 +14,7 @@
#include "MG_State/GLState/RenderbufferState/RenderbufferState.h"
#include "RenderState/RenderState.h"
#include "ProgramState/ProgramState.h"
#include "ProgramState/ProgramPipelineObject.h"
#include "SamplerState/SamplerState.h"
#include "TextureState/TextureState.h"
#include "FramebufferState/FramebufferState.h"
@@ -137,6 +138,19 @@ namespace MobileGL {
void UseProgram(Uint program);
const SharedPtr<ProgramObject>& GetCurrentProgram();
// Program pipeline (GL_ARB_separate_shader_objects, GL 4.6 core 7.4). Like queries
// and transform feedbacks, glGenProgramPipelines only RESERVES a name - the object
// appears on first bind - while glCreateProgramPipelines makes it immediately.
void GenProgramPipelineNames(Uint number, Vector<Uint>& pipelines);
void CreateProgramPipelineObject(Uint index);
Bool ValidateProgramPipelineName(Uint index) const;
Bool IsProgramPipelineObject(Uint index) const;
void BindProgramPipelineObject(Uint index);
void MarkProgramPipelineForDeletion(Uint index);
const SharedPtr<ProgramPipelineObject>& GetProgramPipelineObject(Uint index) const;
Uint GetBoundProgramPipelineName() const { return m_boundProgramPipeline; }
const SharedPtr<ProgramPipelineObject>& GetBoundProgramPipeline() const;
// RenderState
Uint GetRenderStateParametersVersion() const;
const RenderStateParameters& GetRenderStateParameters() const;
@@ -390,6 +404,11 @@ namespace MobileGL {
UnorderedMap<Uint, TransformFeedbackObjectState> m_transformFeedbackObjects;
IndexGenerator<Uint> m_transformFeedbackNames;
Uint m_boundTransformFeedback = 0;
// Map membership IS object existence here: a pipeline has no stateful default
// object 0, so no everBound flag is needed.
UnorderedMap<Uint, SharedPtr<ProgramPipelineObject>> m_programPipelines;
IndexGenerator<Uint> m_programPipelineNames;
Uint m_boundProgramPipeline = 0;
TextureState m_textureState;
ProgramState m_programState;
RenderState m_renderState;