Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move stencil state out of RasterState #5873

Merged
merged 1 commit into from
Aug 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 42 additions & 25 deletions filament/backend/include/backend/DriverEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -787,11 +787,9 @@ struct RasterState {
using DepthFunc = backend::SamplerCompareFunc;
using BlendEquation = backend::BlendEquation;
using BlendFunction = backend::BlendFunction;
using StencilFunction = backend::SamplerCompareFunc;
using StencilOperation = backend::StencilOperation;

RasterState() noexcept { // NOLINT
static_assert(sizeof(RasterState) == sizeof(uint64_t),
static_assert(sizeof(RasterState) == sizeof(uint32_t),
"RasterState size not what was intended");
culling = CullingMode::BACK;
blendEquationRGB = BlendEquation::ADD;
Expand All @@ -800,10 +798,6 @@ struct RasterState {
blendFunctionSrcAlpha = BlendFunction::ONE;
blendFunctionDstRGB = BlendFunction::ZERO;
blendFunctionDstAlpha = BlendFunction::ZERO;
stencilFunc = StencilFunction::A;
stencilOpStencilFail = StencilOperation::KEEP;
stencilOpDepthFail = StencilOperation::KEEP;
stencilOpDepthStencilPass = StencilOperation::KEEP;
}

bool operator == (RasterState rhs) const noexcept { return u == rhs.u; }
Expand Down Expand Up @@ -862,26 +856,10 @@ struct RasterState {
//! whether front face winding direction must be inverted
bool inverseFrontFaces : 1; // 31

//! Whether stencil-buffer writes are enabled
bool stencilWrite : 1; // 32
//! Stencil reference value
uint8_t stencilRef : 8; // 40
//! Stencil test function
StencilFunction stencilFunc : 3; // 43
//! Stencil operation when stencil test fails
StencilOperation stencilOpStencilFail : 3; // 46
//! padding, must be 0
uint8_t padding0 : 2; // 48
//! Stencil operation when stencil test passes but depth test fails
StencilOperation stencilOpDepthFail : 3; // 51
//! Stencil operation when both stencil and depth test pass
StencilOperation stencilOpDepthStencilPass : 3; // 54
//! padding, must be 0
uint8_t padding1 : 2; // 56
//! padding, must be 0
uint8_t padding2 : 8; // 64
uint8_t padding : 1; // 32
};
uint64_t u = 0;
uint32_t u = 0;
};
};

Expand Down Expand Up @@ -975,6 +953,45 @@ struct PolygonOffset {
float constant = 0; // units in GL-speak
};

struct StencilState {
using StencilFunction = SamplerCompareFunc;

StencilState() noexcept : referenceValue(0u), stencilWrite(false) {
static_assert(sizeof(StencilState) == 4u, "StencilState size not what was intended");
frontBack.u = 0u;
frontBack.stencilFunc = StencilFunction::A;
}

bool operator==(StencilState rhs) const noexcept {
return frontBack.u == rhs.frontBack.u &&
referenceValue == rhs.referenceValue &&
stencilWrite == rhs.stencilWrite;
}
bool operator!=(StencilState rhs) const noexcept { return !(*this == rhs); }

union StencilOperations {
struct {
//! Stencil test function
StencilFunction stencilFunc : 3;

//! Stencil operation when stencil test fails
StencilOperation stencilOpStencilFail : 3;

//! Stencil operation when stencil test passes but depth test fails
StencilOperation stencilOpDepthFail : 3;

//! Stencil operation when both stencil and depth test pass
StencilOperation stencilOpDepthStencilPass : 3;
};
uint16_t u = 0;
};

// TODO: separate out front and back stencil states.
StencilOperations frontBack;
uint8_t referenceValue;
//! Whether stencil-buffer writes are enabled
bool stencilWrite;
};

using FrameScheduledCallback = void(*)(PresentCallable callable, void* user);

Expand Down
1 change: 1 addition & 0 deletions filament/backend/include/backend/PipelineState.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace filament::backend {
struct PipelineState {
Handle<HwProgram> program;
RasterState rasterState;
StencilState stencilState;
PolygonOffset polygonOffset;
Viewport scissor{ 0, 0,
(uint32_t)std::numeric_limits<int32_t>::max(),
Expand Down
13 changes: 7 additions & 6 deletions filament/backend/src/metal/MetalDriver.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1234,12 +1234,13 @@
depthState.depthWriteEnabled = rs.depthWrite;
}
if (stencilAttachment) {
depthState.stencilCompare = getMetalCompareFunction(rs.stencilFunc);
depthState.stencilOperationDepthStencilPass = getMetalStencilOperation(rs.stencilOpDepthStencilPass);
depthState.stencilOperationDepthFail = getMetalStencilOperation(rs.stencilOpDepthFail);
depthState.stencilOperationStencilFail = getMetalStencilOperation(rs.stencilOpStencilFail);
depthState.stencilWriteEnabled = rs.stencilWrite;
[mContext->currentRenderPassEncoder setStencilReferenceValue:rs.stencilRef];
const auto& ss = ps.stencilState;
depthState.stencilCompare = getMetalCompareFunction(ss.frontBack.stencilFunc);
depthState.stencilOperationDepthStencilPass = getMetalStencilOperation(ss.frontBack.stencilOpDepthStencilPass);
depthState.stencilOperationDepthFail = getMetalStencilOperation(ss.frontBack.stencilOpDepthFail);
depthState.stencilOperationStencilFail = getMetalStencilOperation(ss.frontBack.stencilOpStencilFail);
depthState.stencilWriteEnabled = ss.stencilWrite;
[mContext->currentRenderPassEncoder setStencilReferenceValue:ss.referenceValue];
}
mContext->depthStencilState.updateState(depthState);
if (mContext->depthStencilState.stateChanged()) {
Expand Down
2 changes: 1 addition & 1 deletion filament/backend/src/metal/MetalEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ constexpr inline MTLCompareFunction getMetalCompareFunction(RasterState::DepthFu
}
}

constexpr inline MTLStencilOperation getMetalStencilOperation(RasterState::StencilOperation op) {
constexpr inline MTLStencilOperation getMetalStencilOperation(StencilOperation op) {
switch (op) {
case StencilOperation::KEEP: return MTLStencilOperationKeep;
case StencilOperation::ZERO: return MTLStencilOperationZero;
Expand Down
42 changes: 25 additions & 17 deletions filament/backend/src/opengl/OpenGLDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,19 +300,6 @@ void OpenGLDriver::setRasterStateSlow(RasterState rs) noexcept {
gl.depthMask(GLboolean(rs.depthWrite));
}

// stencil test / operation
if (rs.stencilFunc == RasterState::StencilFunction::A && !rs.stencilWrite) {
gl.disable(GL_STENCIL_TEST);
} else {
gl.enable(GL_STENCIL_TEST);
gl.stencilFunc(getStencilFunc(rs.stencilFunc), rs.stencilRef, ~GLuint(0));
gl.stencilOp(getStencilOp(rs.stencilOpStencilFail),
getStencilOp(rs.stencilOpDepthFail),
getStencilOp(rs.stencilOpDepthStencilPass));
GLuint stencilMask = rs.stencilWrite ? ~GLuint(0) : 0x00;
gl.stencilMask(stencilMask);
}

// write masks
gl.colorMask(GLboolean(rs.colorWrite));

Expand All @@ -324,6 +311,24 @@ void OpenGLDriver::setRasterStateSlow(RasterState rs) noexcept {
}
}

void OpenGLDriver::setStencilStateSlow(StencilState ss) noexcept {
mStencilState = ss;
auto& gl = mContext;

// stencil test / operation
if (ss.frontBack.stencilFunc == StencilState::StencilFunction::A && !ss.stencilWrite) {
gl.disable(GL_STENCIL_TEST);
} else {
gl.enable(GL_STENCIL_TEST);
gl.stencilFunc(getStencilFunc(ss.frontBack.stencilFunc), ss.referenceValue, ~GLuint(0));
gl.stencilOp(getStencilOp(ss.frontBack.stencilOpStencilFail),
getStencilOp(ss.frontBack.stencilOpDepthFail),
getStencilOp(ss.frontBack.stencilOpDepthStencilPass));
GLuint stencilMask = ss.stencilWrite ? ~GLuint(0) : 0x00;
gl.stencilMask(stencilMask);
}
}

// ------------------------------------------------------------------------------------------------
// Creating driver objects
// ------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -2884,19 +2889,21 @@ UTILS_NOINLINE
void OpenGLDriver::clearWithRasterPipe(TargetBufferFlags clearFlags,
math::float4 const& linearColor, GLfloat depth, GLint stencil) noexcept {
RasterState rs(mRasterState);
StencilState ss(mStencilState);

if (any(clearFlags & TargetBufferFlags::COLOR_ALL)) {
rs.colorWrite = true;
}
if (any(clearFlags & TargetBufferFlags::DEPTH)) {
rs.depthWrite = true;
}
if (any(clearFlags & TargetBufferFlags::STENCIL)) {
rs.stencilWrite = true;
}
if (any(clearFlags)) {
if (any(clearFlags & (TargetBufferFlags::COLOR_ALL | TargetBufferFlags::DEPTH))) {
setRasterState(rs);
}
if (any(clearFlags & TargetBufferFlags::STENCIL)) {
ss.stencilWrite = true;
setStencilState(ss);
}

if (any(clearFlags & TargetBufferFlags::COLOR0)) {
glClearBufferfv(GL_COLOR, 0, linearColor.v);
Expand Down Expand Up @@ -3056,6 +3063,7 @@ void OpenGLDriver::draw(PipelineState state, Handle<HwRenderPrimitive> rph, uint
}

setRasterState(state.rasterState);
setStencilState(state.stencilState);

gl.polygonOffset(state.polygonOffset.slope, state.polygonOffset.constant);

Expand Down
8 changes: 8 additions & 0 deletions filament/backend/src/opengl/OpenGLDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,13 @@ class OpenGLDriver final : public DriverBase {
}
}

void setStencilStateSlow(StencilState ss) noexcept;
void setStencilState(StencilState ss) noexcept {
if (UTILS_UNLIKELY(ss != mStencilState)) {
setStencilStateSlow(ss);
}
}

void setTextureData(GLTexture* t,
uint32_t level,
uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
Expand Down Expand Up @@ -337,6 +344,7 @@ class OpenGLDriver final : public DriverBase {
GLRenderTarget const* rt, TargetBufferFlags buffers) noexcept;

RasterState mRasterState;
StencilState mStencilState;

// state required to represent the current render pass
Handle<HwRenderTarget> mRenderPassTarget;
Expand Down
24 changes: 12 additions & 12 deletions filament/backend/test/test_StencilBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ class BasicStencilBufferTest : public BackendTest {
ps.program = program;
ps.rasterState.colorWrite = false;
ps.rasterState.depthWrite = false;
ps.rasterState.stencilWrite = true;
ps.rasterState.stencilOpDepthStencilPass = StencilOperation::INCR;
ps.stencilState.stencilWrite = true;
ps.stencilState.frontBack.stencilOpDepthStencilPass = StencilOperation::INCR;

api.makeCurrent(swapChain, swapChain);
api.beginFrame(0, 0);
Expand All @@ -120,10 +120,10 @@ class BasicStencilBufferTest : public BackendTest {
params.flags.clear = TargetBufferFlags::NONE;
params.flags.discardStart = TargetBufferFlags::NONE;
ps.rasterState.colorWrite = true;
ps.rasterState.stencilWrite = false;
ps.rasterState.stencilOpDepthStencilPass = StencilOperation::KEEP;
ps.rasterState.stencilFunc = RasterState::StencilFunction::E;
ps.rasterState.stencilRef = 0u;
ps.stencilState.stencilWrite = false;
ps.stencilState.frontBack.stencilOpDepthStencilPass = StencilOperation::KEEP;
ps.stencilState.frontBack.stencilFunc = StencilState::StencilFunction::E;
ps.stencilState.referenceValue = 0u;

api.beginRenderPass(renderTarget, params);
api.draw(ps, triangle.getRenderPrimitive(), 1);
Expand Down Expand Up @@ -233,8 +233,8 @@ TEST_F(BasicStencilBufferTest, StencilBufferMSAA) {
ps.program = program;
ps.rasterState.colorWrite = false;
ps.rasterState.depthWrite = false;
ps.rasterState.stencilWrite = true;
ps.rasterState.stencilOpDepthStencilPass = StencilOperation::INCR;
ps.stencilState.stencilWrite = true;
ps.stencilState.frontBack.stencilOpDepthStencilPass = StencilOperation::INCR;

api.makeCurrent(swapChain, swapChain);
api.beginFrame(0, 0);
Expand All @@ -249,10 +249,10 @@ TEST_F(BasicStencilBufferTest, StencilBufferMSAA) {
params.flags.discardEnd = TargetBufferFlags::STENCIL;
params.clearColor = math::float4(0.0f, 0.0f, 1.0f, 1.0f);
ps.rasterState.colorWrite = true;
ps.rasterState.stencilWrite = false;
ps.rasterState.stencilOpDepthStencilPass = StencilOperation::KEEP;
ps.rasterState.stencilFunc = RasterState::StencilFunction::E;
ps.rasterState.stencilRef = 0u;
ps.stencilState.stencilWrite = false;
ps.stencilState.frontBack.stencilOpDepthStencilPass = StencilOperation::KEEP;
ps.stencilState.frontBack.stencilFunc = StencilState::StencilFunction::E;
ps.stencilState.referenceValue = 0u;

api.beginRenderPass(renderTarget1, params);
api.draw(ps, triangle.getRenderPrimitive(), 1);
Expand Down