feat(srp): add render state block scene draw overrides

- add managed RenderStateBlock authoring types and wire them through DrawingSettings
- let RenderObjectsRendererFeature author depth and stencil overrides for scene draws
- apply scene draw render state overrides inside builtin forward pipeline and document the stage plan
This commit is contained in:
2026-04-20 23:21:04 +08:00
parent 16788fec34
commit 7fe922d1c9
21 changed files with 707 additions and 15 deletions

View File

@@ -963,6 +963,58 @@ static_assert(
sizeof(Rendering::RendererListDesc),
"Managed renderer list desc bridge layout must match native RendererListDesc.");
struct ManagedDepthStateData {
uint8_t writeEnabled = 1u;
uint8_t compareFunction =
static_cast<uint8_t>(Resources::MaterialComparisonFunc::Less);
};
static_assert(
sizeof(ManagedDepthStateData) ==
sizeof(Rendering::DepthState),
"Managed depth state bridge layout must match native DepthState.");
struct ManagedStencilFaceStateData {
uint8_t failOperation =
static_cast<uint8_t>(Resources::MaterialStencilOp::Keep);
uint8_t passOperation =
static_cast<uint8_t>(Resources::MaterialStencilOp::Keep);
uint8_t depthFailOperation =
static_cast<uint8_t>(Resources::MaterialStencilOp::Keep);
uint8_t compareFunction =
static_cast<uint8_t>(Resources::MaterialComparisonFunc::Always);
};
static_assert(
sizeof(ManagedStencilFaceStateData) ==
sizeof(Rendering::StencilFaceState),
"Managed stencil face state bridge layout must match native StencilFaceState.");
struct ManagedStencilStateData {
uint8_t enabled = 0u;
uint8_t readMask = 0xFFu;
uint8_t writeMask = 0xFFu;
ManagedStencilFaceStateData frontFace = {};
ManagedStencilFaceStateData backFace = {};
};
static_assert(
sizeof(ManagedStencilStateData) ==
sizeof(Rendering::StencilState),
"Managed stencil state bridge layout must match native StencilState.");
struct ManagedRenderStateBlockData {
uint32_t mask = 0u;
ManagedDepthStateData depthState = {};
ManagedStencilStateData stencilState = {};
uint8_t stencilReference = 0u;
};
static_assert(
sizeof(ManagedRenderStateBlockData) ==
sizeof(Rendering::RenderStateBlock),
"Managed render state block bridge layout must match native RenderStateBlock.");
Rendering::FinalColorOutputTransferMode ResolveManagedFinalColorOutputTransferMode(
uint8_t value) {
switch (value) {
@@ -995,6 +1047,121 @@ Rendering::FinalColorToneMappingMode ResolveManagedFinalColorToneMappingMode(
}
}
Resources::MaterialComparisonFunc ResolveManagedMaterialComparisonFunc(
uint8_t value) {
switch (value) {
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::Never):
return Resources::MaterialComparisonFunc::Never;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::Equal):
return Resources::MaterialComparisonFunc::Equal;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::LessEqual):
return Resources::MaterialComparisonFunc::LessEqual;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::Greater):
return Resources::MaterialComparisonFunc::Greater;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::NotEqual):
return Resources::MaterialComparisonFunc::NotEqual;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::GreaterEqual):
return Resources::MaterialComparisonFunc::GreaterEqual;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::Always):
return Resources::MaterialComparisonFunc::Always;
case static_cast<uint8_t>(Resources::MaterialComparisonFunc::Less):
default:
return Resources::MaterialComparisonFunc::Less;
}
}
Resources::MaterialStencilOp ResolveManagedMaterialStencilOp(
uint8_t value) {
switch (value) {
case static_cast<uint8_t>(Resources::MaterialStencilOp::Zero):
return Resources::MaterialStencilOp::Zero;
case static_cast<uint8_t>(Resources::MaterialStencilOp::Replace):
return Resources::MaterialStencilOp::Replace;
case static_cast<uint8_t>(Resources::MaterialStencilOp::IncrSat):
return Resources::MaterialStencilOp::IncrSat;
case static_cast<uint8_t>(Resources::MaterialStencilOp::DecrSat):
return Resources::MaterialStencilOp::DecrSat;
case static_cast<uint8_t>(Resources::MaterialStencilOp::Invert):
return Resources::MaterialStencilOp::Invert;
case static_cast<uint8_t>(Resources::MaterialStencilOp::IncrWrap):
return Resources::MaterialStencilOp::IncrWrap;
case static_cast<uint8_t>(Resources::MaterialStencilOp::DecrWrap):
return Resources::MaterialStencilOp::DecrWrap;
case static_cast<uint8_t>(Resources::MaterialStencilOp::Keep):
default:
return Resources::MaterialStencilOp::Keep;
}
}
Rendering::RenderStateMask ResolveManagedRenderStateMask(
uint32_t value) {
const uint32_t knownMask =
Rendering::ToRenderStateMaskBits(Rendering::RenderStateMask::Depth) |
Rendering::ToRenderStateMaskBits(Rendering::RenderStateMask::Stencil);
return static_cast<Rendering::RenderStateMask>(
value & knownMask);
}
Rendering::DepthState BuildManagedDepthState(
const ManagedDepthStateData& depthStateData) {
Rendering::DepthState depthState = {};
depthState.writeEnabled = depthStateData.writeEnabled != 0u;
depthState.compareFunction =
ResolveManagedMaterialComparisonFunc(
depthStateData.compareFunction);
return depthState;
}
Rendering::StencilFaceState BuildManagedStencilFaceState(
const ManagedStencilFaceStateData& stencilFaceData) {
Rendering::StencilFaceState stencilFaceState = {};
stencilFaceState.failOp =
ResolveManagedMaterialStencilOp(
stencilFaceData.failOperation);
stencilFaceState.passOp =
ResolveManagedMaterialStencilOp(
stencilFaceData.passOperation);
stencilFaceState.depthFailOp =
ResolveManagedMaterialStencilOp(
stencilFaceData.depthFailOperation);
stencilFaceState.compareFunction =
ResolveManagedMaterialComparisonFunc(
stencilFaceData.compareFunction);
return stencilFaceState;
}
Rendering::StencilState BuildManagedStencilState(
const ManagedStencilStateData& stencilStateData) {
Rendering::StencilState stencilState = {};
stencilState.enabled = stencilStateData.enabled != 0u;
stencilState.readMask = stencilStateData.readMask;
stencilState.writeMask = stencilStateData.writeMask;
stencilState.frontFace =
BuildManagedStencilFaceState(
stencilStateData.frontFace);
stencilState.backFace =
BuildManagedStencilFaceState(
stencilStateData.backFace);
return stencilState;
}
Rendering::RenderStateBlock BuildManagedRenderStateBlock(
const ManagedRenderStateBlockData& renderStateBlockData) {
Rendering::RenderStateBlock renderStateBlock = {};
renderStateBlock.mask =
ResolveManagedRenderStateMask(
renderStateBlockData.mask);
renderStateBlock.depthState =
BuildManagedDepthState(
renderStateBlockData.depthState);
renderStateBlock.stencilState =
BuildManagedStencilState(
renderStateBlockData.stencilState);
renderStateBlock.stencilReference =
renderStateBlockData.stencilReference;
return renderStateBlock;
}
bool TryUnboxManagedFinalColorSettings(
MonoObject* boxedValue,
Rendering::FinalColorSettings& outSettings) {
@@ -4593,7 +4760,8 @@ InternalCall_Rendering_ScriptableRenderContext_DrawRenderersByDesc(
int32_t scenePhase,
ManagedRendererListDescData* rendererListDescData,
MonoString* overrideMaterialPath,
MonoString* shaderPassName) {
MonoString* shaderPassName,
ManagedRenderStateBlockData* renderStateBlockData) {
ManagedScriptableRenderContextState* const state =
FindManagedScriptableRenderContextState(nativeHandle);
if (state == nullptr ||
@@ -4633,6 +4801,11 @@ InternalCall_Rendering_ScriptableRenderContext_DrawRenderersByDesc(
drawSettings.shaderPassName =
Containers::String(shaderPassNameUtf8.c_str());
}
if (renderStateBlockData != nullptr) {
drawSettings.renderStateBlock =
BuildManagedRenderStateBlock(
*renderStateBlockData);
}
return state->sceneRecorder->RecordSceneDrawSettings(
drawSettings)