Ensure swap chains are resized appropriately.

The swap chain dimensions are a union of all render request
viewport sizes that use the swap chain.

PiperOrigin-RevId: 916078573
Change-Id: If26a9e1486006ed346227120a361773bfa23f292
This commit is contained in:
Haroon Qureshi
2026-05-15 10:43:16 -07:00
committed by Copybara-Service
parent 71ddeb3efc
commit b540909f18
2 changed files with 57 additions and 17 deletions
@@ -14,6 +14,7 @@
#include "experimental/filament/filament/filament_context.h"
#include <algorithm>
#include <cstdint>
#include <memory>
#include <span>
@@ -86,6 +87,13 @@ mjrFrameHandle FilamentContext::Render(
mju_error("Only one read request is supported for now.");
}
if constexpr (UTILS_HAS_THREADING) {
// Wait until previous frame is completed before requesting a new frame.
engine_->flushAndWait();
}
ValidateSwapChains(requests);
bool render_began = false;
mjrRenderTarget* current_target = nullptr;
for (const mjrRenderRequest& request : requests) {
@@ -100,22 +108,6 @@ mjrFrameHandle FilamentContext::Render(
mju_error("Cannot read pixels from the window.");
}
if constexpr (UTILS_HAS_THREADING) {
// Wait until previous frame is completed before requesting a new frame.
engine_->flushAndWait();
}
// If the window size has changed, we need to reacquire the swap chain.
if (request.viewport.width != window_width_ ||
request.viewport.height != window_height_) {
if (window_width_ != 0 && window_height_ != 0) {
engine_->destroy(window_swap_chain_);
window_swap_chain_ = engine_->createSwapChain(config_.native_window);
}
window_width_ = request.viewport.width;
window_height_ = request.viewport.height;
}
if (!render_began) {
render_began = renderer_->beginFrame(window_swap_chain_);
}
@@ -196,4 +188,51 @@ void FilamentContext::GetFrameStats(mjrFrameHandle frame,
}
}
void FilamentContext::ValidateSwapChains(
std::span<const mjrRenderRequest> requests) {
// Determine the maximum extents of the requests.
int max_window_width = 0;
int max_window_height = 0;
int max_offscreen_width = 0;
int max_offscreen_height = 0;
for (const mjrRenderRequest& request : requests) {
const int width = request.viewport.width + request.viewport.left;
const int height = request.viewport.height + request.viewport.bottom;
if (request.target == nullptr) {
max_window_width = std::max(max_window_width, width);
max_window_height = std::max(max_window_height, height);
} else {
max_offscreen_width = std::max(max_offscreen_width, width);
max_offscreen_height = std::max(max_offscreen_height, height);
}
}
if (max_window_width && max_window_height) {
if (max_window_width != window_width_ ||
max_window_width != window_height_) {
engine_->destroy(window_swap_chain_);
window_width_ = max_window_width;
window_height_ = max_window_height;
if (config_.native_window) {
window_swap_chain_ = engine_->createSwapChain(config_.native_window);
} else {
window_swap_chain_ =
engine_->createSwapChain(window_width_, window_height_);
}
}
}
if (max_offscreen_width && max_offscreen_height) {
if (max_offscreen_width != config_.width ||
max_offscreen_height != config_.height) {
engine_->destroy(offscreen_swap_chain_);
config_.width = max_offscreen_width;
config_.height = max_offscreen_height;
offscreen_swap_chain_ =
engine_->createSwapChain(config_.width, config_.height);
}
}
}
} // namespace mujoco
@@ -68,8 +68,9 @@ class FilamentContext : public mjrfContext {
}
private:
mjrFilamentConfig config_;
void ValidateSwapChains(std::span<const mjrRenderRequest> render_requests);
mjrFilamentConfig config_;
filament::Engine* engine_ = nullptr;
filament::Renderer* renderer_ = nullptr;
filament::SwapChain* window_swap_chain_ = nullptr;