Add renderer shader uniform command
This commit is contained in:
@@ -52,6 +52,7 @@ using pp::renderer::TextureDesc;
|
||||
using pp::renderer::TextureFormat;
|
||||
using pp::renderer::Viewport;
|
||||
using pp::renderer::max_shader_source_bytes;
|
||||
using pp::renderer::max_shader_uniform_bytes;
|
||||
using pp::renderer::max_texture_dimension;
|
||||
using pp::renderer::max_texture_slots;
|
||||
using pp::renderer::panopainter_shader_catalog;
|
||||
@@ -77,6 +78,7 @@ using pp::renderer::validate_sampler_filter;
|
||||
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_slot;
|
||||
using pp::renderer::validate_viewport;
|
||||
|
||||
@@ -223,6 +225,24 @@ public:
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
[[nodiscard]] pp::foundation::Status set_shader_uniform(
|
||||
const char* name,
|
||||
std::span<const std::byte> bytes) noexcept override
|
||||
{
|
||||
if (!in_render_pass) {
|
||||
return pp::foundation::Status::invalid_argument("render pass has not begun");
|
||||
}
|
||||
|
||||
const auto status = validate_shader_uniform_write(name, bytes);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
|
||||
last_uniform_name = name;
|
||||
last_uniform_bytes = bytes.size();
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
[[nodiscard]] pp::foundation::Status set_blend_state(BlendState state) noexcept override
|
||||
{
|
||||
if (!in_render_pass) {
|
||||
@@ -386,6 +406,8 @@ public:
|
||||
|
||||
bool in_render_pass = false;
|
||||
const char* shader_name = nullptr;
|
||||
const char* last_uniform_name = nullptr;
|
||||
std::size_t last_uniform_bytes = 0;
|
||||
ScissorRect last_scissor {};
|
||||
BlendState last_blend_state {};
|
||||
DepthState last_depth_state {};
|
||||
@@ -829,6 +851,30 @@ void validates_shader_program_descriptors(pp::tests::Harness& h)
|
||||
PP_EXPECT(h, excessive_source_status.code == StatusCode::out_of_range);
|
||||
}
|
||||
|
||||
void validates_shader_uniform_writes(pp::tests::Harness& h)
|
||||
{
|
||||
const std::array<std::byte, 64> matrix_bytes {};
|
||||
const std::array<std::byte, 1> one_byte {};
|
||||
static const std::array<std::byte, max_shader_uniform_bytes + 1U> excessive_bytes {};
|
||||
|
||||
PP_EXPECT(h, validate_shader_uniform_write("mvp", matrix_bytes).ok());
|
||||
PP_EXPECT(h, validate_shader_uniform_write("opacity", one_byte).ok());
|
||||
|
||||
const auto null_name = validate_shader_uniform_write(nullptr, matrix_bytes);
|
||||
const auto empty_name = validate_shader_uniform_write("", matrix_bytes);
|
||||
const auto empty_bytes = validate_shader_uniform_write("mvp", std::span<const std::byte> {});
|
||||
const auto excessive = validate_shader_uniform_write("mvp", excessive_bytes);
|
||||
|
||||
PP_EXPECT(h, !null_name.ok());
|
||||
PP_EXPECT(h, null_name.code == StatusCode::invalid_argument);
|
||||
PP_EXPECT(h, !empty_name.ok());
|
||||
PP_EXPECT(h, empty_name.code == StatusCode::invalid_argument);
|
||||
PP_EXPECT(h, !empty_bytes.ok());
|
||||
PP_EXPECT(h, empty_bytes.code == StatusCode::invalid_argument);
|
||||
PP_EXPECT(h, !excessive.ok());
|
||||
PP_EXPECT(h, excessive.code == StatusCode::out_of_range);
|
||||
}
|
||||
|
||||
void validates_panopainter_shader_catalog(pp::tests::Harness& h)
|
||||
{
|
||||
const auto catalog = panopainter_shader_catalog();
|
||||
@@ -895,6 +941,7 @@ void renderer_interfaces_support_backend_neutral_dispatch(pp::tests::Harness& h)
|
||||
FakeTexture texture;
|
||||
FakeReadbackBuffer readback_buffer(64U * 32U * 4U);
|
||||
const std::array<std::byte, 80> upload_bytes {};
|
||||
const std::array<std::byte, 64> uniform_bytes {};
|
||||
FakeShaderProgram shader;
|
||||
FakeMesh mesh;
|
||||
|
||||
@@ -920,6 +967,7 @@ void renderer_interfaces_support_backend_neutral_dispatch(pp::tests::Harness& h)
|
||||
})
|
||||
.ok());
|
||||
PP_EXPECT(h, context.bind_shader(shader).ok());
|
||||
PP_EXPECT(h, context.set_shader_uniform("mvp", uniform_bytes).ok());
|
||||
PP_EXPECT(h, context.bind_texture(2, texture).ok());
|
||||
PP_EXPECT(h, context.bind_sampler(2, SamplerDesc {
|
||||
.min_filter = SamplerFilter::linear,
|
||||
@@ -962,6 +1010,8 @@ void renderer_interfaces_support_backend_neutral_dispatch(pp::tests::Harness& h)
|
||||
PP_EXPECT(h, device.context.last_depth_state.test_enabled);
|
||||
PP_EXPECT(h, device.context.last_depth_state.write_enabled);
|
||||
PP_EXPECT(h, device.context.last_depth_state.compare == CompareOp::less_or_equal);
|
||||
PP_EXPECT(h, device.context.last_uniform_name == std::string_view("mvp"));
|
||||
PP_EXPECT(h, device.context.last_uniform_bytes == 64U);
|
||||
PP_EXPECT(h, device.context.last_texture_slot == 2U);
|
||||
PP_EXPECT(h, device.context.last_texture_bytes == 8192U);
|
||||
PP_EXPECT(h, device.context.last_sampler_slot == 2U);
|
||||
@@ -1043,6 +1093,49 @@ void render_devices_create_validated_resources(pp::tests::Harness& h)
|
||||
PP_EXPECT(h, bad_readback.status().code == StatusCode::invalid_argument);
|
||||
}
|
||||
|
||||
void recording_renderer_records_shader_uniform_writes(pp::tests::Harness& h)
|
||||
{
|
||||
RecordingRenderDevice device;
|
||||
RecordingRenderTarget target(TextureDesc {
|
||||
.extent = Extent2D { .width = 16, .height = 8 },
|
||||
.format = TextureFormat::rgba8,
|
||||
.render_target = true,
|
||||
});
|
||||
RecordingShaderProgram shader("uniform-shader");
|
||||
const std::array<std::byte, 64> uniform_bytes {};
|
||||
|
||||
auto& context = device.immediate_context();
|
||||
const auto before_begin = context.set_shader_uniform("mvp", uniform_bytes);
|
||||
PP_EXPECT(h, !before_begin.ok());
|
||||
PP_EXPECT(h, before_begin.code == StatusCode::invalid_argument);
|
||||
|
||||
PP_EXPECT(h, context.begin_render_pass(target, ClearColor {}).ok());
|
||||
const auto before_shader = context.set_shader_uniform("mvp", uniform_bytes);
|
||||
PP_EXPECT(h, !before_shader.ok());
|
||||
PP_EXPECT(h, before_shader.code == StatusCode::invalid_argument);
|
||||
|
||||
PP_EXPECT(h, context.bind_shader(shader).ok());
|
||||
PP_EXPECT(h, context.set_shader_uniform("mvp", uniform_bytes).ok());
|
||||
const auto empty_name = context.set_shader_uniform("", uniform_bytes);
|
||||
const auto empty_bytes = context.set_shader_uniform("mvp", std::span<const std::byte> {});
|
||||
context.end_render_pass();
|
||||
|
||||
PP_EXPECT(h, !empty_name.ok());
|
||||
PP_EXPECT(h, empty_name.code == StatusCode::invalid_argument);
|
||||
PP_EXPECT(h, !empty_bytes.ok());
|
||||
PP_EXPECT(h, empty_bytes.code == StatusCode::invalid_argument);
|
||||
|
||||
const auto commands = device.commands();
|
||||
PP_EXPECT(h, commands.size() == 4U);
|
||||
PP_EXPECT(h, commands[0].kind == RecordedRenderCommandKind::begin_render_pass);
|
||||
PP_EXPECT(h, commands[1].kind == RecordedRenderCommandKind::bind_shader);
|
||||
PP_EXPECT(h, commands[2].kind == RecordedRenderCommandKind::set_shader_uniform);
|
||||
PP_EXPECT(h, commands[2].name == std::string_view("mvp"));
|
||||
PP_EXPECT(h, commands[2].uniform_bytes == 64U);
|
||||
PP_EXPECT(h, recorded_render_command_kind_name(commands[2].kind) == std::string_view("set_shader_uniform"));
|
||||
PP_EXPECT(h, commands[3].kind == RecordedRenderCommandKind::end_render_pass);
|
||||
}
|
||||
|
||||
void recording_renderer_records_valid_command_sequences(pp::tests::Harness& h)
|
||||
{
|
||||
RecordingRenderDevice device;
|
||||
@@ -1485,10 +1578,12 @@ int main()
|
||||
harness.run("validates_sampler_contract", validates_sampler_contract);
|
||||
harness.run("validates_viewports_and_mesh_descriptors", validates_viewports_and_mesh_descriptors);
|
||||
harness.run("validates_shader_program_descriptors", validates_shader_program_descriptors);
|
||||
harness.run("validates_shader_uniform_writes", validates_shader_uniform_writes);
|
||||
harness.run("validates_panopainter_shader_catalog", validates_panopainter_shader_catalog);
|
||||
harness.run("rejects_invalid_shader_catalogs", rejects_invalid_shader_catalogs);
|
||||
harness.run("renderer_interfaces_support_backend_neutral_dispatch", renderer_interfaces_support_backend_neutral_dispatch);
|
||||
harness.run("render_devices_create_validated_resources", render_devices_create_validated_resources);
|
||||
harness.run("recording_renderer_records_shader_uniform_writes", recording_renderer_records_shader_uniform_writes);
|
||||
harness.run("recording_renderer_records_valid_command_sequences", recording_renderer_records_valid_command_sequences);
|
||||
harness.run("recording_renderer_rejects_invalid_command_order_and_targets", recording_renderer_rejects_invalid_command_order_and_targets);
|
||||
return harness.finish();
|
||||
|
||||
Reference in New Issue
Block a user