From 8033c161d00f6bbf18343ccb6724f9beaac9a00e Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Fri, 1 Aug 2025 06:35:25 -0500 Subject: [PATCH] change pipelines --- prosperon/prosperon.cm | 125 +++++++++++++++++++++++++++++++---------- 1 file changed, 94 insertions(+), 31 deletions(-) diff --git a/prosperon/prosperon.cm b/prosperon/prosperon.cm index fe0cad93..24151acb 100644 --- a/prosperon/prosperon.cm +++ b/prosperon/prosperon.cm @@ -276,15 +276,37 @@ function make_shader(sh_file) return shader } -var usepipe +def material_pipeline_cache = {}; + +function get_pipeline_for_material(mat = {}) { + def key = json.encode({ + vert: mat.vertex || sprite_pipeline.vertex, + frag: mat.fragment || sprite_pipeline.fragment, + blend: mat.blend || sprite_pipeline.blend, + cull: mat.cull || sprite_pipeline.cull, + }); + + if (!material_pipeline_cache[key]) { + def cfg = Object.assign({}, sprite_pipeline, { + vertex: mat.vertex || sprite_pipeline.vertex, + fragment: mat.fragment || sprite_pipeline.fragment, + blend: mat.blend || sprite_pipeline.blend, + cull: mat.cull || sprite_pipeline.cull, + }); + + cfg.__proto__ = sprite_pipeline + material_pipeline_cache[key] = load_pipeline(cfg) + log.console(`created pipeline for ${json.encode(cfg)}`) + } + + return material_pipeline_cache[key]; +} + function load_pipeline(config) { - if (usepipe) return usepipe config.vertex = make_shader(config.vertex)[GPU] config.fragment = make_shader(config.fragment)[GPU] - usepipe = new sdl_gpu.graphics_pipeline(device, config) - log.console(usepipe) - return usepipe + return new sdl_gpu.graphics_pipeline(device, config) } // Initialize ImGui with the window and renderer @@ -483,8 +505,6 @@ var sprite_pipeline = { blend: alpha_blend_state } -var pipey = load_pipeline(sprite_pipeline) - var GPU = Symbol() var cur_cam @@ -562,7 +582,7 @@ var draw_queue = [] var index_count = 0 var vertex_count = 0 -function render_geom(geom, img) +function render_geom(geom, img, pipeline = get_pipeline_for_material(null)) { if (!img[GPU]) { if (img.surface) @@ -579,7 +599,7 @@ function render_geom(geom, img) index_blob.write_blob(geom.indices) draw_queue.push({ - pipeline:pipey, + pipeline, texture: img[GPU], num_indices: geom.num_indices, first_index: index_count, @@ -605,7 +625,8 @@ cmd_fns.draw_image = function(cmd) geom.indices = geometry.make_quad_indices(1) geom.num_indices = 6 - render_geom(geom, img) + var pipeline = get_pipeline_for_material(cmd.material) + render_geom(geom, img, pipeline) } cmd_fns.draw_text = function(cmd) @@ -623,31 +644,36 @@ cmd_fns.draw_text = function(cmd) font ) - render_geom(mesh, font) + var pipeline = get_pipeline_for_material(cmd.material) + render_geom(mesh, font, pipeline) } cmd_fns.tilemap = function(cmd) { var geometryCommands = cmd.tilemap.draw() + var pipeline = get_pipeline_for_material(cmd.material) + for (var geomCmd of geometryCommands) { var img = graphics.texture(geomCmd.image) if (!img) continue - render_geom(geomCmd.geometry, img) + render_geom(geomCmd.geometry, img, pipeline) } } cmd_fns.geometry = function(cmd) { + var pipeline = get_pipeline_for_material(cmd.material) + if (typeof cmd.image == 'object') { - render_geom(cmd.geometry, cmd.image) + render_geom(cmd.geometry, cmd.image, pipeline) return } var img = graphics.texture(cmd.image) if (!img) return - render_geom(cmd.geometry, img) + render_geom(cmd.geometry, img, pipeline) } cmd_fns.draw_slice9 = function(cmd) @@ -678,22 +704,23 @@ cmd_fns.draw_slice9 = function(cmd) var mesh = geometry.slice9(img, cmd.rect, slice_lrtb, slice_info) - render_geom(mesh, img) + var pipeline = get_pipeline_for_material(cmd.material) + render_geom(mesh, img, pipeline) } cmd_fns.draw_rect = function(cmd) { // Create geometry for a rectangle quad - var geom = geometry.make_rect_quad(cmd.rect, null, cmd.material.color || [1,1,1,1]) + var geom = geometry.make_rect_quad(cmd.rect, null, cmd.material.color) geom.indices = geometry.make_quad_indices(1) geom.num_indices = 6 // Use white_pixel as the texture so the color modulation works - if (!white_pixel[GPU]) { + if (!white_pixel[GPU]) white_pixel[GPU] = get_img_gpu(white_pixel) - } - render_geom(geom, {[GPU]: white_pixel[GPU]}) + var pipeline = get_pipeline_for_material(cmd.material) + render_geom(geom, {[GPU]: white_pixel[GPU]}, pipeline) } var copy_pass @@ -733,6 +760,11 @@ prosperon.create_batch = function create_batch(draw_cmds, done) { var render_pass var render_target + // State tracking for optimization + var current_pipeline = null + var current_camera_blob = null + var buffers_bound = false + for (var cmd of draw_queue) { if (cmd.camera) { if (!cmd.camera.surface && render_target != "swap") { @@ -740,6 +772,9 @@ prosperon.create_batch = function create_batch(draw_cmds, done) { render_pass.end() render_target = "swap" render_pass = render_queue.swapchain_pass(window) + // Reset state tracking when render pass changes + current_pipeline = null + buffers_bound = false } else if (cmd.camera.surface && render_target != cmd.camera.surface) { if (render_pass) render_pass.end() @@ -754,18 +789,11 @@ prosperon.create_batch = function create_batch(draw_cmds, done) { store: "store", }] }) + // Reset state tracking when render pass changes + current_pipeline = null + buffers_bound = false } - render_pass.bind_pipeline(pipey) - render_pass.bind_buffers(0, [ - { buffer: pos_buffer, offset: 0 }, - { buffer: uv_buffer, offset: 0 }, - { buffer: color_buffer, offset: 0 } - ]) - render_pass.bind_index_buffer( - { buffer: index_buffer, offset: 0 }, // the binding itself is in bytes - 16 // 16 = Uint32 indices - ); var vpW, vpH if (render_target == "swap") { @@ -783,10 +811,45 @@ prosperon.create_batch = function create_batch(draw_cmds, done) { height: cmd.camera.viewport.height * vpH }) - cur_cam = make_camera_pblob(cmd.camera) - render_queue.push_vertex_uniform_data(0, cur_cam) + var new_cam_blob = make_camera_pblob(cmd.camera) + // Only update camera uniform if it changed + if (current_camera_blob != new_cam_blob) { + render_queue.push_vertex_uniform_data(0, new_cam_blob) + current_camera_blob = new_cam_blob + } continue } + + // Only bind pipeline if it changed + if (current_pipeline != cmd.pipeline) { + render_pass.bind_pipeline(cmd.pipeline) + current_pipeline = cmd.pipeline + // When pipeline changes, we need to rebind buffers and uniforms + buffers_bound = false + current_camera_blob = null + } + + // Only bind buffers if not already bound or pipeline changed + if (!buffers_bound) { + render_pass.bind_buffers(0, [ + { buffer: pos_buffer, offset: 0 }, + { buffer: uv_buffer, offset: 0 }, + { buffer: color_buffer, offset: 0 } + ]) + + render_pass.bind_index_buffer( + { buffer: index_buffer, offset: 0 }, // the binding itself is in bytes + 16 // 16 = Uint32 indices + ); + buffers_bound = true + } + + // Rebind camera uniform if needed after pipeline change + if (!current_camera_blob && cur_cam) { + render_queue.push_vertex_uniform_data(0, cur_cam) + current_camera_blob = cur_cam + } + // Use texture's sampler if it has one, otherwise use standard sampler var sampler_to_use = std_sampler if (cmd.texture && cmd.texture.sampler_desc) {