[Feat] (Diligent, MG_Impl): wire BlitNamedFramebuffer color copy

- Explicit read/draw FBO color attachments resolve to Diligent textures/renderbuffers
- CopyTexture between them for same-size color blits
- Update handoff; 16 Diligent tests pass
This commit is contained in:
BZLZHH
2026-08-23 10:11:17 +08:00
parent 34ff95f6f5
commit 51a43518ac
4 changed files with 83 additions and 1 deletions
+1 -1
View File
@@ -155,7 +155,7 @@ Verified locally on Turnip Adreno 750:
- `DrawArraysInstanced` / `DrawElementsInstanced` family
- Indirect draw CPU fallback: `DrawArraysIndirect`, `DrawElementsIndirect`, `MultiDraw*Indirect`, `*IndirectCount`
- `ClearBufferfv` / `ClearBufferfi` / `ClearBufferiv` / `ClearBufferuiv` (incl. stencil clear)
- `BlitFramebuffer` (same-size color copy between current read/draw FBOs)
- `BlitFramebuffer` / `BlitNamedFramebuffer` (same-size color copy between read/draw FBOs)
- `CopyTexImage2D` / `CopyTexSubImage2D` (whole-color copy fallback)
- `CopyImageSubData` (whole-texture copy between two texture objects)
- `GenerateMipmap` (Diligent GPU mip generation on state textures)
@@ -449,6 +449,26 @@ namespace MobileGL::MG_Backend::DiligentBackend {
}
}
void BlitNamedFramebuffer(const SharedPtr<MG_State::GLState::FramebufferObject>& readFramebuffer,
const SharedPtr<MG_State::GLState::FramebufferObject>& drawFramebuffer,
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;
auto* renderer = GetActiveRenderer();
if (renderer != nullptr) {
renderer->BlitNamedFramebuffer(readFramebuffer, drawFramebuffer, mask);
}
}
void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y,
GLsizei width, GLsizei height, GLint border) {
(void)level;
@@ -662,6 +682,7 @@ namespace MobileGL::MG_Backend::DiligentBackend {
m_functions.GL.ClearBufferiv = ClearBufferiv;
m_functions.GL.ClearBufferuiv = ClearBufferuiv;
m_functions.GL.BlitFramebuffer = BlitFramebuffer;
m_functions.GL.BlitNamedFramebuffer = BlitNamedFramebuffer;
m_functions.GL.CopyTexImage2D = CopyTexImage2D;
m_functions.GL.CopyTexSubImage2D = CopyTexSubImage2D;
m_functions.GL.CopyImageSubData = CopyImageSubData;
@@ -1712,6 +1712,63 @@ void main()
m_pContext->UnmapTextureSubresource(pStaging, 0, 0);
}
void DiligentRenderer::BlitNamedFramebuffer(
const SharedPtr<MG_State::GLState::FramebufferObject>& readFbo,
const SharedPtr<MG_State::GLState::FramebufferObject>& drawFbo,
GLbitfield mask) {
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 (readFbo && !readFbo->IsDefaultFramebuffer()) {
auto readBuffer = readFbo->GetReadBuffer();
if (readBuffer == FramebufferAttachmentType::None) {
readBuffer = FramebufferAttachmentType::Color0;
}
const auto& att = readFbo->GetAttachment(readBuffer);
if (att.IsTexture() && SyncTexture(*att.GetTexture()) != nullptr) {
auto it = m_textureCache.find(att.GetTexture()->GetLifetimeId());
if (it != m_textureCache.end() && it->second.Texture) {
pSrcTexture = it->second.Texture;
}
} else if (att.IsRenderbuffer() && SyncRenderbuffer(*att.GetRenderbuffer()) != nullptr) {
auto it = m_renderbufferCache.find(att.GetRenderbuffer()->GetExternalIndex());
if (it != m_renderbufferCache.end() && it->second.Texture) {
pSrcTexture = it->second.Texture;
}
}
}
if (drawFbo && !drawFbo->IsDefaultFramebuffer()) {
for (const auto candidate : drawFbo->GetDrawBuffers()) {
if (candidate == FramebufferAttachmentType::None) {
continue;
}
const auto& att = drawFbo->GetAttachment(candidate);
if (att.IsTexture() && SyncTexture(*att.GetTexture()) != nullptr) {
auto it = m_textureCache.find(att.GetTexture()->GetLifetimeId());
if (it != m_textureCache.end() && it->second.Texture) {
pDstTexture = it->second.Texture;
}
} else if (att.IsRenderbuffer() && SyncRenderbuffer(*att.GetRenderbuffer()) != nullptr) {
auto it = m_renderbufferCache.find(att.GetRenderbuffer()->GetExternalIndex());
if (it != m_renderbufferCache.end() && it->second.Texture) {
pDstTexture = it->second.Texture;
}
}
break;
}
}
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::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter) {
@@ -36,6 +36,7 @@ namespace MobileGL::MG_State::GLState {
class SamplerObject;
class ProgramObject;
class RenderbufferObject;
class FramebufferObject;
}
namespace MobileGL::MG_Backend::DiligentBackend {
@@ -65,6 +66,9 @@ namespace MobileGL::MG_Backend::DiligentBackend {
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
void BlitNamedFramebuffer(const SharedPtr<MG_State::GLState::FramebufferObject>& readFbo,
const SharedPtr<MG_State::GLState::FramebufferObject>& drawFbo,
GLbitfield mask);
void CopyReadFramebufferToTexture(MG_State::GLState::ITextureObject& dst);
void CopyTextureSubData(MG_State::GLState::ITextureObject& src, MG_State::GLState::ITextureObject& dst);
void GenerateMipmap(MG_State::GLState::ITextureObject& texture);