#include "renderer_gl/command_plan.h" #include "test_harness.h" #include #include namespace { pp::renderer::RecordedRenderCommand begin_render_pass_command() noexcept { pp::renderer::RecordedRenderCommand command; command.kind = pp::renderer::RecordedRenderCommandKind::begin_render_pass; command.target_desc.extent = pp::renderer::Extent2D { .width = 64U, .height = 64U }; command.target_desc.format = pp::renderer::TextureFormat::rgba8; command.clear_color_enabled = true; command.clear_depth_enabled = true; return command; } pp::renderer::RecordedRenderCommand command_with_kind( pp::renderer::RecordedRenderCommandKind kind) noexcept { pp::renderer::RecordedRenderCommand command; command.kind = kind; return command; } pp::renderer::RecordedRenderCommand viewport_command() noexcept { pp::renderer::RecordedRenderCommand command; command.kind = pp::renderer::RecordedRenderCommandKind::set_viewport; command.viewport = pp::renderer::Viewport { .width = 64U, .height = 64U }; return command; } pp::renderer::RecordedRenderCommand draw_command() noexcept { pp::renderer::RecordedRenderCommand command; command.kind = pp::renderer::RecordedRenderCommandKind::draw; command.mesh_desc.topology = pp::renderer::PrimitiveTopology::triangles; command.draw_desc.vertex_count = 3U; return command; } pp::renderer::RecordedRenderCommand bind_shader_command(const char* name) noexcept { pp::renderer::RecordedRenderCommand command; command.kind = pp::renderer::RecordedRenderCommandKind::bind_shader; command.name = name; return command; } pp::renderer::RecordedRenderCommand shader_uniform_command(const char* name, std::uint64_t bytes) noexcept { pp::renderer::RecordedRenderCommand command; command.kind = pp::renderer::RecordedRenderCommandKind::set_shader_uniform; command.name = name; command.uniform_bytes = bytes; return command; } pp::renderer::RecordedRenderCommand blit_command(pp::renderer::BlitFilter filter) noexcept { pp::renderer::RecordedRenderCommand command; command.kind = pp::renderer::RecordedRenderCommandKind::blit_render_target; command.source_desc.format = pp::renderer::TextureFormat::rgba8; command.destination_desc.format = pp::renderer::TextureFormat::rgba8; command.blit_filter = filter; return command; } pp::renderer::ReadbackRegion region( std::uint32_t x, std::uint32_t y, std::uint32_t width, std::uint32_t height) noexcept { pp::renderer::ReadbackRegion result; result.x = x; result.y = y; result.width = width; result.height = height; return result; } void maps_render_pass_and_state_commands(pp::tests::Harness& h) { const auto begin = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::begin_render_pass, .target_desc = pp::renderer::TextureDesc { .extent = pp::renderer::Extent2D { .width = 64U, .height = 32U }, .format = pp::renderer::TextureFormat::rgba8, }, .clear_color_enabled = true, .clear_color = pp::renderer::ClearColor { .r = 0.25F, .g = 0.5F, .b = 0.75F, .a = 1.0F }, .clear_depth_enabled = true, .clear_depth = 0.875F, .clear_stencil_enabled = true, .clear_stencil = 3U, }); const auto viewport = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::set_viewport, .viewport = pp::renderer::Viewport { .x = 2, .y = 4, .width = 32U, .height = 16U }, }); const auto scissor = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::set_scissor, .scissor = pp::renderer::ScissorRect { .enabled = true, .x = 3, .y = 5, .width = 8U, .height = 6U }, }); const auto blend = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::set_blend_state, .blend_state = pp::renderer::BlendState { .enabled = true, .source_color = pp::renderer::BlendFactor::source_alpha, .destination_color = pp::renderer::BlendFactor::one_minus_source_alpha, }, }); const auto depth = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::set_depth_state, .depth_state = pp::renderer::DepthState { .test_enabled = true, .write_enabled = true, .compare = pp::renderer::CompareOp::greater, }, }); PP_EXPECT(h, begin.supported); PP_EXPECT(h, begin.kind == pp::renderer::gl::OpenGlPlannedCommandKind::begin_render_pass); PP_EXPECT(h, begin.clear_mask == 0x00004500U); PP_EXPECT(h, begin.clear_values.color[2] == 0.75F); PP_EXPECT(h, begin.clear_values.depth == 0.875F); PP_EXPECT(h, begin.clear_values.stencil == 3U); PP_EXPECT(h, begin.texture_format.internal_format == 0x8058U); PP_EXPECT(h, !begin.requires_render_pass); PP_EXPECT(h, viewport.supported); PP_EXPECT(h, viewport.requires_render_pass); PP_EXPECT(h, viewport.viewport.x == 2); PP_EXPECT(h, viewport.viewport.width == 32); PP_EXPECT(h, scissor.supported); PP_EXPECT(h, scissor.scissor.enabled == 1U); PP_EXPECT(h, scissor.scissor.height == 6); PP_EXPECT(h, blend.supported); PP_EXPECT(h, blend.blend.enabled == 1U); PP_EXPECT(h, blend.blend.source_color_factor == 0x0302U); PP_EXPECT(h, depth.supported); PP_EXPECT(h, depth.depth.test_enabled == 1U); PP_EXPECT(h, depth.depth.compare_function == 0x0204U); } void maps_binding_draw_and_blit_commands(pp::tests::Harness& h) { const auto texture = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::bind_texture, .texture_desc = pp::renderer::TextureDesc { .extent = pp::renderer::Extent2D { .width = 16U, .height = 16U }, .format = pp::renderer::TextureFormat::depth24_stencil8, }, }); const auto sampler = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::bind_sampler, .sampler_desc = pp::renderer::SamplerDesc { .min_filter = pp::renderer::SamplerFilter::nearest, .mag_filter = pp::renderer::SamplerFilter::linear, .mip_filter = pp::renderer::SamplerFilter::linear, .address_u = pp::renderer::SamplerAddressMode::repeat, .address_v = pp::renderer::SamplerAddressMode::mirrored_repeat, .address_w = pp::renderer::SamplerAddressMode::clamp_to_border, }, }); const auto mesh = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::bind_mesh, .mesh_desc = pp::renderer::MeshDesc { .topology = pp::renderer::PrimitiveTopology::triangle_strip }, }); const auto draw = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::draw, .mesh_desc = pp::renderer::MeshDesc { .topology = pp::renderer::PrimitiveTopology::lines }, .draw_desc = pp::renderer::DrawDesc { .vertex_count = 4U, .index_count = 2U }, }); const auto blit = pp::renderer::gl::plan_recorded_render_command( blit_command(pp::renderer::BlitFilter::linear)); PP_EXPECT(h, texture.supported); PP_EXPECT(h, texture.requires_render_pass); PP_EXPECT(h, texture.texture_format.internal_format == 0x88F0U); PP_EXPECT(h, sampler.supported); PP_EXPECT(h, sampler.sampler.min_filter == 0x2702U); PP_EXPECT(h, sampler.sampler.wrap_t == 0x8370U); PP_EXPECT(h, mesh.supported); PP_EXPECT(h, mesh.primitive_mode == 0x0005U); PP_EXPECT(h, draw.supported); PP_EXPECT(h, draw.primitive_mode == 0x0001U); PP_EXPECT(h, draw.draw_vertex_count == 4U); PP_EXPECT(h, draw.draw_index_count == 2U); PP_EXPECT(h, blit.supported); PP_EXPECT(h, !blit.requires_render_pass); PP_EXPECT(h, blit.blit_filter.value == 0x2601U); PP_EXPECT(h, blit.source_texture_format.internal_format == 0x8058U); PP_EXPECT(h, blit.destination_texture_format.internal_format == 0x8058U); } void maps_texture_io_and_capture_commands(pp::tests::Harness& h) { pp::renderer::RecordedRenderCommand upload_command; upload_command.kind = pp::renderer::RecordedRenderCommandKind::upload_texture; upload_command.texture_desc.format = pp::renderer::TextureFormat::r8; upload_command.readback_region = region(1U, 2U, 3U, 4U); upload_command.upload_bytes = 12U; pp::renderer::RecordedRenderCommand mipmap_command; mipmap_command.kind = pp::renderer::RecordedRenderCommandKind::generate_mipmaps; mipmap_command.texture_desc.format = pp::renderer::TextureFormat::rgba8; mipmap_command.generated_mip_levels = 4U; mipmap_command.generated_mip_bytes = 340U; pp::renderer::RecordedRenderCommand transition_command; transition_command.kind = pp::renderer::RecordedRenderCommandKind::transition_texture; transition_command.texture_desc.format = pp::renderer::TextureFormat::rgba8; transition_command.before_state = pp::renderer::TextureState::upload_destination; transition_command.after_state = pp::renderer::TextureState::shader_read; pp::renderer::RecordedRenderCommand copy_command; copy_command.kind = pp::renderer::RecordedRenderCommandKind::copy_texture; copy_command.source_desc.format = pp::renderer::TextureFormat::rgba8; copy_command.destination_desc.format = pp::renderer::TextureFormat::r8; copy_command.source_region = region(0U, 1U, 8U, 4U); copy_command.destination_region = region(2U, 3U, 8U, 4U); copy_command.copy_source_bytes = 128U; copy_command.copy_destination_bytes = 32U; pp::renderer::RecordedRenderCommand read_command; read_command.kind = pp::renderer::RecordedRenderCommandKind::read_texture; read_command.texture_desc.format = pp::renderer::TextureFormat::rgba8; read_command.readback_region = region(4U, 5U, 6U, 7U); read_command.readback_bytes = 168U; pp::renderer::RecordedRenderCommand capture_command; capture_command.kind = pp::renderer::RecordedRenderCommandKind::capture_frame; capture_command.target_desc.format = pp::renderer::TextureFormat::rgba8; capture_command.capture_bytes = 512U; const auto upload = pp::renderer::gl::plan_recorded_render_command(upload_command); const auto mipmap = pp::renderer::gl::plan_recorded_render_command(mipmap_command); const auto transition = pp::renderer::gl::plan_recorded_render_command(transition_command); const auto copy = pp::renderer::gl::plan_recorded_render_command(copy_command); const auto read = pp::renderer::gl::plan_recorded_render_command(read_command); const auto capture = pp::renderer::gl::plan_recorded_render_command(capture_command); PP_EXPECT(h, upload.supported); PP_EXPECT(h, upload.kind == pp::renderer::gl::OpenGlPlannedCommandKind::upload_texture); PP_EXPECT(h, upload.texture_format.internal_format == 0x8229U); PP_EXPECT(h, upload.readback_region.y == 2U); PP_EXPECT(h, upload.upload_bytes == 12U); PP_EXPECT(h, mipmap.supported); PP_EXPECT(h, mipmap.kind == pp::renderer::gl::OpenGlPlannedCommandKind::generate_mipmaps); PP_EXPECT(h, mipmap.generated_mip_levels == 4U); PP_EXPECT(h, mipmap.generated_mip_bytes == 340U); PP_EXPECT(h, transition.supported); PP_EXPECT(h, transition.kind == pp::renderer::gl::OpenGlPlannedCommandKind::transition_texture); PP_EXPECT(h, transition.before_state == pp::renderer::TextureState::upload_destination); PP_EXPECT(h, transition.after_state == pp::renderer::TextureState::shader_read); PP_EXPECT(h, copy.supported); PP_EXPECT(h, copy.kind == pp::renderer::gl::OpenGlPlannedCommandKind::copy_texture); PP_EXPECT(h, copy.source_texture_format.internal_format == 0x8058U); PP_EXPECT(h, copy.destination_texture_format.internal_format == 0x8229U); PP_EXPECT(h, copy.destination_region.x == 2U); PP_EXPECT(h, copy.copy_source_bytes == 128U); PP_EXPECT(h, copy.copy_destination_bytes == 32U); PP_EXPECT(h, read.supported); PP_EXPECT(h, read.kind == pp::renderer::gl::OpenGlPlannedCommandKind::read_texture); PP_EXPECT(h, read.readback_region.width == 6U); PP_EXPECT(h, read.readback_bytes == 168U); PP_EXPECT(h, capture.supported); PP_EXPECT(h, capture.kind == pp::renderer::gl::OpenGlPlannedCommandKind::capture_frame); PP_EXPECT(h, capture.capture_bytes == 512U); } void maps_shader_commands(pp::tests::Harness& h) { const auto shader = pp::renderer::gl::plan_recorded_render_command( bind_shader_command("stroke-composite")); const auto uniform = pp::renderer::gl::plan_recorded_render_command( shader_uniform_command("mvp", 64U)); PP_EXPECT(h, shader.supported); PP_EXPECT(h, shader.kind == pp::renderer::gl::OpenGlPlannedCommandKind::bind_shader); PP_EXPECT(h, shader.name == std::string_view("stroke-composite")); PP_EXPECT(h, shader.requires_render_pass); PP_EXPECT(h, uniform.supported); PP_EXPECT(h, uniform.kind == pp::renderer::gl::OpenGlPlannedCommandKind::set_shader_uniform); PP_EXPECT(h, uniform.name == std::string_view("mvp")); PP_EXPECT(h, uniform.uniform_bytes == 64U); PP_EXPECT(h, uniform.requires_render_pass); } void rejects_unsupported_command_tokens(pp::tests::Harness& h) { const auto bad_blend = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::set_blend_state, .blend_state = pp::renderer::BlendState { .source_color = static_cast(255U), }, }); const auto bad_depth = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::set_depth_state, .depth_state = pp::renderer::DepthState { .compare = static_cast(255U), }, }); const auto bad_sampler = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::bind_sampler, .sampler_desc = pp::renderer::SamplerDesc { .address_u = static_cast(255U), }, }); const auto bad_mesh = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = pp::renderer::RecordedRenderCommandKind::draw, .mesh_desc = pp::renderer::MeshDesc { .topology = static_cast(255U), }, }); const auto bad_blit = pp::renderer::gl::plan_recorded_render_command( blit_command(static_cast(255U))); pp::renderer::RecordedRenderCommand bad_transition_command; bad_transition_command.kind = pp::renderer::RecordedRenderCommandKind::transition_texture; bad_transition_command.texture_desc.format = pp::renderer::TextureFormat::rgba8; bad_transition_command.before_state = static_cast(255U); bad_transition_command.after_state = pp::renderer::TextureState::shader_read; const auto bad_transition = pp::renderer::gl::plan_recorded_render_command(bad_transition_command); const auto bad_shader = pp::renderer::gl::plan_recorded_render_command( bind_shader_command("")); const auto bad_uniform = pp::renderer::gl::plan_recorded_render_command( shader_uniform_command("mvp", 0U)); const auto unknown = pp::renderer::gl::plan_recorded_render_command(pp::renderer::RecordedRenderCommand { .kind = static_cast(255U), }); PP_EXPECT(h, !bad_blend.supported); PP_EXPECT(h, bad_blend.blend.source_color_factor == 0U); PP_EXPECT(h, !bad_depth.supported); PP_EXPECT(h, bad_depth.depth.compare_function == 0U); PP_EXPECT(h, !bad_sampler.supported); PP_EXPECT(h, bad_sampler.sampler.wrap_s == 0U); PP_EXPECT(h, !bad_mesh.supported); PP_EXPECT(h, bad_mesh.primitive_mode == 0U); PP_EXPECT(h, !bad_blit.supported); PP_EXPECT(h, bad_blit.blit_filter.value == 0U); PP_EXPECT(h, !bad_transition.supported); PP_EXPECT(h, bad_transition.kind == pp::renderer::gl::OpenGlPlannedCommandKind::transition_texture); PP_EXPECT(h, !bad_shader.supported); PP_EXPECT(h, bad_shader.kind == pp::renderer::gl::OpenGlPlannedCommandKind::bind_shader); PP_EXPECT(h, !bad_uniform.supported); PP_EXPECT(h, bad_uniform.kind == pp::renderer::gl::OpenGlPlannedCommandKind::set_shader_uniform); PP_EXPECT(h, !unknown.supported); PP_EXPECT(h, unknown.kind == pp::renderer::gl::OpenGlPlannedCommandKind::unknown); } void names_planned_command_kinds(pp::tests::Harness& h) { PP_EXPECT(h, pp::renderer::gl::planned_command_kind_name( pp::renderer::gl::OpenGlPlannedCommandKind::begin_render_pass) == std::string_view("begin_render_pass")); PP_EXPECT(h, pp::renderer::gl::planned_command_kind_name( pp::renderer::gl::OpenGlPlannedCommandKind::passthrough) == std::string_view("passthrough")); PP_EXPECT(h, pp::renderer::gl::planned_command_kind_name( pp::renderer::gl::OpenGlPlannedCommandKind::copy_texture) == std::string_view("copy_texture")); PP_EXPECT(h, pp::renderer::gl::planned_command_kind_name( pp::renderer::gl::OpenGlPlannedCommandKind::set_shader_uniform) == std::string_view("set_shader_uniform")); PP_EXPECT(h, pp::renderer::gl::planned_command_kind_name( static_cast(255U)) == std::string_view("unknown")); } void plans_valid_recorded_command_streams(pp::tests::Harness& h) { const std::vector commands { command_with_kind(pp::renderer::RecordedRenderCommandKind::trace_begin_scope), begin_render_pass_command(), viewport_command(), bind_shader_command("stream-shader"), shader_uniform_command("mvp", 64U), draw_command(), command_with_kind(pp::renderer::RecordedRenderCommandKind::end_render_pass), blit_command(pp::renderer::BlitFilter::nearest), }; const auto plan = pp::renderer::gl::plan_recorded_render_commands(commands); PP_EXPECT(h, plan.supported); PP_EXPECT(h, plan.commands.size() == commands.size()); PP_EXPECT(h, plan.render_pass_count == 1U); PP_EXPECT(h, plan.draw_command_count == 1U); PP_EXPECT(h, plan.shader_bind_command_count == 1U); PP_EXPECT(h, plan.uniform_command_count == 1U); PP_EXPECT(h, plan.passthrough_command_count == 0U); PP_EXPECT(h, plan.trace_command_count == 1U); PP_EXPECT(h, plan.unsupported_command_count == 0U); PP_EXPECT(h, plan.render_pass_order_error_count == 0U); PP_EXPECT(h, plan.first_unsupported_command == pp::renderer::gl::OpenGlCommandPlan::npos); PP_EXPECT(h, plan.first_render_pass_order_error == pp::renderer::gl::OpenGlCommandPlan::npos); PP_EXPECT(h, !plan.ended_in_render_pass); PP_EXPECT(h, plan.commands[1].kind == pp::renderer::gl::OpenGlPlannedCommandKind::begin_render_pass); PP_EXPECT(h, plan.commands[3].kind == pp::renderer::gl::OpenGlPlannedCommandKind::bind_shader); PP_EXPECT(h, plan.commands[4].kind == pp::renderer::gl::OpenGlPlannedCommandKind::set_shader_uniform); PP_EXPECT(h, plan.commands[5].kind == pp::renderer::gl::OpenGlPlannedCommandKind::draw); PP_EXPECT(h, plan.commands[7].kind == pp::renderer::gl::OpenGlPlannedCommandKind::blit_render_target); } void flags_broken_render_pass_command_order(pp::tests::Harness& h) { const std::vector outside_pass { viewport_command(), }; const std::vector nested_pass { begin_render_pass_command(), begin_render_pass_command(), command_with_kind(pp::renderer::RecordedRenderCommandKind::end_render_pass), }; const std::vector unclosed_pass { begin_render_pass_command(), draw_command(), }; const auto outside = pp::renderer::gl::plan_recorded_render_commands(outside_pass); const auto nested = pp::renderer::gl::plan_recorded_render_commands(nested_pass); const auto unclosed = pp::renderer::gl::plan_recorded_render_commands(unclosed_pass); PP_EXPECT(h, !outside.supported); PP_EXPECT(h, outside.render_pass_order_error_count == 1U); PP_EXPECT(h, outside.first_render_pass_order_error == 0U); PP_EXPECT(h, !nested.supported); PP_EXPECT(h, nested.render_pass_order_error_count == 1U); PP_EXPECT(h, nested.first_render_pass_order_error == 1U); PP_EXPECT(h, nested.render_pass_count == 2U); PP_EXPECT(h, !unclosed.supported); PP_EXPECT(h, unclosed.render_pass_order_error_count == 1U); PP_EXPECT(h, unclosed.first_render_pass_order_error == unclosed_pass.size()); PP_EXPECT(h, unclosed.ended_in_render_pass); } void tracks_unsupported_commands_in_streams(pp::tests::Harness& h) { std::vector commands { begin_render_pass_command(), draw_command(), command_with_kind(pp::renderer::RecordedRenderCommandKind::end_render_pass), command_with_kind(static_cast(255U)), }; const auto plan = pp::renderer::gl::plan_recorded_render_commands(commands); PP_EXPECT(h, !plan.supported); PP_EXPECT(h, plan.unsupported_command_count == 1U); PP_EXPECT(h, plan.first_unsupported_command == 3U); PP_EXPECT(h, plan.render_pass_order_error_count == 0U); PP_EXPECT(h, plan.commands[3].kind == pp::renderer::gl::OpenGlPlannedCommandKind::unknown); } void counts_typed_texture_commands_in_streams(pp::tests::Harness& h) { pp::renderer::RecordedRenderCommand upload_command; upload_command.kind = pp::renderer::RecordedRenderCommandKind::upload_texture; upload_command.texture_desc.format = pp::renderer::TextureFormat::rgba8; upload_command.upload_bytes = 4U; pp::renderer::RecordedRenderCommand mipmap_command; mipmap_command.kind = pp::renderer::RecordedRenderCommandKind::generate_mipmaps; mipmap_command.texture_desc.format = pp::renderer::TextureFormat::rgba8; mipmap_command.generated_mip_levels = 2U; pp::renderer::RecordedRenderCommand transition_command; transition_command.kind = pp::renderer::RecordedRenderCommandKind::transition_texture; transition_command.texture_desc.format = pp::renderer::TextureFormat::rgba8; transition_command.before_state = pp::renderer::TextureState::copy_destination; transition_command.after_state = pp::renderer::TextureState::shader_read; pp::renderer::RecordedRenderCommand copy_command; copy_command.kind = pp::renderer::RecordedRenderCommandKind::copy_texture; copy_command.source_desc.format = pp::renderer::TextureFormat::rgba8; copy_command.destination_desc.format = pp::renderer::TextureFormat::rgba8; pp::renderer::RecordedRenderCommand read_command; read_command.kind = pp::renderer::RecordedRenderCommandKind::read_texture; read_command.texture_desc.format = pp::renderer::TextureFormat::rgba8; pp::renderer::RecordedRenderCommand capture_command; capture_command.kind = pp::renderer::RecordedRenderCommandKind::capture_frame; capture_command.target_desc.format = pp::renderer::TextureFormat::rgba8; const std::vector commands { upload_command, mipmap_command, transition_command, copy_command, read_command, capture_command, }; const auto plan = pp::renderer::gl::plan_recorded_render_commands(commands); PP_EXPECT(h, plan.supported); PP_EXPECT(h, plan.upload_command_count == 1U); PP_EXPECT(h, plan.mipmap_command_count == 1U); PP_EXPECT(h, plan.transition_command_count == 1U); PP_EXPECT(h, plan.copy_command_count == 1U); PP_EXPECT(h, plan.readback_command_count == 1U); PP_EXPECT(h, plan.capture_command_count == 1U); PP_EXPECT(h, plan.passthrough_command_count == 0U); PP_EXPECT(h, plan.render_pass_order_error_count == 0U); PP_EXPECT(h, plan.commands[0].kind == pp::renderer::gl::OpenGlPlannedCommandKind::upload_texture); PP_EXPECT(h, plan.commands[5].kind == pp::renderer::gl::OpenGlPlannedCommandKind::capture_frame); } } int main() { pp::tests::Harness harness; harness.run("maps_render_pass_and_state_commands", maps_render_pass_and_state_commands); harness.run("maps_binding_draw_and_blit_commands", maps_binding_draw_and_blit_commands); harness.run("maps_texture_io_and_capture_commands", maps_texture_io_and_capture_commands); harness.run("maps_shader_commands", maps_shader_commands); harness.run("rejects_unsupported_command_tokens", rejects_unsupported_command_tokens); harness.run("names_planned_command_kinds", names_planned_command_kinds); harness.run("plans_valid_recorded_command_streams", plans_valid_recorded_command_streams); harness.run("flags_broken_render_pass_command_order", flags_broken_render_pass_command_order); harness.run("tracks_unsupported_commands_in_streams", tracks_unsupported_commands_in_streams); harness.run("counts_typed_texture_commands_in_streams", counts_typed_texture_commands_in_streams); return harness.finish(); }