mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 20:28:32 +09:00
[Feat, Test] (Diligent, MG_Test): add stencil clear and stencil state test
- Use D24S8 for the default offscreen depth/stencil target - Wire GL_STENCIL_BUFFER_BIT Clear through renderer->ClearStencil - Add DrawsWithStencilTestFromMobileGLState; 13 Diligent tests pass
This commit is contained in:
+4
-2
@@ -105,6 +105,7 @@ Working tree is clean.
|
||||
- `DrawsWithBlendFromMobileGLState`
|
||||
- `DrawsWithDepthTestFromMobileGLState`
|
||||
- `DrawsNamedUniformBlockFromMobileGLState`
|
||||
- `DrawsWithStencilTestFromMobileGLState`
|
||||
|
||||
---
|
||||
|
||||
@@ -128,6 +129,7 @@ Verified locally on Turnip Adreno 750:
|
||||
- Textured draw test passes
|
||||
- Render state:
|
||||
- Blend enable/factors/equations
|
||||
- Stencil clear + test enabled on a D24S8 default depth/stencil target
|
||||
- Depth test enable/func/write mask
|
||||
- Cull face enable/mode/front-face winding
|
||||
- Stencil test enable/masks/ops/func/ref
|
||||
@@ -156,7 +158,7 @@ Verified locally on Turnip Adreno 750:
|
||||
- Local test result:
|
||||
|
||||
```
|
||||
[ PASSED ] 12 tests
|
||||
[ PASSED ] 13 tests
|
||||
```
|
||||
|
||||
---
|
||||
@@ -248,7 +250,7 @@ Notes:
|
||||
- [x] Texture filtering / sampler state test
|
||||
- [x] framebuffer offscreen render-to-texture test
|
||||
- [x] Depth test visual test
|
||||
- [ ] Stencil test
|
||||
- [x] Stencil test
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -47,6 +47,9 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
if ((mask & GL_DEPTH_BUFFER_BIT) != 0) {
|
||||
renderer->ClearDepth(MG_State::pGLContext->GetClearDepth());
|
||||
}
|
||||
if ((mask & GL_STENCIL_BUFFER_BIT) != 0) {
|
||||
renderer->ClearStencil(MG_State::pGLContext->GetClearStencil());
|
||||
}
|
||||
}
|
||||
|
||||
void DrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||
|
||||
@@ -406,7 +406,7 @@ void main()
|
||||
::Diligent::TextureDesc depthDesc;
|
||||
depthDesc.Name = "MobileGL Diligent offscreen depth target";
|
||||
depthDesc.Type = ::Diligent::RESOURCE_DIM_TEX_2D;
|
||||
depthDesc.Format = ::Diligent::TEX_FORMAT_D32_FLOAT;
|
||||
depthDesc.Format = ::Diligent::TEX_FORMAT_D24_UNORM_S8_UINT;
|
||||
depthDesc.Width = m_width;
|
||||
depthDesc.Height = m_height;
|
||||
depthDesc.MipLevels = 1;
|
||||
@@ -535,6 +535,21 @@ void main()
|
||||
::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
|
||||
}
|
||||
|
||||
void DiligentRenderer::ClearStencil(Uint32 stencil) {
|
||||
if (!m_initialized || !m_pContext) {
|
||||
return;
|
||||
}
|
||||
Vector<::Diligent::ITextureView*> rtvs;
|
||||
::Diligent::ITextureView* dsv = nullptr;
|
||||
if (!ResolveCurrentRenderTargets(rtvs, dsv) || dsv == nullptr) {
|
||||
return;
|
||||
}
|
||||
m_pContext->SetRenderTargets(static_cast<::Diligent::Uint32>(rtvs.size()), rtvs.data(), dsv,
|
||||
::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
|
||||
m_pContext->ClearDepthStencil(dsv, ::Diligent::CLEAR_STENCIL_FLAG, 0, stencil,
|
||||
::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
|
||||
}
|
||||
|
||||
void DiligentRenderer::DrawTriangle() {
|
||||
if (!m_initialized || !m_pContext || !m_pPSO) {
|
||||
return;
|
||||
@@ -1315,7 +1330,7 @@ void main()
|
||||
psoDesc.ResourceLayout.DefaultVariableType = ::Diligent::SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC;
|
||||
graphicsPipeline.NumRenderTargets = 1;
|
||||
graphicsPipeline.RTVFormats[0] = ::Diligent::TEX_FORMAT_RGBA8_UNORM;
|
||||
graphicsPipeline.DSVFormat = ::Diligent::TEX_FORMAT_D32_FLOAT;
|
||||
graphicsPipeline.DSVFormat = ::Diligent::TEX_FORMAT_D24_UNORM_S8_UINT;
|
||||
switch (mode) {
|
||||
case GL_POINTS:
|
||||
graphicsPipeline.PrimitiveTopology = ::Diligent::PRIMITIVE_TOPOLOGY_POINT_LIST;
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
Bool Initialize(Uint32 width, Uint32 height);
|
||||
void Clear(Float r, Float g, Float b, Float a);
|
||||
void ClearDepth(Float depth);
|
||||
void ClearStencil(Uint32 stencil);
|
||||
void DrawTriangle();
|
||||
void DrawVertices(const Float* vertices, Uint32 vertexCount);
|
||||
// Creates a simple 2D RGBA8 texture from CPU data and makes it available
|
||||
|
||||
@@ -798,3 +798,90 @@ void main() { Color = u_color; }
|
||||
EXPECT_LT(center[1], 50) << "center should not be green";
|
||||
EXPECT_GT(center[2], 200) << "center should be blue from the named uniform block";
|
||||
}
|
||||
|
||||
|
||||
TEST(DiligentVulkanBackend, DrawsWithStencilTestFromMobileGLState) {
|
||||
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* redFsSrc = R"(#version 330 core
|
||||
out vec4 Color;
|
||||
void main() { Color = vec4(1.0, 0.0, 0.0, 1.0); }
|
||||
)";
|
||||
const char* blueFsSrc = R"(#version 330 core
|
||||
out vec4 Color;
|
||||
void main() { Color = 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 redFs = CreateShader(GL_FRAGMENT_SHADER);
|
||||
ShaderSource(redFs, 1, &redFsSrc, nullptr);
|
||||
CompileShader(redFs);
|
||||
const GLuint redProgram = CreateProgram();
|
||||
AttachShader(redProgram, vs);
|
||||
AttachShader(redProgram, redFs);
|
||||
LinkProgram(redProgram);
|
||||
const GLuint blueFs = CreateShader(GL_FRAGMENT_SHADER);
|
||||
ShaderSource(blueFs, 1, &blueFsSrc, nullptr);
|
||||
CompileShader(blueFs);
|
||||
const GLuint blueProgram = CreateProgram();
|
||||
AttachShader(blueProgram, vs);
|
||||
AttachShader(blueProgram, blueFs);
|
||||
LinkProgram(blueProgram);
|
||||
|
||||
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);
|
||||
|
||||
BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
Disable(GL_DEPTH_TEST);
|
||||
Disable(GL_BLEND);
|
||||
Disable(GL_SCISSOR_TEST);
|
||||
Viewport(0, 0, 256, 256);
|
||||
|
||||
DiligentBackend::BackendObject_Diligent backend;
|
||||
backend.Initialize();
|
||||
auto* renderer = backend.GetRenderer();
|
||||
if (renderer == nullptr) {
|
||||
GTEST_SKIP() << "No Vulkan adapter available; skipping stencil state test";
|
||||
}
|
||||
|
||||
renderer->Clear(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
renderer->ClearStencil(0);
|
||||
|
||||
Enable(GL_STENCIL_TEST);
|
||||
StencilMask(0xFF);
|
||||
StencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
UseProgram(redProgram);
|
||||
renderer->DrawFromState(GL_TRIANGLES, 0, 3, 0, nullptr);
|
||||
|
||||
// Second draw should fail the stencil test (ref 2 != stencil value 1).
|
||||
StencilFunc(GL_EQUAL, 2, 0xFF);
|
||||
StencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
UseProgram(blueProgram);
|
||||
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 remain red after failing stencil draw";
|
||||
EXPECT_LT(center[2], 50) << "center should not become blue";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user