mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08: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`
|
- `DrawsWithStencilTestFromMobileGLState`
|
||||||
- `DrawsToRenderbufferFramebufferFromMobileGLState`
|
- `DrawsToRenderbufferFramebufferFromMobileGLState`
|
||||||
- `DrawsToMultipleColorAttachmentsFromMobileGLState`
|
- `DrawsToMultipleColorAttachmentsFromMobileGLState`
|
||||||
|
- `DrawsIndexedBaseVertexFromMobileGLState`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -149,6 +150,7 @@ Verified locally on Turnip Adreno 750:
|
|||||||
- `ReadPixels` can read back from a user FBO color attachment
|
- `ReadPixels` can read back from a user FBO color attachment
|
||||||
- More GL entry points wired:
|
- More GL entry points wired:
|
||||||
- `DrawRangeElements` / `DrawRangeElementsBaseVertex`
|
- `DrawRangeElements` / `DrawRangeElementsBaseVertex`
|
||||||
|
- `DrawElementsBaseVertex` with real baseVertex selection
|
||||||
- `MultiDrawArrays` / `MultiDrawElements` / `MultiDrawElementsBaseVertex`
|
- `MultiDrawArrays` / `MultiDrawElements` / `MultiDrawElementsBaseVertex`
|
||||||
- `DrawArraysInstanced` / `DrawElementsInstanced` family
|
- `DrawArraysInstanced` / `DrawElementsInstanced` family
|
||||||
- Indirect draw CPU fallback: `DrawArraysIndirect`, `DrawElementsIndirect`, `MultiDraw*Indirect`, `*IndirectCount`
|
- Indirect draw CPU fallback: `DrawArraysIndirect`, `DrawElementsIndirect`, `MultiDraw*Indirect`, `*IndirectCount`
|
||||||
@@ -163,7 +165,7 @@ Verified locally on Turnip Adreno 750:
|
|||||||
- Local test result:
|
- Local test result:
|
||||||
|
|
||||||
```
|
```
|
||||||
[ PASSED ] 15 tests
|
[ PASSED ] 16 tests
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -113,8 +113,10 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
|||||||
const void* indices, GLint basevertex) {
|
const void* indices, GLint basevertex) {
|
||||||
(void)start;
|
(void)start;
|
||||||
(void)end;
|
(void)end;
|
||||||
(void)basevertex;
|
auto* renderer = GetActiveRenderer();
|
||||||
DrawElements(mode, count, type, indices);
|
if (renderer != nullptr) {
|
||||||
|
renderer->DrawFromState(mode, 0, count, type, indices, basevertex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiDrawArrays(GLenum mode, const GLint* first, const GLsizei* count, GLsizei drawcount) {
|
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,
|
void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||||
GLint basevertex) {
|
GLint basevertex) {
|
||||||
// The CPU vertex-upload path currently treats the element indices as absolute
|
auto* renderer = GetActiveRenderer();
|
||||||
// vertex indices; basevertex is accepted for compatibility and applied by the
|
if (renderer != nullptr) {
|
||||||
// UploadVertexDataFromState path when it is extended.
|
renderer->DrawFromState(mode, 0, count, type, indices, basevertex);
|
||||||
(void)basevertex;
|
}
|
||||||
DrawElements(mode, count, type, indices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type,
|
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);
|
const void* indices = reinterpret_cast<const void*>(static_cast<SizeT>(cmd.FirstIndex) * indexSize);
|
||||||
for (Uint32 i = 0; i < cmd.InstanceCount; ++i) {
|
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);
|
const void* indices = reinterpret_cast<const void*>(static_cast<SizeT>(cmd.FirstIndex) * indexSize);
|
||||||
for (Uint32 instance = 0; instance < cmd.InstanceCount; ++instance) {
|
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,
|
void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||||
GLsizei instancecount, GLint basevertex) {
|
GLsizei instancecount, GLint basevertex) {
|
||||||
(void)basevertex;
|
auto* renderer = GetActiveRenderer();
|
||||||
DrawElementsInstanced(mode, count, type, indices, instancecount);
|
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,
|
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,
|
void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type,
|
||||||
const void* indices, GLsizei instancecount,
|
const void* indices, GLsizei instancecount,
|
||||||
GLint basevertex, GLuint baseinstance) {
|
GLint basevertex, GLuint baseinstance) {
|
||||||
(void)basevertex;
|
|
||||||
(void)baseinstance;
|
(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) {
|
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {
|
||||||
|
|||||||
@@ -1190,14 +1190,15 @@ void main()
|
|||||||
return true;
|
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) {
|
if (!m_initialized || !m_pContext || MG_State::pGLContext == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!CreatePipelineFromState(mode)) {
|
if (!CreatePipelineFromState(mode)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!UploadVertexDataFromState(mode, first, count, type, indices)) {
|
if (!UploadVertexDataFromState(mode, first, count, type, indices, baseVertex)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1496,7 +1497,7 @@ void main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bool DiligentRenderer::UploadVertexDataFromState(GLenum mode, GLint first, GLsizei count, GLenum type,
|
Bool DiligentRenderer::UploadVertexDataFromState(GLenum mode, GLint first, GLsizei count, GLenum type,
|
||||||
const void* indices) {
|
const void* indices, GLint baseVertex) {
|
||||||
if (MG_State::pGLContext == nullptr) {
|
if (MG_State::pGLContext == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1581,7 +1582,16 @@ void main()
|
|||||||
|
|
||||||
Vector<Uint8> vertexData(static_cast<SizeT>(drawVertexCount) * vertexStride);
|
Vector<Uint8> vertexData(static_cast<SizeT>(drawVertexCount) * vertexStride);
|
||||||
for (Uint32 vi = 0; vi < drawVertexCount; ++vi) {
|
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;
|
Uint8* dst = vertexData.data() + static_cast<SizeT>(vi) * vertexStride;
|
||||||
for (Uint32 attrIndex : activeAttribs) {
|
for (Uint32 attrIndex : activeAttribs) {
|
||||||
const auto& attr = attributes[attrIndex];
|
const auto& attr = attributes[attrIndex];
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
|||||||
Bool CreateTestTexture(const void* data, Uint32 width, Uint32 height);
|
Bool CreateTestTexture(const void* data, Uint32 width, Uint32 height);
|
||||||
// Draws using the live MG_State GL context: current program, VAO and
|
// Draws using the live MG_State GL context: current program, VAO and
|
||||||
// bound buffers. This is the front-end emulation entry point.
|
// 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 ReadPixels(Uint32 x, Uint32 y, Uint32 width, Uint32 height, void* pixels);
|
||||||
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||||
@@ -91,7 +92,8 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
|||||||
Bool CreatePipeline();
|
Bool CreatePipeline();
|
||||||
Bool CreateVertexBuffer();
|
Bool CreateVertexBuffer();
|
||||||
Bool CreatePipelineFromState(GLenum mode);
|
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* SyncTexture(MG_State::GLState::ITextureObject& texture);
|
||||||
::Diligent::ITextureView* SyncTextureForAttachment(MG_State::GLState::ITextureObject& texture, Bool depth);
|
::Diligent::ITextureView* SyncTextureForAttachment(MG_State::GLState::ITextureObject& texture, Bool depth);
|
||||||
::Diligent::ITextureView* SyncRenderbuffer(MG_State::GLState::RenderbufferObject& renderbuffer);
|
::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_LT(center1[0], 50) << "attachment 1 should not be red";
|
||||||
EXPECT_GT(center1[2], 200) << "attachment 1 should be blue";
|
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