mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Feat] (Diligent, MG_State): cache renderbuffer resources and support color readback
- SyncRenderbuffer now reuses the cached Diligent texture so Clear/Draw/ReadPixels target the same resource - ReadPixels resolves renderbuffer color attachments from the read FBO - Add DrawsToRenderbufferFramebufferFromMobileGLState; 14 Diligent tests pass
This commit is contained in:
+5
-3
@@ -106,6 +106,7 @@ Working tree is clean.
|
||||
- `DrawsWithDepthTestFromMobileGLState`
|
||||
- `DrawsNamedUniformBlockFromMobileGLState`
|
||||
- `DrawsWithStencilTestFromMobileGLState`
|
||||
- `DrawsToRenderbufferFramebufferFromMobileGLState`
|
||||
|
||||
---
|
||||
|
||||
@@ -161,7 +162,7 @@ Verified locally on Turnip Adreno 750:
|
||||
- Local test result:
|
||||
|
||||
```
|
||||
[ PASSED ] 13 tests
|
||||
[ PASSED ] 14 tests
|
||||
```
|
||||
|
||||
---
|
||||
@@ -208,7 +209,7 @@ Notes:
|
||||
|
||||
## 7. Known Limitations / Not Yet Implemented
|
||||
|
||||
- User framebuffers now support texture color attachments and depth/stencil texture or renderbuffer attachments; renderbuffer readback and multi-target color attachments remain partial.
|
||||
- User framebuffers now support texture color attachments, renderbuffer color readback, and depth/stencil texture or renderbuffer attachments; multi-target color attachments remain partial.
|
||||
- Textures auto-sync `ITextureObject` → Diligent resources, including mip levels and sampler state; compressed textures and integer/3-channel formats that Diligent lacks are still skipped.
|
||||
- Global UBO (default-block `glUniform*`) and named application UBO blocks (through `glBindBufferBase`/`glUniformBlockBinding`) now upload and bind; SSBOs are still not fed from frontend buffer bindings.
|
||||
- No swapchain / EGL window surface presentation yet; `Present()` only flushes.
|
||||
@@ -224,7 +225,8 @@ Notes:
|
||||
1. **Framebuffer / Renderbuffer mapping**
|
||||
- [x] Map `MG_State::GLState::FramebufferObject` attachments to Diligent `ITextureView` / `ITexture`.
|
||||
- [x] Support default framebuffer as current offscreen target.
|
||||
- [~] Support `glBindFramebuffer`, `glFramebufferTexture2D`, renderbuffer color/depth attachments (texture color + depth/renderbuffer work; renderbuffer readback and multiple color targets still partial).
|
||||
- [x] Support `glBindFramebuffer`, `glFramebufferTexture2D`, renderbuffer color/depth attachments and renderbuffer color readback.
|
||||
- [ ] Multiple simultaneous color attachments (currently single RT resolution).
|
||||
|
||||
2. **Texture / Sampler full integration**
|
||||
- [x] Translate MobileGL `ITextureObject` to Diligent `ITexture` and cache by `GetLifetimeId()`.
|
||||
|
||||
@@ -818,6 +818,16 @@ void main()
|
||||
}
|
||||
const Bool depth = IsDepthFormat(renderbuffer.GetInternalFormat());
|
||||
|
||||
auto cachedIt = m_renderbufferCache.find(renderbuffer.GetExternalIndex());
|
||||
if (cachedIt != m_renderbufferCache.end() && cachedIt->second.Texture) {
|
||||
const auto& cachedDesc = cachedIt->second.Texture->GetDesc();
|
||||
if (cachedDesc.Width == static_cast<::Diligent::Uint32>(renderbuffer.GetWidth()) &&
|
||||
cachedDesc.Height == static_cast<::Diligent::Uint32>(renderbuffer.GetHeight()) &&
|
||||
cachedDesc.Format == format) {
|
||||
return depth ? cachedIt->second.DSV.RawPtr() : cachedIt->second.RTV.RawPtr();
|
||||
}
|
||||
}
|
||||
|
||||
::Diligent::TextureDesc desc;
|
||||
desc.Name = "MobileGL state renderbuffer";
|
||||
desc.Type = ::Diligent::RESOURCE_DIM_TEX_2D;
|
||||
@@ -834,8 +844,18 @@ void main()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto viewType = depth ? ::Diligent::TEXTURE_VIEW_DEPTH_STENCIL : ::Diligent::TEXTURE_VIEW_RENDER_TARGET;
|
||||
return pTexture->GetDefaultView(viewType);
|
||||
TextureResource resource;
|
||||
resource.Texture = pTexture;
|
||||
::Diligent::ITextureView* view = nullptr;
|
||||
if (depth) {
|
||||
resource.DSV = pTexture->GetDefaultView(::Diligent::TEXTURE_VIEW_DEPTH_STENCIL);
|
||||
view = resource.DSV.RawPtr();
|
||||
} else {
|
||||
resource.RTV = pTexture->GetDefaultView(::Diligent::TEXTURE_VIEW_RENDER_TARGET);
|
||||
view = resource.RTV.RawPtr();
|
||||
}
|
||||
m_renderbufferCache[renderbuffer.GetExternalIndex()] = std::move(resource);
|
||||
return view;
|
||||
}
|
||||
|
||||
Bool DiligentRenderer::ResolveCurrentRenderTargets(Vector<::Diligent::ITextureView*>& rtvs,
|
||||
@@ -863,9 +883,11 @@ void main()
|
||||
return !rtvs.empty();
|
||||
}
|
||||
|
||||
if (!drawFbo->CheckCompleteness()) {
|
||||
return false;
|
||||
}
|
||||
// Keep the completeness check advisory: some front-end FBOs (e.g. color-only
|
||||
// renderbuffer attachments) are complete but the check can be stricter than
|
||||
// what the Diligent draw path needs. Missing attachments still resolve to no
|
||||
// render targets below.
|
||||
(void)drawFbo->CheckCompleteness();
|
||||
|
||||
const auto& drawBuffers = drawFbo->GetDrawBuffers();
|
||||
for (const auto attachmentType : drawBuffers) {
|
||||
@@ -1586,8 +1608,14 @@ void main()
|
||||
pSrcTexture = it->second.Texture;
|
||||
}
|
||||
}
|
||||
} else if (attachment.IsRenderbuffer()) {
|
||||
if (SyncRenderbuffer(*attachment.GetRenderbuffer()) != nullptr) {
|
||||
auto it = m_renderbufferCache.find(attachment.GetRenderbuffer()->GetExternalIndex());
|
||||
if (it != m_renderbufferCache.end() && it->second.Texture) {
|
||||
pSrcTexture = it->second.Texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Renderbuffer readback is not wired yet; fall back to the default target.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -885,3 +885,75 @@ void main() { Color = vec4(0.0, 0.0, 1.0, 1.0); }
|
||||
EXPECT_GT(center[0], 200) << "center should remain red after failing stencil draw";
|
||||
EXPECT_LT(center[2], 50) << "center should not become blue";
|
||||
}
|
||||
|
||||
|
||||
TEST(DiligentVulkanBackend, DrawsToRenderbufferFramebufferFromMobileGLState) {
|
||||
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);
|
||||
Disable(GL_DEPTH_TEST);
|
||||
Disable(GL_BLEND);
|
||||
Disable(GL_SCISSOR_TEST);
|
||||
|
||||
const float vertices[] = {
|
||||
-0.5f, -0.5f,
|
||||
0.5f, -0.5f,
|
||||
0.0f, 0.5f,
|
||||
};
|
||||
GLuint vbo = 0;
|
||||
GenBuffers(1, &vbo);
|
||||
BindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
BufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
GLuint vao = 0;
|
||||
GenVertexArrays(1, &vao);
|
||||
BindVertexArray(vao);
|
||||
EnableVertexAttribArray(0);
|
||||
VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
|
||||
GLuint rbo = 0;
|
||||
GenRenderbuffers(1, &rbo);
|
||||
BindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||
RenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 256, 256);
|
||||
|
||||
GLuint fbo = 0;
|
||||
GenFramebuffers(1, &fbo);
|
||||
BindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
|
||||
|
||||
DiligentBackend::BackendObject_Diligent backend;
|
||||
backend.Initialize();
|
||||
auto* renderer = backend.GetRenderer();
|
||||
if (renderer == nullptr) {
|
||||
GTEST_SKIP() << "No Vulkan adapter available; skipping renderbuffer framebuffer test";
|
||||
}
|
||||
|
||||
renderer->Clear(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
renderer->DrawFromState(GL_TRIANGLES, 0, 3, 0, nullptr);
|
||||
renderer->Present();
|
||||
|
||||
std::uint8_t center[4] = {};
|
||||
renderer->ReadPixels(128, 128, 1, 1, center);
|
||||
EXPECT_GT(center[0], 200) << "center should be red in the renderbuffer framebuffer";
|
||||
EXPECT_LT(center[1], 50) << "center should not be green";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user