Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Significant lag to update window after resize event #11652

Open
radoye opened this issue Dec 16, 2024 · 2 comments
Open

Significant lag to update window after resize event #11652

radoye opened this issue Dec 16, 2024 · 2 comments

Comments

@radoye
Copy link

radoye commented Dec 16, 2024

Please see the attached screen capture and perf report below. What is the recommended way to set up window updates to avoid the problem?

OS: Ubuntu 24.04
SDL: 3 (github) + opengl renderer
compiler: clang w/ -O3
Desktop: ubuntu:GNOME

Example code is below. Window + renderer/texture are done through SDL3. Paining is done with cairomm (github). In an attempt to isolate what causes this, I allocate a very large texture (as large as would fit on display) and do not resize any of the data structures even when the window is resized - I simply paint the background color again.

// toy-sdlw
int main(int argc, char* argv[]) {
  auto sdl = rlib::SdlHandle::Create();
  auto window = rlib::SdlWindow::Create(*sdl, {});

  auto bkg_painter = [](Cairo::Context* cairo_context) {
    cairo_context->set_source_rgb(1.0, 0.75, 0.0);
    cairo_context->paint();
    return absl::OkStatus();
  };

  bool should_exit = false;
  while (!should_exit) {
    auto event = (*window)->GetNextEvent();
    if (!event.has_value()) continue;
    switch (event.value().type) {
      case SDL_EVENT_KEY_DOWN: {
        std::cout << "KEY!\n";
        break;
      }
      case SDL_EVENT_MOUSE_BUTTON_DOWN: {
        std::cout << "MOUSE!\n";
        break;
      }
      case SDL_EVENT_WINDOW_MOVED: {
        std::cout << "WINDOW MOVED!\n";
        break;
      }
      case SDL_EVENT_WINDOW_RESIZED: {
        std::cout << "WINDOW RESIZED!\n";
	(*window)->Paint(bkg_painter);
        break;
      }
      case SDL_EVENT_QUIT: {
        should_exit = true;
        break;
      }
      default: {
        std::cout << "(default) Event type: " << event.value().type << "\n";
        break;
      }
    };
  }

  return 0;
}

// sdlw.cpp
absl::StatusOr<std::unique_ptr<SdlWindow>> SdlWindow::Create(
    std::shared_ptr<SdlHandle> sdl_handle, WindowSpec window_spec) {
  SDL_Window* window =
      SDL_CreateWindow(window_spec.name.data(), window_spec.width,
                       window_spec.height, window_spec.window_mode);
  if (!window) return absl::InternalError(SDL_GetError());

  SDL_DisplayID display_id = SDL_GetDisplayForWindow(window);
  if (!display_id) return absl::InternalError(SDL_GetError());

  const SDL_DisplayMode* display_mode = SDL_GetCurrentDisplayMode(display_id);
  if (!display_mode) return absl::InternalError(SDL_GetError());

  SDL_SetHint(SDL_HINT_RENDER_DRIVER, kRenderDriverHint.data());
  SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr);
  if (!renderer) return absl::InternalError(SDL_GetError());
  std::cout << "SDL renderer: " << SDL_GetRendererName(renderer) << "\n";

  // Create a texture to fit the biggest window on this screen.
  SDL_Texture* texture =
      SDL_CreateTexture(renderer, kTexturePixelFormat, kTextureAccess,
                        display_mode->w, display_mode->h);
  if (!texture) return absl::InternalError(SDL_GetError());

  void* texture_pixels;
  int texture_pitch;
  if (!SDL_LockTexture(texture, nullptr, &texture_pixels, &texture_pitch))
    return absl::InternalError(SDL_GetError());
  auto cairo_surface = Cairo::ImageSurface::create(
      reinterpret_cast<unsigned char*>(texture_pixels),
      Cairo::ImageSurface::Format::ARGB32, display_mode->w, display_mode->h,
      texture_pitch);
  auto cairo_context = Cairo::Context::create(cairo_surface);
  SDL_UnlockTexture(texture);

  auto result = std::unique_ptr<SdlWindow>(
      new SdlWindow(std::move(sdl_handle), window, display_id, display_mode,
                    renderer, texture, cairo_surface, cairo_context));

  auto paint_result = result->Paint([](Cairo::Context* cairo_context) {
    cairo_context->set_source_rgb(1.0, 0.75, 0.0);
    cairo_context->paint();
    return absl::OkStatus();
  });
  if (!paint_result.ok()) return paint_result;
  return result;
}

std::optional<SDL_Event> SdlWindow::GetNextEvent() {
  SDL_Event event;
  if (SDL_PollEvent(&event)) {
    return event;
  }
  return std::nullopt;
}

absl::Status SdlWindow::Paint(
    absl::AnyInvocable<absl::Status(Cairo::Context*)> painter) {
  void* texture_pixels;
  int texture_pitch;
  if (!SDL_LockTexture(sdl_texture_, nullptr, &texture_pixels, &texture_pitch))
    return absl::InternalError(SDL_GetError());
  auto res = painter(cairo_context_.get());
  SDL_UnlockTexture(sdl_texture_);

  // TODO: b/??? - Understand what locking actually does.
  // Why is it OK to unlock the texture that still needs to be read.
  SDL_RenderClear(sdl_renderer_);
  SDL_RenderTexture(sdl_renderer_, sdl_texture_, nullptr, nullptr);
  SDL_RenderPresent(sdl_renderer_);

  return res;
}

Perf was not super illuminating

  11.14%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001f71                                  
   8.93%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace3d7                                  
   8.05%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001fa6                                  
   6.39%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001fa2                                  
   6.28%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001f84                                  
   5.96%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001f76                                  
   5.74%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001f91                                  
   5.73%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001f8d                                  
   5.67%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001f9a                                  
   5.61%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001f7c                                  
   5.55%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace190                                  
   4.22%  toy-sdlw  libpixman-1.so.0.42.2            [.] 0x0000000000072a5f                                  
   3.47%  toy-sdlw  libpixman-1.so.0.42.2            [.] 0x0000000000072a47                                  
   2.21%  toy-sdlw  libpixman-1.so.0.42.2            [.] 0x0000000000072a4f                                  
   2.13%  toy-sdlw  libpixman-1.so.0.42.2            [.] 0x0000000000072a57                                  
   1.06%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001f7e                                  
   0.73%  toy-sdlw  libpixman-1.so.0.42.2            [.] 0x0000000000072a4b                                  
   0.72%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace3e3                                  
   0.53%  toy-sdlw  [unknown]                        [k] 0xffffffff9d8001c6                                  
   0.52%  toy-sdlw  libpixman-1.so.0.42.2            [.] 0x0000000000072a53                                  
   0.52%  toy-sdlw  libpixman-1.so.0.42.2            [.] 0x0000000000072a40                                  
   0.51%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace3c8                                  
   0.50%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001fa0                                  
   0.45%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace3db                                  
   0.39%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace3df                                  
   0.34%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace3e7                                  
   0.32%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace19a                                  
   0.32%  toy-sdlw  [unknown]                        [k] 0xffffffff9d800151                                  
   0.29%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace3eb                                  
   0.29%  toy-sdlw  [unknown]                        [k] 0xffffffff9d80010f                                  
   0.25%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace3cb                                  
   0.24%  toy-sdlw  .glXXXXXX (deleted)              [.] 0x0000000000001f8f                                  
   0.23%  toy-sdlw  libpixman-1.so.0.42.2            [.] 0x0000000000072a5b                                  
   0.21%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace3cf                                  
   0.18%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace193                                  
   0.15%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace3f2                                  
   0.15%  toy-sdlw  libnvidia-glcore.so.550.127.08   [.] 0x0000000000ace3d3   
SDL3_window_resize_update_lag.webm
@AntTheAlchemist
Copy link
Contributor

Instead of painting on a SDL_EVENT_WINDOW_RESIZED, try SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED.

@radoye
Copy link
Author

radoye commented Dec 16, 2024

Thanks for the quick response! No perceptible change even with SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED. In fact, even just painting in the event loop, outside of the case statement has the same laggy behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants