mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 04:38:30 +09:00
[Feat] (Diligent, MG_Impl): honor DrawElementsBaseVertex baseVertex in CPU vertex packing
- Add baseVertex parameter through DrawFromState/UploadVertexDataFromState - Apply baseVertex when resolving indexed vertex indices - Pass baseVertex through DrawElementsBaseVertex, instanced, and indirect indexed draws - Add DrawsIndexedBaseVertexFromMobileGLState; 16 Diligent tests pass
This commit is contained in:
+3
-1
@@ -108,6 +108,7 @@ Working tree is clean.
|
||||
- `DrawsWithStencilTestFromMobileGLState`
|
||||
- `DrawsToRenderbufferFramebufferFromMobileGLState`
|
||||
- `DrawsToMultipleColorAttachmentsFromMobileGLState`
|
||||
- `DrawsIndexedBaseVertexFromMobileGLState`
|
||||
|
||||
---
|
||||
|
||||
@@ -149,6 +150,7 @@ Verified locally on Turnip Adreno 750:
|
||||
- `ReadPixels` can read back from a user FBO color attachment
|
||||
- More GL entry points wired:
|
||||
- `DrawRangeElements` / `DrawRangeElementsBaseVertex`
|
||||
- `DrawElementsBaseVertex` with real baseVertex selection
|
||||
- `MultiDrawArrays` / `MultiDrawElements` / `MultiDrawElementsBaseVertex`
|
||||
- `DrawArraysInstanced` / `DrawElementsInstanced` family
|
||||
- Indirect draw CPU fallback: `DrawArraysIndirect`, `DrawElementsIndirect`, `MultiDraw*Indirect`, `*IndirectCount`
|
||||
@@ -163,7 +165,7 @@ Verified locally on Turnip Adreno 750:
|
||||
- Local test result:
|
||||
|
||||
```
|
||||
[ PASSED ] 15 tests
|
||||
[ PASSED ] 16 tests
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -113,8 +113,10 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
const void* indices, GLint basevertex) {
|
||||
(void)start;
|
||||
(void)end;
|
||||
(void)basevertex;
|
||||
DrawElements(mode, count, type, indices);
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer != nullptr) {
|
||||
renderer->DrawFromState(mode, 0, count, type, indices, basevertex);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiDrawArrays(GLenum mode, const GLint* first, const GLsizei* count, GLsizei drawcount) {
|
||||
@@ -144,11 +146,10 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
|
||||
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||
GLint basevertex) {
|
||||
// The CPU vertex-upload path currently treats the element indices as absolute
|
||||
// vertex indices; basevertex is accepted for compatibility and applied by the
|
||||
// UploadVertexDataFromState path when it is extended.
|
||||
(void)basevertex;
|
||||
DrawElements(mode, count, type, indices);
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer != nullptr) {
|
||||
renderer->DrawFromState(mode, 0, count, type, indices, basevertex);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type,
|
||||
@@ -204,7 +205,8 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
}
|
||||
const void* indices = reinterpret_cast<const void*>(static_cast<SizeT>(cmd.FirstIndex) * indexSize);
|
||||
for (Uint32 i = 0; i < cmd.InstanceCount; ++i) {
|
||||
renderer->DrawFromState(mode, 0, static_cast<GLsizei>(cmd.Count), type, indices);
|
||||
renderer->DrawFromState(mode, 0, static_cast<GLsizei>(cmd.Count), type, indices,
|
||||
static_cast<GLint>(cmd.BaseVertex));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +260,8 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
}
|
||||
const void* indices = reinterpret_cast<const void*>(static_cast<SizeT>(cmd.FirstIndex) * indexSize);
|
||||
for (Uint32 instance = 0; instance < cmd.InstanceCount; ++instance) {
|
||||
renderer->DrawFromState(mode, 0, static_cast<GLsizei>(cmd.Count), type, indices);
|
||||
renderer->DrawFromState(mode, 0, static_cast<GLsizei>(cmd.Count), type, indices,
|
||||
static_cast<GLint>(cmd.BaseVertex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -332,8 +335,13 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
|
||||
void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||
GLsizei instancecount, GLint basevertex) {
|
||||
(void)basevertex;
|
||||
DrawElementsInstanced(mode, count, type, indices, instancecount);
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer == nullptr || instancecount <= 0) {
|
||||
return;
|
||||
}
|
||||
for (GLsizei i = 0; i < instancecount; ++i) {
|
||||
renderer->DrawFromState(mode, 0, count, type, indices, basevertex);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||
@@ -345,9 +353,14 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type,
|
||||
const void* indices, GLsizei instancecount,
|
||||
GLint basevertex, GLuint baseinstance) {
|
||||
(void)basevertex;
|
||||
(void)baseinstance;
|
||||
DrawElementsInstanced(mode, count, type, indices, instancecount);
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer == nullptr || instancecount <= 0) {
|
||||
return;
|
||||
}
|
||||
for (GLsizei i = 0; i < instancecount; ++i) {
|
||||
renderer->DrawFromState(mode, 0, count, type, indices, basevertex);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {
|
||||
|
||||
@@ -1190,14 +1190,15 @@ void main()
|
||||
return true;
|
||||
}
|
||||
|
||||
void DiligentRenderer::DrawFromState(GLenum mode, GLint first, GLsizei count, GLenum type, const void* indices) {
|
||||
void DiligentRenderer::DrawFromState(GLenum mode, GLint first, GLsizei count, GLenum type, const void* indices,
|
||||
GLint baseVertex) {
|
||||
if (!m_initialized || !m_pContext || MG_State::pGLContext == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (!CreatePipelineFromState(mode)) {
|
||||
return;
|
||||
}
|
||||
if (!UploadVertexDataFromState(mode, first, count, type, indices)) {
|
||||
if (!UploadVertexDataFromState(mode, first, count, type, indices, baseVertex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1496,7 +1497,7 @@ void main()
|
||||
}
|
||||
|
||||
Bool DiligentRenderer::UploadVertexDataFromState(GLenum mode, GLint first, GLsizei count, GLenum type,
|
||||
const void* indices) {
|
||||
const void* indices, GLint baseVertex) {
|
||||
if (MG_State::pGLContext == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -1581,7 +1582,16 @@ void main()
|
||||
|
||||
Vector<Uint8> vertexData(static_cast<SizeT>(drawVertexCount) * vertexStride);
|
||||
for (Uint32 vi = 0; vi < drawVertexCount; ++vi) {
|
||||
const Uint32 srcIndex = indicesData.empty() ? (static_cast<Uint32>(first) + vi) : indicesData[vi];
|
||||
Uint32 srcIndex = 0;
|
||||
if (indicesData.empty()) {
|
||||
srcIndex = static_cast<Uint32>(first) + vi;
|
||||
} else {
|
||||
const Int64 resolvedIndex = static_cast<Int64>(indicesData[vi]) + baseVertex;
|
||||
if (resolvedIndex < 0) {
|
||||
return false;
|
||||
}
|
||||
srcIndex = static_cast<Uint32>(resolvedIndex);
|
||||
}
|
||||
Uint8* dst = vertexData.data() + static_cast<SizeT>(vi) * vertexStride;
|
||||
for (Uint32 attrIndex : activeAttribs) {
|
||||
const auto& attr = attributes[attrIndex];
|
||||
|
||||
@@ -59,7 +59,8 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
Bool CreateTestTexture(const void* data, Uint32 width, Uint32 height);
|
||||
// Draws using the live MG_State GL context: current program, VAO and
|
||||
// bound buffers. This is the front-end emulation entry point.
|
||||
void DrawFromState(GLenum mode, GLint first, GLsizei count, GLenum type, const void* indices);
|
||||
void DrawFromState(GLenum mode, GLint first, GLsizei count, GLenum type, const void* indices,
|
||||
GLint baseVertex = 0);
|
||||
void ReadPixels(Uint32 x, Uint32 y, Uint32 width, Uint32 height, void* pixels);
|
||||
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
@@ -91,7 +92,8 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
Bool CreatePipeline();
|
||||
Bool CreateVertexBuffer();
|
||||
Bool CreatePipelineFromState(GLenum mode);
|
||||
Bool UploadVertexDataFromState(GLenum mode, GLint first, GLsizei count, GLenum type, const void* indices);
|
||||
Bool UploadVertexDataFromState(GLenum mode, GLint first, GLsizei count, GLenum type, const void* indices,
|
||||
GLint baseVertex = 0);
|
||||
::Diligent::ITextureView* SyncTexture(MG_State::GLState::ITextureObject& texture);
|
||||
::Diligent::ITextureView* SyncTextureForAttachment(MG_State::GLState::ITextureObject& texture, Bool depth);
|
||||
::Diligent::ITextureView* SyncRenderbuffer(MG_State::GLState::RenderbufferObject& renderbuffer);
|
||||
|
||||
@@ -1046,3 +1046,77 @@ void main() {
|
||||
EXPECT_LT(center1[0], 50) << "attachment 1 should not be red";
|
||||
EXPECT_GT(center1[2], 200) << "attachment 1 should be blue";
|
||||
}
|
||||
|
||||
|
||||
TEST(DiligentVulkanBackend, DrawsIndexedBaseVertexFromMobileGLState) {
|
||||
MobileGL::Initialize();
|
||||
|
||||
const char* vsSrc = R"(#version 330 core
|
||||
layout(location = 0) in vec2 Position;
|
||||
void main() { gl_Position = vec4(Position, 0.0, 1.0); }
|
||||
)";
|
||||
const char* fsSrc = R"(#version 330 core
|
||||
out vec4 Color;
|
||||
void main() { Color = vec4(1.0, 0.0, 0.0, 1.0); }
|
||||
)";
|
||||
|
||||
const GLuint vs = CreateShader(GL_VERTEX_SHADER);
|
||||
ShaderSource(vs, 1, &vsSrc, nullptr);
|
||||
CompileShader(vs);
|
||||
const GLuint fs = CreateShader(GL_FRAGMENT_SHADER);
|
||||
ShaderSource(fs, 1, &fsSrc, nullptr);
|
||||
CompileShader(fs);
|
||||
const GLuint program = CreateProgram();
|
||||
AttachShader(program, vs);
|
||||
AttachShader(program, fs);
|
||||
LinkProgram(program);
|
||||
UseProgram(program);
|
||||
Viewport(0, 0, 256, 256);
|
||||
BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
ReadBuffer(GL_BACK);
|
||||
Disable(GL_DEPTH_TEST);
|
||||
Disable(GL_BLEND);
|
||||
Disable(GL_SCISSOR_TEST);
|
||||
Disable(GL_STENCIL_TEST);
|
||||
|
||||
// First triangle is far offscreen; baseVertex=3 makes indices {0,1,2} select
|
||||
// the second, visible triangle.
|
||||
const float vertices[] = {
|
||||
-10.0f, -10.0f, -9.0f, -10.0f, -9.0f, -9.0f,
|
||||
-0.5f, -0.5f, 0.5f, -0.5f, 0.0f, 0.5f,
|
||||
};
|
||||
const GLuint indices[] = {0, 1, 2};
|
||||
|
||||
GLuint vbo = 0;
|
||||
GenBuffers(1, &vbo);
|
||||
BindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
BufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
GLuint ebo = 0;
|
||||
GenBuffers(1, &ebo);
|
||||
BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
BufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||
|
||||
GLuint vao = 0;
|
||||
GenVertexArrays(1, &vao);
|
||||
BindVertexArray(vao);
|
||||
EnableVertexAttribArray(0);
|
||||
VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
|
||||
DiligentBackend::BackendObject_Diligent backend;
|
||||
backend.Initialize();
|
||||
auto* renderer = backend.GetRenderer();
|
||||
if (renderer == nullptr) {
|
||||
GTEST_SKIP() << "No Vulkan adapter available; skipping base vertex test";
|
||||
}
|
||||
|
||||
renderer->Clear(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
renderer->DrawFromState(GL_TRIANGLES, 0, 3, GL_UNSIGNED_INT, nullptr, 3);
|
||||
renderer->Present();
|
||||
|
||||
std::uint8_t center[4] = {};
|
||||
renderer->ReadPixels(128, 128, 1, 1, center);
|
||||
EXPECT_GT(center[0], 200) << "center should be red from baseVertex-selected triangle";
|
||||
EXPECT_LT(center[1], 50) << "center should not be green";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user