Skip to content

Commit 46b75f1

Browse files
committed
Unify stencil state to single uint64_t and update masks
1 parent 5b2f0a1 commit 46b75f1

8 files changed

Lines changed: 200 additions & 82 deletions

File tree

src/vrhi_backend.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ bool vhCmdBackendState::BE_PresubmitCommon_PipelineDesc(
418418
{
419419
graphicsPipelineDesc->setPrimType( vhTranslatePrimitiveType( state.stateFlags ) );
420420
graphicsPipelineDesc->renderState.blendState = vhTranslateBlendState( state.stateFlags );
421-
graphicsPipelineDesc->renderState.depthStencilState = vhTranslateDepthStencilState( state.stateFlags, state.frontStencil, state.backStencil );
421+
graphicsPipelineDesc->renderState.depthStencilState = vhTranslateDepthStencilState( state.stateFlags, state.stencilState );
422422
graphicsPipelineDesc->renderState.rasterState = vhTranslateRasterState( state.stateFlags );
423423
graphicsPipelineDesc->renderState.rasterState.scissorEnable = ( state.viewScissor.z >= 0.0f && state.viewScissor.w >= 0.0f );
424424
graphicsPipelineDesc->renderState.rasterState.depthBias = state.depthBias;
@@ -1110,7 +1110,7 @@ bool vhCmdBackendState::BE_PreSubmitCommon_State(
11101110
}
11111111

11121112
// nvrhi::DepthStencilState::dynamicStencilRefValue is false, but we set this any way because it's fun.
1113-
graphicsState->dynamicStencilRefValue = ( uint8_t ) ( ( state.frontStencil & VRHI_STENCIL_FUNC_REF_MASK ) >> VRHI_STENCIL_FUNC_REF_SHIFT );
1113+
graphicsState->dynamicStencilRefValue = ( uint8_t ) ( ( state.stencilState & VRHI_STENCIL_FUNC_REF_MASK ) >> VRHI_STENCIL_FUNC_REF_SHIFT );
11141114

11151115
// Bind Framebuffer
11161116
graphicsState->framebuffer = fb ? fb : BE_GetFrameBuffer( state.colourAttachment, state.depthAttachment, state.shadingRateImage );
@@ -2091,8 +2091,7 @@ void vhCmdBackendState::Handle_vhCmdSetStateStencil( VIDL_vhCmdSetStateStencil*
20912091
{
20922092
BE_CmdRAII cmdRAII( cmd );
20932093
auto& state = backendStates[cmd->id];
2094-
state.frontStencil = cmd->front;
2095-
state.backStencil = cmd->back;
2094+
state.stencilState = cmd->stencilState;
20962095
}
20972096

20982097
void vhCmdBackendState::Handle_vhCmdSetStateDepthBias( VIDL_vhCmdSetStateDepthBias* cmd )

src/vrhi_generated.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -502,13 +502,12 @@ struct VIDL_vhCmdSetStateStencil
502502
static constexpr uint64_t kMagic = 0x007FD9BA;
503503
uint64_t MAGIC = kMagic;
504504
vhStateId id;
505-
uint64_t front;
506-
uint64_t back;
505+
uint64_t stencilState;
507506

508507
VIDL_vhCmdSetStateStencil() = default;
509508

510-
VIDL_vhCmdSetStateStencil(vhStateId _id, uint64_t _front, uint64_t _back)
511-
: id(_id), front(_front), back(_back) {}
509+
VIDL_vhCmdSetStateStencil(vhStateId _id, uint64_t _stencilState)
510+
: id(_id), stencilState(_stencilState) {}
512511
};
513512

514513
struct VIDL_vhCmdSetStateDepthBias

src/vrhi_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ void vhWriteStateToGlobalUniform( const vhState& state, vhGlobalUniform& out );
277277
void vhWriteStateToWorldUniform( const vhState& state, vhWorldUniform& out );
278278
nvrhi::PrimitiveType vhTranslatePrimitiveType( uint64_t stateFlags );
279279
nvrhi::BlendState vhTranslateBlendState( uint64_t stateFlags );
280-
nvrhi::DepthStencilState vhTranslateDepthStencilState( uint64_t stateFlags, uint64_t frontStencil, uint64_t backStencil );
280+
nvrhi::DepthStencilState vhTranslateDepthStencilState( uint64_t stateFlags, uint64_t stencilState );
281281
nvrhi::RasterState vhTranslateRasterState( uint64_t stateFlags );
282282
nvrhi::VariableShadingRate vhTranslateShadingRate( uint32_t rate );
283283
nvrhi::ShadingRateCombiner vhTranslateShadingRateCombiner( uint32_t combiner );

src/vrhi_state.cpp

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ void vhCmdSetStateDebugFlags( vhStateId id, uint64_t flags )
7070
vhCmdEnqueue( new VIDL_vhCmdSetStateDebugFlags( id, flags ) );
7171
}
7272

73-
void vhCmdSetStateStencil( vhStateId id, uint64_t front, uint64_t back )
73+
void vhCmdSetStateStencil( vhStateId id, uint64_t stencilState )
7474
{
75-
vhCmdEnqueue( new VIDL_vhCmdSetStateStencil( id, front, back ) );
75+
vhCmdEnqueue( new VIDL_vhCmdSetStateStencil( id, stencilState ) );
7676
}
7777

7878
void vhCmdSetStateDepthBias( vhStateId id, int bias, float clamp, float slopeScaled )
@@ -156,7 +156,7 @@ bool vhSetState( vhStateId id, vhState& state, uint64_t dirtyForceMask )
156156
{
157157
vhCmdSetStateFlags( id, state.stateFlags );
158158
vhCmdSetStateDebugFlags( id, state.debugFlags );
159-
vhCmdSetStateStencil( id, state.frontStencil, state.backStencil );
159+
vhCmdSetStateStencil( id, state.stencilState );
160160
}
161161

162162
if ( dirty & VRHI_DIRTY_DEPTH_BIAS )
@@ -344,7 +344,7 @@ nvrhi::BlendState vhTranslateBlendState( uint64_t stateFlags )
344344
return blendState;
345345
}
346346

347-
nvrhi::DepthStencilState vhTranslateDepthStencilState( uint64_t stateFlags, uint64_t frontStencil, uint64_t backStencil )
347+
nvrhi::DepthStencilState vhTranslateDepthStencilState( uint64_t stateFlags, uint64_t stencilState )
348348
{
349349
nvrhi::DepthStencilState dsState;
350350

@@ -425,38 +425,30 @@ nvrhi::DepthStencilState vhTranslateDepthStencilState( uint64_t stateFlags, uint
425425
desc.stencilFunc = fnConvertComparisonFunc( func );
426426
};
427427

428-
if ( frontStencil != VRHI_STENCIL_NONE || backStencil != VRHI_STENCIL_NONE )
428+
if ( stencilState != VRHI_STENCIL_NONE )
429429
{
430430
dsState.stencilEnable = true;
431-
fnUnpackStencilFront( frontStencil, dsState.frontFaceStencil );
431+
fnUnpackStencilFront( stencilState, dsState.frontFaceStencil );
432432

433433
bool backFaceSet = false;
434434

435-
if ( backStencil != VRHI_STENCIL_NONE )
435+
// Check if stencilState contains baked Back Face bits (mask 0x0FFFF000000000000)
436+
if ( ( stencilState & 0x0FFFF000000000000ULL ) != 0 )
436437
{
437-
fnUnpackStencilFront( backStencil, dsState.backFaceStencil );
438+
fnUnpackStencilBack( stencilState, dsState.backFaceStencil );
438439
backFaceSet = true;
439440
}
440-
else
441-
{
442-
// Check if frontStencil contains baked Back Face bits (mask 0xFFFF0000000000)
443-
if ( ( frontStencil & 0xFFFF0000000000ULL ) != 0 )
444-
{
445-
fnUnpackStencilBack( frontStencil, dsState.backFaceStencil );
446-
backFaceSet = true;
447-
}
448-
}
449441

450442
if ( !backFaceSet )
451443
{
452444
dsState.backFaceStencil = dsState.frontFaceStencil;
453445
}
454446

455-
dsState.stencilRefValue = ( uint8_t ) ( ( frontStencil & VRHI_STENCIL_FUNC_REF_MASK ) >> VRHI_STENCIL_FUNC_REF_SHIFT );
456-
dsState.stencilReadMask = ( uint8_t ) ( ( frontStencil & VRHI_STENCIL_FUNC_RMASK_MASK ) >> VRHI_STENCIL_FUNC_RMASK_SHIFT );
447+
dsState.stencilRefValue = ( uint8_t ) ( ( stencilState & VRHI_STENCIL_FUNC_REF_MASK ) >> VRHI_STENCIL_FUNC_REF_SHIFT );
448+
dsState.stencilReadMask = ( uint8_t ) ( ( stencilState & VRHI_STENCIL_FUNC_RMASK_MASK ) >> VRHI_STENCIL_FUNC_RMASK_SHIFT );
457449

458-
uint8_t wmask = ( uint8_t ) ( ( frontStencil & VRHI_STENCIL_FUNC_WMASK_MASK ) >> VRHI_STENCIL_FUNC_WMASK_SHIFT );
459-
if ( wmask != 0 || ( frontStencil & VRHI_STENCIL_FUNC_WMASK_MASK ) != 0 )
450+
uint8_t wmask = ( uint8_t ) ( ( stencilState & VRHI_STENCIL_FUNC_WMASK_MASK ) >> VRHI_STENCIL_FUNC_WMASK_SHIFT );
451+
if ( wmask != 0 || ( stencilState & VRHI_STENCIL_FUNC_WMASK_MASK ) != 0 )
460452
{
461453
dsState.stencilWriteMask = wmask;
462454
}

test/test_gfx.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -503,19 +503,19 @@ UTEST_F( Graphics, StencilTest )
503503
.SetProgram( vhCreateGfxProgram( vs, ps ) )
504504
.SetVertexBuffer( vb, 0 );
505505

506-
// Pass 1: Write 1 to stencil
506+
// Pass 1: Write 1 to stencil (using helper overload)
507507
state.SetStateFlags( VRHI_STATE_WRITE_MASK )
508-
.SetStencil( VRHI_STENCIL_TEST_ALWAYS | VRHI_STENCIL_OP_FAIL_S_REPLACE | VRHI_STENCIL_OP_FAIL_Z_REPLACE | VRHI_STENCIL_OP_PASS_Z_REPLACE | VRHI_STENCIL_FUNC_REF( 1 ) );
508+
.SetStencil( 1, 0xFF, 0xFF, VRHI_STENCIL_TEST_ALWAYS, VRHI_STENCIL_OP_FAIL_S_REPLACE, VRHI_STENCIL_OP_FAIL_Z_REPLACE, VRHI_STENCIL_OP_PASS_Z_REPLACE );
509509

510510
vhStateId sid1 = 501;
511511
vhSetState( sid1, state );
512512
vhClear( sid1, VRHI_CLEAR_COLOR | VRHI_CLEAR_STENCIL );
513513
vhDraw( sid1, 6 );
514514
vhFinish();
515515

516-
// Pass 2: Only draw if stencil is 0 (should draw nothing)
516+
// Pass 2: Only draw if stencil is 0 (should draw nothing) - using packed format
517517
state.SetViewClear( VRHI_CLEAR_COLOR, glm::vec4( 0.0f, 0.0f, 0.0f, 1.0f ) )
518-
.SetStencil( VRHI_STENCIL_TEST_EQUAL | VRHI_STENCIL_OP_FAIL_S_KEEP | VRHI_STENCIL_OP_FAIL_Z_KEEP | VRHI_STENCIL_OP_PASS_Z_KEEP | VRHI_STENCIL_FUNC_REF( 0 ) );
518+
.SetStencil( VRHI_STENCIL_FUNC_REF( 0 ) | VRHI_STENCIL_FUNC_RMASK( 0xFF ) | VRHI_STENCIL_FUNC_WMASK( 0xFF ) | VRHI_STENCIL_TEST_EQUAL | VRHI_STENCIL_OP_FAIL_S_KEEP | VRHI_STENCIL_OP_FAIL_Z_KEEP | VRHI_STENCIL_OP_PASS_Z_KEEP );
519519

520520
vhStateId sid2 = 502;
521521
vhSetState( sid2, state.DirtyAll() );
@@ -524,8 +524,8 @@ UTEST_F( Graphics, StencilTest )
524524
vhFinish();
525525
EXPECT_TRUE( VerifyPixel( rt, 32, 32, 0xFF000000 ) ); // Black
526526

527-
// Pass 3: Only draw if stencil is 1 (should draw white)
528-
state.SetStencil( VRHI_STENCIL_TEST_EQUAL | VRHI_STENCIL_OP_FAIL_S_KEEP | VRHI_STENCIL_OP_FAIL_Z_KEEP | VRHI_STENCIL_OP_PASS_Z_KEEP | VRHI_STENCIL_FUNC_REF( 1 ) );
527+
// Pass 3: Only draw if stencil is 1 (should draw white) - using helper overload
528+
state.SetStencil( 1, 0xFF, 0xFF, VRHI_STENCIL_TEST_EQUAL, VRHI_STENCIL_OP_FAIL_S_KEEP, VRHI_STENCIL_OP_FAIL_Z_KEEP, VRHI_STENCIL_OP_PASS_Z_KEEP );
529529

530530
vhStateId sid3 = 503;
531531
vhSetState( sid3, state.DirtyAll() );

test/test_shader.cpp

Lines changed: 126 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ UTEST( ShaderInternal, StateToDesc )
7070
nvrhi::RasterState rs = vhTranslateRasterState( VRHI_STATE_DEFAULT );
7171
EXPECT_EQ( rs.cullMode, nvrhi::RasterCullMode::Back );
7272

73-
nvrhi::DepthStencilState ds = vhTranslateDepthStencilState( VRHI_STATE_DEFAULT, 0, 0 );
73+
nvrhi::DepthStencilState ds = vhTranslateDepthStencilState( VRHI_STATE_DEFAULT, VRHI_STENCIL_NONE );
7474
EXPECT_TRUE( ds.depthTestEnable );
7575
EXPECT_EQ( ds.depthFunc, nvrhi::ComparisonFunc::Less );
7676
EXPECT_TRUE( ds.depthWriteEnable );
@@ -85,7 +85,7 @@ UTEST( ShaderInternal, StateToDesc )
8585

8686
// Test Depth Always
8787
{
88-
nvrhi::DepthStencilState ds = vhTranslateDepthStencilState( VRHI_STATE_DEPTH_TEST_ALWAYS, 0, 0 );
88+
nvrhi::DepthStencilState ds = vhTranslateDepthStencilState( VRHI_STATE_DEPTH_TEST_ALWAYS, VRHI_STENCIL_NONE );
8989
EXPECT_TRUE( ds.depthTestEnable );
9090
EXPECT_EQ( ds.depthFunc, nvrhi::ComparisonFunc::Always );
9191
}
@@ -100,7 +100,7 @@ UTEST( ShaderInternal, StateToDesc )
100100
VRHI_STENCIL_OP_FAIL_Z_REPLACE |
101101
VRHI_STENCIL_OP_PASS_Z_INCR;
102102

103-
nvrhi::DepthStencilState ds = vhTranslateDepthStencilState( VRHI_STATE_DEFAULT, stencil, VRHI_STENCIL_NONE );
103+
nvrhi::DepthStencilState ds = vhTranslateDepthStencilState( VRHI_STATE_DEFAULT, stencil );
104104

105105
EXPECT_TRUE( ds.stencilEnable );
106106
EXPECT_EQ( ds.stencilRefValue, 0x80 );
@@ -117,22 +117,143 @@ UTEST( ShaderInternal, StateToDesc )
117117
EXPECT_EQ( ds.backFaceStencil.passOp, nvrhi::StencilOp::IncrementAndWrap );
118118
}
119119

120-
// Test Stencil Separate
120+
// Test Stencil Separate (manually packed into single uint64_t)
121121
{
122122
uint64_t front = VRHI_STENCIL_TEST_ALWAYS | VRHI_STENCIL_OP_PASS_Z_KEEP;
123123
uint64_t back = VRHI_STENCIL_TEST_NEVER | VRHI_STENCIL_OP_PASS_Z_REPLACE;
124+
125+
// Pack back face bits into the unified format
126+
uint64_t packedStencil = front |
127+
((back & VRHI_STENCIL_TEST_MASK) << (VRHI_STENCIL_BACK_TEST_SHIFT - VRHI_STENCIL_TEST_SHIFT)) |
128+
((back & VRHI_STENCIL_OP_PASS_Z_MASK) << (VRHI_STENCIL_BACK_OP_PASS_Z_SHIFT - VRHI_STENCIL_OP_PASS_Z_SHIFT));
129+
130+
nvrhi::DepthStencilState ds = vhTranslateDepthStencilState( VRHI_STATE_DEFAULT, packedStencil );
131+
132+
EXPECT_TRUE( ds.stencilEnable );
133+
EXPECT_EQ( ds.frontFaceStencil.stencilFunc, nvrhi::ComparisonFunc::Always );
134+
EXPECT_EQ( ds.frontFaceStencil.passOp, nvrhi::StencilOp::Keep );
135+
136+
EXPECT_EQ( ds.backFaceStencil.stencilFunc, nvrhi::ComparisonFunc::Never );
137+
EXPECT_EQ( ds.backFaceStencil.passOp, nvrhi::StencilOp::Replace );
138+
}
139+
}
140+
141+
// Test that verifies all stencil mask/shift combinations extract correct values
142+
UTEST_F( Shader, StencilMaskShiftConsistency )
143+
{
144+
// Test VRHI_STENCIL_TEST_* constants
145+
{
146+
EXPECT_EQ( (VRHI_STENCIL_TEST_LESS & VRHI_STENCIL_TEST_MASK) >> VRHI_STENCIL_TEST_SHIFT, 1 );
147+
EXPECT_EQ( (VRHI_STENCIL_TEST_EQUAL & VRHI_STENCIL_TEST_MASK) >> VRHI_STENCIL_TEST_SHIFT, 3 );
148+
EXPECT_EQ( (VRHI_STENCIL_TEST_ALWAYS & VRHI_STENCIL_TEST_MASK) >> VRHI_STENCIL_TEST_SHIFT, 8 );
149+
}
150+
151+
// Test VRHI_STENCIL_OP_FAIL_S_* constants
152+
{
153+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_S_KEEP & VRHI_STENCIL_OP_FAIL_S_MASK) >> VRHI_STENCIL_OP_FAIL_S_SHIFT, 1 );
154+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_S_REPLACE & VRHI_STENCIL_OP_FAIL_S_MASK) >> VRHI_STENCIL_OP_FAIL_S_SHIFT, 2 );
155+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_S_INCR & VRHI_STENCIL_OP_FAIL_S_MASK) >> VRHI_STENCIL_OP_FAIL_S_SHIFT, 3 );
156+
}
157+
158+
// Test VRHI_STENCIL_OP_FAIL_Z_* constants
159+
{
160+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_Z_KEEP & VRHI_STENCIL_OP_FAIL_Z_MASK) >> VRHI_STENCIL_OP_FAIL_Z_SHIFT, 1 );
161+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_Z_REPLACE & VRHI_STENCIL_OP_FAIL_Z_MASK) >> VRHI_STENCIL_OP_FAIL_Z_SHIFT, 2 );
162+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_Z_INCR & VRHI_STENCIL_OP_FAIL_Z_MASK) >> VRHI_STENCIL_OP_FAIL_Z_SHIFT, 3 );
163+
}
164+
165+
// Test VRHI_STENCIL_OP_PASS_Z_* constants
166+
{
167+
EXPECT_EQ( (VRHI_STENCIL_OP_PASS_Z_KEEP & VRHI_STENCIL_OP_PASS_Z_MASK) >> VRHI_STENCIL_OP_PASS_Z_SHIFT, 1 );
168+
EXPECT_EQ( (VRHI_STENCIL_OP_PASS_Z_REPLACE & VRHI_STENCIL_OP_PASS_Z_MASK) >> VRHI_STENCIL_OP_PASS_Z_SHIFT, 2 );
169+
EXPECT_EQ( (VRHI_STENCIL_OP_PASS_Z_INCR & VRHI_STENCIL_OP_PASS_Z_MASK) >> VRHI_STENCIL_OP_PASS_Z_SHIFT, 3 );
170+
}
124171

125-
nvrhi::DepthStencilState ds = vhTranslateDepthStencilState( VRHI_STATE_DEFAULT, front, back );
172+
// Test FUNC_REF, RMASK, WMASK constants
173+
{
174+
EXPECT_EQ( (VRHI_STENCIL_FUNC_REF(0x80) & VRHI_STENCIL_FUNC_REF_MASK) >> VRHI_STENCIL_FUNC_REF_SHIFT, 0x80 );
175+
EXPECT_EQ( (VRHI_STENCIL_FUNC_RMASK(0xFF) & VRHI_STENCIL_FUNC_RMASK_MASK) >> VRHI_STENCIL_FUNC_RMASK_SHIFT, 0xFF );
176+
EXPECT_EQ( (VRHI_STENCIL_FUNC_WMASK(0x7F) & VRHI_STENCIL_FUNC_WMASK_MASK) >> VRHI_STENCIL_FUNC_WMASK_SHIFT, 0x7F );
177+
}
178+
}
126179

180+
// Test that verifies unified stencil packing of separate front/back states
181+
UTEST_F( Shader, StencilUnifiedPacking )
182+
{
183+
// Test case 1: Simple front-only stencil (no back face bits)
184+
{
185+
uint64_t frontOnly = VRHI_STENCIL_TEST_ALWAYS | VRHI_STENCIL_OP_PASS_Z_KEEP;
186+
nvrhi::DepthStencilState ds = vhTranslateDepthStencilState( VRHI_STATE_DEFAULT, frontOnly );
187+
127188
EXPECT_TRUE( ds.stencilEnable );
128189
EXPECT_EQ( ds.frontFaceStencil.stencilFunc, nvrhi::ComparisonFunc::Always );
129190
EXPECT_EQ( ds.frontFaceStencil.passOp, nvrhi::StencilOp::Keep );
191+
192+
// Back face should match front when no back bits are set
193+
EXPECT_EQ( ds.backFaceStencil.stencilFunc, ds.frontFaceStencil.stencilFunc );
194+
EXPECT_EQ( ds.backFaceStencil.passOp, ds.frontFaceStencil.passOp );
195+
}
130196

197+
// Test case 2: Different front and back (manually packed)
198+
{
199+
uint64_t front = VRHI_STENCIL_TEST_ALWAYS | VRHI_STENCIL_OP_PASS_Z_KEEP;
200+
uint64_t back = VRHI_STENCIL_TEST_NEVER | VRHI_STENCIL_OP_PASS_Z_REPLACE;
201+
202+
// Pack back face bits into the unified format (simulating user packing)
203+
uint64_t packedStencil = front |
204+
((back & VRHI_STENCIL_TEST_MASK) << (VRHI_STENCIL_BACK_TEST_SHIFT - VRHI_STENCIL_TEST_SHIFT)) |
205+
((back & VRHI_STENCIL_OP_PASS_Z_MASK) << (VRHI_STENCIL_BACK_OP_PASS_Z_SHIFT - VRHI_STENCIL_OP_PASS_Z_SHIFT));
206+
207+
nvrhi::DepthStencilState ds = vhTranslateDepthStencilState( VRHI_STATE_DEFAULT, packedStencil );
208+
209+
EXPECT_TRUE( ds.stencilEnable );
210+
EXPECT_EQ( ds.frontFaceStencil.stencilFunc, nvrhi::ComparisonFunc::Always );
211+
EXPECT_EQ( ds.frontFaceStencil.passOp, nvrhi::StencilOp::Keep );
131212
EXPECT_EQ( ds.backFaceStencil.stencilFunc, nvrhi::ComparisonFunc::Never );
132213
EXPECT_EQ( ds.backFaceStencil.passOp, nvrhi::StencilOp::Replace );
133214
}
134215
}
135216

217+
// Test that validates stencil operation constants have correct enum mapping values
218+
UTEST_F( Shader, StencilConstantValues )
219+
{
220+
// Test all stencil operations - extracted values should match enum indices
221+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_S_KEEP & VRHI_STENCIL_OP_FAIL_S_MASK) >> VRHI_STENCIL_OP_FAIL_S_SHIFT, 1 );
222+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_S_REPLACE & VRHI_STENCIL_OP_FAIL_S_MASK) >> VRHI_STENCIL_OP_FAIL_S_SHIFT, 2 );
223+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_S_INCR & VRHI_STENCIL_OP_FAIL_S_MASK) >> VRHI_STENCIL_OP_FAIL_S_SHIFT, 3 );
224+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_S_INCRSAT & VRHI_STENCIL_OP_FAIL_S_MASK) >> VRHI_STENCIL_OP_FAIL_S_SHIFT, 4 );
225+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_S_DECR & VRHI_STENCIL_OP_FAIL_S_MASK) >> VRHI_STENCIL_OP_FAIL_S_SHIFT, 5 );
226+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_S_DECRSAT & VRHI_STENCIL_OP_FAIL_S_MASK) >> VRHI_STENCIL_OP_FAIL_S_SHIFT, 6 );
227+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_S_INVERT & VRHI_STENCIL_OP_FAIL_S_MASK) >> VRHI_STENCIL_OP_FAIL_S_SHIFT, 7 );
228+
229+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_Z_KEEP & VRHI_STENCIL_OP_FAIL_Z_MASK) >> VRHI_STENCIL_OP_FAIL_Z_SHIFT, 1 );
230+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_Z_REPLACE & VRHI_STENCIL_OP_FAIL_Z_MASK) >> VRHI_STENCIL_OP_FAIL_Z_SHIFT, 2 );
231+
EXPECT_EQ( (VRHI_STENCIL_OP_FAIL_Z_INCR & VRHI_STENCIL_OP_FAIL_Z_MASK) >> VRHI_STENCIL_OP_FAIL_Z_SHIFT, 3 );
232+
233+
EXPECT_EQ( (VRHI_STENCIL_OP_PASS_Z_KEEP & VRHI_STENCIL_OP_PASS_Z_MASK) >> VRHI_STENCIL_OP_PASS_Z_SHIFT, 1 );
234+
EXPECT_EQ( (VRHI_STENCIL_OP_PASS_Z_REPLACE & VRHI_STENCIL_OP_PASS_Z_MASK) >> VRHI_STENCIL_OP_PASS_Z_SHIFT, 2 );
235+
EXPECT_EQ( (VRHI_STENCIL_OP_PASS_Z_INCR & VRHI_STENCIL_OP_PASS_Z_MASK) >> VRHI_STENCIL_OP_PASS_Z_SHIFT, 3 );
236+
EXPECT_EQ( (VRHI_STENCIL_OP_PASS_Z_INCRSAT & VRHI_STENCIL_OP_PASS_Z_MASK) >> VRHI_STENCIL_OP_PASS_Z_SHIFT, 4 );
237+
EXPECT_EQ( (VRHI_STENCIL_OP_PASS_Z_DECR & VRHI_STENCIL_OP_PASS_Z_MASK) >> VRHI_STENCIL_OP_PASS_Z_SHIFT, 5 );
238+
EXPECT_EQ( (VRHI_STENCIL_OP_PASS_Z_DECRSAT & VRHI_STENCIL_OP_PASS_Z_MASK) >> VRHI_STENCIL_OP_PASS_Z_SHIFT, 6 );
239+
EXPECT_EQ( (VRHI_STENCIL_OP_PASS_Z_INVERT & VRHI_STENCIL_OP_PASS_Z_MASK) >> VRHI_STENCIL_OP_PASS_Z_SHIFT, 7 );
240+
241+
// Verify comparison function constants
242+
EXPECT_EQ( (VRHI_STENCIL_TEST_LESS & VRHI_STENCIL_TEST_MASK) >> VRHI_STENCIL_TEST_SHIFT, 1 );
243+
EXPECT_EQ( (VRHI_STENCIL_TEST_LEQUAL & VRHI_STENCIL_TEST_MASK) >> VRHI_STENCIL_TEST_SHIFT, 2 );
244+
EXPECT_EQ( (VRHI_STENCIL_TEST_EQUAL & VRHI_STENCIL_TEST_MASK) >> VRHI_STENCIL_TEST_SHIFT, 3 );
245+
EXPECT_EQ( (VRHI_STENCIL_TEST_GEQUAL & VRHI_STENCIL_TEST_MASK) >> VRHI_STENCIL_TEST_SHIFT, 4 );
246+
EXPECT_EQ( (VRHI_STENCIL_TEST_GREATER & VRHI_STENCIL_TEST_MASK) >> VRHI_STENCIL_TEST_SHIFT, 5 );
247+
EXPECT_EQ( (VRHI_STENCIL_TEST_NOTEQUAL & VRHI_STENCIL_TEST_MASK) >> VRHI_STENCIL_TEST_SHIFT, 6 );
248+
EXPECT_EQ( (VRHI_STENCIL_TEST_NEVER & VRHI_STENCIL_TEST_MASK) >> VRHI_STENCIL_TEST_SHIFT, 7 );
249+
EXPECT_EQ( (VRHI_STENCIL_TEST_ALWAYS & VRHI_STENCIL_TEST_MASK) >> VRHI_STENCIL_TEST_SHIFT, 8 );
250+
251+
// Verify reference, read mask, write mask constants
252+
EXPECT_EQ( (VRHI_STENCIL_FUNC_REF(0x42) & VRHI_STENCIL_FUNC_REF_MASK) >> VRHI_STENCIL_FUNC_REF_SHIFT, 0x42 );
253+
EXPECT_EQ( (VRHI_STENCIL_FUNC_RMASK(0x55) & VRHI_STENCIL_FUNC_RMASK_MASK) >> VRHI_STENCIL_FUNC_RMASK_SHIFT, 0x55 );
254+
EXPECT_EQ( (VRHI_STENCIL_FUNC_WMASK(0xAA) & VRHI_STENCIL_FUNC_WMASK_MASK) >> VRHI_STENCIL_FUNC_WMASK_SHIFT, 0xAA );
255+
}
256+
136257
UTEST_F( Shader, ValidateBinding )
137258
{
138259
vhShaderReflectionResource res;

0 commit comments

Comments
 (0)