Update editor viewport rendering integration

This commit is contained in:
2026-04-28 18:34:28 +08:00
parent d1a717091d
commit 9b6adf1806
6 changed files with 141 additions and 2 deletions

View File

@@ -20,9 +20,11 @@
#include "EnvironmentFlags.h"
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
#include <XCEngine/Debug/Logger.h>
#include <XCEditor/Windowing/System/EditorWindowSystem.h>
#include <XCEditor/Workspace/UIEditorWindowWorkspaceModel.h>
#include <shellscalingapi.h>
#include <sstream>
#include <utility>
namespace XCEngine::UI::Editor {
@@ -34,6 +36,24 @@ constexpr const wchar_t* kWindowTitle = L"Main Scene * - Main.xx - XCEngine Edit
constexpr DWORD kBorderlessWindowStyle = WS_POPUP | WS_THICKFRAME;
constexpr int kDefaultSmokeTestDurationSeconds = 12;
class UIEditorRuntimeTraceLogSink final : public ::XCEngine::Debug::ILogSink {
public:
void Log(const ::XCEngine::Debug::LogEntry& entry) override {
if (entry.category != ::XCEngine::Debug::LogCategory::Rendering ||
entry.level < ::XCEngine::Debug::LogLevel::Warning) {
return;
}
std::ostringstream stream = {};
stream << ::XCEngine::Debug::LogLevelToString(entry.level)
<< ' '
<< entry.message.CStr();
AppendUIEditorRuntimeTrace("engine", stream.str());
}
void Flush() override {}
};
bool HasEditorWorkspaceMarkers(const std::filesystem::path& root) {
return std::filesystem::exists(root / "CMakeLists.txt") &&
std::filesystem::exists(root / "editor" / "resources") &&
@@ -160,6 +180,9 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) {
const std::filesystem::path logRoot = m_resourceService->GetExecutableDirectory() / "logs";
InitializeUIEditorRuntimeTrace(logRoot);
auto runtimeTraceLogSink = std::make_unique<UIEditorRuntimeTraceLogSink>();
m_runtimeTraceLogSink = runtimeTraceLogSink.get();
::XCEngine::Debug::Logger::Get().AddSink(std::move(runtimeTraceLogSink));
SetUnhandledExceptionFilter(&Application::HandleUnhandledException);
AppendUIEditorRuntimeTrace("app", "initialize begin");
@@ -313,6 +336,10 @@ void Application::Shutdown() {
m_smokeTestCloseRequested = false;
AppendUIEditorRuntimeTrace("app", "shutdown end");
if (m_runtimeTraceLogSink != nullptr) {
::XCEngine::Debug::Logger::Get().RemoveSink(m_runtimeTraceLogSink);
m_runtimeTraceLogSink = nullptr;
}
ShutdownUIEditorRuntimeTrace();
}

View File

@@ -12,6 +12,10 @@
#include <filesystem>
#include <memory>
namespace XCEngine::Debug {
class ILogSink;
}
namespace XCEngine::UI::Editor {
class EditorWindowSystem;
@@ -69,6 +73,7 @@ private:
std::unique_ptr<Host::EditorHostResourceService> m_resourceService = {};
std::unique_ptr<App::EditorWindowManager> m_windowManager = {};
std::unique_ptr<System::SystemInteractionService> m_systemInteractionHost = {};
XCEngine::Debug::ILogSink* m_runtimeTraceLogSink = nullptr;
int m_smokeTestFrameLimit = 0;
int m_smokeTestRenderedFrameCount = 0;
bool m_smokeTestEnabled = false;

View File

@@ -6,6 +6,7 @@
#include "Viewport/SceneViewportResourcePaths.h"
#include "ViewportRenderHost.h"
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
#include <XCEngine/RHI/RHICommandList.h>
#include <utility>
@@ -330,6 +331,9 @@ void ViewportHostService::ApplyViewportFallback(
const ::XCEngine::Rendering::RenderContext& renderContext,
const ViewportRenderResult& renderResult) {
entry.statusText = renderResult.statusText;
::XCEngine::UI::Editor::AppendUIEditorRuntimeTrace(
"viewport",
"fallback clear: " + entry.statusText);
entry.renderTargets.hasValidObjectIdFrame = false;
entry.renderTargets.objectIdFrameSerial = 0u;
ClearViewport(

View File

@@ -1,5 +1,7 @@
# XCEngine Rendering Agent Guide
Editor viewport 边界补充SceneViewport 的 render request 是 editor 每帧快照,不属于 SRP fallback 兜底范围。workspace/panel frame events 若会打开或切换场景,必须在事件消费完成后、`RenderRequestedViewports()` 前重新同步 request不要通过放宽 `ScriptableRenderPipelineHost` authoritative stage recorder 或恢复 backend fallback 来掩盖过期请求。
本文面向以后在 `engine/include/XCEngine/Rendering/**``engine/src/Rendering/**` 以及对应 managed SRP/URP 绑定上工作的 agent / 开发者。这里的目标不是写愿景,而是固定当前 checkout 的真实结构、Unity SRP/URP 对齐方向、职责边界和验证入口。
如果本文与代码、`engine/CMakeLists.txt``tests/Rendering/**` 或 managed API 冲突,以当前代码为准,并在同一次改动中更新本文。

View File

@@ -189,7 +189,8 @@ BuiltinForwardPipeline::CachedDescriptorSet* BuiltinForwardPipeline::GetOrCreate
}
}
const Core::uint64 materialVersion = material != nullptr ? material->GetChangeVersion() : 0;
const Core::uint64 materialVersion =
material != nullptr ? material->GetChangeVersion() : 1u;
if (setLayout.usesMaterial) {
if (!passLayout.material.IsValid() || passLayout.material.set != setIndex) {
return nullptr;

View File

@@ -25,6 +25,15 @@ namespace {
constexpr float kForwardAmbientIntensity = 0.28f;
constexpr float kSpotInnerAngleRatio = 0.8f;
struct BuiltinForwardMaterialConstants {
Math::Vector4 baseColorFactor = Math::Vector4::One();
Math::Vector4 alphaCutoffParams = Math::Vector4(0.5f, 0.0f, 0.0f, 0.0f);
};
struct BuiltinUnlitMaterialConstants {
Math::Vector4 baseColorFactor = Math::Vector4::One();
};
Resources::ShaderKeywordSet ResolvePassKeywordSet(
const RenderSceneData& sceneData,
const Resources::Material* material) {
@@ -106,6 +115,82 @@ bool UsesDynamicSurfaceDescriptorSet(const BuiltinPassSetLayoutMetadata& setLayo
setLayout.usesMaterialBuffers;
}
MaterialConstantPayloadView ResolveBuiltinForwardMaterialConstantPayload(
const Resources::Material* material,
BuiltinForwardMaterialConstants& outConstants,
Resources::MaterialConstantFieldDesc (&outLayout)[2]) {
outConstants.baseColorFactor = ResolveBuiltinBaseColorFactor(material);
outConstants.alphaCutoffParams =
Math::Vector4(ResolveBuiltinAlphaCutoff(material), 0.0f, 0.0f, 0.0f);
outLayout[0].name = "gBaseColorFactor";
outLayout[0].type = Resources::MaterialPropertyType::Float4;
outLayout[0].offset = 0u;
outLayout[0].size = static_cast<Core::uint32>(sizeof(Math::Vector4));
outLayout[0].alignedSize = static_cast<Core::uint32>(sizeof(Math::Vector4));
outLayout[1].name = "gAlphaCutoffParams";
outLayout[1].type = Resources::MaterialPropertyType::Float4;
outLayout[1].offset = static_cast<Core::uint32>(sizeof(Math::Vector4));
outLayout[1].size = static_cast<Core::uint32>(sizeof(Math::Vector4));
outLayout[1].alignedSize = static_cast<Core::uint32>(sizeof(Math::Vector4));
MaterialConstantLayoutView layoutView = {};
layoutView.fields = outLayout;
layoutView.count = 2u;
layoutView.size = sizeof(BuiltinForwardMaterialConstants);
return { &outConstants, sizeof(BuiltinForwardMaterialConstants), layoutView };
}
MaterialConstantPayloadView ResolveBuiltinUnlitMaterialConstantPayload(
const Resources::Material* material,
BuiltinUnlitMaterialConstants& outConstants,
Resources::MaterialConstantFieldDesc (&outLayout)[1]) {
outConstants.baseColorFactor = ResolveBuiltinBaseColorFactor(material);
outLayout[0].name = "gBaseColorFactor";
outLayout[0].type = Resources::MaterialPropertyType::Float4;
outLayout[0].offset = 0u;
outLayout[0].size = static_cast<Core::uint32>(sizeof(Math::Vector4));
outLayout[0].alignedSize = static_cast<Core::uint32>(sizeof(Math::Vector4));
MaterialConstantLayoutView layoutView = {};
layoutView.fields = outLayout;
layoutView.count = 1u;
layoutView.size = sizeof(BuiltinUnlitMaterialConstants);
return { &outConstants, sizeof(BuiltinUnlitMaterialConstants), layoutView };
}
MaterialConstantPayloadView ResolveSurfaceMaterialConstantPayload(
const Resources::Shader* resolvedShader,
const Resources::Material* material,
const Resources::Shader* builtinForwardShader,
const Resources::Shader* builtinUnlitShader,
const Resources::Shader* builtinDepthOnlyShader,
const Resources::Shader* builtinShadowCasterShader,
BuiltinForwardMaterialConstants& outForwardConstants,
Resources::MaterialConstantFieldDesc (&outForwardLayout)[2],
BuiltinUnlitMaterialConstants& outUnlitConstants,
Resources::MaterialConstantFieldDesc (&outUnlitLayout)[1]) {
if (resolvedShader == builtinUnlitShader) {
return ResolveBuiltinUnlitMaterialConstantPayload(
material,
outUnlitConstants,
outUnlitLayout);
}
if (resolvedShader == builtinForwardShader ||
resolvedShader == builtinDepthOnlyShader ||
resolvedShader == builtinShadowCasterShader) {
return ResolveBuiltinForwardMaterialConstantPayload(
material,
outForwardConstants,
outForwardLayout);
}
return ResolveSchemaMaterialConstantPayload(material);
}
bool TryResolveRequestedSurfacePassType(
const DrawSettings& drawSettings,
BuiltinMaterialPass& outPass,
@@ -557,7 +642,22 @@ bool BuiltinForwardPipeline::DrawVisibleItem(
return false;
}
MaterialConstantPayloadView materialConstants = ResolveSchemaMaterialConstantPayload(material);
BuiltinForwardMaterialConstants builtinForwardConstants = {};
Resources::MaterialConstantFieldDesc builtinForwardLayout[2] = {};
BuiltinUnlitMaterialConstants builtinUnlitConstants = {};
Resources::MaterialConstantFieldDesc builtinUnlitLayout[1] = {};
MaterialConstantPayloadView materialConstants =
ResolveSurfaceMaterialConstantPayload(
resolvedShaderPass.shader,
material,
m_builtinForwardShader.Get(),
m_builtinUnlitShader.Get(),
m_builtinDepthOnlyShader.Get(),
m_builtinShadowCasterShader.Get(),
builtinForwardConstants,
builtinForwardLayout,
builtinUnlitConstants,
builtinUnlitLayout);
if (passLayout->material.IsValid() && !materialConstants.IsValid()) {
Debug::Logger::Get().Error(
Debug::LogCategory::Rendering,