Skip to main content

CPU Rendering with a Visualizer

Overview

  • Obtain a session as in earlier tutorials (rejoin or onboard)
  • Subscribe to incoming render stream requests and wait for a peer (e.g. a Visualizer) to request one
  • Create a CPU render sender for the requesting peer and submit a short gradient animation

Prerequisites

  • Complete the GUI Panel Operations tutorial
  • A running QarOS hub (for the first run, read the pairing code off its onboarding screen), with a peer that requests a render stream from this application once it is running

Build and Run

 cmake --build --preset x64-windows-debug --target cpu_rendering_visualizer
 ./build/x64-windows/Debug/cpu_rendering_visualizer.exe
 <path-to-qar-streaming-c.dll> [runtime-dir] [pairing-code]

Parse Arguments

  if(argc < 2)
  {
  print_usage(argv[0]);
  return 1;
  }
 
  const char* library_path = argv[1];
  const char* runtime_dir = NULL;
  char runtime_dir_buffer[1024] = { 0 };
 
  if(argc >= 3)
  {
  runtime_dir = argv[2];
  }
  else if(get_dir_from_path(
  library_path, runtime_dir_buffer, sizeof(runtime_dir_buffer)
  ))
  {
  runtime_dir = runtime_dir_buffer;
  }
 
  const char* pairing_code = (argc >= 4) ? argv[3] : NULL;

Library, Runtime, and Session Setup

The session is obtained with the shared rejoin-or-onboard helper described in the Onboarding and Rejoin tutorial.

  if(!qar_library_load(library_path))
  {
  fprintf(stderr, "Failed to load '%s'.\n", library_path);
  return 2;
  }
 
  library_init.enable_console_logging = true;
  QarResult library_result = qar_library_init(&library_init);
  if(qar_result_is_error(library_result))
  {
  log_result("qar_library_init", library_result);
  return 3;
  }
 
  QarRuntime* runtime = NULL;
  runtime_init.runtime_binaries_folder_path = runtime_dir;
  QarResult runtime_result = qar_runtime_create(&runtime_init, &runtime);
  if(qar_result_is_error(runtime_result) || runtime == NULL)
  {
  log_result("qar_runtime_create", runtime_result);
  return 4;
  }
 
  QarSession* session = NULL;
  runtime,
  pairing_code,
  "cpu_rendering_visualizer.onboarding-id.txt",
  "CPU Renderer",
  &onboarding_id,
  &session
  ) != 0
  || session == NULL)
  {
  qar_runtime_destroy(runtime);
  return 5;
  }

Wait for a Render Stream Request

  RenderRequestState request_state = { false, qar_peer_id_default() };
  session, on_render_request, &request_state, NULL
  );
  log_result("qar_render_sender_subscribe_requests", subscribe_result);
 
  printf(
  "Waiting for a peer to request a render stream (e.g. open a "
  "Visualizer on the hub) ...\n"
  );
  while(!request_state.has_request)
  {
  Sleep(50);
  }

Render and Submit Frames

  sender_init.peer_id = request_state.target_peer_id;
 
  QarRenderSender* sender = NULL;
  QarResult sender_result =
  qar_render_sender_create(session, &sender_init, NULL, &sender);
  if(qar_result_is_error(sender_result) || sender == NULL)
  {
  log_result("qar_render_sender_create", sender_result);
  log_result("qar_session_leave", qar_session_leave(session));
  qar_runtime_destroy(runtime);
  return 6;
  }
  log_result("qar_render_sender_create", sender_result);
 
  QarResult layout_result = qar_render_sender_layout(sender, &layout);
  log_result("qar_render_sender_layout", layout_result);
 
  const size_t frame_count = 3;
  for(size_t frame_index = 0; frame_index < frame_count; ++frame_index)
  {
  QarRenderFrameInfo* frame_info = NULL;
  QarResult begin_result =
  qar_render_sender_begin_frame(sender, NULL, &frame_info);
  log_result("qar_render_sender_begin_frame", begin_result);
  if(qar_result_is_error(begin_result) || frame_info == NULL)
  {
  break;
  }
 
  QarResult frame_result = qar_render_sender_frame_cpu(sender, &frame);
  log_result("qar_render_sender_frame_cpu", frame_result);
  if(qar_result_is_success(frame_result))
  {
  render_gradient(&frame, frame_index);
 
  show.rendered_near_far.far_plane = 10.0f;
  "qar_render_sender_show_frame",
  );
  }
 
  }
 

Generated via doxygen2docusaurus 2.2.1 by Doxygen 1.9.8.