mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (Diligent): support multiple simultaneous color attachments
- PSO RTV count/formats now derive from the bound draw FBO color attachments - Include RT layout in the last-PSO cache key - Add DrawsToMultipleColorAttachmentsFromMobileGLState; 15 Diligent tests pass
This commit is contained in:
+4
-3
@@ -107,6 +107,7 @@ Working tree is clean.
|
||||
- `DrawsNamedUniformBlockFromMobileGLState`
|
||||
- `DrawsWithStencilTestFromMobileGLState`
|
||||
- `DrawsToRenderbufferFramebufferFromMobileGLState`
|
||||
- `DrawsToMultipleColorAttachmentsFromMobileGLState`
|
||||
|
||||
---
|
||||
|
||||
@@ -162,7 +163,7 @@ Verified locally on Turnip Adreno 750:
|
||||
- Local test result:
|
||||
|
||||
```
|
||||
[ PASSED ] 14 tests
|
||||
[ PASSED ] 15 tests
|
||||
```
|
||||
|
||||
---
|
||||
@@ -209,7 +210,7 @@ Notes:
|
||||
|
||||
## 7. Known Limitations / Not Yet Implemented
|
||||
|
||||
- User framebuffers now support texture color attachments, renderbuffer color readback, and depth/stencil texture or renderbuffer attachments; multi-target color attachments remain partial.
|
||||
- User framebuffers now support texture color attachments, renderbuffer color readback, multiple simultaneous color targets, and depth/stencil texture or renderbuffer attachments.
|
||||
- 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.
|
||||
@@ -226,7 +227,7 @@ Notes:
|
||||
- [x] Map `MG_State::GLState::FramebufferObject` attachments to Diligent `ITextureView` / `ITexture`.
|
||||
- [x] Support default framebuffer as current offscreen target.
|
||||
- [x] Support `glBindFramebuffer`, `glFramebufferTexture2D`, renderbuffer color/depth attachments and renderbuffer color readback.
|
||||
- [ ] Multiple simultaneous color attachments (currently single RT resolution).
|
||||
- [x] Multiple simultaneous color attachments.
|
||||
|
||||
2. **Texture / Sampler full integration**
|
||||
- [x] Translate MobileGL `ITextureObject` to Diligent `ITexture` and cache by `GetLifetimeId()`.
|
||||
|
||||
@@ -1268,6 +1268,37 @@ void main()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resolve the current draw-FBO color attachment set so the PSO is created with
|
||||
// matching RTV formats/count.
|
||||
Uint32 rtCount = 1;
|
||||
::Diligent::TEXTURE_FORMAT rtFormats[8] = {};
|
||||
rtFormats[0] = ::Diligent::TEX_FORMAT_RGBA8_UNORM;
|
||||
if (MG_State::pGLContext != nullptr) {
|
||||
auto drawFbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject();
|
||||
if (drawFbo && !drawFbo->IsDefaultFramebuffer()) {
|
||||
rtCount = 0;
|
||||
for (const auto attachmentType : drawFbo->GetDrawBuffers()) {
|
||||
if (attachmentType == FramebufferAttachmentType::None) {
|
||||
continue;
|
||||
}
|
||||
const auto& attachment = drawFbo->GetAttachment(attachmentType);
|
||||
::Diligent::TEXTURE_FORMAT fmt = ::Diligent::TEX_FORMAT_UNKNOWN;
|
||||
if (attachment.IsTexture()) {
|
||||
fmt = ConvertInternalFormatToDiligent(attachment.GetTexture()->GetFormat());
|
||||
} else if (attachment.IsRenderbuffer()) {
|
||||
fmt = ConvertInternalFormatToDiligent(attachment.GetRenderbuffer()->GetInternalFormat());
|
||||
}
|
||||
if (fmt != ::Diligent::TEX_FORMAT_UNKNOWN && rtCount < 8) {
|
||||
rtFormats[rtCount++] = fmt;
|
||||
}
|
||||
}
|
||||
if (rtCount == 0) {
|
||||
rtCount = 1;
|
||||
rtFormats[0] = ::Diligent::TEX_FORMAT_RGBA8_UNORM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cheap last-PSO cache: the pipeline depends only on the program, the
|
||||
// render-state subset baked into the PSO, the primitive topology and the
|
||||
// enabled vertex-attribute layout. Textures/UBOs are bound dynamically, so
|
||||
@@ -1277,6 +1308,10 @@ void main()
|
||||
Uint64 psoKey = program->GetLifetimeId();
|
||||
psoKey = psoKey * 1099511628211ull + MG_State::pGLContext->GetPipelineStateVersion();
|
||||
psoKey = psoKey * 1099511628211ull + static_cast<Uint64>(mode);
|
||||
psoKey = psoKey * 1099511628211ull + rtCount;
|
||||
for (Uint32 i = 0; i < rtCount; ++i) {
|
||||
psoKey = psoKey * 1099511628211ull + static_cast<Uint64>(rtFormats[i]);
|
||||
}
|
||||
for (Uint32 i = 0; i < cachedVao.MAX_VERTEX_ATTRIBS; ++i) {
|
||||
const auto& attr = cachedAttributes[i];
|
||||
if (!attr.Enabled) {
|
||||
@@ -1350,8 +1385,10 @@ void main()
|
||||
psoDesc.PipelineType = ::Diligent::PIPELINE_TYPE_GRAPHICS;
|
||||
psoDesc.Name = "MobileGL Diligent state PSO";
|
||||
psoDesc.ResourceLayout.DefaultVariableType = ::Diligent::SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC;
|
||||
graphicsPipeline.NumRenderTargets = 1;
|
||||
graphicsPipeline.RTVFormats[0] = ::Diligent::TEX_FORMAT_RGBA8_UNORM;
|
||||
graphicsPipeline.NumRenderTargets = static_cast<::Diligent::Uint8>(rtCount);
|
||||
for (Uint32 i = 0; i < rtCount; ++i) {
|
||||
graphicsPipeline.RTVFormats[i] = rtFormats[i];
|
||||
}
|
||||
graphicsPipeline.DSVFormat = ::Diligent::TEX_FORMAT_D24_UNORM_S8_UINT;
|
||||
switch (mode) {
|
||||
case GL_POINTS:
|
||||
|
||||
@@ -957,3 +957,92 @@ void main() { Color = vec4(1.0, 0.0, 0.0, 1.0); }
|
||||
EXPECT_GT(center[0], 200) << "center should be red in the renderbuffer framebuffer";
|
||||
EXPECT_LT(center[1], 50) << "center should not be green";
|
||||
}
|
||||
|
||||
|
||||
TEST(DiligentVulkanBackend, DrawsToMultipleColorAttachmentsFromMobileGLState) {
|
||||
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
|
||||
layout(location = 0) out vec4 Color0;
|
||||
layout(location = 1) out vec4 Color1;
|
||||
void main() {
|
||||
Color0 = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
Color1 = vec4(0.0, 0.0, 1.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 tex0 = 0, tex1 = 0;
|
||||
GenTextures(1, &tex0);
|
||||
BindTexture(GL_TEXTURE_2D, tex0);
|
||||
TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
GenTextures(1, &tex1);
|
||||
BindTexture(GL_TEXTURE_2D, tex1);
|
||||
TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
GLuint fbo = 0;
|
||||
GenFramebuffers(1, &fbo);
|
||||
BindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0, 0);
|
||||
FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex1, 0);
|
||||
const GLenum bufs[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
|
||||
DrawBuffers(2, bufs);
|
||||
|
||||
DiligentBackend::BackendObject_Diligent backend;
|
||||
backend.Initialize();
|
||||
auto* renderer = backend.GetRenderer();
|
||||
if (renderer == nullptr) {
|
||||
GTEST_SKIP() << "No Vulkan adapter available; skipping multi-color attachment test";
|
||||
}
|
||||
|
||||
renderer->Clear(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
renderer->DrawFromState(GL_TRIANGLES, 0, 3, 0, nullptr);
|
||||
renderer->Present();
|
||||
|
||||
ReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
std::uint8_t center0[4] = {};
|
||||
renderer->ReadPixels(128, 128, 1, 1, center0);
|
||||
EXPECT_GT(center0[0], 200) << "attachment 0 should be red";
|
||||
EXPECT_LT(center0[2], 50) << "attachment 0 should not be blue";
|
||||
|
||||
ReadBuffer(GL_COLOR_ATTACHMENT1);
|
||||
std::uint8_t center1[4] = {};
|
||||
renderer->ReadPixels(128, 128, 1, 1, center1);
|
||||
EXPECT_LT(center1[0], 50) << "attachment 1 should not be red";
|
||||
EXPECT_GT(center1[2], 200) << "attachment 1 should be blue";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user