Route cube textures and samplers through renderer GL

This commit is contained in:
2026-06-03 06:46:06 +02:00
parent 779d6b0387
commit f20595aff6
6 changed files with 714 additions and 59 deletions

View File

@@ -84,6 +84,18 @@ struct RecordedOpenGlBlitFramebufferCall {
std::uint32_t filter = 0;
};
struct RecordedOpenGlSamplerParameterCall {
std::uint32_t sampler = 0;
std::uint32_t parameter = 0;
std::int32_t value = 0;
};
struct RecordedOpenGlSamplerBorderCall {
std::uint32_t sampler = 0;
std::uint32_t parameter = 0;
const float* values = nullptr;
};
std::vector<RecordedOpenGlStateCall> recorded_state_calls;
std::vector<std::uint32_t> recorded_string_queries;
std::vector<pp::renderer::gl::OpenGlDefaultClear> recorded_clear_calls;
@@ -103,8 +115,12 @@ std::vector<RecordedOpenGlFramebufferAttachmentCall> recorded_framebuffer_attach
std::vector<std::uint32_t> recorded_framebuffer_status_queries;
std::vector<RecordedOpenGlReadPixelsCall> recorded_read_pixels_calls;
std::vector<RecordedOpenGlBlitFramebufferCall> recorded_blit_framebuffer_calls;
std::vector<std::uint32_t> recorded_generated_sampler_counts;
std::vector<RecordedOpenGlSamplerParameterCall> recorded_sampler_parameter_calls;
std::vector<RecordedOpenGlSamplerBorderCall> recorded_sampler_border_calls;
std::uint32_t next_texture_id = 91U;
std::uint32_t next_framebuffer_id = 44U;
std::uint32_t next_sampler_id = 71U;
std::uint32_t configured_framebuffer_status = 0x8CD5U;
void record_enable(std::uint32_t state) noexcept
@@ -447,6 +463,38 @@ void record_blit_framebuffer(
});
}
void record_gen_samplers(std::uint32_t count, std::uint32_t* ids) noexcept
{
recorded_generated_sampler_counts.push_back(count);
for (std::uint32_t i = 0U; i < count; ++i) {
ids[i] = next_sampler_id + i;
}
}
void record_sampler_parameter_i(
std::uint32_t sampler,
std::uint32_t parameter,
std::int32_t value) noexcept
{
recorded_sampler_parameter_calls.push_back(RecordedOpenGlSamplerParameterCall {
.sampler = sampler,
.parameter = parameter,
.value = value,
});
}
void record_sampler_parameter_fv(
std::uint32_t sampler,
std::uint32_t parameter,
const float* values) noexcept
{
recorded_sampler_border_calls.push_back(RecordedOpenGlSamplerBorderCall {
.sampler = sampler,
.parameter = parameter,
.values = values,
});
}
void detects_common_extension_capabilities(pp::tests::Harness& h)
{
constexpr std::array<std::string_view, 2> extensions {
@@ -1626,6 +1674,276 @@ void deletes_and_binds_texture_2d_through_dispatch(pp::tests::Harness& h)
PP_EXPECT(h, recorded_binding_calls[0].second == 27U);
}
void deletes_texture_objects_through_dispatch(pp::tests::Harness& h)
{
recorded_deleted_textures.clear();
constexpr std::array<std::uint32_t, 3> textures { 0U, 7U, 11U };
const auto status = pp::renderer::gl::delete_opengl_texture_objects(
textures,
pp::renderer::gl::OpenGlTexture2DDeleteDispatch {
.delete_textures = record_delete_textures,
});
PP_EXPECT(h, status.ok());
PP_EXPECT(h, recorded_deleted_textures.size() == 3U);
PP_EXPECT(h, recorded_deleted_textures[0] == 0U);
PP_EXPECT(h, recorded_deleted_textures[1] == 7U);
PP_EXPECT(h, recorded_deleted_textures[2] == 11U);
}
void allocates_texture_cube_through_dispatch(pp::tests::Harness& h)
{
recorded_generated_texture_counts.clear();
recorded_binding_calls.clear();
recorded_texture_image_calls.clear();
next_texture_id = 121U;
const auto texture = pp::renderer::gl::allocate_opengl_texture_cube(
pp::renderer::gl::OpenGlTextureCubeAllocation {
.resolution = 64,
.internal_format = 0x8058,
.pixel_format = 0x1908U,
.component_type = 0x1401U,
},
pp::renderer::gl::OpenGlTextureCubeAllocationDispatch {
.gen_textures = record_gen_textures,
.bind_texture = record_bind_texture,
.tex_image_2d = record_tex_image_2d,
});
PP_EXPECT(h, texture.ok());
PP_EXPECT(h, texture.value() == 121U);
PP_EXPECT(h, recorded_generated_texture_counts.size() == 1U);
PP_EXPECT(h, recorded_generated_texture_counts[0] == 1U);
PP_EXPECT(h, recorded_binding_calls.size() == 1U);
PP_EXPECT(h, recorded_binding_calls[0].kind == RecordedOpenGlBindingCall::Kind::bind_texture);
PP_EXPECT(h, recorded_binding_calls[0].first == 0x8513U);
PP_EXPECT(h, recorded_binding_calls[0].second == 121U);
PP_EXPECT(h, recorded_texture_image_calls.size() == 6U);
for (std::size_t i = 0U; i < recorded_texture_image_calls.size(); ++i) {
PP_EXPECT(h, recorded_texture_image_calls[i].target == 0x8515U + static_cast<std::uint32_t>(i));
PP_EXPECT(h, recorded_texture_image_calls[i].width == 64);
PP_EXPECT(h, recorded_texture_image_calls[i].height == 64);
PP_EXPECT(h, recorded_texture_image_calls[i].internal_format == 0x8058);
PP_EXPECT(h, recorded_texture_image_calls[i].pixel_format == 0x1908U);
PP_EXPECT(h, recorded_texture_image_calls[i].component_type == 0x1401U);
PP_EXPECT(h, recorded_texture_image_calls[i].data == nullptr);
}
}
void rejects_invalid_texture_cube_allocation(pp::tests::Harness& h)
{
const auto missing_dispatch = pp::renderer::gl::allocate_opengl_texture_cube(
pp::renderer::gl::OpenGlTextureCubeAllocation {
.resolution = 1,
.internal_format = 0x8058,
.pixel_format = 0x1908U,
.component_type = 0x1401U,
},
pp::renderer::gl::OpenGlTextureCubeAllocationDispatch {
.gen_textures = record_gen_textures,
.bind_texture = record_bind_texture,
});
const auto invalid_resolution = pp::renderer::gl::allocate_opengl_texture_cube(
pp::renderer::gl::OpenGlTextureCubeAllocation {
.resolution = 0,
.internal_format = 0x8058,
.pixel_format = 0x1908U,
.component_type = 0x1401U,
},
pp::renderer::gl::OpenGlTextureCubeAllocationDispatch {
.gen_textures = record_gen_textures,
.bind_texture = record_bind_texture,
.tex_image_2d = record_tex_image_2d,
});
PP_EXPECT(h, !missing_dispatch.ok());
PP_EXPECT(h, missing_dispatch.status().code == pp::foundation::StatusCode::invalid_argument);
PP_EXPECT(h, !invalid_resolution.ok());
PP_EXPECT(h, invalid_resolution.status().code == pp::foundation::StatusCode::invalid_argument);
}
void binds_texture_cube_through_dispatch(pp::tests::Harness& h)
{
recorded_binding_calls.clear();
const auto status = pp::renderer::gl::bind_opengl_texture_cube(
33U,
pp::renderer::gl::OpenGlTexture2DBindDispatch {
.bind_texture = record_bind_texture,
});
PP_EXPECT(h, status.ok());
PP_EXPECT(h, recorded_binding_calls.size() == 1U);
PP_EXPECT(h, recorded_binding_calls[0].kind == RecordedOpenGlBindingCall::Kind::bind_texture);
PP_EXPECT(h, recorded_binding_calls[0].first == 0x8513U);
PP_EXPECT(h, recorded_binding_calls[0].second == 33U);
}
void creates_sampler_through_dispatch(pp::tests::Harness& h)
{
recorded_generated_sampler_counts.clear();
recorded_sampler_parameter_calls.clear();
next_sampler_id = 81U;
const auto parameters = pp::renderer::gl::sampler_parameters_for_filter_wrap(0x2601U, 0x812FU);
const auto sampler = pp::renderer::gl::create_opengl_sampler(
parameters,
pp::renderer::gl::OpenGlSamplerCreateDispatch {
.gen_samplers = record_gen_samplers,
.sampler_parameter_i = record_sampler_parameter_i,
});
PP_EXPECT(h, sampler.ok());
PP_EXPECT(h, sampler.value() == 81U);
PP_EXPECT(h, recorded_generated_sampler_counts.size() == 1U);
PP_EXPECT(h, recorded_generated_sampler_counts[0] == 1U);
PP_EXPECT(h, recorded_sampler_parameter_calls.size() == parameters.size());
for (std::size_t i = 0U; i < parameters.size(); ++i) {
PP_EXPECT(h, recorded_sampler_parameter_calls[i].sampler == 81U);
PP_EXPECT(h, recorded_sampler_parameter_calls[i].parameter == parameters[i].name);
PP_EXPECT(h, recorded_sampler_parameter_calls[i].value == static_cast<std::int32_t>(parameters[i].value));
}
}
void sets_sampler_parameters_through_dispatch(pp::tests::Harness& h)
{
recorded_sampler_parameter_calls.clear();
const auto parameters = pp::renderer::gl::sampler_filter_parameters(0x2600U, 0x2601U);
const auto status = pp::renderer::gl::set_opengl_sampler_parameters(
17U,
parameters,
pp::renderer::gl::OpenGlSamplerParameterDispatch {
.sampler_parameter_i = record_sampler_parameter_i,
});
PP_EXPECT(h, status.ok());
PP_EXPECT(h, recorded_sampler_parameter_calls.size() == 2U);
PP_EXPECT(h, recorded_sampler_parameter_calls[0].sampler == 17U);
PP_EXPECT(h, recorded_sampler_parameter_calls[0].parameter == 0x2801U);
PP_EXPECT(h, recorded_sampler_parameter_calls[0].value == 0x2600);
PP_EXPECT(h, recorded_sampler_parameter_calls[1].parameter == 0x2800U);
PP_EXPECT(h, recorded_sampler_parameter_calls[1].value == 0x2601);
}
void sets_sampler_border_color_through_dispatch(pp::tests::Harness& h)
{
recorded_sampler_border_calls.clear();
constexpr std::array<float, 4> rgba { 0.25F, 0.5F, 0.75F, 1.0F };
const auto status = pp::renderer::gl::set_opengl_sampler_border_color(
19U,
0x1004U,
rgba.data(),
pp::renderer::gl::OpenGlSamplerBorderDispatch {
.sampler_parameter_fv = record_sampler_parameter_fv,
});
PP_EXPECT(h, status.ok());
PP_EXPECT(h, recorded_sampler_border_calls.size() == 1U);
PP_EXPECT(h, recorded_sampler_border_calls[0].sampler == 19U);
PP_EXPECT(h, recorded_sampler_border_calls[0].parameter == 0x1004U);
PP_EXPECT(h, recorded_sampler_border_calls[0].values == rgba.data());
}
void binds_sampler_through_dispatch(pp::tests::Harness& h)
{
recorded_binding_calls.clear();
const auto bind_status = pp::renderer::gl::bind_opengl_sampler_object(
3U,
23U,
pp::renderer::gl::OpenGlSamplerBindDispatch {
.bind_sampler = record_bind_sampler,
});
const auto unbind_status = pp::renderer::gl::bind_opengl_sampler_object(
3U,
0U,
pp::renderer::gl::OpenGlSamplerBindDispatch {
.bind_sampler = record_bind_sampler,
});
PP_EXPECT(h, bind_status.ok());
PP_EXPECT(h, unbind_status.ok());
PP_EXPECT(h, recorded_binding_calls.size() == 2U);
PP_EXPECT(h, recorded_binding_calls[0].kind == RecordedOpenGlBindingCall::Kind::bind_sampler);
PP_EXPECT(h, recorded_binding_calls[0].first == 3U);
PP_EXPECT(h, recorded_binding_calls[0].second == 23U);
PP_EXPECT(h, recorded_binding_calls[1].kind == RecordedOpenGlBindingCall::Kind::bind_sampler);
PP_EXPECT(h, recorded_binding_calls[1].first == 3U);
PP_EXPECT(h, recorded_binding_calls[1].second == 0U);
}
void rejects_invalid_sampler_dispatch(pp::tests::Harness& h)
{
constexpr std::array<pp::renderer::gl::OpenGlTextureParameter, 1> parameters {
pp::renderer::gl::OpenGlTextureParameter { .name = 0x2801U, .value = 0x2601U },
};
constexpr std::array<pp::renderer::gl::OpenGlTextureParameter, 1> invalid_parameters {
pp::renderer::gl::OpenGlTextureParameter { .name = 0U, .value = 0x2601U },
};
constexpr std::array<float, 4> rgba { 1.0F, 1.0F, 1.0F, 1.0F };
const auto missing_create_dispatch = pp::renderer::gl::create_opengl_sampler(
parameters,
pp::renderer::gl::OpenGlSamplerCreateDispatch {
.gen_samplers = record_gen_samplers,
});
const auto empty_create_parameters = pp::renderer::gl::create_opengl_sampler(
{},
pp::renderer::gl::OpenGlSamplerCreateDispatch {
.gen_samplers = record_gen_samplers,
.sampler_parameter_i = record_sampler_parameter_i,
});
const auto zero_sampler_parameters = pp::renderer::gl::set_opengl_sampler_parameters(
0U,
parameters,
pp::renderer::gl::OpenGlSamplerParameterDispatch {
.sampler_parameter_i = record_sampler_parameter_i,
});
const auto invalid_parameter_name = pp::renderer::gl::set_opengl_sampler_parameters(
7U,
invalid_parameters,
pp::renderer::gl::OpenGlSamplerParameterDispatch {
.sampler_parameter_i = record_sampler_parameter_i,
});
const auto null_border = pp::renderer::gl::set_opengl_sampler_border_color(
7U,
0x1004U,
nullptr,
pp::renderer::gl::OpenGlSamplerBorderDispatch {
.sampler_parameter_fv = record_sampler_parameter_fv,
});
const auto zero_border_parameter = pp::renderer::gl::set_opengl_sampler_border_color(
7U,
0U,
rgba.data(),
pp::renderer::gl::OpenGlSamplerBorderDispatch {
.sampler_parameter_fv = record_sampler_parameter_fv,
});
const auto missing_bind_dispatch = pp::renderer::gl::bind_opengl_sampler_object(
0U,
7U,
pp::renderer::gl::OpenGlSamplerBindDispatch {});
PP_EXPECT(h, !missing_create_dispatch.ok());
PP_EXPECT(h, missing_create_dispatch.status().code == pp::foundation::StatusCode::invalid_argument);
PP_EXPECT(h, !empty_create_parameters.ok());
PP_EXPECT(h, empty_create_parameters.status().code == pp::foundation::StatusCode::invalid_argument);
PP_EXPECT(h, !zero_sampler_parameters.ok());
PP_EXPECT(h, zero_sampler_parameters.code == pp::foundation::StatusCode::invalid_argument);
PP_EXPECT(h, !invalid_parameter_name.ok());
PP_EXPECT(h, invalid_parameter_name.code == pp::foundation::StatusCode::invalid_argument);
PP_EXPECT(h, !null_border.ok());
PP_EXPECT(h, null_border.code == pp::foundation::StatusCode::invalid_argument);
PP_EXPECT(h, !zero_border_parameter.ok());
PP_EXPECT(h, zero_border_parameter.code == pp::foundation::StatusCode::invalid_argument);
PP_EXPECT(h, !missing_bind_dispatch.ok());
PP_EXPECT(h, missing_bind_dispatch.code == pp::foundation::StatusCode::invalid_argument);
}
void updates_texture_2d_through_dispatch(pp::tests::Harness& h)
{
recorded_binding_calls.clear();
@@ -2399,6 +2717,15 @@ int main()
harness.run("allocates_texture_2d_through_dispatch", allocates_texture_2d_through_dispatch);
harness.run("rejects_invalid_texture_2d_allocation", rejects_invalid_texture_2d_allocation);
harness.run("deletes_and_binds_texture_2d_through_dispatch", deletes_and_binds_texture_2d_through_dispatch);
harness.run("deletes_texture_objects_through_dispatch", deletes_texture_objects_through_dispatch);
harness.run("allocates_texture_cube_through_dispatch", allocates_texture_cube_through_dispatch);
harness.run("rejects_invalid_texture_cube_allocation", rejects_invalid_texture_cube_allocation);
harness.run("binds_texture_cube_through_dispatch", binds_texture_cube_through_dispatch);
harness.run("creates_sampler_through_dispatch", creates_sampler_through_dispatch);
harness.run("sets_sampler_parameters_through_dispatch", sets_sampler_parameters_through_dispatch);
harness.run("sets_sampler_border_color_through_dispatch", sets_sampler_border_color_through_dispatch);
harness.run("binds_sampler_through_dispatch", binds_sampler_through_dispatch);
harness.run("rejects_invalid_sampler_dispatch", rejects_invalid_sampler_dispatch);
harness.run("updates_texture_2d_through_dispatch", updates_texture_2d_through_dispatch);
harness.run("generates_texture_2d_mipmaps_through_dispatch", generates_texture_2d_mipmaps_through_dispatch);
harness.run("reads_back_texture_2d_through_framebuffer_dispatch", reads_back_texture_2d_through_framebuffer_dispatch);