#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <SDL3_image/SDL_image.h>
static SDL_Window *window;
static SDL_GPUDevice *device;
static SDL_GPUTexture *texture;
static int texture_width;
static int texture_height;
static const char *get_file_path(const char *file)
{
static char path[4096];
if (*file != '/' && !SDL_GetPathInfo(file, NULL)) {
SDL_snprintf(path, sizeof(path), "%s%s", SDL_GetBasePath(), file);
if (SDL_GetPathInfo(path, NULL)) {
return path;
}
}
return file;
}
static bool load_image(SDL_GPUCommandBuffer *command_buffer, const char *path)
{
SDL_ReleaseGPUTexture(device, texture);
texture = NULL;
SDL_GPUCopyPass *copy_pass = SDL_BeginGPUCopyPass(command_buffer);
if (!copy_pass) {
SDL_Log("SDL_BeginGPUCopyPass() failed: %s", SDL_GetError());
return false;
}
texture = IMG_LoadGPUTexture(device, copy_pass, get_file_path(path), &texture_width, &texture_height);
if (!texture) {
SDL_Log("IMG_LoadGPUTexture() failed: %s", SDL_GetError());
}
SDL_EndGPUCopyPass(copy_pass);
return texture != NULL;
}
int main(int argc, char *argv[])
{
int result = 0;
bool quit = false;
SDL_GPUCommandBuffer *command_buffer = NULL;
SDL_Event event = {0};
SDL_GPUTexture *swapchain_texture = NULL;
Uint32 swapchain_width = 0;
Uint32 swapchain_height = 0;
SDL_GPUBlitInfo blit_info = {0};
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("SDL_Init(SDL_INIT_VIDEO) failed: %s", SDL_GetError());
result = 2;
goto done;
}
window = SDL_CreateWindow("", 960, 720, SDL_WINDOW_RESIZABLE);
if (!window) {
SDL_Log("SDL_CreateWindow() failed: %s", SDL_GetError());
result = 2;
goto done;
}
device = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL, true, NULL);
if (!window) {
SDL_Log("SDL_CreateGPUDevice() failed: %s", SDL_GetError());
result = 2;
goto done;
}
if (!SDL_ClaimWindowForGPUDevice(device, window)) {
SDL_Log("SDL_ClaimWindowForGPUDevice() failed: %s", SDL_GetError());
result = 2;
goto done;
}
if (argc > 1) {
SDL_GPUCommandBuffer *command_buffer = SDL_AcquireGPUCommandBuffer(device);
if (!command_buffer) {
SDL_Log("SDL_AcquireGPUCommandBuffer() failed: %s", SDL_GetError());
result = 2;
goto done;
}
if (!load_image(command_buffer, argv[1])) {
result = 2;
goto done;
}
SDL_SubmitGPUCommandBuffer(command_buffer);
}
while (!quit) {
command_buffer = SDL_AcquireGPUCommandBuffer(device);
if (!command_buffer) {
SDL_Log("SDL_AcquireGPUCommandBuffer() failed: %s", SDL_GetError());
continue;
}
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_EVENT_QUIT:
quit = true;
break;
case SDL_EVENT_DROP_FILE:
load_image(command_buffer, event.drop.data);
break;
}
}
if (quit) {
break;
}
if (!SDL_WaitAndAcquireGPUSwapchainTexture(command_buffer, window, &swapchain_texture, &swapchain_width, &swapchain_height)) {
SDL_Log("SDL_WaitAndAcquireGPUSwapchainTexture() failed: %s", SDL_GetError());
SDL_CancelGPUCommandBuffer(command_buffer);
continue;
}
if (!swapchain_texture || !swapchain_width || !swapchain_height) {
SDL_CancelGPUCommandBuffer(command_buffer);
continue;
}
if (texture) {
blit_info.source.texture = texture;
blit_info.source.w = texture_width;
blit_info.source.h = texture_height;
blit_info.destination.texture = swapchain_texture;
blit_info.destination.w = swapchain_width;
blit_info.destination.h = swapchain_height;
SDL_BlitGPUTexture(command_buffer, &blit_info);
}
SDL_SubmitGPUCommandBuffer(command_buffer);
}
done:
SDL_ReleaseGPUTexture(device, texture);
SDL_ReleaseWindowFromGPUDevice(device, window);
SDL_DestroyGPUDevice(device);
SDL_DestroyWindow(window);
SDL_Quit();
return result;
}