mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +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`
|
- `DrawsWithBlendFromMobileGLState`
|
||||||
- `DrawsWithDepthTestFromMobileGLState`
|
- `DrawsWithDepthTestFromMobileGLState`
|
||||||
- `DrawsNamedUniformBlockFromMobileGLState`
|
- `DrawsNamedUniformBlockFromMobileGLState`
|
||||||
|
- `DrawsWithStencilTestFromMobileGLState`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -128,6 +129,7 @@ Verified locally on Turnip Adreno 750:
|
|||||||
- Textured draw test passes
|
- Textured draw test passes
|
||||||
- Render state:
|
- Render state:
|
||||||
- Blend enable/factors/equations
|
- Blend enable/factors/equations
|
||||||
|
- Stencil clear + test enabled on a D24S8 default depth/stencil target
|
||||||
- Depth test enable/func/write mask
|
- Depth test enable/func/write mask
|
||||||
- Cull face enable/mode/front-face winding
|
- Cull face enable/mode/front-face winding
|
||||||
- Stencil test enable/masks/ops/func/ref
|
- Stencil test enable/masks/ops/func/ref
|
||||||
@@ -156,7 +158,7 @@ Verified locally on Turnip Adreno 750:
|
|||||||
- Local test result:
|
- Local test result:
|
||||||
|
|
||||||
```
|
```
|
||||||
[ PASSED ] 12 tests
|
[ PASSED ] 13 tests
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -248,7 +250,7 @@ Notes:
|
|||||||
- [x] Texture filtering / sampler state test
|
- [x] Texture filtering / sampler state test
|
||||||
- [x] framebuffer offscreen render-to-texture test
|
- [x] framebuffer offscreen render-to-texture test
|
||||||
- [x] Depth test visual 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) {
|
if ((mask & GL_DEPTH_BUFFER_BIT) != 0) {
|
||||||
renderer->ClearDepth(MG_State::pGLContext->GetClearDepth());
|
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) {
|
void DrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ void main()
|
|||||||
::Diligent::TextureDesc depthDesc;
|
::Diligent::TextureDesc depthDesc;
|
||||||
depthDesc.Name = "MobileGL Diligent offscreen depth target";
|
depthDesc.Name = "MobileGL Diligent offscreen depth target";
|
||||||
depthDesc.Type = ::Diligent::RESOURCE_DIM_TEX_2D;
|
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.Width = m_width;
|
||||||
depthDesc.Height = m_height;
|
depthDesc.Height = m_height;
|
||||||
depthDesc.MipLevels = 1;
|
depthDesc.MipLevels = 1;
|
||||||
@@ -535,6 +535,21 @@ void main()
|
|||||||
::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
|
::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() {
|
void DiligentRenderer::DrawTriangle() {
|
||||||
if (!m_initialized || !m_pContext || !m_pPSO) {
|
if (!m_initialized || !m_pContext || !m_pPSO) {
|
||||||
return;
|
return;
|
||||||
@@ -1315,7 +1330,7 @@ void main()
|
|||||||
psoDesc.ResourceLayout.DefaultVariableType = ::Diligent::SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC;
|
psoDesc.ResourceLayout.DefaultVariableType = ::Diligent::SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC;
|
||||||
graphicsPipeline.NumRenderTargets = 1;
|
graphicsPipeline.NumRenderTargets = 1;
|
||||||
graphicsPipeline.RTVFormats[0] = ::Diligent::TEX_FORMAT_RGBA8_UNORM;
|
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) {
|
switch (mode) {
|
||||||
case GL_POINTS:
|
case GL_POINTS:
|
||||||
graphicsPipeline.PrimitiveTopology = ::Diligent::PRIMITIVE_TOPOLOGY_POINT_LIST;
|
graphicsPipeline.PrimitiveTopology = ::Diligent::PRIMITIVE_TOPOLOGY_POINT_LIST;
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
|||||||
Bool Initialize(Uint32 width, Uint32 height);
|
Bool Initialize(Uint32 width, Uint32 height);
|
||||||
void Clear(Float r, Float g, Float b, Float a);
|
void Clear(Float r, Float g, Float b, Float a);
|
||||||
void ClearDepth(Float depth);
|
void ClearDepth(Float depth);
|
||||||
|
void ClearStencil(Uint32 stencil);
|
||||||
void DrawTriangle();
|
void DrawTriangle();
|
||||||
void DrawVertices(const Float* vertices, Uint32 vertexCount);
|
void DrawVertices(const Float* vertices, Uint32 vertexCount);
|
||||||
// Creates a simple 2D RGBA8 texture from CPU data and makes it available
|
// 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_LT(center[1], 50) << "center should not be green";
|
||||||
EXPECT_GT(center[2], 200) << "center should be blue from the named uniform block";
|
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