feat(srp): add shader pass selection for scene draws
- let DrawingSettings carry an optional shaderPassName across managed and native scene draw APIs - allow RenderObjectsRendererFeature to author explicit ForwardLit or Unlit scene draws - exercise the new scene draw pass selection seam in the project render pipeline probe
This commit is contained in:
@@ -106,6 +106,32 @@ bool UsesDynamicSurfaceDescriptorSet(const BuiltinPassSetLayoutMetadata& setLayo
|
||||
setLayout.usesMaterialBuffers;
|
||||
}
|
||||
|
||||
bool TryResolveRequestedSurfacePassType(
|
||||
const DrawSettings& drawSettings,
|
||||
BuiltinMaterialPass& outPass,
|
||||
bool& outHasRequestedPass) {
|
||||
outHasRequestedPass = false;
|
||||
if (!drawSettings.HasShaderPassName()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
outHasRequestedPass = true;
|
||||
const Containers::String normalizedPassName =
|
||||
NormalizeBuiltinPassMetadataValue(drawSettings.shaderPassName);
|
||||
if (normalizedPassName == Containers::String("forward") ||
|
||||
MatchesBuiltinPassName(normalizedPassName, BuiltinMaterialPass::ForwardLit)) {
|
||||
outPass = BuiltinMaterialPass::ForwardLit;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (MatchesBuiltinPassName(normalizedPassName, BuiltinMaterialPass::Unlit)) {
|
||||
outPass = BuiltinMaterialPass::Unlit;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RHI::InputLayoutDesc BuiltinForwardPipeline::BuildInputLayout() {
|
||||
@@ -172,7 +198,17 @@ RHI::InputLayoutDesc BuiltinForwardPipeline::BuildInputLayout() {
|
||||
|
||||
bool BuiltinForwardPipeline::TryResolveSurfacePassType(
|
||||
const Resources::Material* material,
|
||||
const BuiltinMaterialPass* preferredPass,
|
||||
BuiltinMaterialPass& outPass) {
|
||||
if (preferredPass != nullptr) {
|
||||
if (MatchesBuiltinPass(material, *preferredPass)) {
|
||||
outPass = *preferredPass;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MatchesBuiltinPass(material, BuiltinMaterialPass::Unlit)) {
|
||||
outPass = BuiltinMaterialPass::Unlit;
|
||||
return true;
|
||||
@@ -188,10 +224,14 @@ bool BuiltinForwardPipeline::TryResolveSurfacePassType(
|
||||
|
||||
BuiltinForwardPipeline::ResolvedShaderPass BuiltinForwardPipeline::ResolveSurfaceShaderPass(
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material) const {
|
||||
const Resources::Material* material,
|
||||
const BuiltinMaterialPass* preferredPass) const {
|
||||
ResolvedShaderPass resolved = {};
|
||||
BuiltinMaterialPass pass = BuiltinMaterialPass::ForwardLit;
|
||||
if (!TryResolveSurfacePassType(material, pass)) {
|
||||
BuiltinMaterialPass pass =
|
||||
preferredPass != nullptr
|
||||
? *preferredPass
|
||||
: BuiltinMaterialPass::ForwardLit;
|
||||
if (!TryResolveSurfacePassType(material, preferredPass, pass)) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
@@ -227,9 +267,14 @@ RHI::RHIPipelineState* BuiltinForwardPipeline::GetOrCreatePipelineState(
|
||||
const RenderContext& context,
|
||||
const RenderSurface& surface,
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material) {
|
||||
const Resources::Material* material,
|
||||
const BuiltinMaterialPass* preferredPass) {
|
||||
const Resources::ShaderKeywordSet keywordSet = ResolvePassKeywordSet(sceneData, material);
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolveSurfaceShaderPass(sceneData, material);
|
||||
const ResolvedShaderPass resolvedShaderPass =
|
||||
ResolveSurfaceShaderPass(
|
||||
sceneData,
|
||||
material,
|
||||
preferredPass);
|
||||
if (resolvedShaderPass.shader == nullptr || resolvedShaderPass.pass == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
@@ -402,7 +447,8 @@ bool BuiltinForwardPipeline::ExecuteForwardTransparentPass(
|
||||
bool BuiltinForwardPipeline::DrawVisibleItem(
|
||||
const FrameExecutionContext& executionContext,
|
||||
const VisibleRenderItem& visibleItem,
|
||||
const Resources::Material* material) {
|
||||
const Resources::Material* material,
|
||||
const BuiltinMaterialPass* preferredPass) {
|
||||
const RenderContext& context = executionContext.renderContext;
|
||||
const RenderSceneData& sceneData = executionContext.sceneData;
|
||||
|
||||
@@ -435,7 +481,11 @@ bool BuiltinForwardPipeline::DrawVisibleItem(
|
||||
shadowReceiverConstants.shadowSampling = sceneData.lighting.mainDirectionalShadow.sampling;
|
||||
}
|
||||
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolveSurfaceShaderPass(sceneData, material);
|
||||
const ResolvedShaderPass resolvedShaderPass =
|
||||
ResolveSurfaceShaderPass(
|
||||
sceneData,
|
||||
material,
|
||||
preferredPass);
|
||||
if (resolvedShaderPass.shader == nullptr || resolvedShaderPass.pass == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -578,6 +628,25 @@ bool BuiltinForwardPipeline::DrawVisibleItems(
|
||||
RHI::RHICommandList* commandList = context.commandList;
|
||||
RHI::RHIPipelineState* currentPipelineState = nullptr;
|
||||
bool drawFailed = false;
|
||||
BuiltinMaterialPass requestedPass = BuiltinMaterialPass::ForwardLit;
|
||||
bool hasRequestedPass = false;
|
||||
if (!TryResolveRequestedSurfacePassType(
|
||||
drawSettings,
|
||||
requestedPass,
|
||||
hasRequestedPass)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
(Containers::String(
|
||||
"BuiltinForwardPipeline only supports explicit shaderPassName values of ForwardLit or Unlit for scene draws, received: ") +
|
||||
drawSettings.shaderPassName)
|
||||
.CStr());
|
||||
return false;
|
||||
}
|
||||
|
||||
const BuiltinMaterialPass* preferredPass =
|
||||
hasRequestedPass
|
||||
? &requestedPass
|
||||
: nullptr;
|
||||
|
||||
auto drawVisibleItem = [&](const VisibleRenderItem& visibleItem) {
|
||||
if (drawFailed) {
|
||||
@@ -588,12 +657,24 @@ bool BuiltinForwardPipeline::DrawVisibleItems(
|
||||
drawSettings.HasOverrideMaterial()
|
||||
? drawSettings.overrideMaterial.Get()
|
||||
: ResolveMaterial(visibleItem);
|
||||
BuiltinMaterialPass pass = BuiltinMaterialPass::ForwardLit;
|
||||
if (!TryResolveSurfacePassType(material, pass)) {
|
||||
BuiltinMaterialPass pass =
|
||||
preferredPass != nullptr
|
||||
? *preferredPass
|
||||
: BuiltinMaterialPass::ForwardLit;
|
||||
if (!TryResolveSurfacePassType(
|
||||
material,
|
||||
preferredPass,
|
||||
pass)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RHI::RHIPipelineState* pipelineState = GetOrCreatePipelineState(context, surface, sceneData, material);
|
||||
RHI::RHIPipelineState* pipelineState =
|
||||
GetOrCreatePipelineState(
|
||||
context,
|
||||
surface,
|
||||
sceneData,
|
||||
material,
|
||||
preferredPass);
|
||||
if (pipelineState == nullptr) {
|
||||
drawFailed = true;
|
||||
return;
|
||||
@@ -603,7 +684,11 @@ bool BuiltinForwardPipeline::DrawVisibleItems(
|
||||
currentPipelineState = pipelineState;
|
||||
}
|
||||
|
||||
if (!DrawVisibleItem(executionContext, visibleItem, material)) {
|
||||
if (!DrawVisibleItem(
|
||||
executionContext,
|
||||
visibleItem,
|
||||
material,
|
||||
preferredPass)) {
|
||||
drawFailed = true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4592,7 +4592,8 @@ InternalCall_Rendering_ScriptableRenderContext_DrawRenderersByDesc(
|
||||
uint64_t nativeHandle,
|
||||
int32_t scenePhase,
|
||||
ManagedRendererListDescData* rendererListDescData,
|
||||
MonoString* overrideMaterialPath) {
|
||||
MonoString* overrideMaterialPath,
|
||||
MonoString* shaderPassName) {
|
||||
ManagedScriptableRenderContextState* const state =
|
||||
FindManagedScriptableRenderContextState(nativeHandle);
|
||||
if (state == nullptr ||
|
||||
@@ -4626,6 +4627,13 @@ InternalCall_Rendering_ScriptableRenderContext_DrawRenderersByDesc(
|
||||
}
|
||||
}
|
||||
|
||||
const std::string shaderPassNameUtf8 =
|
||||
MonoStringToUtf8(shaderPassName);
|
||||
if (!shaderPassNameUtf8.empty()) {
|
||||
drawSettings.shaderPassName =
|
||||
Containers::String(shaderPassNameUtf8.c_str());
|
||||
}
|
||||
|
||||
return state->sceneRecorder->RecordSceneDrawSettings(
|
||||
drawSettings)
|
||||
? 1
|
||||
|
||||
Reference in New Issue
Block a user