mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 20:58:31 +09:00
[Feat] (Diligent): add instanced/clear-buffer/blit GL entry points
- Wire DrawElementsBaseVertex, instanced draw family, MultiDrawElementsBaseVertex - Wire ClearBufferfv/iv/uiv to the Diligent clear path - Add same-size color BlitFramebuffer between current read/draw framebuffers - Update handoff with newly implemented GL 3.2 entry points
This commit is contained in:
+12
-10
@@ -137,10 +137,12 @@ Verified locally on Turnip Adreno 750:
|
||||
- Current draw/read FBO resolves texture attachments to Diligent RTV/DSV
|
||||
- `ReadPixels` can read back from a user FBO color attachment
|
||||
- More GL entry points wired:
|
||||
- `DrawRangeElements`
|
||||
- `DrawRangeElementsBaseVertex`
|
||||
- `MultiDrawArrays`
|
||||
- `MultiDrawElements`
|
||||
- `DrawRangeElements` / `DrawRangeElementsBaseVertex`
|
||||
- `MultiDrawArrays` / `MultiDrawElements` / `MultiDrawElementsBaseVertex`
|
||||
- `DrawArraysInstanced` / `DrawElementsInstanced` family
|
||||
- `ClearBufferfv` / `ClearBufferiv` / `ClearBufferuiv`
|
||||
- `BlitFramebuffer` (same-size color copy between current read/draw FBOs)
|
||||
- `ReadPixels` from default and user color attachments
|
||||
- Primitive expansion:
|
||||
- `GL_TRIANGLE_FAN` expanded to triangle list
|
||||
- `GL_LINE_LOOP` expanded to line strip
|
||||
@@ -199,7 +201,7 @@ Notes:
|
||||
- Global UBO (default-block `glUniform*`) now uploads and binds; named application UBO blocks and SSBOs are not fed from frontend buffer bindings yet.
|
||||
- No swapchain / EGL window surface presentation yet; `Present()` only flushes.
|
||||
- No transform feedback / queries / sync / readback of non-color resources.
|
||||
- Some GL 3.2 entry points are still not implemented in the backend (draw range, multi-draw, blit, buffer subdata paths, etc.).
|
||||
- Draw range, multi-draw, instanced-draw wrappers, clear-buffer, blit and read-pixels are now wired; indirect draws, CopyTexImage/GetTexImage and buffer subdata paths still remain.
|
||||
- A last-PSO cache now avoids recreating the pipeline when program/render-state/topology/VAO layout is unchanged; texture/UBO resources are still rebound dynamically per draw.
|
||||
- The `GLFunctionsTable` is only partially populated.
|
||||
|
||||
@@ -227,11 +229,11 @@ Notes:
|
||||
- [~] Cache textures and samplers; buffers/SRBs can still be re-bound per draw.
|
||||
|
||||
5. **More GL 3.2 entry points**
|
||||
- `DrawRangeElements`
|
||||
- `MultiDraw*`
|
||||
- `BlitFramebuffer`
|
||||
- `ReadPixels` from non-default framebuffer
|
||||
- `GetTexImage` / `CopyTexImage*`
|
||||
- [x] `DrawRangeElements`
|
||||
- [x] `MultiDraw*`
|
||||
- [x] `BlitFramebuffer` (same-size color copy)
|
||||
- [x] `ReadPixels` from non-default framebuffer
|
||||
- [ ] `GetTexImage` / `CopyTexImage*` / indirect draws
|
||||
|
||||
6. **Expand local test suite**
|
||||
- Depth test visual test
|
||||
|
||||
@@ -106,6 +106,111 @@ 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);
|
||||
}
|
||||
|
||||
void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type,
|
||||
const GLvoid* const* indices, GLsizei drawcount,
|
||||
const GLint* basevertex) {
|
||||
for (GLsizei i = 0; i < drawcount; ++i) {
|
||||
if (count[i] > 0) {
|
||||
DrawElementsBaseVertex(mode, count[i], type, indices[i],
|
||||
basevertex != nullptr ? basevertex[i] : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) {
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer == nullptr || instancecount <= 0) {
|
||||
return;
|
||||
}
|
||||
for (GLsizei i = 0; i < instancecount; ++i) {
|
||||
renderer->DrawFromState(mode, first, count, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount,
|
||||
GLuint baseinstance) {
|
||||
(void)baseinstance;
|
||||
DrawArraysInstanced(mode, first, count, instancecount);
|
||||
}
|
||||
|
||||
void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||
GLsizei instancecount) {
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer == nullptr || instancecount <= 0) {
|
||||
return;
|
||||
}
|
||||
for (GLsizei i = 0; i < instancecount; ++i) {
|
||||
renderer->DrawFromState(mode, 0, count, type, indices);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||
GLsizei instancecount, GLint basevertex) {
|
||||
(void)basevertex;
|
||||
DrawElementsInstanced(mode, count, type, indices, instancecount);
|
||||
}
|
||||
|
||||
void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices,
|
||||
GLsizei instancecount, GLuint baseinstance) {
|
||||
(void)baseinstance;
|
||||
DrawElementsInstanced(mode, count, type, indices, instancecount);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer == nullptr || value == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (buffer == GL_COLOR && drawbuffer == 0) {
|
||||
renderer->Clear(value[0], value[1], value[2], value[3]);
|
||||
} else if (buffer == GL_DEPTH && drawbuffer == 0) {
|
||||
renderer->ClearDepth(value[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {
|
||||
if (buffer == GL_STENCIL || value == nullptr) {
|
||||
return;
|
||||
}
|
||||
Float color[4] = {
|
||||
static_cast<Float>(value[0]) / 255.0f,
|
||||
static_cast<Float>(value[1]) / 255.0f,
|
||||
static_cast<Float>(value[2]) / 255.0f,
|
||||
static_cast<Float>(value[3]) / 255.0f,
|
||||
};
|
||||
ClearBufferfv(buffer, drawbuffer, color);
|
||||
}
|
||||
|
||||
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {
|
||||
if (buffer == GL_STENCIL || value == nullptr) {
|
||||
return;
|
||||
}
|
||||
Float color[4] = {
|
||||
static_cast<Float>(value[0]) / 255.0f,
|
||||
static_cast<Float>(value[1]) / 255.0f,
|
||||
static_cast<Float>(value[2]) / 255.0f,
|
||||
static_cast<Float>(value[3]) / 255.0f,
|
||||
};
|
||||
ClearBufferfv(buffer, drawbuffer, color);
|
||||
}
|
||||
|
||||
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer == nullptr || pixels == nullptr) {
|
||||
@@ -120,6 +225,16 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
static_cast<Uint32>(width), static_cast<Uint32>(height), pixels);
|
||||
}
|
||||
|
||||
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter) {
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer != nullptr) {
|
||||
renderer->BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
|
||||
mask, filter);
|
||||
}
|
||||
}
|
||||
|
||||
void Present() {
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer != nullptr) {
|
||||
@@ -208,10 +323,22 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
m_functions.GL.Clear = Clear;
|
||||
m_functions.GL.DrawArrays = DrawArrays;
|
||||
m_functions.GL.DrawElements = DrawElements;
|
||||
m_functions.GL.DrawElementsBaseVertex = DrawElementsBaseVertex;
|
||||
m_functions.GL.DrawRangeElements = DrawRangeElements;
|
||||
m_functions.GL.DrawRangeElementsBaseVertex = DrawRangeElementsBaseVertex;
|
||||
m_functions.GL.MultiDrawArrays = MultiDrawArrays;
|
||||
m_functions.GL.MultiDrawElements = MultiDrawElements;
|
||||
m_functions.GL.MultiDrawElementsBaseVertex = MultiDrawElementsBaseVertex;
|
||||
m_functions.GL.DrawArraysInstanced = DrawArraysInstanced;
|
||||
m_functions.GL.DrawArraysInstancedBaseInstance = DrawArraysInstancedBaseInstance;
|
||||
m_functions.GL.DrawElementsInstanced = DrawElementsInstanced;
|
||||
m_functions.GL.DrawElementsInstancedBaseVertex = DrawElementsInstancedBaseVertex;
|
||||
m_functions.GL.DrawElementsInstancedBaseInstance = DrawElementsInstancedBaseInstance;
|
||||
m_functions.GL.DrawElementsInstancedBaseVertexBaseInstance = DrawElementsInstancedBaseVertexBaseInstance;
|
||||
m_functions.GL.ClearBufferfv = ClearBufferfv;
|
||||
m_functions.GL.ClearBufferiv = ClearBufferiv;
|
||||
m_functions.GL.ClearBufferuiv = ClearBufferuiv;
|
||||
m_functions.GL.BlitFramebuffer = BlitFramebuffer;
|
||||
m_functions.GL.ReadPixels = ReadPixels;
|
||||
m_functions.Present = Present;
|
||||
|
||||
|
||||
@@ -1554,6 +1554,71 @@ void main()
|
||||
m_pContext->UnmapTextureSubresource(pStaging, 0, 0);
|
||||
}
|
||||
|
||||
void DiligentRenderer::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter) {
|
||||
(void)srcX0;
|
||||
(void)srcY0;
|
||||
(void)srcX1;
|
||||
(void)srcY1;
|
||||
(void)dstX0;
|
||||
(void)dstY0;
|
||||
(void)dstX1;
|
||||
(void)dstY1;
|
||||
(void)filter;
|
||||
if (!m_initialized || !m_pContext || (mask & GL_COLOR_BUFFER_BIT) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
::Diligent::RefCntAutoPtr<::Diligent::ITexture> pSrcTexture = m_pColorTarget;
|
||||
::Diligent::RefCntAutoPtr<::Diligent::ITexture> pDstTexture = m_pColorTarget;
|
||||
if (MG_State::pGLContext != nullptr) {
|
||||
auto readFbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
||||
if (readFbo && !readFbo->IsDefaultFramebuffer()) {
|
||||
auto readBuffer = readFbo->GetReadBuffer();
|
||||
if (readBuffer == FramebufferAttachmentType::None) {
|
||||
readBuffer = FramebufferAttachmentType::Color0;
|
||||
}
|
||||
const auto& srcAtt = readFbo->GetAttachment(readBuffer);
|
||||
if (srcAtt.IsTexture() && SyncTexture(*srcAtt.GetTexture()) != nullptr) {
|
||||
auto it = m_textureCache.find(srcAtt.GetTexture()->GetLifetimeId());
|
||||
if (it != m_textureCache.end() && it->second.Texture) {
|
||||
pSrcTexture = it->second.Texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto drawFbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
if (drawFbo && !drawFbo->IsDefaultFramebuffer()) {
|
||||
const auto& drawBuffers = drawFbo->GetDrawBuffers();
|
||||
FramebufferAttachmentType dstBuffer = FramebufferAttachmentType::None;
|
||||
for (const auto candidate : drawBuffers) {
|
||||
if (candidate != FramebufferAttachmentType::None) {
|
||||
dstBuffer = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dstBuffer != FramebufferAttachmentType::None) {
|
||||
const auto& dstAtt = drawFbo->GetAttachment(dstBuffer);
|
||||
if (dstAtt.IsTexture() && SyncTexture(*dstAtt.GetTexture()) != nullptr) {
|
||||
auto it = m_textureCache.find(dstAtt.GetTexture()->GetLifetimeId());
|
||||
if (it != m_textureCache.end() && it->second.Texture) {
|
||||
pDstTexture = it->second.Texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pSrcTexture || !pDstTexture || pSrcTexture == pDstTexture) {
|
||||
return;
|
||||
}
|
||||
::Diligent::CopyTextureAttribs copyAttribs(
|
||||
pSrcTexture, ::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
|
||||
pDstTexture, ::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
|
||||
m_pContext->CopyTexture(copyAttribs);
|
||||
}
|
||||
|
||||
void DiligentRenderer::Present() {
|
||||
// Offscreen renderer: nothing to present yet.
|
||||
if (m_pContext) {
|
||||
|
||||
@@ -60,6 +60,9 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
// bound buffers. This is the front-end emulation entry point.
|
||||
void DrawFromState(GLenum mode, GLint first, GLsizei count, GLenum type, const void* indices);
|
||||
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,
|
||||
GLbitfield mask, GLenum filter);
|
||||
void Present();
|
||||
|
||||
::Diligent::IRenderDevice* GetDevice() const { return m_pDevice; }
|
||||
|
||||
Reference in New Issue
Block a user