2025-03-22 17:36:09 +01:00
# include <assert.h>
# include <stdint.h>
# include <stdio.h>
# include <stdlib.h>
# include <SDL3/SDL.h>
# include <SDL3/SDL_gpu.h>
# include <cimgui.h>
# include <cimgui_impl.h>
# define igGetIO igGetIO_Nil
int main ( ) {
if ( ! SDL_Init ( SDL_INIT_VIDEO ) ) {
fprintf ( stderr , " Failed to init video! %s " , SDL_GetError ( ) ) ;
return 1 ;
} ;
SDL_Window * window = NULL ;
window = SDL_CreateWindow ( " cimgui SDL3+SDL_GPU example " , 1280 , 720 , SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY ) ;
if ( window = = NULL )
{
printf ( " Error: SDL_CreateWindow(): %s \n " , SDL_GetError ( ) ) ;
return - 1 ;
}
// Create GPU Device
SDL_GPUDevice * gpu_device = SDL_CreateGPUDevice ( SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_METALLIB , true , NULL ) ;
if ( gpu_device = = NULL )
{
printf ( " Error: SDL_CreateGPUDevice(): %s \n " , SDL_GetError ( ) ) ;
return - 1 ;
}
// Claim window for GPU Device
if ( ! SDL_ClaimWindowForGPUDevice ( gpu_device , window ) )
{
printf ( " Error: SDL_ClaimWindowForGPUDevice(): %s \n " , SDL_GetError ( ) ) ;
return - 1 ;
}
SDL_SetGPUSwapchainParameters ( gpu_device , window , SDL_GPU_SWAPCHAINCOMPOSITION_SDR , SDL_GPU_PRESENTMODE_MAILBOX ) ;
// Setup Dear ImGui context
//IMGUI_CHECKVERSION();
igCreateContext ( NULL ) ;
ImGuiIO * io = igGetIO ( ) ; ( void ) io ;
io - > ConfigFlags | = ImGuiConfigFlags_NavEnableKeyboard ; // Enable Keyboard Controls
io - > ConfigFlags | = ImGuiConfigFlags_NavEnableGamepad ; // Enable Gamepad Controls
// Setup Dear ImGui style
igStyleColorsDark ( NULL ) ;
//igStyleColorsLight(NULL);
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForSDLGPU ( window ) ;
2025-03-23 20:02:17 +01:00
ImGui_ImplSDLGPU3_InitInfo init_info ; //= {};
2025-03-22 17:36:09 +01:00
init_info . Device = gpu_device ;
init_info . ColorTargetFormat = SDL_GetGPUSwapchainTextureFormat ( gpu_device , window ) ;
init_info . MSAASamples = SDL_GPU_SAMPLECOUNT_1 ;
ImGui_ImplSDLGPU3_Init ( & init_info ) ;
// finish loading data
// Our state
bool show_demo_window = true ;
bool show_another_window = false ;
ImVec4 clear_color ;
clear_color . x = 0.45f ;
clear_color . y = 0.55f ;
clear_color . z = 0.60f ;
clear_color . w = 1.00f ;
// Main loop
bool done = false ;
while ( ! done )
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
// [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function]
SDL_Event event ;
while ( SDL_PollEvent ( & event ) )
{
ImGui_ImplSDL3_ProcessEvent ( & event ) ;
if ( event . type = = SDL_EVENT_QUIT )
done = true ;
if ( event . type = = SDL_EVENT_WINDOW_CLOSE_REQUESTED & & event . window . windowID = = SDL_GetWindowID ( window ) )
done = true ;
}
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function]
if ( SDL_GetWindowFlags ( window ) & SDL_WINDOW_MINIMIZED )
{
SDL_Delay ( 10 ) ;
continue ;
}
// Start the Dear ImGui frame
ImGui_ImplSDLGPU3_NewFrame ( ) ;
ImGui_ImplSDL3_NewFrame ( ) ;
igNewFrame ( ) ;
// 1. Show the big demo window (Most of the sample code is in igShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if ( show_demo_window )
igShowDemoWindow ( & show_demo_window ) ;
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
{
static float f = 0.0f ;
static int counter = 0 ;
igBegin ( " Hello, world! " , NULL , 0 ) ; // Create a window called "Hello, world!" and append into it.
igText ( " This is some useful text. " ) ; // Display some text (you can use a format strings too)
igCheckbox ( " Demo Window " , & show_demo_window ) ; // Edit bools storing our window open/close state
igCheckbox ( " Another Window " , & show_another_window ) ;
igSliderFloat ( " float " , & f , 0.0f , 1.0f , " %.3f " , 0 ) ; // Edit 1 float using a slider from 0.0f to 1.0f
igColorEdit4 ( " clear color " , ( float * ) & clear_color , 0 ) ; // Edit 3 floats representing a color
ImVec2 buttonSize ;
buttonSize . x = 0 ;
buttonSize . y = 0 ;
if ( igButton ( " Button " , buttonSize ) ) // Buttons return true when clicked (most widgets return true when edited/activated)
counter + + ;
igSameLine ( 0.0f , - 1.0f ) ;
igText ( " counter = %d " , counter ) ;
igText ( " Application average %.3f ms/frame (%.1f FPS) " , 1000.0f / io - > Framerate , io - > Framerate ) ;
igEnd ( ) ;
}
// 3. Show another simple window.
if ( show_another_window )
{
igBegin ( " Another Window " , & show_another_window , 0 ) ; // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
igText ( " Hello from another window! " ) ;
ImVec2 buttonSize ;
buttonSize . x = 0 ; buttonSize . y = 0 ;
if ( igButton ( " Close Me " , buttonSize ) )
show_another_window = false ;
igEnd ( ) ;
}
// Rendering
igRender ( ) ;
ImDrawData * draw_data = igGetDrawData ( ) ;
const bool is_minimized = ( draw_data - > DisplaySize . x < = 0.0f | | draw_data - > DisplaySize . y < = 0.0f ) ;
SDL_GPUCommandBuffer * command_buffer = SDL_AcquireGPUCommandBuffer ( gpu_device ) ; // Acquire a GPU command buffer
SDL_GPUTexture * swapchain_texture ;
SDL_AcquireGPUSwapchainTexture ( command_buffer , window , & swapchain_texture , NULL , NULL ) ; // Acquire a swapchain texture
if ( swapchain_texture ! = NULL & & ! is_minimized )
{
// This is mandatory: call Imgui_ImplSDLGPU3_PrepareDrawData() to upload the vertex/index buffer!
Imgui_ImplSDLGPU3_PrepareDrawData ( draw_data , command_buffer ) ;
// Setup and start a render pass
2025-03-23 20:02:17 +01:00
SDL_GPUColorTargetInfo target_info ; //= {};
2025-03-22 17:36:09 +01:00
target_info . texture = swapchain_texture ;
target_info . clear_color . r = clear_color . x ;
target_info . clear_color . g = clear_color . y ;
target_info . clear_color . b = clear_color . z ;
target_info . clear_color . a = clear_color . w ;
target_info . load_op = SDL_GPU_LOADOP_CLEAR ;
target_info . store_op = SDL_GPU_STOREOP_STORE ;
target_info . mip_level = 0 ;
target_info . layer_or_depth_plane = 0 ;
target_info . cycle = false ;
2025-03-23 20:02:17 +01:00
target_info . resolve_texture = NULL ;
target_info . resolve_mip_level = 0 ;
target_info . resolve_layer = 0 ;
target_info . cycle_resolve_texture = false ;
target_info . padding1 = 0 ;
target_info . padding2 = 0 ;
2025-03-22 17:36:09 +01:00
SDL_GPURenderPass * render_pass = SDL_BeginGPURenderPass ( command_buffer , & target_info , 1 , NULL ) ;
// Render ImGui
ImGui_ImplSDLGPU3_RenderDrawData ( draw_data , command_buffer , render_pass , NULL ) ;
SDL_EndGPURenderPass ( render_pass ) ;
}
// Submit the command buffer
SDL_SubmitGPUCommandBuffer ( command_buffer ) ;
}
// Cleanup
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function]
SDL_WaitForGPUIdle ( gpu_device ) ;
ImGui_ImplSDL3_Shutdown ( ) ;
ImGui_ImplSDLGPU3_Shutdown ( ) ;
igDestroyContext ( NULL ) ;
SDL_ReleaseWindowFromGPUDevice ( gpu_device , window ) ;
SDL_DestroyGPUDevice ( gpu_device ) ;
SDL_DestroyWindow ( window ) ;
SDL_Quit ( ) ;
return 0 ;
}