Validate renderer blit descriptors first

This commit is contained in:
2026-06-02 18:06:23 +02:00
parent 831e5deeae
commit 0fc73d51d2
4 changed files with 55 additions and 8 deletions

View File

@@ -303,7 +303,7 @@ Known local toolchain state:
blend state, texture-slot binding, sampler-state binding, texture-upload byte
counts, texture mip-level counts, texture/mesh/shader resource debug labels, mipmap-generation commands,
texture-state transitions, shader-uniform writes, explicit draw descriptor ranges, texture-copy regions,
readback descriptor/bounds, frame-capture sources, destination buffer sizes, and
readback/frame-capture/blit descriptor validation, readback bounds, destination buffer sizes, and
render-target blit regions, records
render-pass-clear/scissor/depth/blend/shader-uniform/texture-bind/
sampler-bind/draw/upload/mipmap-generation/texture-transition/texture-copy/readback/

View File

@@ -428,7 +428,7 @@ descriptor, mesh, render target, readback byte-size helpers,
texture mip-level validation, resource debug-label validation,
texture-upload/readback command validation,
mipmap-generation command validation, texture-state transition validation, frame-capture byte-size helpers,
readback/copy descriptor validation, frame-capture command validation, render-target blit validation, texture-slot
readback/copy/frame-capture/blit descriptor validation, frame-capture command validation, render-target blit validation, texture-slot
binding validation, blend-state validation, scissor-state validation,
depth-state validation, trace marker/scope validation, sampler-state validation,
texture/mesh/shader resource-label validation,

View File

@@ -624,6 +624,11 @@ pp::foundation::Result<std::uint64_t> readback_byte_size(TextureDesc desc, Readb
pp::foundation::Result<std::uint64_t> frame_capture_byte_size(TextureDesc desc) noexcept
{
const auto desc_status = validate_texture_desc(desc);
if (!desc_status.ok()) {
return pp::foundation::Result<std::uint64_t>::failure(desc_status);
}
if (!has_texture_usage(desc.usage, TextureUsage::render_target)) {
return pp::foundation::Result<std::uint64_t>::failure(
pp::foundation::Status::invalid_argument("frame capture source must be a render target"));
@@ -778,6 +783,16 @@ pp::foundation::Status validate_blit_filter(BlitFilter filter) noexcept
pp::foundation::Status validate_blit_descs(TextureDesc source, TextureDesc destination) noexcept
{
const auto source_status = validate_texture_desc(source);
if (!source_status.ok()) {
return source_status;
}
const auto destination_status = validate_texture_desc(destination);
if (!destination_status.ok()) {
return destination_status;
}
if (!has_texture_usage(source.usage, TextureUsage::render_target)
|| !has_texture_usage(destination.usage, TextureUsage::render_target)) {
return pp::foundation::Status::invalid_argument("blit endpoints must be render targets");
@@ -795,14 +810,14 @@ pp::foundation::Status validate_blit_descs(TextureDesc source, TextureDesc desti
return pp::foundation::Status::invalid_argument("blit endpoints must use matching texture formats");
}
const auto source_status = texture_byte_size(source);
if (!source_status.ok()) {
return source_status.status();
const auto source_bytes = texture_byte_size(source);
if (!source_bytes.ok()) {
return source_bytes.status();
}
const auto destination_status = texture_byte_size(destination);
if (!destination_status.ok()) {
return destination_status.status();
const auto destination_bytes = texture_byte_size(destination);
if (!destination_bytes.ok()) {
return destination_bytes.status();
}
return pp::foundation::Status::success();

View File

@@ -1132,14 +1132,30 @@ void computes_frame_capture_byte_sizes(pp::tests::Harness& h)
.format = TextureFormat::rgba8,
.usage = TextureUsage::sampled | TextureUsage::upload_destination | TextureUsage::readback_source | TextureUsage::copy_source | TextureUsage::copy_destination,
};
const TextureDesc unsupported_usage_desc {
.extent = Extent2D { .width = 16, .height = 8 },
.format = TextureFormat::rgba8,
.usage = TextureUsage::render_target | TextureUsage::readback_source | static_cast<TextureUsage>(1U << 31U),
};
const TextureDesc unknown_format_desc {
.extent = Extent2D { .width = 16, .height = 8 },
.format = static_cast<TextureFormat>(255),
.usage = TextureUsage::render_target | TextureUsage::readback_source,
};
const auto capture = frame_capture_byte_size(target_desc);
const auto non_target = frame_capture_byte_size(texture_desc);
const auto unsupported_usage = frame_capture_byte_size(unsupported_usage_desc);
const auto unknown_format = frame_capture_byte_size(unknown_format_desc);
PP_EXPECT(h, capture.ok());
PP_EXPECT(h, capture.value() == 512U);
PP_EXPECT(h, !non_target.ok());
PP_EXPECT(h, non_target.status().code == StatusCode::invalid_argument);
PP_EXPECT(h, !unsupported_usage.ok());
PP_EXPECT(h, unsupported_usage.status().code == StatusCode::invalid_argument);
PP_EXPECT(h, !unknown_format.ok());
PP_EXPECT(h, unknown_format.status().code == StatusCode::invalid_argument);
}
void validates_blit_contract(pp::tests::Harness& h)
@@ -1159,6 +1175,16 @@ void validates_blit_contract(pp::tests::Harness& h)
.format = TextureFormat::rgba8,
.usage = TextureUsage::sampled | TextureUsage::upload_destination | TextureUsage::readback_source | TextureUsage::copy_source | TextureUsage::copy_destination,
};
const TextureDesc unknown_format_target_desc {
.extent = Extent2D { .width = 16, .height = 8 },
.format = static_cast<TextureFormat>(255),
.usage = TextureUsage::render_target | TextureUsage::copy_source | TextureUsage::copy_destination,
};
const TextureDesc unsupported_usage_target_desc {
.extent = Extent2D { .width = 16, .height = 8 },
.format = TextureFormat::rgba8,
.usage = TextureUsage::render_target | TextureUsage::copy_source | TextureUsage::copy_destination | static_cast<TextureUsage>(1U << 31U),
};
PP_EXPECT(h, validate_blit_descs(target_desc, target_desc).ok());
PP_EXPECT(h, validate_blit_filter(BlitFilter::nearest).ok());
@@ -1167,12 +1193,18 @@ void validates_blit_contract(pp::tests::Harness& h)
const auto non_target = validate_blit_descs(texture_desc, target_desc);
const auto mismatched_format = validate_blit_descs(target_desc, r8_target_desc);
const auto unknown_format = validate_blit_descs(unknown_format_target_desc, unknown_format_target_desc);
const auto unsupported_usage = validate_blit_descs(unsupported_usage_target_desc, target_desc);
const auto bad_filter = validate_blit_filter(static_cast<BlitFilter>(255));
PP_EXPECT(h, !non_target.ok());
PP_EXPECT(h, non_target.code == StatusCode::invalid_argument);
PP_EXPECT(h, !mismatched_format.ok());
PP_EXPECT(h, mismatched_format.code == StatusCode::invalid_argument);
PP_EXPECT(h, !unknown_format.ok());
PP_EXPECT(h, unknown_format.code == StatusCode::invalid_argument);
PP_EXPECT(h, !unsupported_usage.ok());
PP_EXPECT(h, unsupported_usage.code == StatusCode::invalid_argument);
PP_EXPECT(h, !bad_filter.ok());
PP_EXPECT(h, bad_filter.code == StatusCode::invalid_argument);
PP_EXPECT(h, blit_filter_name(static_cast<BlitFilter>(255)) == std::string_view("unknown"));