move framebuffer management from the renderer to the app

This commit is contained in:
Sven Balzer
2026-07-03 14:42:20 +02:00
parent 18c1b3639c
commit f3dcd26ce7
4 changed files with 115 additions and 104 deletions
+46 -44
View File
@@ -16,11 +16,11 @@ typedef struct R_Texture_Impl {
Uint32 width;
Uint32 height;
Uint32 sample_count;
bool multisampled;
R_Texture_Format format;
} R_Texture_Impl;
R_Texture R_framebuffer;
R_Texture R_surface;
static bool init_done;
@@ -30,10 +30,8 @@ static WGPUDevice device;
static WGPUQueue queue;
static WGPUSurface surface;
static R_Texture_Format surface_format;
static WGPUSurfaceConfiguration surface_configuration;
static WGPUSurfaceTexture surface_texture;
static WGPUTextureView surface_texture_view;
static R_Texture_Impl surface_texture;
static R_Texture framebuffer;
@@ -92,7 +90,7 @@ static WGPUStoreOp store_ops[] = {
};
static_assert(SDL_arraysize(store_ops) == R_STORE_OP_COUNT);
R_Texture renderer_texture_create(R_Texture_Format format, R_Texture_Usage usage, Uint32 sample_count, Uint32 width, Uint32 height, void *data, const char *debug_name) {
R_Texture renderer_texture_create(R_Texture_Format format, R_Texture_Usage usage, bool multisampled, Uint32 width, Uint32 height, void *data, const char *debug_name) {
WGPUTextureDescriptor descriptor = {
.label = { .data = debug_name, .length = WGPU_STRLEN },
.usage = texture_usages[usage] | WGPUTextureUsage_CopyDst,
@@ -100,7 +98,7 @@ R_Texture renderer_texture_create(R_Texture_Format format, R_Texture_Usage usage
.size = { .width = width, .height = height, .depthOrArrayLayers = 1 },
.format = texture_formats[format],
.mipLevelCount = 1,
.sampleCount = sample_count,
.sampleCount = multisampled ? 4 : 1,
.viewFormatCount = 0,
.viewFormats = NULL,
};
@@ -153,8 +151,8 @@ R_Texture renderer_texture_create(R_Texture_Format format, R_Texture_Usage usage
.width = width,
.height = height,
.sample_count = sample_count,
.format = format,
.multisampled = multisampled,
.format = format,
};
return result;
@@ -185,6 +183,22 @@ void renderer_texture_destroy(R_Texture texture) {
SDL_free(texture);
}
Uint32 renderer_texture_get_width(R_Texture texture) {
return texture->width;
}
Uint32 renderer_texture_get_height(R_Texture texture) {
return texture->height;
}
bool renderer_texture_get_multisampled(R_Texture texture) {
return texture->multisampled;
}
R_Texture_Format renderer_texture_get_format(R_Texture texture) {
return texture->format;
}
R_Buffer renderer_buffer_create(R_Buffer_Usage usage, Uint32 num_bytes, void *data, const char *debug_name) {
WGPUBufferDescriptor descriptor = {
.label = { .data = debug_name, .length = WGPU_STRLEN },
@@ -227,9 +241,17 @@ void renderer_buffer_destroy(R_Buffer buffer) {
SDL_free(buffer);
}
Uint32 renderer_buffer_get_size(R_Buffer buffer) {
return buffer->num_bytes;
}
R_Buffer_Usage renderer_buffer_get_usage(R_Buffer buffer){
return buffer->usage;
}
void renderer_frame_begin() {
SDL_assert(command_encoder == NULL);
SDL_assert(R_framebuffer == NULL);
SDL_assert(R_surface == NULL);
Sint32 window_width = 0, window_height = 0;
SDL_GetWindowSizeInPixels(window, &window_width, &window_height);
@@ -240,30 +262,25 @@ void renderer_frame_begin() {
wgpuSurfaceConfigure(surface, &surface_configuration);
}
wgpuSurfaceGetCurrentTexture(surface, &surface_texture);
if (surface_texture.status != WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal && surface_texture.status != WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal) {
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to get current surface texture (%x). Exiting.", surface_texture.status);
WGPUSurfaceTexture wgpu_surface_texture;
wgpuSurfaceGetCurrentTexture(surface, &wgpu_surface_texture);
if (wgpu_surface_texture.status != WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal && wgpu_surface_texture.status != WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal) {
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to get current surface texture (%x). Exiting.", wgpu_surface_texture.status);
SDL_assert_always(false); // TODO: recovery on outdated or device loss
return;
}
surface_texture_view = wgpuTextureCreateView(surface_texture.texture, NULL);
if (!framebuffer || framebuffer->width != surface_configuration.width || framebuffer->height != surface_configuration.height) {
if (framebuffer) {
renderer_texture_destroy(framebuffer);
framebuffer = NULL;
}
framebuffer = renderer_texture_create(surface_format, R_TEXTURE_USAGE_TARGET, 4, surface_configuration.width, surface_configuration.height, NULL, "R_framebuffer");
}
surface_texture.texture = wgpu_surface_texture.texture;
surface_texture.view = wgpuTextureCreateView(wgpu_surface_texture.texture, NULL);
surface_texture.width = surface_configuration.width;
surface_texture.height = surface_configuration.height;
command_encoder = wgpuDeviceCreateCommandEncoder(device, NULL);
R_framebuffer = framebuffer;
R_surface = &surface_texture;
}
void renderer_frame_end() {
SDL_assert(command_encoder);
SDL_assert(R_framebuffer);
SDL_assert(R_surface);
if (pass_encoder) {
wgpuRenderPassEncoderEnd(pass_encoder);
@@ -271,23 +288,8 @@ void renderer_frame_end() {
pass_encoder = NULL;
}
pass_encoder = wgpuCommandEncoderBeginRenderPass(command_encoder, &(WGPURenderPassDescriptor){
.colorAttachmentCount = 1,
.colorAttachments = &(WGPURenderPassColorAttachment) {
.view = framebuffer->view,
.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED,
.resolveTarget = surface_texture_view,
.loadOp = WGPULoadOp_Load,
.storeOp = WGPUStoreOp_Discard,
.clearValue = { .r = 0.0f, .g = 0.0f, .b = 0.0f, .a = 0.0f },
},
});
wgpuRenderPassEncoderEnd(pass_encoder);
wgpuRenderPassEncoderRelease(pass_encoder);
pass_encoder = NULL;
wgpuTextureViewRelease(surface_texture_view);
surface_texture_view = NULL;
wgpuTextureViewRelease(surface_texture.view);
surface_texture.view = NULL;
WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish(command_encoder, NULL);
wgpuCommandEncoderRelease(command_encoder);
@@ -300,7 +302,7 @@ void renderer_frame_end() {
wgpuTextureRelease(surface_texture.texture);
surface_texture.texture = NULL;
R_framebuffer = NULL;
R_surface = NULL;
}
void renderer_frame_set_target(R_Texture target, R_Texture resolve_target, R_Load_Op load_op, R_Store_Op store_op, R_Color clear_color) {
@@ -628,7 +630,7 @@ bool renderer_init(SDL_Window *window_) {
return false;
}
surface_format = R_TEXTURE_FORMAT_BGRA8_UNORM_SRGB;
surface_texture.format = R_TEXTURE_FORMAT_BGRA8_UNORM_SRGB;
surface_configuration = (WGPUSurfaceConfiguration){
.device = device,
.format = WGPUTextureFormat_BGRA8UnormSrgb,