[Feat] (DirectVulkan): emulate GL_LINE_LOOP with closed indexed line strips

Vulkan has no LINE_LOOP topology and the frontend used to reject the mode
with GL_INVALID_OPERATION, which is itself non-conformant (several KHR-GL33
transform_feedback tests draw line loops and expect no error). DrawArrays,
DrawElements and DrawElementsBaseVertex now rewrite the draw into an
indexed GL_LINE_STRIP whose synthesized uint32 index list revisits the
first vertex, delivered through the client-memory index path (a new
forceClientMemory flag keeps a bound element-array buffer from hijacking
the synthesized pointer). Entry points without the rewrite degrade to an
open line strip instead of a triangle list.
This commit is contained in:
BZLZHH
2026-07-31 16:25:46 -04:00
parent b9ecfef0b6
commit 92140405c1
5 changed files with 95 additions and 11 deletions
@@ -2848,7 +2848,9 @@ void main() {
}
const Uint8* indexBytes = nullptr;
const auto& indexBufferShared = vao.GetIndexBufferBindingSlot().GetBoundObject();
const auto& indexBufferShared = indexView.forceClientMemory
? SharedPtr<MG_State::GLState::BufferObject>{}
: vao.GetIndexBufferBindingSlot().GetBoundObject();
if (indexBufferShared != nullptr) {
const SizeT bufferSize = indexBufferShared->GetSize();
if (indexBufferShared->MappedData() == nullptr || indexView.indexByteOffset > bufferSize ||
@@ -3262,7 +3264,8 @@ void main() {
}
}
const auto* indexBuffer = vao.GetIndexBufferBindingSlot().GetBoundObject().get();
const auto* indexBuffer =
pIndexBufferView->forceClientMemory ? nullptr : vao.GetIndexBufferBindingSlot().GetBoundObject().get();
if (indexBuffer == nullptr) {
// No element-array buffer: the view's byte offset is a raw client pointer
// (desktop drivers accept client-memory indices and the GL CTS relies on
@@ -76,6 +76,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
GLenum indexType = GL_UNSIGNED_SHORT;
SizeT indexByteOffset = 0;
SizeT indexByteSize = 0;
// Interpret indexByteOffset as a raw client pointer even when an element
// array buffer is bound (backend-synthesized index lists, e.g. the
// GL_LINE_LOOP -> LINE_STRIP rewrite).
Bool forceClientMemory = false;
};
struct DrawIndexedCmd {