Add renderer texture copy command
This commit is contained in:
@@ -288,18 +288,18 @@ Known local toolchain state:
|
||||
backend-owned resource creation, command order, render-pass color/depth/
|
||||
stencil clear intent, scissor state, depth state, blend state, texture-slot
|
||||
binding, sampler-state binding, texture-upload byte counts,
|
||||
shader-uniform writes, explicit draw descriptor ranges, readback bounds,
|
||||
frame-capture sources, destination buffer sizes, and render-target blit
|
||||
regions, records
|
||||
shader-uniform writes, explicit draw descriptor ranges, texture-copy regions,
|
||||
readback bounds, frame-capture sources, destination buffer sizes, and
|
||||
render-target blit regions, records
|
||||
render-pass-clear/scissor/depth/blend/shader-uniform/texture-bind/
|
||||
sampler-bind/draw/upload/readback/frame-capture/blit commands, draw mesh
|
||||
inputs, explicit draw ranges, and records trace markers without a window or
|
||||
GL context.
|
||||
sampler-bind/draw/upload/texture-copy/readback/frame-capture/blit commands,
|
||||
draw mesh inputs, explicit draw ranges, and records trace markers without a
|
||||
window or GL context.
|
||||
- `pano_cli record-render` exposes the recording renderer through JSON
|
||||
automation, including render-pass/depth-clear counts, scissor/depth/blend/
|
||||
shader-uniform/texture-bind/sampler-bind/upload/readback/frame-capture/blit
|
||||
command and byte totals, backend resource creation counts, plus draw
|
||||
descriptor vertex/index totals, and is covered by
|
||||
shader-uniform/texture-bind/sampler-bind/upload/texture-copy/readback/
|
||||
frame-capture/blit command and byte totals, backend resource creation counts,
|
||||
plus draw descriptor vertex/index totals, and is covered by
|
||||
`pano_cli_record_render_smoke` plus
|
||||
`pano_cli_record_render_rejects_oversized_target`.
|
||||
- `pano_cli simulate-document-history` exposes `pp_document::DocumentHistory`
|
||||
|
||||
@@ -726,10 +726,11 @@ Results:
|
||||
validation, blend-state validation, scissor-state validation,
|
||||
render-pass color/depth/stencil clear validation, shader-uniform write
|
||||
validation, draw descriptor/range validation, backend-neutral resource
|
||||
factory validation, recording
|
||||
factory validation, texture-copy validation, recording
|
||||
render-pass clear/scissor/depth/blend/shader-uniform/texture/sampler-bind/
|
||||
upload/readback/frame-capture/blit command capture, draw mesh-input capture,
|
||||
explicit draw-range capture, and invalid catalog rejection.
|
||||
upload/texture-copy/readback/frame-capture/blit command capture, draw
|
||||
mesh-input capture, explicit draw-range capture, and invalid catalog
|
||||
rejection.
|
||||
- `pp_paint_renderer_compositor_tests` passed.
|
||||
- `pp_ui_core_color_tests` passed.
|
||||
- `pp_ui_core_layout_value_tests` passed.
|
||||
@@ -826,20 +827,21 @@ Results:
|
||||
renderer-owned resource factory and
|
||||
command-order/render-pass-clear/scissor-state/depth-state/blend-state/
|
||||
texture-bind/sampler-bind/shader-uniform/texture-upload/readback/
|
||||
frame-capture/blit validation plus explicit draw descriptor validation; it
|
||||
creates validated textures, render targets, shaders, meshes, and readback
|
||||
buffers, then records commands, trace markers, render-pass color/depth/
|
||||
stencil clear intent, scissor state, depth state, blend state, shader uniform
|
||||
writes, texture/sampler binds, draw mesh inputs, explicit draw ranges,
|
||||
uploads/readbacks, frame captures, and render-target blits, giving automation
|
||||
a backend-neutral render path that does not require a window or GL context.
|
||||
frame-capture/blit validation plus explicit draw descriptor and texture-copy
|
||||
validation; it creates validated textures, render targets, shaders, meshes,
|
||||
and readback buffers, then records commands, trace markers, render-pass
|
||||
color/depth/stencil clear intent, scissor state, depth state, blend state,
|
||||
shader uniform writes, texture/sampler binds, draw mesh inputs, explicit draw
|
||||
ranges, texture uploads/copies/readbacks, frame captures, and render-target
|
||||
blits, giving automation a backend-neutral render path that does not require
|
||||
a window or GL context.
|
||||
- `pano_cli record-render` exercises that headless recording renderer and emits
|
||||
JSON command counts, resource creation counts, target dimensions, backend
|
||||
name, trace/draw summary, render-pass/depth-clear counts, and draw
|
||||
descriptor vertex/index totals, scissor/depth/blend-state plus
|
||||
shader-uniform/texture/sampler-bind/upload/readback/frame-capture/blit
|
||||
command/byte totals for agent automation, with an expected-failure smoke for oversized
|
||||
render/readback targets.
|
||||
shader-uniform/texture/sampler-bind/upload/texture-copy/readback/
|
||||
frame-capture/blit command/byte totals for agent automation, with an
|
||||
expected-failure smoke for oversized render/readback targets.
|
||||
- `pano_cli simulate-document-history` exercises pure document history
|
||||
apply/undo/redo behavior and emits JSON layer/frame/history state for agent
|
||||
automation.
|
||||
|
||||
@@ -397,6 +397,49 @@ pp::foundation::Status RecordingCommandContext::upload_texture(
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
pp::foundation::Status RecordingCommandContext::copy_texture(
|
||||
ITexture2D& source,
|
||||
ReadbackRegion source_region,
|
||||
ITexture2D& destination,
|
||||
ReadbackRegion destination_region) noexcept
|
||||
{
|
||||
if (in_render_pass_) {
|
||||
return pp::foundation::Status::invalid_argument("texture copy must be outside a render pass");
|
||||
}
|
||||
|
||||
const auto source_desc = source.desc();
|
||||
const auto destination_desc = destination.desc();
|
||||
const auto desc_status = validate_texture_copy_descs(
|
||||
source_desc,
|
||||
source_region,
|
||||
destination_desc,
|
||||
destination_region);
|
||||
if (!desc_status.ok()) {
|
||||
return desc_status;
|
||||
}
|
||||
|
||||
const auto source_bytes = readback_byte_size(source_desc, source_region);
|
||||
if (!source_bytes.ok()) {
|
||||
return source_bytes.status();
|
||||
}
|
||||
|
||||
const auto destination_bytes = readback_byte_size(destination_desc, destination_region);
|
||||
if (!destination_bytes.ok()) {
|
||||
return destination_bytes.status();
|
||||
}
|
||||
|
||||
push_command(commands_, RecordedRenderCommand {
|
||||
.kind = RecordedRenderCommandKind::copy_texture,
|
||||
.source_desc = source_desc,
|
||||
.destination_desc = destination_desc,
|
||||
.source_region = source_region,
|
||||
.destination_region = destination_region,
|
||||
.copy_source_bytes = source_bytes.value(),
|
||||
.copy_destination_bytes = destination_bytes.value(),
|
||||
});
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
pp::foundation::Status RecordingCommandContext::capture_frame(
|
||||
IRenderTarget& target,
|
||||
IReadbackBuffer& destination) noexcept
|
||||
@@ -626,6 +669,8 @@ const char* recorded_render_command_kind_name(RecordedRenderCommandKind kind) no
|
||||
return "draw";
|
||||
case RecordedRenderCommandKind::upload_texture:
|
||||
return "upload_texture";
|
||||
case RecordedRenderCommandKind::copy_texture:
|
||||
return "copy_texture";
|
||||
case RecordedRenderCommandKind::read_texture:
|
||||
return "read_texture";
|
||||
case RecordedRenderCommandKind::capture_frame:
|
||||
|
||||
@@ -20,6 +20,7 @@ enum class RecordedRenderCommandKind : std::uint8_t {
|
||||
bind_mesh,
|
||||
draw,
|
||||
upload_texture,
|
||||
copy_texture,
|
||||
read_texture,
|
||||
capture_frame,
|
||||
blit_render_target,
|
||||
@@ -53,6 +54,8 @@ struct RecordedRenderCommand {
|
||||
ReadbackRegion destination_region {};
|
||||
BlitFilter blit_filter = BlitFilter::nearest;
|
||||
std::uint64_t upload_bytes = 0;
|
||||
std::uint64_t copy_source_bytes = 0;
|
||||
std::uint64_t copy_destination_bytes = 0;
|
||||
std::uint64_t readback_bytes = 0;
|
||||
std::uint64_t capture_bytes = 0;
|
||||
std::uint64_t blit_source_bytes = 0;
|
||||
@@ -138,6 +141,11 @@ public:
|
||||
ITexture2D& texture,
|
||||
ReadbackRegion region,
|
||||
std::span<const std::byte> rgba_or_channel_bytes) noexcept override;
|
||||
[[nodiscard]] pp::foundation::Status copy_texture(
|
||||
ITexture2D& source,
|
||||
ReadbackRegion source_region,
|
||||
ITexture2D& destination,
|
||||
ReadbackRegion destination_region) noexcept override;
|
||||
[[nodiscard]] pp::foundation::Status capture_frame(
|
||||
IRenderTarget& target,
|
||||
IReadbackBuffer& destination) noexcept override;
|
||||
|
||||
@@ -489,6 +489,28 @@ pp::foundation::Result<std::uint64_t> frame_capture_byte_size(TextureDesc desc)
|
||||
return texture_byte_size(desc);
|
||||
}
|
||||
|
||||
pp::foundation::Status validate_texture_copy_descs(
|
||||
TextureDesc source,
|
||||
ReadbackRegion source_region,
|
||||
TextureDesc destination,
|
||||
ReadbackRegion destination_region) noexcept
|
||||
{
|
||||
if (source.format != destination.format) {
|
||||
return pp::foundation::Status::invalid_argument("texture copy endpoints must use matching formats");
|
||||
}
|
||||
|
||||
if (source_region.width != destination_region.width || source_region.height != destination_region.height) {
|
||||
return pp::foundation::Status::invalid_argument("texture copy regions must have matching dimensions");
|
||||
}
|
||||
|
||||
const auto source_status = validate_readback_region(source, source_region);
|
||||
if (!source_status.ok()) {
|
||||
return source_status;
|
||||
}
|
||||
|
||||
return validate_readback_region(destination, destination_region);
|
||||
}
|
||||
|
||||
pp::foundation::Status validate_blit_filter(BlitFilter filter) noexcept
|
||||
{
|
||||
switch (filter) {
|
||||
|
||||
@@ -243,6 +243,11 @@ public:
|
||||
ITexture2D& texture,
|
||||
ReadbackRegion region,
|
||||
std::span<const std::byte> rgba_or_channel_bytes) noexcept = 0;
|
||||
[[nodiscard]] virtual pp::foundation::Status copy_texture(
|
||||
ITexture2D& source,
|
||||
ReadbackRegion source_region,
|
||||
ITexture2D& destination,
|
||||
ReadbackRegion destination_region) noexcept = 0;
|
||||
[[nodiscard]] virtual pp::foundation::Status capture_frame(
|
||||
IRenderTarget& target,
|
||||
IReadbackBuffer& destination) noexcept = 0;
|
||||
@@ -299,6 +304,11 @@ public:
|
||||
ReadbackRegion region) noexcept;
|
||||
[[nodiscard]] pp::foundation::Result<std::uint64_t> frame_capture_byte_size(TextureDesc desc) noexcept;
|
||||
[[nodiscard]] pp::foundation::Status validate_readback_region(TextureDesc desc, ReadbackRegion region) noexcept;
|
||||
[[nodiscard]] pp::foundation::Status validate_texture_copy_descs(
|
||||
TextureDesc source,
|
||||
ReadbackRegion source_region,
|
||||
TextureDesc destination,
|
||||
ReadbackRegion destination_region) noexcept;
|
||||
[[nodiscard]] pp::foundation::Status validate_blit_filter(BlitFilter filter) noexcept;
|
||||
[[nodiscard]] pp::foundation::Status validate_blit_descs(
|
||||
TextureDesc source,
|
||||
|
||||
@@ -365,7 +365,7 @@ if(TARGET pano_cli)
|
||||
COMMAND pano_cli record-render --width 32 --height 16)
|
||||
set_tests_properties(pano_cli_record_render_smoke PROPERTIES
|
||||
LABELS "renderer;integration;desktop-fast"
|
||||
PASS_REGULAR_EXPRESSION "\"backend\":\"recording\".*\"width\":32.*\"height\":16.*\"createdResources\":6.*\"commands\":17.*\"renderPasses\":1.*\"depthClears\":1.*\"stencilClears\":0.*\"drawCommands\":1.*\"drawVertices\":3.*\"drawIndices\":3.*\"scissorCommands\":1.*\"blendCommands\":1.*\"depthCommands\":1.*\"uniformCommands\":1.*\"uniformBytes\":64.*\"bindTextureCommands\":1.*\"bindSamplerCommands\":1.*\"boundTextureBytes\":2048.*\"uploadCommands\":1.*\"uploadBytes\":4.*\"readbackCommands\":1.*\"readbackBytes\":2048.*\"captureCommands\":1.*\"captureBytes\":2048.*\"blitCommands\":1.*\"blitSourceBytes\":2048.*\"blitDestinationBytes\":2048")
|
||||
PASS_REGULAR_EXPRESSION "\"backend\":\"recording\".*\"width\":32.*\"height\":16.*\"createdResources\":6.*\"commands\":18.*\"renderPasses\":1.*\"depthClears\":1.*\"stencilClears\":0.*\"drawCommands\":1.*\"drawVertices\":3.*\"drawIndices\":3.*\"scissorCommands\":1.*\"blendCommands\":1.*\"depthCommands\":1.*\"uniformCommands\":1.*\"uniformBytes\":64.*\"bindTextureCommands\":1.*\"bindSamplerCommands\":1.*\"boundTextureBytes\":2048.*\"uploadCommands\":1.*\"uploadBytes\":4.*\"copyCommands\":1.*\"copySourceBytes\":2048.*\"copyDestinationBytes\":2048.*\"readbackCommands\":1.*\"readbackBytes\":2048.*\"captureCommands\":1.*\"captureBytes\":2048.*\"blitCommands\":1.*\"blitSourceBytes\":2048.*\"blitDestinationBytes\":2048")
|
||||
|
||||
add_test(NAME pano_cli_record_render_rejects_oversized_target
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
|
||||
@@ -84,6 +84,7 @@ using pp::renderer::validate_scissor;
|
||||
using pp::renderer::validate_shader_catalog;
|
||||
using pp::renderer::validate_shader_program_desc;
|
||||
using pp::renderer::validate_shader_uniform_write;
|
||||
using pp::renderer::validate_texture_copy_descs;
|
||||
using pp::renderer::validate_texture_slot;
|
||||
using pp::renderer::validate_viewport;
|
||||
|
||||
@@ -380,6 +381,36 @@ public:
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
[[nodiscard]] pp::foundation::Status copy_texture(
|
||||
pp::renderer::ITexture2D& source,
|
||||
ReadbackRegion source_region,
|
||||
pp::renderer::ITexture2D& destination,
|
||||
ReadbackRegion destination_region) noexcept override
|
||||
{
|
||||
const auto status = validate_texture_copy_descs(
|
||||
source.desc(),
|
||||
source_region,
|
||||
destination.desc(),
|
||||
destination_region);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
|
||||
const auto source_bytes = readback_byte_size(source.desc(), source_region);
|
||||
if (!source_bytes.ok()) {
|
||||
return source_bytes.status();
|
||||
}
|
||||
|
||||
const auto destination_bytes = readback_byte_size(destination.desc(), destination_region);
|
||||
if (!destination_bytes.ok()) {
|
||||
return destination_bytes.status();
|
||||
}
|
||||
|
||||
last_copy_source_bytes = source_bytes.value();
|
||||
last_copy_destination_bytes = destination_bytes.value();
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
[[nodiscard]] pp::foundation::Status capture_frame(
|
||||
IRenderTarget& target,
|
||||
pp::renderer::IReadbackBuffer& destination) noexcept override
|
||||
@@ -450,6 +481,8 @@ public:
|
||||
std::uint32_t last_sampler_slot = 0;
|
||||
SamplerDesc last_sampler_desc {};
|
||||
std::uint64_t last_upload_bytes = 0;
|
||||
std::uint64_t last_copy_source_bytes = 0;
|
||||
std::uint64_t last_copy_destination_bytes = 0;
|
||||
std::uint64_t last_readback_bytes = 0;
|
||||
std::uint64_t last_capture_bytes = 0;
|
||||
std::uint64_t last_blit_source_bytes = 0;
|
||||
@@ -698,6 +731,48 @@ void validates_blit_contract(pp::tests::Harness& h)
|
||||
PP_EXPECT(h, blit_filter_name(static_cast<BlitFilter>(255)) == std::string_view("unknown"));
|
||||
}
|
||||
|
||||
void validates_texture_copy_contract(pp::tests::Harness& h)
|
||||
{
|
||||
const TextureDesc rgba_desc {
|
||||
.extent = Extent2D { .width = 16, .height = 8 },
|
||||
.format = TextureFormat::rgba8,
|
||||
};
|
||||
const TextureDesc r8_desc {
|
||||
.extent = Extent2D { .width = 16, .height = 8 },
|
||||
.format = TextureFormat::r8,
|
||||
};
|
||||
|
||||
PP_EXPECT(h, validate_texture_copy_descs(
|
||||
rgba_desc,
|
||||
ReadbackRegion { .x = 1, .y = 2, .width = 4, .height = 3 },
|
||||
rgba_desc,
|
||||
ReadbackRegion { .x = 5, .y = 4, .width = 4, .height = 3 })
|
||||
.ok());
|
||||
|
||||
const auto mismatched_format = validate_texture_copy_descs(
|
||||
rgba_desc,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 1, .height = 1 },
|
||||
r8_desc,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 1, .height = 1 });
|
||||
const auto mismatched_region = validate_texture_copy_descs(
|
||||
rgba_desc,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 2, .height = 1 },
|
||||
rgba_desc,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 1, .height = 1 });
|
||||
const auto outside_source = validate_texture_copy_descs(
|
||||
rgba_desc,
|
||||
ReadbackRegion { .x = 15, .y = 0, .width = 2, .height = 1 },
|
||||
rgba_desc,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 2, .height = 1 });
|
||||
|
||||
PP_EXPECT(h, !mismatched_format.ok());
|
||||
PP_EXPECT(h, mismatched_format.code == StatusCode::invalid_argument);
|
||||
PP_EXPECT(h, !mismatched_region.ok());
|
||||
PP_EXPECT(h, mismatched_region.code == StatusCode::invalid_argument);
|
||||
PP_EXPECT(h, !outside_source.ok());
|
||||
PP_EXPECT(h, outside_source.code == StatusCode::out_of_range);
|
||||
}
|
||||
|
||||
void validates_blend_contract(pp::tests::Harness& h)
|
||||
{
|
||||
const BlendState alpha_blend {
|
||||
@@ -1105,6 +1180,12 @@ void renderer_interfaces_support_backend_neutral_dispatch(pp::tests::Harness& h)
|
||||
ReadbackRegion { .x = 2, .y = 3, .width = 4, .height = 5 },
|
||||
upload_bytes)
|
||||
.ok());
|
||||
PP_EXPECT(h, context.copy_texture(
|
||||
texture,
|
||||
ReadbackRegion { .x = 2, .y = 3, .width = 4, .height = 5 },
|
||||
texture,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 4, .height = 5 })
|
||||
.ok());
|
||||
PP_EXPECT(h, context.read_texture(
|
||||
texture,
|
||||
ReadbackRegion { .x = 2, .y = 3, .width = 4, .height = 5 },
|
||||
@@ -1141,6 +1222,8 @@ void renderer_interfaces_support_backend_neutral_dispatch(pp::tests::Harness& h)
|
||||
PP_EXPECT(h, device.context.last_sampler_desc.mag_filter == SamplerFilter::nearest);
|
||||
PP_EXPECT(h, device.context.last_sampler_desc.address_u == SamplerAddressMode::repeat);
|
||||
PP_EXPECT(h, device.context.last_upload_bytes == 80U);
|
||||
PP_EXPECT(h, device.context.last_copy_source_bytes == 80U);
|
||||
PP_EXPECT(h, device.context.last_copy_destination_bytes == 80U);
|
||||
PP_EXPECT(h, device.context.last_readback_bytes == 80U);
|
||||
PP_EXPECT(h, device.context.last_capture_bytes == 8192U);
|
||||
PP_EXPECT(h, device.context.last_blit_source_bytes == 80U);
|
||||
@@ -1390,28 +1473,43 @@ void recording_renderer_records_valid_command_sequences(pp::tests::Harness& h)
|
||||
PP_EXPECT(h, commands_after_upload[12].upload_bytes == 96U);
|
||||
PP_EXPECT(h, recorded_render_command_kind_name(commands_after_upload[12].kind) == std::string_view("upload_texture"));
|
||||
|
||||
PP_EXPECT(h, context.copy_texture(
|
||||
texture,
|
||||
ReadbackRegion { .x = 4, .y = 5, .width = 8, .height = 3 },
|
||||
texture,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 8, .height = 3 })
|
||||
.ok());
|
||||
const auto commands_after_copy = device.commands();
|
||||
PP_EXPECT(h, commands_after_copy.size() == 14U);
|
||||
PP_EXPECT(h, commands_after_copy[13].kind == RecordedRenderCommandKind::copy_texture);
|
||||
PP_EXPECT(h, commands_after_copy[13].source_region.x == 4U);
|
||||
PP_EXPECT(h, commands_after_copy[13].destination_region.x == 0U);
|
||||
PP_EXPECT(h, commands_after_copy[13].copy_source_bytes == 96U);
|
||||
PP_EXPECT(h, commands_after_copy[13].copy_destination_bytes == 96U);
|
||||
PP_EXPECT(h, recorded_render_command_kind_name(commands_after_copy[13].kind) == std::string_view("copy_texture"));
|
||||
|
||||
PP_EXPECT(h, context.read_texture(
|
||||
texture,
|
||||
ReadbackRegion { .x = 4, .y = 5, .width = 8, .height = 3 },
|
||||
readback_buffer)
|
||||
.ok());
|
||||
const auto commands_after_readback = device.commands();
|
||||
PP_EXPECT(h, commands_after_readback.size() == 14U);
|
||||
PP_EXPECT(h, commands_after_readback[13].kind == RecordedRenderCommandKind::read_texture);
|
||||
PP_EXPECT(h, commands_after_readback[13].texture_desc.extent.width == 64U);
|
||||
PP_EXPECT(h, commands_after_readback[13].readback_region.x == 4U);
|
||||
PP_EXPECT(h, commands_after_readback[13].readback_region.height == 3U);
|
||||
PP_EXPECT(h, commands_after_readback[13].readback_bytes == 96U);
|
||||
PP_EXPECT(h, recorded_render_command_kind_name(commands_after_readback[13].kind) == std::string_view("read_texture"));
|
||||
PP_EXPECT(h, commands_after_readback.size() == 15U);
|
||||
PP_EXPECT(h, commands_after_readback[14].kind == RecordedRenderCommandKind::read_texture);
|
||||
PP_EXPECT(h, commands_after_readback[14].texture_desc.extent.width == 64U);
|
||||
PP_EXPECT(h, commands_after_readback[14].readback_region.x == 4U);
|
||||
PP_EXPECT(h, commands_after_readback[14].readback_region.height == 3U);
|
||||
PP_EXPECT(h, commands_after_readback[14].readback_bytes == 96U);
|
||||
PP_EXPECT(h, recorded_render_command_kind_name(commands_after_readback[14].kind) == std::string_view("read_texture"));
|
||||
|
||||
PP_EXPECT(h, context.capture_frame(target, readback_buffer).ok());
|
||||
const auto commands_after_capture = device.commands();
|
||||
PP_EXPECT(h, commands_after_capture.size() == 15U);
|
||||
PP_EXPECT(h, commands_after_capture[14].kind == RecordedRenderCommandKind::capture_frame);
|
||||
PP_EXPECT(h, commands_after_capture[14].target_desc.extent.width == 64U);
|
||||
PP_EXPECT(h, commands_after_capture[14].target_desc.extent.height == 32U);
|
||||
PP_EXPECT(h, commands_after_capture[14].capture_bytes == 8192U);
|
||||
PP_EXPECT(h, recorded_render_command_kind_name(commands_after_capture[14].kind) == std::string_view("capture_frame"));
|
||||
PP_EXPECT(h, commands_after_capture.size() == 16U);
|
||||
PP_EXPECT(h, commands_after_capture[15].kind == RecordedRenderCommandKind::capture_frame);
|
||||
PP_EXPECT(h, commands_after_capture[15].target_desc.extent.width == 64U);
|
||||
PP_EXPECT(h, commands_after_capture[15].target_desc.extent.height == 32U);
|
||||
PP_EXPECT(h, commands_after_capture[15].capture_bytes == 8192U);
|
||||
PP_EXPECT(h, recorded_render_command_kind_name(commands_after_capture[15].kind) == std::string_view("capture_frame"));
|
||||
|
||||
PP_EXPECT(h, context.blit_render_target(
|
||||
target,
|
||||
@@ -1421,16 +1519,16 @@ void recording_renderer_records_valid_command_sequences(pp::tests::Harness& h)
|
||||
BlitFilter::linear)
|
||||
.ok());
|
||||
const auto commands_after_blit = device.commands();
|
||||
PP_EXPECT(h, commands_after_blit.size() == 16U);
|
||||
PP_EXPECT(h, commands_after_blit[15].kind == RecordedRenderCommandKind::blit_render_target);
|
||||
PP_EXPECT(h, commands_after_blit[15].source_desc.extent.width == 64U);
|
||||
PP_EXPECT(h, commands_after_blit[15].destination_desc.extent.height == 32U);
|
||||
PP_EXPECT(h, commands_after_blit[15].source_region.width == 16U);
|
||||
PP_EXPECT(h, commands_after_blit[15].destination_region.x == 2U);
|
||||
PP_EXPECT(h, commands_after_blit[15].blit_filter == BlitFilter::linear);
|
||||
PP_EXPECT(h, commands_after_blit[15].blit_source_bytes == 512U);
|
||||
PP_EXPECT(h, commands_after_blit[15].blit_destination_bytes == 128U);
|
||||
PP_EXPECT(h, recorded_render_command_kind_name(commands_after_blit[15].kind) == std::string_view("blit_render_target"));
|
||||
PP_EXPECT(h, commands_after_blit.size() == 17U);
|
||||
PP_EXPECT(h, commands_after_blit[16].kind == RecordedRenderCommandKind::blit_render_target);
|
||||
PP_EXPECT(h, commands_after_blit[16].source_desc.extent.width == 64U);
|
||||
PP_EXPECT(h, commands_after_blit[16].destination_desc.extent.height == 32U);
|
||||
PP_EXPECT(h, commands_after_blit[16].source_region.width == 16U);
|
||||
PP_EXPECT(h, commands_after_blit[16].destination_region.x == 2U);
|
||||
PP_EXPECT(h, commands_after_blit[16].blit_filter == BlitFilter::linear);
|
||||
PP_EXPECT(h, commands_after_blit[16].blit_source_bytes == 512U);
|
||||
PP_EXPECT(h, commands_after_blit[16].blit_destination_bytes == 128U);
|
||||
PP_EXPECT(h, recorded_render_command_kind_name(commands_after_blit[16].kind) == std::string_view("blit_render_target"));
|
||||
|
||||
device.clear();
|
||||
PP_EXPECT(h, device.commands().empty());
|
||||
@@ -1517,6 +1615,14 @@ void recording_renderer_rejects_invalid_command_order_and_targets(pp::tests::Har
|
||||
PP_EXPECT(h, !read_during_render_pass.ok());
|
||||
PP_EXPECT(h, read_during_render_pass.code == StatusCode::invalid_argument);
|
||||
|
||||
const auto copy_during_render_pass = context.copy_texture(
|
||||
texture,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 1, .height = 1 },
|
||||
texture,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 1, .height = 1 });
|
||||
PP_EXPECT(h, !copy_during_render_pass.ok());
|
||||
PP_EXPECT(h, copy_during_render_pass.code == StatusCode::invalid_argument);
|
||||
|
||||
const auto capture_during_render_pass = context.capture_frame(target, full_readback_buffer);
|
||||
PP_EXPECT(h, !capture_during_render_pass.ok());
|
||||
PP_EXPECT(h, capture_during_render_pass.code == StatusCode::invalid_argument);
|
||||
@@ -1653,6 +1759,22 @@ void recording_renderer_rejects_invalid_command_order_and_targets(pp::tests::Har
|
||||
PP_EXPECT(h, !upload_outside_bounds.ok());
|
||||
PP_EXPECT(h, upload_outside_bounds.code == StatusCode::out_of_range);
|
||||
|
||||
const auto copy_mismatched_regions = context.copy_texture(
|
||||
texture,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 2, .height = 1 },
|
||||
texture,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 1, .height = 1 });
|
||||
PP_EXPECT(h, !copy_mismatched_regions.ok());
|
||||
PP_EXPECT(h, copy_mismatched_regions.code == StatusCode::invalid_argument);
|
||||
|
||||
const auto copy_outside_bounds = context.copy_texture(
|
||||
texture,
|
||||
ReadbackRegion { .x = 31, .y = 15, .width = 2, .height = 1 },
|
||||
texture,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 2, .height = 1 });
|
||||
PP_EXPECT(h, !copy_outside_bounds.ok());
|
||||
PP_EXPECT(h, copy_outside_bounds.code == StatusCode::out_of_range);
|
||||
|
||||
const auto upload_with_wrong_size = context.upload_texture(
|
||||
texture,
|
||||
ReadbackRegion { .x = 0, .y = 0, .width = 1, .height = 1 },
|
||||
@@ -1723,6 +1845,7 @@ int main()
|
||||
harness.run("computes_readback_byte_sizes", computes_readback_byte_sizes);
|
||||
harness.run("computes_frame_capture_byte_sizes", computes_frame_capture_byte_sizes);
|
||||
harness.run("validates_blit_contract", validates_blit_contract);
|
||||
harness.run("validates_texture_copy_contract", validates_texture_copy_contract);
|
||||
harness.run("validates_blend_contract", validates_blend_contract);
|
||||
harness.run("validates_depth_contract", validates_depth_contract);
|
||||
harness.run("validates_sampler_contract", validates_sampler_contract);
|
||||
|
||||
@@ -2403,6 +2403,26 @@ int record_render(int argc, char** argv)
|
||||
return 2;
|
||||
}
|
||||
|
||||
const auto copy_status = context.copy_texture(
|
||||
*texture.value(),
|
||||
pp::renderer::ReadbackRegion {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = args.width,
|
||||
.height = args.height,
|
||||
},
|
||||
*texture.value(),
|
||||
pp::renderer::ReadbackRegion {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = args.width,
|
||||
.height = args.height,
|
||||
});
|
||||
if (!copy_status.ok()) {
|
||||
print_error("record-render", copy_status.message);
|
||||
return 2;
|
||||
}
|
||||
|
||||
const auto capture_status = context.capture_frame(*target.value(), *readback_buffer.value());
|
||||
if (!capture_status.ok()) {
|
||||
print_error("record-render", capture_status.message);
|
||||
@@ -2438,6 +2458,7 @@ int record_render(int argc, char** argv)
|
||||
std::size_t bind_texture_commands = 0;
|
||||
std::size_t bind_sampler_commands = 0;
|
||||
std::size_t upload_commands = 0;
|
||||
std::size_t copy_commands = 0;
|
||||
std::size_t readback_commands = 0;
|
||||
std::size_t capture_commands = 0;
|
||||
std::size_t blit_commands = 0;
|
||||
@@ -2449,6 +2470,8 @@ int record_render(int argc, char** argv)
|
||||
std::uint64_t draw_indices = 0;
|
||||
std::uint64_t uniform_bytes = 0;
|
||||
std::uint64_t upload_bytes = 0;
|
||||
std::uint64_t copy_source_bytes = 0;
|
||||
std::uint64_t copy_destination_bytes = 0;
|
||||
std::uint64_t bound_texture_bytes = 0;
|
||||
std::uint64_t readback_bytes = 0;
|
||||
std::uint64_t capture_bytes = 0;
|
||||
@@ -2488,6 +2511,10 @@ int record_render(int argc, char** argv)
|
||||
} else if (command.kind == pp::renderer::RecordedRenderCommandKind::upload_texture) {
|
||||
++upload_commands;
|
||||
upload_bytes += command.upload_bytes;
|
||||
} else if (command.kind == pp::renderer::RecordedRenderCommandKind::copy_texture) {
|
||||
++copy_commands;
|
||||
copy_source_bytes += command.copy_source_bytes;
|
||||
copy_destination_bytes += command.copy_destination_bytes;
|
||||
} else if (command.kind == pp::renderer::RecordedRenderCommandKind::read_texture) {
|
||||
++readback_commands;
|
||||
readback_bytes += command.readback_bytes;
|
||||
@@ -2526,6 +2553,9 @@ int record_render(int argc, char** argv)
|
||||
<< ",\"boundTextureBytes\":" << bound_texture_bytes
|
||||
<< ",\"uploadCommands\":" << upload_commands
|
||||
<< ",\"uploadBytes\":" << upload_bytes
|
||||
<< ",\"copyCommands\":" << copy_commands
|
||||
<< ",\"copySourceBytes\":" << copy_source_bytes
|
||||
<< ",\"copyDestinationBytes\":" << copy_destination_bytes
|
||||
<< ",\"readbackCommands\":" << readback_commands
|
||||
<< ",\"readbackBytes\":" << readback_bytes
|
||||
<< ",\"captureCommands\":" << capture_commands
|
||||
|
||||
Reference in New Issue
Block a user