[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 - `DrawArraysInstanced` / `DrawElementsInstanced` family
- Indirect draw CPU fallback: `DrawArraysIndirect`, `DrawElementsIndirect`, `MultiDraw*Indirect`, `*IndirectCount` - Indirect draw CPU fallback: `DrawArraysIndirect`, `DrawElementsIndirect`, `MultiDraw*Indirect`, `*IndirectCount`
- `ClearBufferfv` / `ClearBufferfi` / `ClearBufferiv` / `ClearBufferuiv` (incl. stencil clear) - `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) - `CopyTexImage2D` / `CopyTexSubImage2D` (whole-color copy fallback)
- `CopyImageSubData` (whole-texture copy between two texture objects) - `CopyImageSubData` (whole-texture copy between two texture objects)
- `GenerateMipmap` (Diligent GPU mip generation on state textures) - `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, void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y,
GLsizei width, GLsizei height, GLint border) { GLsizei width, GLsizei height, GLint border) {
(void)level; (void)level;
@@ -662,6 +682,7 @@ namespace MobileGL::MG_Backend::DiligentBackend {
m_functions.GL.ClearBufferiv = ClearBufferiv; m_functions.GL.ClearBufferiv = ClearBufferiv;
m_functions.GL.ClearBufferuiv = ClearBufferuiv; m_functions.GL.ClearBufferuiv = ClearBufferuiv;
m_functions.GL.BlitFramebuffer = BlitFramebuffer; m_functions.GL.BlitFramebuffer = BlitFramebuffer;
m_functions.GL.BlitNamedFramebuffer = BlitNamedFramebuffer;
m_functions.GL.CopyTexImage2D = CopyTexImage2D; m_functions.GL.CopyTexImage2D = CopyTexImage2D;
m_functions.GL.CopyTexSubImage2D = CopyTexSubImage2D; m_functions.GL.CopyTexSubImage2D = CopyTexSubImage2D;
m_functions.GL.CopyImageSubData = CopyImageSubData; m_functions.GL.CopyImageSubData = CopyImageSubData;
@@ -1712,6 +1712,63 @@ void main()
m_pContext->UnmapTextureSubresource(pStaging, 0, 0); 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, void DiligentRenderer::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,
GLbitfield mask, GLenum filter) { GLbitfield mask, GLenum filter) {
@@ -36,6 +36,7 @@ namespace MobileGL::MG_State::GLState {
class SamplerObject; class SamplerObject;
class ProgramObject; class ProgramObject;
class RenderbufferObject; class RenderbufferObject;
class FramebufferObject;
} }
namespace MobileGL::MG_Backend::DiligentBackend { namespace MobileGL::MG_Backend::DiligentBackend {
@@ -65,6 +66,9 @@ namespace MobileGL::MG_Backend::DiligentBackend {
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,
GLbitfield mask, GLenum filter); 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 CopyReadFramebufferToTexture(MG_State::GLState::ITextureObject& dst);
void CopyTextureSubData(MG_State::GLState::ITextureObject& src, MG_State::GLState::ITextureObject& dst); void CopyTextureSubData(MG_State::GLState::ITextureObject& src, MG_State::GLState::ITextureObject& dst);
void GenerateMipmap(MG_State::GLState::ITextureObject& texture); void GenerateMipmap(MG_State::GLState::ITextureObject& texture);