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/
|
render-pass-clear/scissor/depth/blend/shader-uniform/texture-bind/
|
||||||
sampler-bind/draw/upload/mipmap-generation/texture-transition/texture-copy/readback/
|
sampler-bind/draw/upload/mipmap-generation/texture-transition/texture-copy/readback/
|
||||||
frame-capture/blit commands, draw mesh inputs, explicit draw ranges, and
|
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
|
- `pano_cli record-render` exposes the recording renderer through JSON
|
||||||
automation, including backend feature flags, render-pass/depth-clear counts, scissor/depth/blend/
|
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/
|
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
|
frame-capture command validation, render-target blit validation, texture-slot
|
||||||
binding validation, blend-state validation, scissor-state validation,
|
binding validation, blend-state validation, scissor-state validation,
|
||||||
depth-state validation, trace marker/scope validation, sampler-state validation,
|
depth-state validation, trace marker/scope validation, sampler-state validation,
|
||||||
and the canonical PanoPainter shader catalog now consumed by the legacy OpenGL
|
recording-device reuse/reset validation, and the canonical PanoPainter shader
|
||||||
app initialization path.
|
catalog now consumed by the legacy OpenGL app initialization path.
|
||||||
`pp_renderer_gl` now exists as the first OpenGL backend library and owns pure
|
`pp_renderer_gl` now exists as the first OpenGL backend library and owns pure
|
||||||
OpenGL capability detection for framebuffer fetch, map-buffer alignment, and
|
OpenGL capability detection for framebuffer fetch, map-buffer alignment, and
|
||||||
float texture support. It also owns the OpenGL texture upload-type mapping used
|
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
|
shader uniform writes, texture/sampler binds, draw mesh inputs, explicit draw
|
||||||
ranges, texture uploads/mipmap generations/state transitions/copies/readbacks, frame captures,
|
ranges, texture uploads/mipmap generations/state transitions/copies/readbacks, frame captures,
|
||||||
and render-target blits, giving automation a backend-neutral render path that
|
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
|
- `pano_cli record-render` exercises that headless recording renderer and emits
|
||||||
JSON command counts, backend feature flags, resource creation counts, target dimensions, backend
|
JSON command counts, backend feature flags, resource creation counts, target dimensions, backend
|
||||||
name, trace marker/scope and draw summary, labeled descriptor counts,
|
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_;
|
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
|
RecordingRenderTrace::RecordingRenderTrace(std::vector<RecordedRenderCommand>& commands) noexcept
|
||||||
: commands_(&commands)
|
: commands_(&commands)
|
||||||
{
|
{
|
||||||
@@ -643,6 +652,11 @@ pp::foundation::Status RecordingRenderTrace::end_scope() noexcept
|
|||||||
return pp::foundation::Status::success();
|
return pp::foundation::Status::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RecordingRenderTrace::reset() noexcept
|
||||||
|
{
|
||||||
|
scope_depth_ = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
RecordingRenderDevice::RecordingRenderDevice() noexcept
|
RecordingRenderDevice::RecordingRenderDevice() noexcept
|
||||||
: context_(commands_)
|
: context_(commands_)
|
||||||
, trace_(commands_)
|
, trace_(commands_)
|
||||||
@@ -757,6 +771,8 @@ std::span<const RecordedRenderCommand> RecordingRenderDevice::commands() const n
|
|||||||
void RecordingRenderDevice::clear() noexcept
|
void RecordingRenderDevice::clear() noexcept
|
||||||
{
|
{
|
||||||
commands_.clear();
|
commands_.clear();
|
||||||
|
context_.reset();
|
||||||
|
trace_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* recorded_render_command_kind_name(RecordedRenderCommandKind kind) noexcept
|
const char* recorded_render_command_kind_name(RecordedRenderCommandKind kind) noexcept
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ public:
|
|||||||
void end_render_pass() noexcept override;
|
void end_render_pass() noexcept override;
|
||||||
|
|
||||||
[[nodiscard]] bool in_render_pass() const noexcept;
|
[[nodiscard]] bool in_render_pass() const noexcept;
|
||||||
|
void reset() noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<RecordedRenderCommand>* commands_ = nullptr;
|
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 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 begin_scope(const char* component, const char* name) noexcept override;
|
||||||
[[nodiscard]] pp::foundation::Status end_scope() noexcept override;
|
[[nodiscard]] pp::foundation::Status end_scope() noexcept override;
|
||||||
|
void reset() noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<RecordedRenderCommand>* commands_ = nullptr;
|
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());
|
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)
|
void recording_renderer_rejects_invalid_command_order_and_targets(pp::tests::Harness& h)
|
||||||
{
|
{
|
||||||
RecordingRenderDevice device;
|
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_mipmap_generation", recording_renderer_records_mipmap_generation);
|
||||||
harness.run("recording_renderer_records_texture_transitions", recording_renderer_records_texture_transitions);
|
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_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);
|
harness.run("recording_renderer_rejects_invalid_command_order_and_targets", recording_renderer_rejects_invalid_command_order_and_targets);
|
||||||
return harness.finish();
|
return harness.finish();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user