Skip to content
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
Binary file modified OloEditor/SandboxProject/AssetRegistry.oar
Binary file not shown.
Binary file modified OloEditor/assets/tests/visual/WorldOriginRebase_far_before.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 29 additions & 13 deletions OloEditor/src/MCP/McpToolsRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "OloEngine/Renderer/Passes/CommandBufferRenderPass.h"
#include "OloEngine/Renderer/Passes/VolumetricFogPass.h"
#include "OloEngine/Renderer/RenderGraph.h"
#include "OloEngine/Renderer/Debug/RenderGraphResourceIdentity.h"
#include "OloEngine/Renderer/TransientPool.h"
#include "OloEngine/Renderer/Renderer2D.h"
#include "OloEngine/Renderer/Renderer3D.h"
Expand Down Expand Up @@ -414,7 +415,7 @@ namespace OloEngine::MCP
// frame's (transients can re-alias next frame).
if (resource.TextureHandle.IsValid())
{
info.GLTextureId = graph->ResolveTexture(resource.TextureHandle);
info.GLTextureId = Debug::NativeTextureIdForDiagnostics(*graph, resource.TextureHandle);
info.ViewOfParentLayer = graph->GetTextureViewLayerIndex(resource.Name);
}
if (resource.FramebufferHandle.IsValid())
Expand Down Expand Up @@ -474,6 +475,16 @@ namespace OloEngine::MCP
if (const u32 textureId = Renderer3D::ResolveFrameGraphTexture(name); textureId != 0)
return textureId;

// Same fallback, by name rather than by handle — this path is what
// olo_render_capture_target uses, and the by-name lookups live on
// Renderer3D rather than on RenderGraph.
if (const u32 nativeId =
Debug::NativeTextureIdForDiagnostics(Renderer3D::ResolveFrameGraphTextureHandle(name));
nativeId != 0)
{
return nativeId;
}

const Ref<Framebuffer> framebuffer = Renderer3D::ResolveFrameGraphFramebuffer(name);
if (!framebuffer)
return 0;
Expand Down Expand Up @@ -3696,7 +3707,7 @@ namespace OloEngine::MCP
RenderValidate::ResourceIdentity identity;
identity.Name = resource.Name;
if (resource.TextureHandle.IsValid())
identity.GLTextureId = graph->ResolveTexture(resource.TextureHandle);
identity.GLTextureId = Debug::NativeTextureIdForDiagnostics(*graph, resource.TextureHandle);
else if (resource.FramebufferHandle.IsValid())
identity.GLTextureId = ResolveTargetTexture(resource.Name);
if (resource.BufferHandle.IsValid())
Expand Down Expand Up @@ -4121,19 +4132,24 @@ namespace OloEngine::MCP
Json ResolvedMaterialJson(const Material& material, const PODMaterialData& data,
u32 submeshIndex, std::string_view source)
{
// NATIVE ids, matching this tool's published schema ("Bound GL
// texture id per slot ... 0 = none") and comparable with the ids
// olo_render_list_targets reports. The fields are identities since
// issue #691 step 3, so resolve rather than reformat — printing
// "#3:1" here would silently break every existing consumer.
Json textures;
textures["albedo"] = data.albedoMapID;
textures["metallicRoughness"] = data.metallicRoughnessMapID;
textures["normal"] = data.normalMapID;
textures["ao"] = data.aoMapID;
textures["emissive"] = data.emissiveMapID;
textures["albedo"] = Debug::NativeTextureIdForDiagnostics(data.albedoMapID);
textures["metallicRoughness"] = Debug::NativeTextureIdForDiagnostics(data.metallicRoughnessMapID);
textures["normal"] = Debug::NativeTextureIdForDiagnostics(data.normalMapID);
textures["ao"] = Debug::NativeTextureIdForDiagnostics(data.aoMapID);
textures["emissive"] = Debug::NativeTextureIdForDiagnostics(data.emissiveMapID);

Json useMaps;
useMaps["useAlbedoMap"] = data.albedoMapID != 0;
useMaps["useMetallicRoughnessMap"] = data.metallicRoughnessMapID != 0;
useMaps["useNormalMap"] = data.normalMapID != 0;
useMaps["useAOMap"] = data.aoMapID != 0;
useMaps["useEmissiveMap"] = data.emissiveMapID != 0;
useMaps["useAlbedoMap"] = data.albedoMapID.IsValid();
useMaps["useMetallicRoughnessMap"] = data.metallicRoughnessMapID.IsValid();
useMaps["useNormalMap"] = data.normalMapID.IsValid();
useMaps["useAOMap"] = data.aoMapID.IsValid();
useMaps["useEmissiveMap"] = data.emissiveMapID.IsValid();

Json j;
j["submesh"] = submeshIndex;
Expand Down Expand Up @@ -4254,7 +4270,7 @@ namespace OloEngine::MCP
source = "MeshSource imported material (per-submesh)";
}

const PODMaterialData data = Renderer3D::CreatePODMaterialDataForMaterial(*material, 0);
const PODMaterialData data = Renderer3D::CreatePODMaterialDataForMaterial(*material, RHI::NullResource);
submeshes.push_back(ResolvedMaterialJson(*material, data, index, source));
}

Expand Down
14 changes: 10 additions & 4 deletions OloEngine/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -591,10 +591,14 @@
"OloEngine/Renderer/PlanarReflection.cpp"
"OloEngine/Renderer/RendererAPI.cpp"
"OloEngine/Renderer/RendererAPI.h"
# Declaration-only RHI vocabulary (issue #691 Phase 1, ADR 0011). No .cpp
# and no consumers yet — these exist so the Phase 2 sweep has a fixed
# target to convert toward. Listed here only so they show up in the IDE
# project tree; RHIBoundaryRatchetTest is what actually compiles them.
# RHI vocabulary (issue #691 Phases 1-2, ADR 0011). No longer
# declaration-only: RHIResourceRegistry.{h,cpp} mints the generation-checked
# RHI::ResourceHandle (defined in RHITypes.h) that the Platform/OpenGL
# resource classes, RenderCommand and the render graph now carry.
# RHIResources.h is mostly still forward-looking vocabulary; its live part
# is GetNativeHandleForDebug, included by RHIResourceRegistry.cpp and by
# Renderer/Debug/RenderGraphResourceIdentity.cpp.
# RHIBoundaryRatchetTest guards the no-backend-types boundary.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"OloEngine/Renderer/RHI/RHITypes.h"
"OloEngine/Renderer/RHI/RHIResources.h"
"OloEngine/Renderer/RHI/RHIResourceRegistry.h"
Expand Down Expand Up @@ -724,6 +728,8 @@
"OloEngine/Renderer/Debug/RenderGraphFrameCapture.cpp"
"OloEngine/Renderer/Debug/RenderGraphPassSnapshot.h"
"OloEngine/Renderer/Debug/RenderGraphPassSnapshot.cpp"
"OloEngine/Renderer/Debug/RenderGraphResourceIdentity.h"
"OloEngine/Renderer/Debug/RenderGraphResourceIdentity.cpp"
"OloEngine/Renderer/Debug/CapturedFrameData.h"
"OloEngine/Renderer/Debug/CapturedFrameData.cpp"
"OloEngine/Renderer/Debug/CommandPacketDebugger.h"
Expand Down
36 changes: 18 additions & 18 deletions OloEngine/src/OloEngine/Renderer/CloudShadowMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,33 +31,33 @@ namespace OloEngine
// Lazy-create GPU resources on the first call (raw-id handling
// mirrors SSAORenderPass::CreateNoiseTexture; the render pipeline
// owns the call site so a live GL context is guaranteed).
if (s_Data.m_TextureID == 0 || !s_Data.m_GenerateShader)
if (!s_Data.m_Texture.IsValid() || !s_Data.m_GenerateShader)
{
if (s_Data.m_TextureID == 0)
if (!s_Data.m_Texture.IsValid())
{
s_Data.m_TextureID = RenderCommand::CreateTexture2D(kShadowResolution, kShadowResolution, RHI::Format::R8UNorm);
if (s_Data.m_TextureID != 0)
s_Data.m_Texture = RenderCommand::CreateTexture2DHandle(kShadowResolution, kShadowResolution, RHI::Format::R8UNorm);
if (s_Data.m_Texture.IsValid())
{
RenderCommand::SetTextureFilter(s_Data.m_TextureID, RHI::Filter::Linear, RHI::Filter::Linear);
RenderCommand::SetTextureWrap(s_Data.m_TextureID, RHI::AddressMode::ClampToEdge);
RenderCommand::SetTextureFilter(s_Data.m_Texture, RHI::Filter::Linear, RHI::Filter::Linear);
RenderCommand::SetTextureWrap(s_Data.m_Texture, RHI::AddressMode::ClampToEdge);
}
}
if (!s_Data.m_GenerateShader)
{
s_Data.m_GenerateShader = ComputeShader::Create("assets/shaders/compute/CloudShadow_Generate.comp");
}

const bool textureValid = s_Data.m_TextureID != 0;
const bool textureValid = s_Data.m_Texture.IsValid();
const bool shaderValid = s_Data.m_GenerateShader && s_Data.m_GenerateShader->IsValid();
if (!textureValid || !shaderValid)
{
OLO_CORE_ERROR("CloudShadowMap::Update failed — {}",
!shaderValid ? "CloudShadow_Generate.comp could not be loaded/compiled"
: "R8 shadow texture could not be created");
if (s_Data.m_TextureID != 0)
if (s_Data.m_Texture.IsValid())
{
RenderCommand::DeleteTexture(s_Data.m_TextureID);
s_Data.m_TextureID = 0;
RenderCommand::DeleteTexture(s_Data.m_Texture);
s_Data.m_Texture = {};
}
s_Data.m_GenerateShader = nullptr;
s_Data.m_CreationFailed = true;
Expand All @@ -80,7 +80,7 @@ namespace OloEngine
s_Data.m_GenerateShader->SetFloat("u_ShadowWorldSize", worldSize);
s_Data.m_GenerateShader->SetInt("u_ShadowResolution", static_cast<int>(kShadowResolution));

RenderCommand::BindImageTexture(0, s_Data.m_TextureID, 0, false, 0, RHI::Access::StorageWrite, RHI::Format::R8UNorm);
RenderCommand::BindImageTexture(0, s_Data.m_Texture, 0, false, 0, RHI::Access::StorageWrite, RHI::Format::R8UNorm);
constexpr u32 kGroups = (kShadowResolution + kLocalSize - 1) / kLocalSize;
RenderCommand::DispatchCompute(kGroups, kGroups, 1);

Expand All @@ -98,21 +98,21 @@ namespace OloEngine
{
OLO_PROFILE_FUNCTION();

const bool hadState = s_Data.m_TextureID != 0 || s_Data.m_GenerateShader || s_Data.m_CreationFailed;
const bool hadState = s_Data.m_Texture.IsValid() || s_Data.m_GenerateShader || s_Data.m_CreationFailed;

if (s_Data.m_TextureID != 0)
if (s_Data.m_Texture.IsValid())
{
// The shadow map is bound through the PBR mesh dispatch's TRACKED
// path (CommandDispatch::SetCloudShadowTextureID), so drop any
// cached "slot already has this texture" entry before the ID is
// deleted — a future bind with a recycled GL ID must not be
// skipped against stale tracking (the same contract the
// OpenGLTexture2D destructor honors).
CommandDispatch::InvalidateTextureBinding(s_Data.m_TextureID);
RenderCommand::DeleteTexture(s_Data.m_TextureID);
CommandDispatch::InvalidateTextureBinding(s_Data.m_Texture);
RenderCommand::DeleteTexture(s_Data.m_Texture);
}
s_Data.m_GenerateShader = nullptr;
s_Data.m_TextureID = 0;
s_Data.m_Texture = {};
s_Data.m_Center = glm::vec2(0.0f, 0.0f);
s_Data.m_WorldSize = 0.0f;
s_Data.m_Ready = false;
Expand All @@ -129,9 +129,9 @@ namespace OloEngine
return s_Data.m_Ready;
}

u32 CloudShadowMap::GetTextureID()
RHI::ResourceHandle CloudShadowMap::GetTextureHandle()
{
return s_Data.m_Ready ? s_Data.m_TextureID : 0;
return s_Data.m_Ready ? s_Data.m_Texture : RHI::NullResource;
}

glm::vec2 CloudShadowMap::GetCenter()
Expand Down
12 changes: 9 additions & 3 deletions OloEngine/src/OloEngine/Renderer/CloudShadowMap.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "OloEngine/Core/Base.h"
#include "OloEngine/Renderer/RHI/RHITypes.h"
#include "OloEngine/Core/Ref.h"

#include <glm/glm.hpp>
Expand Down Expand Up @@ -58,8 +59,8 @@ namespace OloEngine
/// @return true after the first successful Update() dispatch.
[[nodiscard]] static bool IsReady();

/// @return GL renderer id of the R8 512² shadow map (0 when not ready).
[[nodiscard]] static u32 GetTextureID();
/// @return Identity of the R8 512² shadow map; RHI::NullResource when not ready.
[[nodiscard]] static RHI::ResourceHandle GetTextureHandle();

/// @return world-XZ center of the current map (texel-snapped).
[[nodiscard]] static glm::vec2 GetCenter();
Expand All @@ -71,7 +72,12 @@ namespace OloEngine
struct CloudShadowMapData
{
Ref<ComputeShader> m_GenerateShader;
u32 m_TextureID = 0; // raw GL R8 512², owned (RenderCommand::CreateTexture2D / DeleteTexture)
// Owned R8 512² identity (issue #691 step 3, slice 6). Migrated off the
// raw GL name because it is bound through CommandDispatch's redundant-bind
// cache, which now keys on identities — feeding it a native id would not
// compile, and half-migrating the chain would leave a step that cannot
// reach the currency the next one wants.
RHI::ResourceHandle m_Texture{};
glm::vec2 m_Center{ 0.0f, 0.0f };
f32 m_WorldSize = 0.0f;
bool m_Ready = false;
Expand Down
9 changes: 7 additions & 2 deletions OloEngine/src/OloEngine/Renderer/Commands/CommandBucket.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "OloEngine/Core/Base.h"
#include "OloEngine/Renderer/RHI/RHITypes.h"
#include "OloEngine/Memory/Platform.h"
#include "CommandPacket.h"
#include "CommandAllocator.h"
Expand Down Expand Up @@ -35,7 +36,11 @@ namespace OloEngine
// right — which is what made this look like a distance-dependent LOD bug).
struct InstanceGroupKey
{
u32 vertexArrayID = 0;
// Identity, not driver name (issue #691 step 3, slice 6): batching two
// draws together because their VAOs share a recycled GL name would
// render one mesh with the other's geometry. Two LIVE handles cannot
// collide, so this is a correctness improvement, not a retype.
RHI::ResourceHandle vertexArrayID{};
u32 indexCount = 0;
u32 baseIndex = 0;
u16 materialDataIndex = 0;
Expand All @@ -48,7 +53,7 @@ namespace OloEngine
{
sizet operator()(const InstanceGroupKey& key) const
{
sizet h = std::hash<u32>{}(key.vertexArrayID);
sizet h = std::hash<u64>{}(RHI::HashKey(key.vertexArrayID));
h ^= std::hash<u32>{}(key.indexCount) + 0x9e3779b9 + (h << 6) + (h >> 2);
h ^= std::hash<u32>{}(key.baseIndex) + 0x9e3779b9 + (h << 6) + (h >> 2);
h ^= std::hash<u16>{}(key.materialDataIndex) + 0x9e3779b9 + (h << 6) + (h >> 2);
Expand Down
Loading
Loading