Route VR and startup GL state through backend
This commit is contained in:
@@ -371,8 +371,8 @@ Known local toolchain state:
|
||||
filters/wraps, and render-target formats resolve through backend-owned
|
||||
overloads.
|
||||
The Windows entrypoint also consumes backend-owned generic OpenGL
|
||||
error-code/info-string tokens and WGL core-context/pixel-format attribute
|
||||
catalogs.
|
||||
error-code/info-string tokens, runtime string query ordering, and WGL
|
||||
core-context/pixel-format attribute catalogs.
|
||||
The headless OpenGL command planner consumes `pp_renderer_api` recorded
|
||||
commands and maps render-pass clear masks/values, viewport/scissor state,
|
||||
blend/depth/sampler state, texture formats, primitive modes, draw counts, and
|
||||
@@ -391,9 +391,10 @@ Known local toolchain state:
|
||||
counts so automation can assert backend interpretation without an OpenGL
|
||||
context.
|
||||
Desktop VR drawing also consumes backend-owned scissor/depth/blend state,
|
||||
depth clear masks, active texture units, and fallback 2D texture unbind
|
||||
targets; VR SDK start/stop now dispatches through `PlatformServices` while
|
||||
retaining the existing Windows OpenVR bridge shape.
|
||||
blend/depth state query-restore, depth clear masks, active texture units,
|
||||
and fallback 2D texture unbind targets; VR SDK start/stop now dispatches
|
||||
through `PlatformServices` while retaining the existing Windows OpenVR bridge
|
||||
shape.
|
||||
Canvas mode overlay, mask, and transform paths also consume backend-owned
|
||||
blend/depth state, active texture units, 2D texture copy targets, and RGBA8
|
||||
readback format tokens.
|
||||
@@ -599,12 +600,13 @@ Known local toolchain state:
|
||||
shared layout parser.
|
||||
- `pp_renderer_gl` owns the tested `OpenGlInitialState` startup depth/blend
|
||||
policy and dispatch application consumed by `App::init`, tested runtime
|
||||
version/vendor/renderer/GLSL string query dispatch, tested default clear
|
||||
version/vendor/renderer/GLSL string query dispatch consumed by `App::init`
|
||||
and Windows startup logging/title construction, tested default clear
|
||||
color/buffer dispatch consumed by `App::clear`, tested app UI
|
||||
viewport/scissor dispatch consumed by `App::draw` and `App::vr_draw_ui`,
|
||||
tested generic capability/buffer-clear dispatch consumed by VR draw state
|
||||
setup, tested saved-state snapshot/restore dispatch consumed by the retained
|
||||
`gl_state` utility, tested texture lifecycle/readback dispatch consumed by
|
||||
tested generic capability query/apply and buffer-clear dispatch consumed by
|
||||
VR draw state setup and restore, tested saved-state snapshot/restore dispatch
|
||||
consumed by the retained `gl_state` utility, tested texture lifecycle/readback dispatch consumed by
|
||||
the retained `Texture2D` utility, tested framebuffer blit/readback dispatch
|
||||
consumed by retained `RTT` resize/copy/readback paths, tested framebuffer
|
||||
bind/restore dispatch consumed by retained `RTT` render-target pass entry
|
||||
|
||||
@@ -781,7 +781,9 @@ delegates to the backend dispatch path instead of hard-coding the policy or
|
||||
operation order.
|
||||
OpenGL runtime version/vendor/renderer/GLSL string queries now also use a
|
||||
tested `pp_renderer_gl` dispatch contract, leaving `App::init` to log the
|
||||
result while the backend owns the query set and order.
|
||||
result while the backend owns the query set and order. The Windows entrypoint
|
||||
also uses that contract for early context logging and renderer-name window
|
||||
title construction before replacing the temporary WGL context.
|
||||
The default app clear color and color-buffer clear operation now dispatch
|
||||
through `pp_renderer_gl` as well, moving another direct OpenGL operation out
|
||||
of `App::clear` while preserving the current gray clear behavior.
|
||||
@@ -792,10 +794,10 @@ the live OpenGL call sequence.
|
||||
VR UI framebuffer viewport and scissor-test setup now also consumes those
|
||||
`pp_renderer_gl` contracts, keeping desktop and VR UI rendering aligned while
|
||||
the retained OpenVR app path is split incrementally.
|
||||
VR draw blend/depth state transitions and depth-buffer clears now use generic
|
||||
tested `pp_renderer_gl` capability and clear dispatch contracts, reducing
|
||||
direct OpenGL execution in the retained VR app path without changing state
|
||||
restore behavior.
|
||||
VR draw blend/depth state snapshots, transitions, restore, and depth-buffer
|
||||
clears now use generic tested `pp_renderer_gl` capability query/apply and clear
|
||||
dispatch contracts, reducing direct OpenGL execution in the retained VR app
|
||||
path without changing state restore behavior.
|
||||
The retained `gl_state` save/restore utility now snapshots and restores through
|
||||
tested `pp_renderer_gl` saved-state dispatch contracts, covering capability
|
||||
state, viewport, clear color, framebuffer/program bindings, active texture,
|
||||
@@ -1081,7 +1083,8 @@ longer expose raw OpenGL enum defaults; default texture formats, sampler
|
||||
filters/wraps, and render-target formats are resolved through backend-owned
|
||||
overloads.
|
||||
The Windows entrypoint now delegates generic OpenGL error-code/info-string
|
||||
tokens and WGL core-context/pixel-format attribute catalogs to `pp_renderer_gl`.
|
||||
tokens, runtime string query ordering, and WGL core-context/pixel-format
|
||||
attribute catalogs to `pp_renderer_gl`.
|
||||
The headless OpenGL command planner now consumes `pp_renderer_api` recorded
|
||||
commands and maps render-pass clear masks/values, viewport/scissor state,
|
||||
blend/depth/sampler state, texture formats, primitive modes, draw counts, and
|
||||
@@ -1966,9 +1969,9 @@ Results:
|
||||
- Android arm64 configured with NDK 29.0.14206865 through the platform-build
|
||||
wrapper and compiled headless foundation/tool/test targets.
|
||||
- Desktop VR drawing now routes generic OpenGL scissor/depth/blend state,
|
||||
depth clears, active texture units, and fallback 2D texture unbinds through
|
||||
the renderer GL backend mapping; platform VR SDK bridges remain isolated for
|
||||
later platform-shell extraction.
|
||||
blend/depth state snapshots and restores, depth clears, active texture units,
|
||||
and fallback 2D texture unbinds through the renderer GL backend mapping;
|
||||
platform VR SDK bridges remain isolated for later platform-shell extraction.
|
||||
- Canvas mode overlay, mask, and transform paths now route generic OpenGL
|
||||
blend/depth state, active texture units, 2D copy targets, and RGBA8
|
||||
readback formats through the renderer GL backend mapping.
|
||||
|
||||
@@ -29,6 +29,11 @@ void disable_opengl_state(std::uint32_t state) noexcept
|
||||
glDisable(static_cast<GLenum>(state));
|
||||
}
|
||||
|
||||
std::uint8_t is_opengl_state_enabled(std::uint32_t state) noexcept
|
||||
{
|
||||
return static_cast<std::uint8_t>(glIsEnabled(static_cast<GLenum>(state)));
|
||||
}
|
||||
|
||||
void set_opengl_viewport(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height) noexcept
|
||||
{
|
||||
glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height));
|
||||
@@ -75,6 +80,20 @@ void apply_vr_render_capability(std::uint32_t state, bool enabled)
|
||||
LOG("OpenGL VR render state failed: %s", status.message);
|
||||
}
|
||||
|
||||
bool query_vr_render_capability(std::uint32_t state)
|
||||
{
|
||||
const auto result = pp::renderer::gl::query_opengl_capability_state(
|
||||
state,
|
||||
pp::renderer::gl::OpenGlCapabilityStateQueryDispatch {
|
||||
.is_enabled = is_opengl_state_enabled,
|
||||
});
|
||||
if (!result.ok()) {
|
||||
LOG("OpenGL VR render state query failed: %s", result.status().message);
|
||||
return false;
|
||||
}
|
||||
return result.value();
|
||||
}
|
||||
|
||||
void clear_vr_depth_buffer()
|
||||
{
|
||||
const auto status = pp::renderer::gl::clear_opengl_buffers(
|
||||
@@ -262,8 +281,8 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
glm::vec3 origin = glm::vec3(0, 0, -1) * glm::transpose(glm::mat3(pose));
|
||||
vr_rot = glm::lookAt({ 0, 0, 0 }, origin, { 0, 1, 0 });
|
||||
|
||||
auto blend = glIsEnabled(pp::renderer::gl::blend_state());
|
||||
auto depth = glIsEnabled(pp::renderer::gl::depth_test_state());
|
||||
const bool blend = query_vr_render_capability(pp::renderer::gl::blend_state());
|
||||
const bool depth = query_vr_render_capability(pp::renderer::gl::depth_test_state());
|
||||
|
||||
apply_vr_render_capability(pp::renderer::gl::blend_state(), false);
|
||||
apply_vr_render_capability(pp::renderer::gl::depth_test_state(), false);
|
||||
@@ -556,8 +575,8 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
mode->on_Draw(ortho_proj, proj, camera);
|
||||
*/
|
||||
|
||||
apply_vr_render_capability(pp::renderer::gl::blend_state(), blend != 0U);
|
||||
apply_vr_render_capability(pp::renderer::gl::depth_test_state(), depth != 0U);
|
||||
apply_vr_render_capability(pp::renderer::gl::blend_state(), blend);
|
||||
apply_vr_render_capability(pp::renderer::gl::depth_test_state(), depth);
|
||||
sampler.unbind();
|
||||
}
|
||||
|
||||
|
||||
24
src/main.cpp
24
src/main.cpp
@@ -89,6 +89,11 @@ void win32_renderdoc_frame_start() { }
|
||||
void win32_renderdoc_frame_end() { }
|
||||
#endif
|
||||
|
||||
const char* query_opengl_string(std::uint32_t name) noexcept
|
||||
{
|
||||
return reinterpret_cast<const char*>(glGetString(static_cast<GLenum>(name)));
|
||||
}
|
||||
|
||||
HRESULT(*GetDpiForMonitor_fn)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);
|
||||
HRESULT(*SetProcessDpiAwareness_fn)(PROCESS_DPI_AWARENESS value);
|
||||
void init_shcore_API()
|
||||
@@ -853,17 +858,28 @@ int main(int argc, char** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG("GL version: %s", glGetString(static_cast<GLenum>(pp::renderer::gl::version_string_name())));
|
||||
LOG("GL vendor: %s", glGetString(static_cast<GLenum>(pp::renderer::gl::vendor_string_name())));
|
||||
LOG("GL renderer: %s", glGetString(static_cast<GLenum>(pp::renderer::gl::renderer_string_name())));
|
||||
auto runtime_info = pp::renderer::gl::OpenGlRuntimeInfo {};
|
||||
const auto runtime_info_result = pp::renderer::gl::query_opengl_runtime_info(
|
||||
pp::renderer::gl::OpenGlRuntimeInfoDispatch {
|
||||
.get_string = query_opengl_string,
|
||||
});
|
||||
if (runtime_info_result.ok()) {
|
||||
runtime_info = runtime_info_result.value();
|
||||
LOG("GL version: %s", runtime_info.version);
|
||||
LOG("GL vendor: %s", runtime_info.vendor);
|
||||
LOG("GL renderer: %s", runtime_info.renderer);
|
||||
} else {
|
||||
LOG("OpenGL runtime info query failed: %s", runtime_info_result.status().message);
|
||||
}
|
||||
|
||||
#ifdef USE_RENDERDOC
|
||||
if (!win32_renderdoc_init())
|
||||
LOG("Renderdoc not started");
|
||||
#endif // USE_RENDERDOC
|
||||
|
||||
const auto renderer_name = std::string(runtime_info.renderer != nullptr ? runtime_info.renderer : "");
|
||||
swprintf_s(window_title, L"PanoPainter %s (%s)", g_version_number_w,
|
||||
str2wstr((char*)glGetString(static_cast<GLenum>(pp::renderer::gl::renderer_string_name()))).c_str());
|
||||
str2wstr(renderer_name).c_str());
|
||||
|
||||
// If supported create a 3.3 context
|
||||
if (GLAD_WGL_ARB_create_context)
|
||||
|
||||
@@ -526,6 +526,18 @@ pp::foundation::Status apply_opengl_capability(
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
pp::foundation::Result<bool> query_opengl_capability_state(
|
||||
std::uint32_t state,
|
||||
OpenGlCapabilityStateQueryDispatch dispatch) noexcept
|
||||
{
|
||||
if (dispatch.is_enabled == nullptr) {
|
||||
return pp::foundation::Result<bool>::failure(
|
||||
pp::foundation::Status::invalid_argument("OpenGL capability state query callback must not be null"));
|
||||
}
|
||||
|
||||
return pp::foundation::Result<bool>::success(dispatch.is_enabled(state) != 0U);
|
||||
}
|
||||
|
||||
pp::foundation::Status apply_opengl_render_platform_hints(
|
||||
OpenGlRenderPlatformHintDispatch dispatch) noexcept
|
||||
{
|
||||
|
||||
@@ -530,6 +530,10 @@ struct OpenGlCapabilityDispatch {
|
||||
OpenGlCapabilityFn disable = nullptr;
|
||||
};
|
||||
|
||||
struct OpenGlCapabilityStateQueryDispatch {
|
||||
OpenGlIsEnabledFn is_enabled = nullptr;
|
||||
};
|
||||
|
||||
struct OpenGlRenderPlatformHintDispatch {
|
||||
OpenGlCapabilityFn enable = nullptr;
|
||||
};
|
||||
@@ -760,6 +764,9 @@ struct OpenGlMeshDeleteDispatch {
|
||||
std::uint32_t state,
|
||||
bool enabled,
|
||||
OpenGlCapabilityDispatch dispatch) noexcept;
|
||||
[[nodiscard]] pp::foundation::Result<bool> query_opengl_capability_state(
|
||||
std::uint32_t state,
|
||||
OpenGlCapabilityStateQueryDispatch dispatch) noexcept;
|
||||
[[nodiscard]] pp::foundation::Status apply_opengl_render_platform_hints(
|
||||
OpenGlRenderPlatformHintDispatch dispatch) noexcept;
|
||||
[[nodiscard]] pp::foundation::Status apply_opengl_debug_output_states(
|
||||
|
||||
@@ -2246,6 +2246,35 @@ void rejects_incomplete_generic_capability_dispatch(pp::tests::Harness& h)
|
||||
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
||||
}
|
||||
|
||||
void queries_generic_capability_state(pp::tests::Harness& h)
|
||||
{
|
||||
const auto blend = pp::renderer::gl::query_opengl_capability_state(
|
||||
0x0BE2U,
|
||||
pp::renderer::gl::OpenGlCapabilityStateQueryDispatch {
|
||||
.is_enabled = record_is_enabled,
|
||||
});
|
||||
const auto depth = pp::renderer::gl::query_opengl_capability_state(
|
||||
0x0B71U,
|
||||
pp::renderer::gl::OpenGlCapabilityStateQueryDispatch {
|
||||
.is_enabled = record_is_enabled,
|
||||
});
|
||||
|
||||
PP_EXPECT(h, blend.ok());
|
||||
PP_EXPECT(h, blend.value());
|
||||
PP_EXPECT(h, depth.ok());
|
||||
PP_EXPECT(h, !depth.value());
|
||||
}
|
||||
|
||||
void rejects_incomplete_generic_capability_state_query(pp::tests::Harness& h)
|
||||
{
|
||||
const auto result = pp::renderer::gl::query_opengl_capability_state(
|
||||
0x0BE2U,
|
||||
pp::renderer::gl::OpenGlCapabilityStateQueryDispatch {});
|
||||
|
||||
PP_EXPECT(h, !result.ok());
|
||||
PP_EXPECT(h, result.status().code == pp::foundation::StatusCode::invalid_argument);
|
||||
}
|
||||
|
||||
void applies_render_platform_hints(pp::tests::Harness& h)
|
||||
{
|
||||
recorded_state_calls.clear();
|
||||
@@ -4435,6 +4464,8 @@ int main()
|
||||
harness.run("rejects_incomplete_scissor_test_dispatch", rejects_incomplete_scissor_test_dispatch);
|
||||
harness.run("applies_generic_capability_dispatch", applies_generic_capability_dispatch);
|
||||
harness.run("rejects_incomplete_generic_capability_dispatch", rejects_incomplete_generic_capability_dispatch);
|
||||
harness.run("queries_generic_capability_state", queries_generic_capability_state);
|
||||
harness.run("rejects_incomplete_generic_capability_state_query", rejects_incomplete_generic_capability_state_query);
|
||||
harness.run("applies_render_platform_hints", applies_render_platform_hints);
|
||||
harness.run("rejects_incomplete_render_platform_hint_dispatch", rejects_incomplete_render_platform_hint_dispatch);
|
||||
harness.run("applies_debug_output_states", applies_debug_output_states);
|
||||
|
||||
Reference in New Issue
Block a user