mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-13 14:48:32 +09:00
[Feat] (MG_Impl, MG_State): implement the direct state access transform feedback API
glCreateTransformFeedbacks, glTransformFeedbackBufferBase, glTransformFeedbackBufferRange and the three glGetTransformFeedback* queries were all stubs, so a transform feedback object could only be configured and inspected by binding it first - the exact thing direct state access exists to avoid. The queries were the worse half: they returned nothing and raised no error, so an application could not tell that it had learned nothing. glCreateTransformFeedbacks creates the objects outright. glGenTransformFeedbacks only reserves names, and a reserved name becomes an object when it is first bound (GL 4.6 core 13.2.1); the DSA form has no bind step to create them from. The queries and the buffer bindings read and write a named object's state. That state lives in two places: the context keeps one live copy of the capture bindings and the active/paused flags for whichever object is bound, and every other object's copy sits in its saved state until a bind swaps it in. The by-name accessors added to the context resolve that, so a query for the bound object reads the live copy rather than a stale save. GL_TRANSFORM_FEEDBACK_BUFFER_START and _SIZE are answered as zero unless the binding was made by the range form, matching what the buffer object binding points already do. Takes direct_state_access.xfb_* from 0 to 4 of 5 on both backends; xfb_functional still fails on the capture itself, which is a separate defect.
This commit is contained in:
@@ -842,6 +842,64 @@ namespace MobileGL::MG_State {
|
||||
const auto it = m_transformFeedbackObjects.find(index);
|
||||
return it != m_transformFeedbackObjects.end() && it->second.hasCompletedSpan;
|
||||
}
|
||||
|
||||
void GLContext::CreateTransformFeedbackObject(Uint index) {
|
||||
// glCreateTransformFeedbacks has no bind step to infer existence from, so the name it
|
||||
// hands out is already the name of an object (GL 4.6 core 13.2.1).
|
||||
m_transformFeedbackObjects[index] = {};
|
||||
m_transformFeedbackObjects[index].everBound = true;
|
||||
}
|
||||
|
||||
Bool GLContext::IsNamedTransformFeedbackActive(Uint index) const {
|
||||
if (index == m_boundTransformFeedback) return m_transformFeedbackActive;
|
||||
const auto it = m_transformFeedbackObjects.find(index);
|
||||
return it != m_transformFeedbackObjects.end() && it->second.active;
|
||||
}
|
||||
|
||||
Bool GLContext::IsNamedTransformFeedbackPaused(Uint index) const {
|
||||
if (index == m_boundTransformFeedback) return m_transformFeedbackPaused;
|
||||
const auto it = m_transformFeedbackObjects.find(index);
|
||||
return it != m_transformFeedbackObjects.end() && it->second.paused;
|
||||
}
|
||||
|
||||
NamedTransformFeedbackBinding GLContext::GetNamedTransformFeedbackBinding(Uint index, Uint bufferIndex) const {
|
||||
NamedTransformFeedbackBinding result;
|
||||
if (bufferIndex >= MAX_TRANSFORM_FEEDBACK_BUFFERS) return result;
|
||||
// The bound object's capture bindings live in the context's own binding points, not in
|
||||
// the saved copy - that one is only written when the object is swapped out.
|
||||
if (index == m_boundTransformFeedback) {
|
||||
const auto& point = m_bufferState.GetBindingPoint(BufferTarget::TransformFeedback, bufferIndex);
|
||||
result.Buffer = point.GetBoundObject();
|
||||
result.Range = point.GetRange();
|
||||
result.HasExplicitRange = point.HasExplicitRange();
|
||||
return result;
|
||||
}
|
||||
const auto it = m_transformFeedbackObjects.find(index);
|
||||
if (it == m_transformFeedbackObjects.end()) return result;
|
||||
const auto& saved = it->second.bindings[bufferIndex];
|
||||
result.Buffer = saved.buffer;
|
||||
result.Range = saved.range;
|
||||
result.HasExplicitRange = saved.hasExplicitRange;
|
||||
return result;
|
||||
}
|
||||
|
||||
void GLContext::SetNamedTransformFeedbackBinding(Uint index, Uint bufferIndex,
|
||||
const SharedPtr<BufferObject>& buffer, Range1D range,
|
||||
Bool hasExplicitRange) {
|
||||
if (bufferIndex >= MAX_TRANSFORM_FEEDBACK_BUFFERS) return;
|
||||
if (index == m_boundTransformFeedback) {
|
||||
auto& point = m_bufferState.GetBindingPoint(BufferTarget::TransformFeedback, bufferIndex);
|
||||
point.Bind(buffer);
|
||||
if (buffer && hasExplicitRange) {
|
||||
point.SetRange(range, true);
|
||||
} else {
|
||||
point.ClearRange();
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto& object = m_transformFeedbackObjects[index];
|
||||
object.bindings[bufferIndex] = {buffer, range, hasExplicitRange};
|
||||
}
|
||||
} // namespace GLState
|
||||
|
||||
// Leak-at-exit storage; see GlobalObjects.cpp.
|
||||
|
||||
Reference in New Issue
Block a user