Add renderer resource label contract

This commit is contained in:
2026-06-02 17:01:10 +02:00
parent bbe3db1747
commit a5dbf05ab5
7 changed files with 132 additions and 14 deletions

View File

@@ -59,6 +59,7 @@ using pp::renderer::Viewport;
using pp::renderer::max_shader_source_bytes;
using pp::renderer::max_shader_uniform_bytes;
using pp::renderer::max_mip_levels_for_extent;
using pp::renderer::max_resource_label_bytes;
using pp::renderer::max_texture_dimension;
using pp::renderer::max_texture_slots;
using pp::renderer::max_trace_label_bytes;
@@ -82,6 +83,7 @@ using pp::renderer::validate_mesh_desc;
using pp::renderer::validate_mipmap_generation_desc;
using pp::renderer::validate_readback_region;
using pp::renderer::validate_render_pass_desc;
using pp::renderer::validate_resource_label;
using pp::renderer::validate_sampler_address_mode;
using pp::renderer::validate_sampler_desc;
using pp::renderer::validate_sampler_filter;
@@ -744,6 +746,50 @@ void validates_texture_usage_contract(pp::tests::Harness& h)
PP_EXPECT(h, unknown_format.code == StatusCode::invalid_argument);
}
void validates_resource_labels(pp::tests::Harness& h)
{
std::array<char, max_resource_label_bytes + 2U> oversized_label {};
oversized_label.fill('r');
oversized_label[max_resource_label_bytes + 1U] = '\0';
PP_EXPECT(h, validate_resource_label("").ok());
PP_EXPECT(h, validate_resource_label("stroke-target").ok());
PP_EXPECT(h, validate_texture_desc(TextureDesc {
.extent = Extent2D { .width = 4, .height = 4 },
.format = TextureFormat::rgba8,
.debug_name = "paint-texture",
})
.ok());
PP_EXPECT(h, validate_mesh_desc(MeshDesc {
.vertex_count = 3,
.topology = PrimitiveTopology::triangles,
.debug_name = "brush-quad",
})
.ok());
const auto null_label = validate_resource_label(nullptr);
const auto oversized = validate_resource_label(oversized_label.data());
const auto null_texture_label = validate_texture_desc(TextureDesc {
.extent = Extent2D { .width = 4, .height = 4 },
.format = TextureFormat::rgba8,
.debug_name = nullptr,
});
const auto oversized_mesh_label = validate_mesh_desc(MeshDesc {
.vertex_count = 3,
.topology = PrimitiveTopology::triangles,
.debug_name = oversized_label.data(),
});
PP_EXPECT(h, !null_label.ok());
PP_EXPECT(h, null_label.code == StatusCode::invalid_argument);
PP_EXPECT(h, !oversized.ok());
PP_EXPECT(h, oversized.code == StatusCode::out_of_range);
PP_EXPECT(h, !null_texture_label.ok());
PP_EXPECT(h, null_texture_label.code == StatusCode::invalid_argument);
PP_EXPECT(h, !oversized_mesh_label.ok());
PP_EXPECT(h, oversized_mesh_label.code == StatusCode::out_of_range);
}
void validates_mipmap_generation_contract(pp::tests::Harness& h)
{
const TextureDesc mipmapped_desc {
@@ -1469,11 +1515,13 @@ void render_devices_create_validated_resources(pp::tests::Harness& h)
.extent = Extent2D { .width = 8, .height = 4 },
.format = TextureFormat::rgba8,
.usage = TextureUsage::sampled | TextureUsage::upload_destination | TextureUsage::readback_source | TextureUsage::copy_source | TextureUsage::copy_destination,
.debug_name = "factory-texture",
});
const auto target = device.create_render_target(TextureDesc {
.extent = Extent2D { .width = 8, .height = 4 },
.format = TextureFormat::rgba8,
.usage = TextureUsage::render_target | TextureUsage::sampled | TextureUsage::upload_destination | TextureUsage::readback_source | TextureUsage::copy_source | TextureUsage::copy_destination,
.debug_name = "factory-target",
});
const auto shader = device.create_shader_program(ShaderProgramDesc {
.debug_name = "factory-shader",
@@ -1484,18 +1532,22 @@ void render_devices_create_validated_resources(pp::tests::Harness& h)
.vertex_count = 6,
.index_count = 6,
.topology = PrimitiveTopology::triangles,
.debug_name = "factory-mesh",
});
const auto readback = device.create_readback_buffer(8U * 4U * 4U);
PP_EXPECT(h, texture.ok());
PP_EXPECT(h, texture.value()->desc().extent.width == 8U);
PP_EXPECT(h, !has_texture_usage(texture.value()->desc().usage, TextureUsage::render_target));
PP_EXPECT(h, texture.value()->desc().debug_name == std::string_view("factory-texture"));
PP_EXPECT(h, target.ok());
PP_EXPECT(h, has_texture_usage(target.value()->color_desc().usage, TextureUsage::render_target));
PP_EXPECT(h, target.value()->color_desc().debug_name == std::string_view("factory-target"));
PP_EXPECT(h, shader.ok());
PP_EXPECT(h, shader.value()->debug_name() == std::string_view("factory-shader"));
PP_EXPECT(h, mesh.ok());
PP_EXPECT(h, mesh.value()->desc().index_count == 6U);
PP_EXPECT(h, mesh.value()->desc().debug_name == std::string_view("factory-mesh"));
PP_EXPECT(h, readback.ok());
PP_EXPECT(h, readback.value()->size_bytes() == 128U);
@@ -1620,6 +1672,7 @@ void recording_renderer_records_valid_command_sequences(pp::tests::Harness& h)
.extent = Extent2D { .width = 64, .height = 32 },
.format = TextureFormat::rgba8,
.usage = TextureUsage::render_target | TextureUsage::sampled | TextureUsage::upload_destination | TextureUsage::readback_source | TextureUsage::copy_source | TextureUsage::copy_destination,
.debug_name = "recorded-texture",
});
RecordingReadbackBuffer readback_buffer(64U * 32U * 4U);
const std::array<std::byte, 96> upload_bytes {};
@@ -1627,14 +1680,21 @@ void recording_renderer_records_valid_command_sequences(pp::tests::Harness& h)
.extent = Extent2D { .width = 64, .height = 32 },
.format = TextureFormat::rgba8,
.usage = TextureUsage::render_target | TextureUsage::sampled | TextureUsage::upload_destination | TextureUsage::readback_source | TextureUsage::copy_source | TextureUsage::copy_destination,
.debug_name = "recorded-target",
});
RecordingRenderTarget blit_target(TextureDesc {
.extent = Extent2D { .width = 64, .height = 32 },
.format = TextureFormat::rgba8,
.usage = TextureUsage::render_target | TextureUsage::sampled | TextureUsage::upload_destination | TextureUsage::readback_source | TextureUsage::copy_source | TextureUsage::copy_destination,
.debug_name = "recorded-blit-target",
});
RecordingShaderProgram shader("recorded-shader");
RecordingMesh mesh(MeshDesc { .vertex_count = 3, .index_count = 3, .topology = PrimitiveTopology::triangles });
RecordingMesh mesh(MeshDesc {
.vertex_count = 3,
.index_count = 3,
.topology = PrimitiveTopology::triangles,
.debug_name = "recorded-mesh",
});
PP_EXPECT(h, device.backend_name() == std::string_view("recording"));
PP_EXPECT(h, device.trace()->begin_scope("renderer", "recorded-frame").ok());
@@ -1693,6 +1753,7 @@ void recording_renderer_records_valid_command_sequences(pp::tests::Harness& h)
PP_EXPECT(h, recorded_render_command_kind_name(commands[2].kind) == std::string_view("trace_end_scope"));
PP_EXPECT(h, commands[3].kind == RecordedRenderCommandKind::begin_render_pass);
PP_EXPECT(h, commands[3].target_desc.extent.width == 64U);
PP_EXPECT(h, commands[3].target_desc.debug_name == std::string_view("recorded-target"));
PP_EXPECT(h, commands[3].clear_color_enabled);
PP_EXPECT(h, commands[3].clear_color.a == 1.0F);
PP_EXPECT(h, commands[3].clear_depth_enabled);
@@ -1720,6 +1781,7 @@ void recording_renderer_records_valid_command_sequences(pp::tests::Harness& h)
PP_EXPECT(h, commands[9].kind == RecordedRenderCommandKind::bind_texture);
PP_EXPECT(h, commands[9].texture_slot == 1U);
PP_EXPECT(h, commands[9].texture_desc.extent.height == 32U);
PP_EXPECT(h, commands[9].texture_desc.debug_name == std::string_view("recorded-texture"));
PP_EXPECT(h, recorded_render_command_kind_name(commands[9].kind) == std::string_view("bind_texture"));
PP_EXPECT(h, commands[10].kind == RecordedRenderCommandKind::bind_sampler);
PP_EXPECT(h, commands[10].sampler_slot == 1U);
@@ -1729,6 +1791,7 @@ void recording_renderer_records_valid_command_sequences(pp::tests::Harness& h)
PP_EXPECT(h, commands[11].kind == RecordedRenderCommandKind::bind_mesh);
PP_EXPECT(h, commands[11].mesh_desc.vertex_count == 3U);
PP_EXPECT(h, commands[11].mesh_desc.index_count == 3U);
PP_EXPECT(h, commands[11].mesh_desc.debug_name == std::string_view("recorded-mesh"));
PP_EXPECT(h, commands[12].kind == RecordedRenderCommandKind::draw);
PP_EXPECT(h, commands[12].mesh_desc.vertex_count == 3U);
PP_EXPECT(h, commands[12].mesh_desc.index_count == 3U);
@@ -2225,6 +2288,7 @@ int main()
pp::tests::Harness harness;
harness.run("computes_texture_sizes", computes_texture_sizes);
harness.run("validates_texture_usage_contract", validates_texture_usage_contract);
harness.run("validates_resource_labels", validates_resource_labels);
harness.run("validates_mipmap_generation_contract", validates_mipmap_generation_contract);
harness.run("rejects_invalid_or_excessive_extents", rejects_invalid_or_excessive_extents);
harness.run("validates_readback_bounds", validates_readback_bounds);