This commit is contained in:
2026-08-29 14:00:25 +08:00
parent 899223c7a7
commit 4ff2220e38
14 changed files with 452 additions and 60 deletions
+48
View File
@@ -123,6 +123,30 @@ Frame_Statistics_Sample Render_Frame::statistics() const {
Frame_Statistic::backend_apply_ms, Frame_Statistic::backend_apply_ms,
Frame_Statistic::backend_plan_ms, Frame_Statistic::backend_plan_ms,
Frame_Statistic::backend_execute_ms, Frame_Statistic::backend_execute_ms,
Frame_Statistic::backend_target_acquire_ms,
Frame_Statistic::backend_structure_check_ms,
Frame_Statistic::backend_query_ms,
Frame_Statistic::backend_runtime_plan_ms,
Frame_Statistic::backend_runtime_execute_ms,
Frame_Statistic::backend_mvp_update_ms,
Frame_Statistic::backend_frame_begin_ms,
Frame_Statistic::backend_frame_plan_ms,
Frame_Statistic::backend_external_register_ms,
Frame_Statistic::backend_frame_attach_ms,
Frame_Statistic::backend_frame_execute_ms,
Frame_Statistic::backend_frame_finish_ms,
Frame_Statistic::backend_drp_validation_ms,
Frame_Statistic::backend_drp_state_ms,
Frame_Statistic::backend_drp_buffer_create_ms,
Frame_Statistic::backend_drp_texture_create_ms,
Frame_Statistic::backend_drp_shader_create_ms,
Frame_Statistic::backend_drp_shader_compile_ms,
Frame_Statistic::backend_drp_shader_module_create_ms,
Frame_Statistic::backend_drp_pipeline_create_ms,
Frame_Statistic::backend_drp_binding_create_ms,
Frame_Statistic::backend_drp_upload_ms,
Frame_Statistic::backend_drp_transfer_ms,
Frame_Statistic::backend_drp_record_ms,
Frame_Statistic::backend_submit_queue_ms, Frame_Statistic::backend_submit_queue_ms,
Frame_Statistic::backend_submit_ms, Frame_Statistic::backend_submit_ms,
Frame_Statistic::gpu_completion_observation_ms, Frame_Statistic::gpu_completion_observation_ms,
@@ -136,6 +160,30 @@ Frame_Statistics_Sample Render_Frame::statistics() const {
Frame_Trace_Measurement::backend_apply_ns, Frame_Trace_Measurement::backend_apply_ns,
Frame_Trace_Measurement::backend_plan_ns, Frame_Trace_Measurement::backend_plan_ns,
Frame_Trace_Measurement::backend_execute_ns, Frame_Trace_Measurement::backend_execute_ns,
Frame_Trace_Measurement::backend_target_acquire_ns,
Frame_Trace_Measurement::backend_structure_check_ns,
Frame_Trace_Measurement::backend_query_ns,
Frame_Trace_Measurement::backend_runtime_plan_ns,
Frame_Trace_Measurement::backend_runtime_execute_ns,
Frame_Trace_Measurement::backend_mvp_update_ns,
Frame_Trace_Measurement::backend_frame_begin_ns,
Frame_Trace_Measurement::backend_frame_plan_ns,
Frame_Trace_Measurement::backend_external_register_ns,
Frame_Trace_Measurement::backend_frame_attach_ns,
Frame_Trace_Measurement::backend_frame_execute_ns,
Frame_Trace_Measurement::backend_frame_finish_ns,
Frame_Trace_Measurement::backend_drp_validation_ns,
Frame_Trace_Measurement::backend_drp_state_ns,
Frame_Trace_Measurement::backend_drp_buffer_create_ns,
Frame_Trace_Measurement::backend_drp_texture_create_ns,
Frame_Trace_Measurement::backend_drp_shader_create_ns,
Frame_Trace_Measurement::backend_drp_shader_compile_ns,
Frame_Trace_Measurement::backend_drp_shader_module_create_ns,
Frame_Trace_Measurement::backend_drp_pipeline_create_ns,
Frame_Trace_Measurement::backend_drp_binding_create_ns,
Frame_Trace_Measurement::backend_drp_upload_ns,
Frame_Trace_Measurement::backend_drp_transfer_ns,
Frame_Trace_Measurement::backend_drp_record_ns,
Frame_Trace_Measurement::backend_submit_queue_ns, Frame_Trace_Measurement::backend_submit_queue_ns,
Frame_Trace_Measurement::backend_submit_ns, Frame_Trace_Measurement::backend_submit_ns,
Frame_Trace_Measurement::gpu_completion_observation_ns, Frame_Trace_Measurement::gpu_completion_observation_ns,
+24
View File
@@ -54,6 +54,30 @@ enum struct Frame_Trace_Measurement : std::uint8_t {
backend_apply_ns, backend_apply_ns,
backend_plan_ns, backend_plan_ns,
backend_execute_ns, backend_execute_ns,
backend_target_acquire_ns,
backend_structure_check_ns,
backend_query_ns,
backend_runtime_plan_ns,
backend_runtime_execute_ns,
backend_mvp_update_ns,
backend_frame_begin_ns,
backend_frame_plan_ns,
backend_external_register_ns,
backend_frame_attach_ns,
backend_frame_execute_ns,
backend_frame_finish_ns,
backend_drp_validation_ns,
backend_drp_state_ns,
backend_drp_buffer_create_ns,
backend_drp_texture_create_ns,
backend_drp_shader_create_ns,
backend_drp_shader_compile_ns,
backend_drp_shader_module_create_ns,
backend_drp_pipeline_create_ns,
backend_drp_binding_create_ns,
backend_drp_upload_ns,
backend_drp_transfer_ns,
backend_drp_record_ns,
backend_submit_queue_ns, backend_submit_queue_ns,
backend_submit_ns, backend_submit_ns,
gpu_completion_observation_ns, gpu_completion_observation_ns,
+24
View File
@@ -19,6 +19,30 @@ enum struct Frame_Statistic : std::uint8_t {
backend_apply_ms, backend_apply_ms,
backend_plan_ms, backend_plan_ms,
backend_execute_ms, backend_execute_ms,
backend_target_acquire_ms,
backend_structure_check_ms,
backend_query_ms,
backend_runtime_plan_ms,
backend_runtime_execute_ms,
backend_mvp_update_ms,
backend_frame_begin_ms,
backend_frame_plan_ms,
backend_external_register_ms,
backend_frame_attach_ms,
backend_frame_execute_ms,
backend_frame_finish_ms,
backend_drp_validation_ms,
backend_drp_state_ms,
backend_drp_buffer_create_ms,
backend_drp_texture_create_ms,
backend_drp_shader_create_ms,
backend_drp_shader_compile_ms,
backend_drp_shader_module_create_ms,
backend_drp_pipeline_create_ms,
backend_drp_binding_create_ms,
backend_drp_upload_ms,
backend_drp_transfer_ms,
backend_drp_record_ms,
backend_submit_queue_ms, backend_submit_queue_ms,
backend_submit_ms, backend_submit_ms,
gpu_completion_observation_ms, gpu_completion_observation_ms,
+29 -3
View File
@@ -354,9 +354,34 @@ nlohmann::json datoviz_observation_json(
"queue_submit_wait", "queue_submit_wait",
milliseconds(value.queue_submit_wait_ns) milliseconds(value.queue_submit_wait_ns)
}, },
{"target_acquire", milliseconds(value.target_acquire_ns)},
{"structure_check", milliseconds(value.structure_check_ns)},
{"apply", milliseconds(value.apply_ns)}, {"apply", milliseconds(value.apply_ns)},
{"emit", milliseconds(value.emit_ns)}, {"query", milliseconds(value.query_ns)},
{"execute", milliseconds(value.execute_ns)}, {"runtime_plan", milliseconds(value.runtime_plan_ns)},
{"runtime_execute", milliseconds(value.runtime_execute_ns)},
{"mvp_update", milliseconds(value.mvp_update_ns)},
{"frame_begin", milliseconds(value.frame_begin_ns)},
{"frame_plan", milliseconds(value.frame_plan_ns)},
{"external_register", milliseconds(value.external_register_ns)},
{"frame_attach", milliseconds(value.frame_attach_ns)},
{"frame_execute", milliseconds(value.frame_execute_ns)},
{"frame_finish", milliseconds(value.frame_finish_ns)},
{"drp_validation", milliseconds(value.drp_validation_ns)},
{"drp_state", milliseconds(value.drp_state_ns)},
{"drp_buffer_create", milliseconds(value.drp_buffer_create_ns)},
{"drp_texture_create", milliseconds(value.drp_texture_create_ns)},
{"drp_shader_create", milliseconds(value.drp_shader_create_ns)},
{"drp_shader_compile", milliseconds(value.drp_shader_compile_ns)},
{
"drp_shader_module_create",
milliseconds(value.drp_shader_module_create_ns)
},
{"drp_pipeline_create", milliseconds(value.drp_pipeline_create_ns)},
{"drp_binding_create", milliseconds(value.drp_binding_create_ns)},
{"drp_upload", milliseconds(value.drp_upload_ns)},
{"drp_transfer", milliseconds(value.drp_transfer_ns)},
{"drp_record", milliseconds(value.drp_record_ns)},
{"submit", milliseconds(value.submit_ns)}, {"submit", milliseconds(value.submit_ns)},
{ {
"gpu_completion_observation", "gpu_completion_observation",
@@ -372,7 +397,8 @@ nlohmann::json datoviz_observation_json(
{ {
"traffic", { "traffic", {
{"uploaded_bytes", value.uploaded_bytes}, {"uploaded_bytes", value.uploaded_bytes},
{"readback_bytes", value.readback_bytes} {"readback_bytes", value.readback_bytes},
{"pipeline_create_count", value.drp_pipeline_create_count}
} }
}, },
{ {
+77
View File
@@ -387,6 +387,44 @@ protected:
statistic_value("backend_execute_ms", "p95"); statistic_value("backend_execute_ms", "p95");
state.counters[prefix + "backend_execute_max_ms"] = state.counters[prefix + "backend_execute_max_ms"] =
statistic_value("backend_execute_ms", "maximum"); statistic_value("backend_execute_ms", "maximum");
constexpr std::array detailed_backend_statistics{
"backend_target_acquire_ms",
"backend_structure_check_ms",
"backend_query_ms",
"backend_runtime_plan_ms",
"backend_runtime_execute_ms",
"backend_mvp_update_ms",
"backend_frame_begin_ms",
"backend_frame_plan_ms",
"backend_external_register_ms",
"backend_frame_attach_ms",
"backend_frame_execute_ms",
"backend_frame_finish_ms"};
constexpr std::array detailed_drp_statistics{
"backend_drp_validation_ms",
"backend_drp_state_ms",
"backend_drp_buffer_create_ms",
"backend_drp_texture_create_ms",
"backend_drp_shader_create_ms",
"backend_drp_shader_compile_ms",
"backend_drp_shader_module_create_ms",
"backend_drp_pipeline_create_ms",
"backend_drp_binding_create_ms",
"backend_drp_upload_ms",
"backend_drp_transfer_ms",
"backend_drp_record_ms"};
for (const std::string_view name : detailed_backend_statistics) {
state.counters[prefix + std::string{name} + "/p95"] =
statistic_value(name, "p95");
state.counters[prefix + std::string{name} + "/max"] =
statistic_value(name, "maximum");
}
for (const std::string_view name : detailed_drp_statistics) {
state.counters[prefix + std::string{name} + "/p95"] =
statistic_value(name, "p95");
state.counters[prefix + std::string{name} + "/max"] =
statistic_value(name, "maximum");
}
state.counters[prefix + "backend_submit_queue_ms"] = state.counters[prefix + "backend_submit_queue_ms"] =
statistic_value("backend_submit_queue_ms", "average"); statistic_value("backend_submit_queue_ms", "average");
state.counters[prefix + "backend_submit_queue_p95_ms"] = state.counters[prefix + "backend_submit_queue_p95_ms"] =
@@ -546,6 +584,45 @@ public:
<< std::setw(10) << counter(prefix + "slot_backpressure") << std::setw(10) << counter(prefix + "slot_backpressure")
<< std::setw(9) << counter(prefix + "scene_rejected") << std::setw(9) << counter(prefix + "scene_rejected")
<< '\n'; << '\n';
constexpr std::array detailed_backend_statistics{
std::pair{"acquire", "backend_target_acquire_ms"},
std::pair{"structure", "backend_structure_check_ms"},
std::pair{"query", "backend_query_ms"},
std::pair{"runtime-plan", "backend_runtime_plan_ms"},
std::pair{"runtime-exec", "backend_runtime_execute_ms"},
std::pair{"mvp", "backend_mvp_update_ms"},
std::pair{"frame-begin", "backend_frame_begin_ms"},
std::pair{"frame-plan", "backend_frame_plan_ms"},
std::pair{"external", "backend_external_register_ms"},
std::pair{"attach", "backend_frame_attach_ms"},
std::pair{"frame-exec", "backend_frame_execute_ms"},
std::pair{"finish", "backend_frame_finish_ms"}};
output << " backend-detail " << id;
for (const auto& [label, statistic] :
detailed_backend_statistics)
output << " " << label << "95/max="
<< counter(prefix + statistic + "/p95") << "/"
<< counter(prefix + statistic + "/max");
output << '\n';
constexpr std::array detailed_drp_statistics{
std::pair{"validate", "backend_drp_validation_ms"},
std::pair{"state", "backend_drp_state_ms"},
std::pair{"buffer", "backend_drp_buffer_create_ms"},
std::pair{"texture", "backend_drp_texture_create_ms"},
std::pair{"shader", "backend_drp_shader_create_ms"},
std::pair{"shader-compile", "backend_drp_shader_compile_ms"},
std::pair{"shader-module", "backend_drp_shader_module_create_ms"},
std::pair{"pipeline", "backend_drp_pipeline_create_ms"},
std::pair{"binding", "backend_drp_binding_create_ms"},
std::pair{"upload", "backend_drp_upload_ms"},
std::pair{"transfer", "backend_drp_transfer_ms"},
std::pair{"record", "backend_drp_record_ms"}};
output << " drp-detail " << id;
for (const auto& [label, statistic] : detailed_drp_statistics)
output << " " << label << "95/max="
<< counter(prefix + statistic + "/p95") << "/"
<< counter(prefix + statistic + "/max");
output << '\n';
} }
output << "aggregate_fps=" << counter("aggregate_fps") output << "aggregate_fps=" << counter("aggregate_fps")
<< " min_fps=" << counter("minimum_plot_fps") << " min_fps=" << counter("minimum_plot_fps")
@@ -31,9 +31,32 @@ struct Datoviz_Frame_Observation {
bool controller_input_applied{}; /* 本帧是否把已提交输入应用到 Datoviz 控制器。 */ bool controller_input_applied{}; /* 本帧是否把已提交输入应用到 Datoviz 控制器。 */
bool prepare_released_after_submission{}; /* 本帧实际提交后是否立即允许下一帧 Prepare。 */ bool prepare_released_after_submission{}; /* 本帧实际提交后是否立即允许下一帧 Prepare。 */
std::uint64_t queue_submit_wait_ns{}; /* 获取共享 VkQueue 提交权的墙钟耗时。 */ std::uint64_t queue_submit_wait_ns{}; /* 获取共享 VkQueue 提交权的墙钟耗时。 */
std::uint64_t apply_ns{}; /* 应用本帧 Visual 数据耗时。 */ std::uint64_t target_acquire_ns{}; /* 查找或创建本帧三槽目标的墙钟耗时。 */
std::uint64_t emit_ns{}; /* 生成 Datoviz 帧计划耗时。 */ std::uint64_t structure_check_ns{}; /* 判断命令结构是否变化的墙钟耗时。 */
std::uint64_t execute_ns{}; /* 执行 Datoviz 帧计划耗时。 */ std::uint64_t apply_ns{}; /* 应用 Camera、Axes 和 Visual 数据的墙钟耗时。 */
std::uint64_t query_ns{}; /* 处理 Datoviz 查询与悬浮读数的墙钟耗时。 */
std::uint64_t runtime_plan_ns{}; /* 生成增量 Runtime 资源命令流的墙钟耗时。 */
std::uint64_t runtime_execute_ns{}; /* 执行增量 Runtime 资源命令流的墙钟耗时。 */
std::uint64_t mvp_update_ns{}; /* 更新可复用命令所引用 MVP 缓冲的墙钟耗时。 */
std::uint64_t frame_begin_ns{}; /* 重置并开始目标命令缓冲录制的墙钟耗时。 */
std::uint64_t frame_plan_ns{}; /* 生成完整 Datoviz 帧计划的墙钟耗时。 */
std::uint64_t external_register_ns{}; /* 注册外部属性缓冲的墙钟耗时。 */
std::uint64_t frame_attach_ns{}; /* 把借用目标附加到 DRP2 Runtime 的墙钟耗时。 */
std::uint64_t frame_execute_ns{}; /* 执行完整帧命令流的墙钟耗时。 */
std::uint64_t frame_finish_ns{}; /* 完成命令录制并建立提交描述的墙钟耗时。 */
std::uint64_t drp_validation_ns{}; /* DRP2 语义验证与状态复制耗时。 */
std::uint64_t drp_state_ns{}; /* DRP2 状态建立与提交耗时。 */
std::uint64_t drp_buffer_create_ns{}; /* Vulkan Buffer 创建命令耗时。 */
std::uint64_t drp_texture_create_ns{}; /* Vulkan Texture 创建命令耗时。 */
std::uint64_t drp_shader_create_ns{}; /* Vulkan Shader Module 创建命令耗时。 */
std::uint64_t drp_shader_compile_ns{}; /* Shader Module 命令中 GLSL 到 SPIR-V 的编译耗时。 */
std::uint64_t drp_shader_module_create_ns{}; /* Shader Module 命令中 vkCreateShaderModule 的耗时。 */
std::uint64_t drp_pipeline_create_ns{}; /* Vulkan Pipeline 创建命令耗时。 */
std::uint64_t drp_binding_create_ns{}; /* Sampler、Layout 与 Bind Group 创建命令耗时。 */
std::uint64_t drp_upload_ns{}; /* Buffer 与 Texture 写入命令耗时。 */
std::uint64_t drp_transfer_ns{}; /* 显式 Copy 命令耗时。 */
std::uint64_t drp_record_ns{}; /* Render/Compute Pass 录制命令耗时。 */
std::uint32_t drp_pipeline_create_count{}; /* 本帧实际创建的图形/计算管线数。 */
std::uint64_t submit_ns{}; /* Vulkan 队列提交耗时。 */ std::uint64_t submit_ns{}; /* Vulkan 队列提交耗时。 */
std::uint64_t gpu_completion_observation_ns{}; /* 从 watch 到探测到 fence 完成的墙钟耗时。 */ std::uint64_t gpu_completion_observation_ns{}; /* 从 watch 到探测到 fence 完成的墙钟耗时。 */
std::uint64_t completion_task_queue_ns{}; /* 探测到 fence 完成后,Scene completion task 的排队耗时。 */ std::uint64_t completion_task_queue_ns{}; /* 探测到 fence 完成后,Scene completion task 的排队耗时。 */
+59 -4
View File
@@ -208,12 +208,67 @@ inline void publish_datoviz_observation(
if (observation.apply_ns) if (observation.apply_ns)
frame->record(Frame_Trace_Measurement::backend_apply_ns, frame->record(Frame_Trace_Measurement::backend_apply_ns,
observation.apply_ns); observation.apply_ns);
if (observation.emit_ns) const auto plan_ns = observation.runtime_plan_ns +
observation.frame_plan_ns;
const auto execute_ns = observation.runtime_execute_ns +
observation.frame_attach_ns + observation.frame_execute_ns;
if (plan_ns)
frame->record(Frame_Trace_Measurement::backend_plan_ns, frame->record(Frame_Trace_Measurement::backend_plan_ns,
observation.emit_ns); plan_ns);
if (observation.execute_ns) if (execute_ns)
frame->record(Frame_Trace_Measurement::backend_execute_ns, frame->record(Frame_Trace_Measurement::backend_execute_ns,
observation.execute_ns); execute_ns);
const std::array detailed_timings{
std::pair{Frame_Trace_Measurement::backend_target_acquire_ns,
observation.target_acquire_ns},
std::pair{Frame_Trace_Measurement::backend_structure_check_ns,
observation.structure_check_ns},
std::pair{Frame_Trace_Measurement::backend_query_ns,
observation.query_ns},
std::pair{Frame_Trace_Measurement::backend_runtime_plan_ns,
observation.runtime_plan_ns},
std::pair{Frame_Trace_Measurement::backend_runtime_execute_ns,
observation.runtime_execute_ns},
std::pair{Frame_Trace_Measurement::backend_mvp_update_ns,
observation.mvp_update_ns},
std::pair{Frame_Trace_Measurement::backend_frame_begin_ns,
observation.frame_begin_ns},
std::pair{Frame_Trace_Measurement::backend_frame_plan_ns,
observation.frame_plan_ns},
std::pair{Frame_Trace_Measurement::backend_external_register_ns,
observation.external_register_ns},
std::pair{Frame_Trace_Measurement::backend_frame_attach_ns,
observation.frame_attach_ns},
std::pair{Frame_Trace_Measurement::backend_frame_execute_ns,
observation.frame_execute_ns},
std::pair{Frame_Trace_Measurement::backend_frame_finish_ns,
observation.frame_finish_ns},
std::pair{Frame_Trace_Measurement::backend_drp_validation_ns,
observation.drp_validation_ns},
std::pair{Frame_Trace_Measurement::backend_drp_state_ns,
observation.drp_state_ns},
std::pair{Frame_Trace_Measurement::backend_drp_buffer_create_ns,
observation.drp_buffer_create_ns},
std::pair{Frame_Trace_Measurement::backend_drp_texture_create_ns,
observation.drp_texture_create_ns},
std::pair{Frame_Trace_Measurement::backend_drp_shader_create_ns,
observation.drp_shader_create_ns},
std::pair{Frame_Trace_Measurement::backend_drp_shader_compile_ns,
observation.drp_shader_compile_ns},
std::pair{Frame_Trace_Measurement::backend_drp_shader_module_create_ns,
observation.drp_shader_module_create_ns},
std::pair{Frame_Trace_Measurement::backend_drp_pipeline_create_ns,
observation.drp_pipeline_create_ns},
std::pair{Frame_Trace_Measurement::backend_drp_binding_create_ns,
observation.drp_binding_create_ns},
std::pair{Frame_Trace_Measurement::backend_drp_upload_ns,
observation.drp_upload_ns},
std::pair{Frame_Trace_Measurement::backend_drp_transfer_ns,
observation.drp_transfer_ns},
std::pair{Frame_Trace_Measurement::backend_drp_record_ns,
observation.drp_record_ns}};
for (const auto& [measurement, value] : detailed_timings)
if (value) frame->record(measurement, value);
if (observation.queue_submit_wait_ns) if (observation.queue_submit_wait_ns)
frame->record(Frame_Trace_Measurement::backend_submit_queue_ns, frame->record(Frame_Trace_Measurement::backend_submit_queue_ns,
observation.queue_submit_wait_ns); observation.queue_submit_wait_ns);
@@ -6,6 +6,60 @@
namespace aethera::render_3d::detail { namespace aethera::render_3d::detail {
namespace {
void accumulate_execution_timing(
const DvzDrp2ExecutionTiming& source,
Datoviz_Frame_Observation& target) noexcept {
const auto command = [&](DvzDrp2CommandType type) noexcept {
return source.command_ns[static_cast<std::uint32_t>(type)];
};
const auto count = [&](DvzDrp2CommandType type) noexcept {
return source.command_count[static_cast<std::uint32_t>(type)];
};
target.drp_validation_ns += source.validation_ns;
target.drp_state_ns += source.state_ensure_ns + source.state_commit_ns;
target.drp_buffer_create_ns += command(DVZ_DRP2_COMMAND_CREATE_BUFFER);
target.drp_texture_create_ns += command(DVZ_DRP2_COMMAND_CREATE_TEXTURE);
target.drp_shader_create_ns += command(DVZ_DRP2_COMMAND_CREATE_SHADER_MODULE);
target.drp_shader_compile_ns += source.shader_compile_ns;
target.drp_shader_module_create_ns += source.shader_module_create_ns;
target.drp_pipeline_create_ns +=
command(DVZ_DRP2_COMMAND_CREATE_RENDER_PIPELINE) +
command(DVZ_DRP2_COMMAND_CREATE_COMPUTE_PIPELINE);
target.drp_pipeline_create_count +=
count(DVZ_DRP2_COMMAND_CREATE_RENDER_PIPELINE) +
count(DVZ_DRP2_COMMAND_CREATE_COMPUTE_PIPELINE);
target.drp_binding_create_ns +=
command(DVZ_DRP2_COMMAND_CREATE_SAMPLER) +
command(DVZ_DRP2_COMMAND_CREATE_BIND_GROUP_LAYOUT) +
command(DVZ_DRP2_COMMAND_CREATE_BIND_GROUP);
target.drp_upload_ns += command(DVZ_DRP2_COMMAND_WRITE_BUFFER) +
command(DVZ_DRP2_COMMAND_WRITE_TEXTURE);
target.drp_transfer_ns +=
command(DVZ_DRP2_COMMAND_COPY_BUFFER_TO_BUFFER) +
command(DVZ_DRP2_COMMAND_COPY_BUFFER_TO_TEXTURE) +
command(DVZ_DRP2_COMMAND_COPY_TEXTURE_TO_BUFFER) +
command(DVZ_DRP2_COMMAND_COPY_TEXTURE_TO_TEXTURE);
constexpr std::array record_commands{
DVZ_DRP2_COMMAND_BEGIN_RENDER_PASS,
DVZ_DRP2_COMMAND_BEGIN_COMPUTE_PASS,
DVZ_DRP2_COMMAND_SET_VIEWPORT,
DVZ_DRP2_COMMAND_SET_SCISSOR,
DVZ_DRP2_COMMAND_SET_PIPELINE,
DVZ_DRP2_COMMAND_SET_BIND_GROUP,
DVZ_DRP2_COMMAND_SET_VERTEX_BUFFER,
DVZ_DRP2_COMMAND_SET_INDEX_BUFFER,
DVZ_DRP2_COMMAND_DRAW,
DVZ_DRP2_COMMAND_DRAW_INDEXED,
DVZ_DRP2_COMMAND_DISPATCH_WORKGROUPS,
DVZ_DRP2_COMMAND_END_RENDER_PASS,
DVZ_DRP2_COMMAND_END_COMPUTE_PASS,
DVZ_DRP2_COMMAND_RESOURCE_BARRIER};
for (const auto type : record_commands)
target.drp_record_ns += command(type);
}
}
/* Datoviz Scene 根据当前权威资源生成 DRP2 命令流描述,不提交 GPU。 */ /* Datoviz Scene 根据当前权威资源生成 DRP2 命令流描述,不提交 GPU。 */
DvzSceneFrameArtifact* Scene_Datoviz_State::emit( DvzSceneFrameArtifact* Scene_Datoviz_State::emit(
const Scene_3D_Parameters& scene, std::uint8_t target_index) { const Scene_3D_Parameters& scene, std::uint8_t target_index) {
@@ -143,12 +197,6 @@ std::optional<Datoviz_Pending_Frame> Scene_Datoviz_State::prepare(
* VkQueue。它必须和 Render Domain 的显式 submit 使用同一外部同步域。 * VkQueue。它必须和 Render Domain 的显式 submit 使用同一外部同步域。
* 热路径的已录制目标复用在此锁之前返回,仍可在各 Scene 准备线程并行。 * 热路径的已录制目标复用在此锁之前返回,仍可在各 Scene 准备线程并行。
*/ */
std::optional<std::uint8_t> target_index;
{
std::lock_guard resource_lock(target_mutex_);
target_index = acquire_target(scene.viewport);
}
if (!target_index) return std::nullopt;
Datoviz_Frame_Observation observation; Datoviz_Frame_Observation observation;
observation.render_sequence = frame_sequence; observation.render_sequence = frame_sequence;
observation.path = Datoviz_Frame_Path::recorded; observation.path = Datoviz_Frame_Path::recorded;
@@ -156,14 +204,26 @@ std::optional<Datoviz_Pending_Frame> Scene_Datoviz_State::prepare(
observation.readback_requested = readback; observation.readback_requested = readback;
observation.controller_input_applied = input_changed_; observation.controller_input_applied = input_changed_;
std::uint64_t phase_started = trace_now_ns(); std::uint64_t phase_started = trace_now_ns();
std::optional<std::uint8_t> target_index;
{
std::lock_guard resource_lock(target_mutex_);
target_index = acquire_target(scene.viewport);
}
observation.target_acquire_ns = trace_now_ns() - phase_started;
if (!target_index) return std::nullopt;
phase_started = trace_now_ns();
const bool content_changed = !matches_command_structure(scene, visuals); const bool content_changed = !matches_command_structure(scene, visuals);
observation.structure_check_ns = trace_now_ns() - phase_started;
if (content_changed) ++command_revision_; if (content_changed) ++command_revision_;
auto& frame_target = *targets_->values[*target_index]; auto& frame_target = *targets_->values[*target_index];
const bool bind_target = const bool bind_target =
!frame_target.can_reuse_commands(command_revision_, readback); !frame_target.can_reuse_commands(command_revision_, readback);
phase_started = trace_now_ns();
observation.uploaded_bytes = apply( observation.uploaded_bytes = apply(
scene, visuals, *target_index, bind_target); scene, visuals, *target_index, bind_target);
observation.apply_ns = trace_now_ns() - phase_started;
bool query_changed_scene{}; bool query_changed_scene{};
phase_started = trace_now_ns();
if (item_interaction_ != nullptr) { if (item_interaction_ != nullptr) {
static_cast<void>(dvz_figure_process_queries( static_cast<void>(dvz_figure_process_queries(
figure_, runtime_slots_[*target_index].runtime, nullptr)); figure_, runtime_slots_[*target_index].runtime, nullptr));
@@ -198,8 +258,8 @@ std::optional<Datoviz_Pending_Frame> Scene_Datoviz_State::prepare(
} }
} }
} }
observation.query_ns = trace_now_ns() - phase_started;
if (query_changed_scene) ++command_revision_; if (query_changed_scene) ++command_revision_;
observation.apply_ns = trace_now_ns() - phase_started;
bool runtime_resources_updated{}; bool runtime_resources_updated{};
if (frame_target.can_reuse_commands(command_revision_, readback) && if (frame_target.can_reuse_commands(command_revision_, readback) &&
!target_runtime_resources_current(visuals, *target_index)) { !target_runtime_resources_current(visuals, *target_index)) {
@@ -220,7 +280,7 @@ std::optional<Datoviz_Pending_Frame> Scene_Datoviz_State::prepare(
&uploaded_bytes, &command_recording_valid, &report), &uploaded_bytes, &command_recording_valid, &report),
&dvz_drp2_stream_destroy &dvz_drp2_stream_destroy
}; };
observation.emit_ns += trace_now_ns() - phase_started; observation.runtime_plan_ns = trace_now_ns() - phase_started;
if (!update_stream) { if (!update_stream) {
std::string message = std::string message =
"failed to prepare Datoviz retained runtime resources"; "failed to prepare Datoviz retained runtime resources";
@@ -233,11 +293,13 @@ std::optional<Datoviz_Pending_Frame> Scene_Datoviz_State::prepare(
phase_started = trace_now_ns(); phase_started = trace_now_ns();
DvzDrp2ValidationResult update_result{}; DvzDrp2ValidationResult update_result{};
{ {
update_result = dvz_drp2_runtime_execute( DvzDrp2ExecutionTiming timing{};
update_result = dvz_drp2_runtime_execute_timed(
runtime_slots_[*target_index].runtime, runtime_slots_[*target_index].runtime,
update_stream.get()); update_stream.get(), &timing);
accumulate_execution_timing(timing, observation);
} }
observation.execute_ns += trace_now_ns() - phase_started; observation.runtime_execute_ns = trace_now_ns() - phase_started;
if (!update_result.ok) if (!update_result.ok)
throw std::runtime_error( throw std::runtime_error(
"failed to execute Datoviz retained runtime resources"); "failed to execute Datoviz retained runtime resources");
@@ -252,6 +314,7 @@ std::optional<Datoviz_Pending_Frame> Scene_Datoviz_State::prepare(
* rebuilding the Figure artifact or re-recording commands. Structural Scene * rebuilding the Figure artifact or re-recording commands. Structural Scene
* changes keep using command_revision_ and fall through to full recording. */ * changes keep using command_revision_ and fall through to full recording. */
bool mvp_updated{}; bool mvp_updated{};
phase_started = trace_now_ns();
if (frame_target.can_reuse_commands(command_revision_, readback) && if (frame_target.can_reuse_commands(command_revision_, readback) &&
!frame_target.can_reuse( !frame_target.can_reuse(
command_revision_, controller_revision_, readback)) { command_revision_, controller_revision_, readback)) {
@@ -265,6 +328,7 @@ std::optional<Datoviz_Pending_Frame> Scene_Datoviz_State::prepare(
mvp_updated = true; mvp_updated = true;
} }
} }
observation.mvp_update_ns = trace_now_ns() - phase_started;
if (frame_target.can_reuse( if (frame_target.can_reuse(
command_revision_, controller_revision_, readback)) { command_revision_, controller_revision_, readback)) {
{ {
@@ -284,9 +348,11 @@ std::optional<Datoviz_Pending_Frame> Scene_Datoviz_State::prepare(
}; };
} }
{ {
phase_started = trace_now_ns();
std::lock_guard recording_lock(target_mutex_); std::lock_guard recording_lock(target_mutex_);
frame_target.begin( frame_target.begin(
observe, readback, command_revision_, controller_revision_); observe, readback, command_revision_, controller_revision_);
observation.frame_begin_ns = trace_now_ns() - phase_started;
} }
struct Recording_Scope { struct Recording_Scope {
Datoviz_Frame_Target& target; /* 异常退出时回收尚未发布的录制槽。 */ Datoviz_Frame_Target& target; /* 异常退出时回收尚未发布的录制槽。 */
@@ -307,7 +373,7 @@ std::optional<Datoviz_Pending_Frame> Scene_Datoviz_State::prepare(
try { try {
phase_started = trace_now_ns(); phase_started = trace_now_ns();
artifact.reset(emit(scene, *target_index)); artifact.reset(emit(scene, *target_index));
observation.emit_ns = trace_now_ns() - phase_started; observation.frame_plan_ns = trace_now_ns() - phase_started;
} }
catch (...) { catch (...) {
raise_context("preparing Datoviz frame", std::current_exception()); raise_context("preparing Datoviz frame", std::current_exception());
@@ -322,21 +388,26 @@ std::optional<Datoviz_Pending_Frame> Scene_Datoviz_State::prepare(
} }
const DvzDrp2CommandStream* stream = const DvzDrp2CommandStream* stream =
dvz_scene_frame_artifact_stream(artifact.get()); dvz_scene_frame_artifact_stream(artifact.get());
register_external_attributes(stream, *target_index);
const DvzStreamFrame target_frame = frame_target.stream_frame();
phase_started = trace_now_ns(); phase_started = trace_now_ns();
register_external_attributes(stream, *target_index);
observation.external_register_ns = trace_now_ns() - phase_started;
const DvzStreamFrame target_frame = frame_target.stream_frame();
bool attached{}; bool attached{};
DvzDrp2ValidationResult result{}; DvzDrp2ValidationResult result{};
{ phase_started = trace_now_ns();
attached = stream != nullptr && attached = stream != nullptr &&
dvz_drp2_runtime_attach_frame_target( dvz_drp2_runtime_attach_frame_target(
runtime_slots_[*target_index].runtime, runtime_slots_[*target_index].runtime,
color_target_id, &target_frame); color_target_id, &target_frame);
if (attached) observation.frame_attach_ns = trace_now_ns() - phase_started;
result = dvz_drp2_runtime_execute( if (attached) {
runtime_slots_[*target_index].runtime, stream); phase_started = trace_now_ns();
DvzDrp2ExecutionTiming timing{};
result = dvz_drp2_runtime_execute_timed(
runtime_slots_[*target_index].runtime, stream, &timing);
accumulate_execution_timing(timing, observation);
observation.frame_execute_ns = trace_now_ns() - phase_started;
} }
observation.execute_ns = trace_now_ns() - phase_started;
observation.validation_performed = true; observation.validation_performed = true;
observation.validation_ok = attached && result.ok; observation.validation_ok = attached && result.ok;
observation.validation_code = static_cast<std::uint32_t>(result.code); observation.validation_code = static_cast<std::uint32_t>(result.code);
@@ -364,8 +435,10 @@ std::optional<Datoviz_Pending_Frame> Scene_Datoviz_State::prepare(
} }
mark_target_runtime_resources_uploaded(*target_index); mark_target_runtime_resources_uploaded(*target_index);
{ {
phase_started = trace_now_ns();
std::lock_guard recording_lock(target_mutex_); std::lock_guard recording_lock(target_mutex_);
frame_target.finish_recording(); frame_target.finish_recording();
observation.frame_finish_ns = trace_now_ns() - phase_started;
} }
recording_scope.released = true; recording_scope.released = true;
input_changed_ = false; input_changed_ = false;
@@ -35,6 +35,7 @@ EXTERN_C_ON
typedef struct DvzDrp2ValidationResult DvzDrp2ValidationResult; typedef struct DvzDrp2ValidationResult DvzDrp2ValidationResult;
typedef struct DvzDrp2RuntimeConfig DvzDrp2RuntimeConfig; typedef struct DvzDrp2RuntimeConfig DvzDrp2RuntimeConfig;
typedef struct DvzDrp2ExternalBufferDesc DvzDrp2ExternalBufferDesc; typedef struct DvzDrp2ExternalBufferDesc DvzDrp2ExternalBufferDesc;
typedef struct DvzDrp2ExecutionTiming DvzDrp2ExecutionTiming;
typedef struct DvzDevice DvzDevice; typedef struct DvzDevice DvzDevice;
typedef struct DvzStreamFrame DvzStreamFrame; typedef struct DvzStreamFrame DvzStreamFrame;
typedef struct DvzVma DvzVma; typedef struct DvzVma DvzVma;
@@ -72,6 +73,19 @@ struct DvzDrp2ExternalBufferDesc
uint32_t usage; uint32_t usage;
}; };
#define DVZ_DRP2_COMMAND_TYPE_COUNT ((uint32_t)DVZ_DRP2_COMMAND_QUEUE_SUBMIT_REPLY + 1U)
struct DvzDrp2ExecutionTiming
{
uint64_t validation_ns;
uint64_t state_ensure_ns;
uint64_t shader_compile_ns;
uint64_t shader_module_create_ns;
uint64_t command_ns[DVZ_DRP2_COMMAND_TYPE_COUNT];
uint32_t command_count[DVZ_DRP2_COMMAND_TYPE_COUNT];
uint64_t state_commit_ns;
};
/*************************************************************************************************/ /*************************************************************************************************/
@@ -202,6 +216,10 @@ dvz_drp2_validate_stream(const DvzDrp2CommandStream* stream);
DVZ_EXPORT DvzDrp2ValidationResult DVZ_EXPORT DvzDrp2ValidationResult
dvz_drp2_runtime_execute(DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream); dvz_drp2_runtime_execute(DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream);
DVZ_EXPORT DvzDrp2ValidationResult dvz_drp2_runtime_execute_timed(
DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream,
DvzDrp2ExecutionTiming* timing);
/** /**
* Attach a borrowed stream frame as a runtime render target. * Attach a borrowed stream frame as a runtime render target.
+4 -2
View File
@@ -315,7 +315,8 @@ bool _vklite_attach_frame_target(
bool _vklite_retire_frame_target_depth( bool _vklite_retire_frame_target_depth(
Drp2VkliteState* state, Drp2VkliteObject* object); Drp2VkliteState* state, Drp2VkliteObject* object);
DvzDrp2ValidationResult _vklite_execute( DvzDrp2ValidationResult _vklite_execute(
DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream); DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream,
DvzDrp2ExecutionTiming* timing);
VkImageView _vklite_object_image_view(const Drp2VkliteObject* object); VkImageView _vklite_object_image_view(const Drp2VkliteObject* object);
void _vklite_state_cleanup(Drp2VkliteState* state); void _vklite_state_cleanup(Drp2VkliteState* state);
bool _vklite_defer_destroy_object( bool _vklite_defer_destroy_object(
@@ -337,7 +338,8 @@ void _vklite_transition_image_access(
bool _vklite_compile_glsl( bool _vklite_compile_glsl(
const char* stage, const char* code, uint32_t** spv, uint64_t* spv_size); const char* stage, const char* code, uint32_t** spv, uint64_t* spv_size);
DvzDrp2ValidationResult _vklite_create_shader_module( DvzDrp2ValidationResult _vklite_create_shader_module(
Drp2VkliteState* state, const DvzDrp2Command* command, uint32_t command_index); Drp2VkliteState* state, const DvzDrp2Command* command, uint32_t command_index,
DvzDrp2ExecutionTiming* timing);
DvzDrp2ValidationResult _vklite_create_sampler( DvzDrp2ValidationResult _vklite_create_sampler(
Drp2VkliteState* state, const DvzDrp2Command* command, uint32_t command_index); Drp2VkliteState* state, const DvzDrp2Command* command, uint32_t command_index);
DvzDrp2ValidationResult _vklite_create_bind_group_layout( DvzDrp2ValidationResult _vklite_create_bind_group_layout(
+13 -2
View File
@@ -23,6 +23,7 @@
#include "_assertions.h" #include "_assertions.h"
#include "_runtime.h" #include "_runtime.h"
#include "_stream.h" #include "_stream.h"
#include "datoviz/common/functions.h"
@@ -573,7 +574,9 @@ static DvzDrp2ValidationResult _vklite_destroy_shader_module(
DvzDrp2ValidationResult DvzDrp2ValidationResult
_vklite_execute(DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream) _vklite_execute(
DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream,
DvzDrp2ExecutionTiming* timing)
{ {
ANN(runtime); ANN(runtime);
ANN(stream); ANN(stream);
@@ -590,6 +593,7 @@ _vklite_execute(DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream)
for (uint32_t i = 0; i < stream->count; i++) for (uint32_t i = 0; i < stream->count; i++)
{ {
const DvzDrp2Command* command = &stream->commands[i]; const DvzDrp2Command* command = &stream->commands[i];
const uint64_t command_started = timing != NULL ? dvz_time_monotonic_ns() : 0;
switch (command->type) switch (command->type)
{ {
case DVZ_DRP2_COMMAND_CREATE_BUFFER: case DVZ_DRP2_COMMAND_CREATE_BUFFER:
@@ -607,7 +611,7 @@ _vklite_execute(DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream)
state, command->u.destroy_texture.texture_id, DRP2_OBJECT_TEXTURE, i); state, command->u.destroy_texture.texture_id, DRP2_OBJECT_TEXTURE, i);
break; break;
case DVZ_DRP2_COMMAND_CREATE_SHADER_MODULE: case DVZ_DRP2_COMMAND_CREATE_SHADER_MODULE:
result = _vklite_create_shader_module(state, command, i); result = _vklite_create_shader_module(state, command, i, timing);
break; break;
case DVZ_DRP2_COMMAND_DESTROY_SHADER_MODULE: case DVZ_DRP2_COMMAND_DESTROY_SHADER_MODULE:
result = _vklite_destroy_shader_module( result = _vklite_destroy_shader_module(
@@ -712,6 +716,13 @@ _vklite_execute(DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream)
break; break;
} }
if (timing != NULL && command->type < DVZ_DRP2_COMMAND_TYPE_COUNT)
{
timing->command_ns[command->type] +=
dvz_time_monotonic_ns() - command_started;
timing->command_count[command->type]++;
}
if (!result.ok) if (!result.ok)
break; break;
} }
+9 -1
View File
@@ -34,6 +34,7 @@ typedef int shaderc_shader_kind;
#include "_runtime.h" #include "_runtime.h"
#include "_stream.h" #include "_stream.h"
#include "_vk_utils.h" #include "_vk_utils.h"
#include "datoviz/common/functions.h"
@@ -444,7 +445,8 @@ bool _vklite_compile_glsl(
* @return DRP2 validation result * @return DRP2 validation result
*/ */
DvzDrp2ValidationResult _vklite_create_shader_module( DvzDrp2ValidationResult _vklite_create_shader_module(
Drp2VkliteState* state, const DvzDrp2Command* command, uint32_t command_index) Drp2VkliteState* state, const DvzDrp2Command* command, uint32_t command_index,
DvzDrp2ExecutionTiming* timing)
{ {
ANN(state); ANN(state);
ANN(command); ANN(command);
@@ -464,10 +466,13 @@ DvzDrp2ValidationResult _vklite_create_shader_module(
if (is_glsl) if (is_glsl)
{ {
const uint64_t compile_started = timing != NULL ? dvz_time_monotonic_ns() : 0;
if (!_vklite_compile_glsl( if (!_vklite_compile_glsl(
command->u.create_shader_module.stage, command->u.create_shader_module.code, command->u.create_shader_module.stage, command->u.create_shader_module.code,
&spv_owned, &spv_size)) &spv_owned, &spv_size))
return _drp2_fail(DVZ_DRP2_VALIDATION_INVALID_ARGUMENT, command_index); return _drp2_fail(DVZ_DRP2_VALIDATION_INVALID_ARGUMENT, command_index);
if (timing != NULL)
timing->shader_compile_ns += dvz_time_monotonic_ns() - compile_started;
spv = spv_owned; spv = spv_owned;
} }
else else
@@ -499,7 +504,10 @@ DvzDrp2ValidationResult _vklite_create_shader_module(
} }
object->shader = shader; object->shader = shader;
const uint64_t module_started = timing != NULL ? dvz_time_monotonic_ns() : 0;
int out = dvz_shader(state->runtime->device, spv_size, spv, shader); int out = dvz_shader(state->runtime->device, spv_size, spv, shader);
if (timing != NULL)
timing->shader_module_create_ns += dvz_time_monotonic_ns() - module_started;
dvz_free(spv_owned); dvz_free(spv_owned);
if (out != 0) if (out != 0)
return _vklite_fail_destroy_object( return _vklite_fail_destroy_object(
+20 -1
View File
@@ -28,6 +28,7 @@
#include "_log.h" #include "_log.h"
#include "_overflow.h" #include "_overflow.h"
#include "_runtime.h" #include "_runtime.h"
#include "datoviz/common/functions.h"
#include "_stream.h" #include "_stream.h"
#include "datoviz/vk/gpu_ctx.h" #include "datoviz/vk/gpu_ctx.h"
@@ -509,25 +510,40 @@ bool _dvz_drp2_runtime_vklite_download_buffer(
*/ */
DvzDrp2ValidationResult DvzDrp2ValidationResult
dvz_drp2_runtime_execute(DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream) dvz_drp2_runtime_execute(DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream)
{
return dvz_drp2_runtime_execute_timed(runtime, stream, NULL);
}
DvzDrp2ValidationResult dvz_drp2_runtime_execute_timed(
DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* stream,
DvzDrp2ExecutionTiming* timing)
{ {
if (runtime == NULL) if (runtime == NULL)
return _drp2_fail(DVZ_DRP2_VALIDATION_INVALID_ARGUMENT, 0); return _drp2_fail(DVZ_DRP2_VALIDATION_INVALID_ARGUMENT, 0);
if (stream == NULL) if (stream == NULL)
return _drp2_fail(DVZ_DRP2_VALIDATION_INVALID_ARGUMENT, 0); return _drp2_fail(DVZ_DRP2_VALIDATION_INVALID_ARGUMENT, 0);
if (timing != NULL)
*timing = (DvzDrp2ExecutionTiming){0};
uint64_t phase_started = timing != NULL ? dvz_time_monotonic_ns() : 0;
Drp2RuntimeState next_state = {0}; Drp2RuntimeState next_state = {0};
DvzDrp2ValidationResult result = _drp2_runtime_validate_stream(runtime, stream, &next_state); DvzDrp2ValidationResult result = _drp2_runtime_validate_stream(runtime, stream, &next_state);
if (timing != NULL)
timing->validation_ns = dvz_time_monotonic_ns() - phase_started;
if (!result.ok) if (!result.ok)
{ {
_drp2_runtime_state_cleanup(&next_state); _drp2_runtime_state_cleanup(&next_state);
return result; return result;
} }
phase_started = timing != NULL ? dvz_time_monotonic_ns() : 0;
if (!_drp2_runtime_state_ensure(runtime)) if (!_drp2_runtime_state_ensure(runtime))
{ {
_drp2_runtime_state_cleanup(&next_state); _drp2_runtime_state_cleanup(&next_state);
return _drp2_fail(DVZ_DRP2_VALIDATION_INVALID_STATE, 0); return _drp2_fail(DVZ_DRP2_VALIDATION_INVALID_STATE, 0);
} }
if (timing != NULL)
timing->state_ensure_ns = dvz_time_monotonic_ns() - phase_started;
if (runtime->semantic_only) if (runtime->semantic_only)
{ {
@@ -540,17 +556,20 @@ dvz_drp2_runtime_execute(DvzDrp2Runtime* runtime, const DvzDrp2CommandStream* st
} }
#if DVZ_DRP2_HAS_VKLITE #if DVZ_DRP2_HAS_VKLITE
DvzDrp2ValidationResult backend_result = _vklite_execute(runtime, stream); DvzDrp2ValidationResult backend_result = _vklite_execute(runtime, stream, timing);
if (!backend_result.ok) if (!backend_result.ok)
{ {
_drp2_runtime_state_cleanup(&next_state); _drp2_runtime_state_cleanup(&next_state);
return backend_result; return backend_result;
} }
phase_started = timing != NULL ? dvz_time_monotonic_ns() : 0;
if (!_drp2_runtime_state_commit(runtime, &next_state)) if (!_drp2_runtime_state_commit(runtime, &next_state))
{ {
_drp2_runtime_state_cleanup(&next_state); _drp2_runtime_state_cleanup(&next_state);
return _drp2_fail(DVZ_DRP2_VALIDATION_INVALID_STATE, 0); return _drp2_fail(DVZ_DRP2_VALIDATION_INVALID_STATE, 0);
} }
if (timing != NULL)
timing->state_commit_ns = dvz_time_monotonic_ns() - phase_started;
return backend_result; return backend_result;
#else #else
_drp2_runtime_state_cleanup(&next_state); _drp2_runtime_state_cleanup(&next_state);
@@ -57,23 +57,6 @@ static const char ENCODE_GLSL[] =
" outColor = vec4(linearToSrgb(color.rgb), clamp(color.a, 0.0, 1.0));\n" " outColor = vec4(linearToSrgb(color.rgb), clamp(color.a, 0.0, 1.0));\n"
"}\n"; "}\n";
static const char ENCODE_WGSL[] =
"@group(0) @binding(0) var source_tex: texture_2d<f32>;\n"
"@group(0) @binding(1) var samp: sampler;\n"
"fn linear_to_srgb(linear_color: vec3f) -> vec3f {\n"
" let clipped = clamp(linear_color, vec3f(0.0), vec3f(1.0));\n"
" let lo = vec3f(12.92) * clipped;\n"
" let hi = vec3f(1.055) * pow(clipped, vec3f(1.0 / 2.4)) - vec3f(0.055);\n"
" return select(hi, lo, clipped <= vec3f(0.0031308));\n"
"}\n"
"@fragment fn main(@builtin(position) pos: vec4f) -> @location(0) vec4f {\n"
" let p = vec2i(pos.xy);\n"
" let color = textureLoad(source_tex, p, 0);\n"
" return vec4f(linear_to_srgb(color.rgb), clamp(color.a, 0.0, 1.0));\n"
"}\n";
static bool _render_pass_external_target_needs_encode(const DvzFramePlanEmitConfig* cfg) static bool _render_pass_external_target_needs_encode(const DvzFramePlanEmitConfig* cfg)
{ {
if (cfg != NULL && cfg->color_pipeline == DVZ_COLOR_PIPELINE_LEGACY_SRGB_BLEND) if (cfg != NULL && cfg->color_pipeline == DVZ_COLOR_PIPELINE_LEGACY_SRGB_BLEND)
@@ -302,15 +285,16 @@ bool _render_pass_emit_final_encode(
if (vs_id == 0) if (vs_id == 0)
return false; return false;
if (ok && is_new) if (ok && is_new)
ok = ok && _emit_shader(stream, vs_id, "VERTEX", _fullscreen_vertex_wgsl(), ok = ok && _emit_shader_spirv(
_builtin_shader_glsl(DVZ_SCENE_BUILTIN_SHADER_WBOIT_RESOLVE, false), stream, vs_id, "VERTEX", "fullscreen_vert",
cfg); _builtin_shader_glsl(DVZ_SCENE_BUILTIN_SHADER_WBOIT_RESOLVE, false), cfg);
uint64_t fs_id = _obj_id(emitter, fs_key, &is_new); uint64_t fs_id = _obj_id(emitter, fs_key, &is_new);
if (fs_id == 0) if (fs_id == 0)
return false; return false;
if (ok && is_new) if (ok && is_new)
ok = ok && _emit_shader(stream, fs_id, "FRAGMENT", ENCODE_WGSL, ENCODE_GLSL, cfg); ok = ok && _emit_shader_spirv(
stream, fs_id, "FRAGMENT", "final_srgb_encode_frag", ENCODE_GLSL, cfg);
uint64_t pipe_id = _obj_id(emitter, pipe_key, &is_new); uint64_t pipe_id = _obj_id(emitter, pipe_key, &is_new);
if (pipe_id == 0) if (pipe_id == 0)