Reset recording renderer state on clear
This commit is contained in:
@@ -308,7 +308,9 @@ Known local toolchain state:
|
||||
render-pass-clear/scissor/depth/blend/shader-uniform/texture-bind/
|
||||
sampler-bind/draw/upload/mipmap-generation/texture-transition/texture-copy/readback/
|
||||
frame-capture/blit commands, draw mesh inputs, explicit draw ranges, and
|
||||
records trace markers and scopes without a window or GL context.
|
||||
records trace markers and scopes without a window or GL context. Recorder
|
||||
`clear()` also resets active render-pass and trace-scope state so automation
|
||||
can reuse the same recording device after an interrupted frame.
|
||||
- `pano_cli record-render` exposes the recording renderer through JSON
|
||||
automation, including backend feature flags, render-pass/depth-clear counts, scissor/depth/blend/
|
||||
shader-uniform/texture-bind/sampler-bind/upload/mipmap-generation/texture-transition/texture-copy/readback/
|
||||
|
||||
@@ -431,8 +431,8 @@ mipmap-generation command validation, texture-state transition validation, frame
|
||||
frame-capture command validation, render-target blit validation, texture-slot
|
||||
binding validation, blend-state validation, scissor-state validation,
|
||||
depth-state validation, trace marker/scope validation, sampler-state validation,
|
||||
and the canonical PanoPainter shader catalog now consumed by the legacy OpenGL
|
||||
app initialization path.
|
||||
recording-device reuse/reset validation, and the canonical PanoPainter shader
|
||||
catalog now consumed by the legacy OpenGL app initialization path.
|
||||
`pp_renderer_gl` now exists as the first OpenGL backend library and owns pure
|
||||
OpenGL capability detection for framebuffer fetch, map-buffer alignment, and
|
||||
float texture support. It also owns the OpenGL texture upload-type mapping used
|
||||
@@ -851,7 +851,9 @@ Results:
|
||||
shader uniform writes, texture/sampler binds, draw mesh inputs, explicit draw
|
||||
ranges, texture uploads/mipmap generations/state transitions/copies/readbacks, frame captures,
|
||||
and render-target blits, giving automation a backend-neutral render path that
|
||||
does not require a window or GL context.
|
||||
does not require a window or GL context. Clearing the recording device now
|
||||
resets active render-pass and trace-scope state so interrupted automation can
|
||||
reuse a recorder without carrying stale frame state forward.
|
||||
- `pano_cli record-render` exercises that headless recording renderer and emits
|
||||
JSON command counts, backend feature flags, resource creation counts, target dimensions, backend
|
||||
name, trace marker/scope and draw summary, labeled descriptor counts,
|
||||
|
||||
@@ -594,6 +594,15 @@ bool RecordingCommandContext::in_render_pass() const noexcept
|
||||
return in_render_pass_;
|
||||
}
|
||||
|
||||
void RecordingCommandContext::reset() noexcept
|
||||
{
|
||||
active_target_ = TextureDesc {};
|
||||
active_mesh_ = MeshDesc {};
|
||||
in_render_pass_ = false;
|
||||
shader_bound_ = false;
|
||||
mesh_bound_ = false;
|
||||
}
|
||||
|
||||
RecordingRenderTrace::RecordingRenderTrace(std::vector<RecordedRenderCommand>& commands) noexcept
|
||||
: commands_(&commands)
|
||||
{
|
||||
@@ -643,6 +652,11 @@ pp::foundation::Status RecordingRenderTrace::end_scope() noexcept
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
void RecordingRenderTrace::reset() noexcept
|
||||
{
|
||||
scope_depth_ = 0U;
|
||||
}
|
||||
|
||||
RecordingRenderDevice::RecordingRenderDevice() noexcept
|
||||
: context_(commands_)
|
||||
, trace_(commands_)
|
||||
@@ -757,6 +771,8 @@ std::span<const RecordedRenderCommand> RecordingRenderDevice::commands() const n
|
||||
void RecordingRenderDevice::clear() noexcept
|
||||
{
|
||||
commands_.clear();
|
||||
context_.reset();
|
||||
trace_.reset();
|
||||
}
|
||||
|
||||
const char* recorded_render_command_kind_name(RecordedRenderCommandKind kind) noexcept
|
||||
|
||||
@@ -172,6 +172,7 @@ public:
|
||||
void end_render_pass() noexcept override;
|
||||
|
||||
[[nodiscard]] bool in_render_pass() const noexcept;
|
||||
void reset() noexcept;
|
||||
|
||||
private:
|
||||
std::vector<RecordedRenderCommand>* commands_ = nullptr;
|
||||
@@ -188,6 +189,7 @@ public:
|
||||
[[nodiscard]] pp::foundation::Status marker(const char* component, const char* name) noexcept override;
|
||||
[[nodiscard]] pp::foundation::Status begin_scope(const char* component, const char* name) noexcept override;
|
||||
[[nodiscard]] pp::foundation::Status end_scope() noexcept override;
|
||||
void reset() noexcept;
|
||||
|
||||
private:
|
||||
std::vector<RecordedRenderCommand>* commands_ = nullptr;
|
||||
|
||||
@@ -2127,6 +2127,49 @@ void recording_renderer_records_valid_command_sequences(pp::tests::Harness& h)
|
||||
PP_EXPECT(h, device.commands().empty());
|
||||
}
|
||||
|
||||
void recording_renderer_clear_resets_context_and_trace_state(pp::tests::Harness& h)
|
||||
{
|
||||
RecordingRenderDevice device;
|
||||
RecordingRenderTarget target(TextureDesc {
|
||||
.extent = Extent2D { .width = 16, .height = 8 },
|
||||
.format = TextureFormat::rgba8,
|
||||
.usage = TextureUsage::render_target | TextureUsage::sampled | TextureUsage::readback_source,
|
||||
.debug_name = "reset-target",
|
||||
});
|
||||
|
||||
auto* trace = device.trace();
|
||||
PP_EXPECT(h, trace != nullptr);
|
||||
if (trace == nullptr) {
|
||||
return;
|
||||
}
|
||||
PP_EXPECT(h, trace->begin_scope("renderer", "interrupted-frame").ok());
|
||||
|
||||
auto& context = device.immediate_context();
|
||||
PP_EXPECT(h, context.begin_render_pass(target, RenderPassDesc {}).ok());
|
||||
PP_EXPECT(h, !device.commands().empty());
|
||||
|
||||
device.clear();
|
||||
PP_EXPECT(h, device.commands().empty());
|
||||
|
||||
const auto trace_end_after_clear = trace->end_scope();
|
||||
PP_EXPECT(h, !trace_end_after_clear.ok());
|
||||
PP_EXPECT(h, trace_end_after_clear.code == StatusCode::invalid_argument);
|
||||
PP_EXPECT(h, device.commands().empty());
|
||||
|
||||
PP_EXPECT(h, trace->begin_scope("renderer", "next-frame").ok());
|
||||
PP_EXPECT(h, trace->end_scope().ok());
|
||||
|
||||
PP_EXPECT(h, context.begin_render_pass(target, RenderPassDesc {}).ok());
|
||||
context.end_render_pass();
|
||||
|
||||
const auto commands = device.commands();
|
||||
PP_EXPECT(h, commands.size() == 4U);
|
||||
PP_EXPECT(h, commands[0].kind == RecordedRenderCommandKind::trace_begin_scope);
|
||||
PP_EXPECT(h, commands[1].kind == RecordedRenderCommandKind::trace_end_scope);
|
||||
PP_EXPECT(h, commands[2].kind == RecordedRenderCommandKind::begin_render_pass);
|
||||
PP_EXPECT(h, commands[3].kind == RecordedRenderCommandKind::end_render_pass);
|
||||
}
|
||||
|
||||
void recording_renderer_rejects_invalid_command_order_and_targets(pp::tests::Harness& h)
|
||||
{
|
||||
RecordingRenderDevice device;
|
||||
@@ -2565,6 +2608,7 @@ int main()
|
||||
harness.run("recording_renderer_records_mipmap_generation", recording_renderer_records_mipmap_generation);
|
||||
harness.run("recording_renderer_records_texture_transitions", recording_renderer_records_texture_transitions);
|
||||
harness.run("recording_renderer_records_valid_command_sequences", recording_renderer_records_valid_command_sequences);
|
||||
harness.run("recording_renderer_clear_resets_context_and_trace_state", recording_renderer_clear_resets_context_and_trace_state);
|
||||
harness.run("recording_renderer_rejects_invalid_command_order_and_targets", recording_renderer_rejects_invalid_command_order_and_targets);
|
||||
return harness.finish();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user