diff --git a/prosperon/prosperon.cm b/prosperon/prosperon.cm index 5103309d..fd56fb22 100644 --- a/prosperon/prosperon.cm +++ b/prosperon/prosperon.cm @@ -6,9 +6,42 @@ var video = use('sdl_video') var surface = use('surface') var sdl_gpu = use('sdl_gpu') var io = use('io') +var geometry = use('geometry') var os = use('os') +// suppose your render‐surface is W×H pixels, and +// your camera.viewport = { x:0, y:0, width:1, height:1 }; +// so vpW = W*1, vpH = H*1 + +def vpW = 640 +def vpH = 360 + +// how many world‑units from center to left/right? +// if zoom = 1 means 1 world‑unit == 1 pixel: +def halfW = vpW * 0.5; +def halfH = vpH * 0.5; + +// define your clipping‐volume in camera‑space: +def l = -halfW, r = +halfW; +def b = -halfH, t = +halfH; +def n = 0, f = 1; + +// Metal wants z in [0,1], so we use the “zero‐to‐one” variant: +function makeOrthoMetal(l,r,b,t,n,f){ + return [ + 2/(r-l), 0, 0, 0, + 0, 2/(t-b), 0, 0, + 0, 0, 1/(f-n), 0, + -(r+l)/(r-l), -(t+b)/(t-b), -n/(f-n), 1 + ] +} + +def P = makeOrthoMetal(l,r,b,t,n,f); + +var Pblob = geometry.array_blob(P) +log.console(Pblob.length) + var driver = "vulkan" switch(os.platform()) { case "Linux": @@ -63,7 +96,7 @@ var default_window = { // Basic properties title: "Prosperon Window", width: 640, - height: 480, + height: 360, // Position - can be numbers or "centered" x: null, // SDL_WINDOWPOS_null by default @@ -122,6 +155,7 @@ var device = new sdl_gpu.gpu({ }) device.claim_window(window) device.set_swapchain(window, 'sdr', 'vsync') + var shader_type = device.shader_format()[0] shader_type = 'msl' var std_sampler = new sdl_gpu.sampler(device, default_sampler) @@ -130,6 +164,25 @@ var std_sampler = new sdl_gpu.sampler(device, default_sampler) var shader_cache = {} var pipeline_cache = {} +function upload(copypass, buffer, toblob) +{ + var trans = new sdl_gpu.transfer_buffer(device, { + size: toblob.length/8, + usage:"upload" + }) + + trans.copy_blob(device, toblob) + + copypass.upload_to_buffer({ + transfer_buffer: trans, + offset:0 + }, { + buffer: buffer, + offset: 0, + size: toblob.length/8 + }) +} + function make_shader(sh_file) { var file = `shaders/${shader_type}/${sh_file}.${shader_type}` @@ -147,210 +200,26 @@ function make_shader(sh_file) entrypoint: shader_type == "msl" ? "main0" : "main" } - shader.gpu = context.make_shader(shader) + shader.gpu = new sdl_gpu.shader(device, shader) shader.reflection = refl; shader_cache[file] = shader shader.file = sh_file return shader } -function load_shader(vert, frag, pipeline_config) { - // Default to sprite pipeline config if not provided - pipeline_config = pipeline_config || sprite_pipeline_config - - // Check cache first - var cache_key = `${vert}:${frag}:${json.encode(pipeline_config)}` - if (pipeline_cache[cache_key]) - return pipeline_cache[cache_key] - - // Load shader reflections - var vert_reflection = load_shader_reflection(vert, 'vert') - var frag_reflection = load_shader_reflection(frag, 'frag') - - if (!vert_reflection || !frag_reflection) - return null - - // Load shaders based on platform - var vert_path = `accio/shaders/${shader_type}/${vert}.vert.${shader_type}` - var frag_path = `accio/shaders/${shader_type}/${frag}.frag.${shader_type}` - - if (!io.exists(vert_path) || !io.exists(frag_path)) { - log.error(`Shaders not found: ${vert_path}, ${frag_path}`) - return null - } - - var vert_code = io.slurpbytes(vert_path) - var frag_code = io.slurpbytes(frag_path) - - // Extract shader info from reflection - var vert_shader_info = { - stage: "vertex", - code: vert_code, - entrypoint: "main0", - format: shader_type, - num_samplers: 0, - num_textures: 0, - num_storage_buffers: 0, - num_uniform_buffers: 0 - } - - log.console(json.encode(vert_reflection)) - - // Count fragment shader resources - var num_samplers = 0 - var num_textures = 0 - - if (frag_reflection.separate_images) - num_textures = frag_reflection.separate_images.length - if (frag_reflection.separate_samplers) - num_samplers = frag_reflection.separate_samplers.length - - var frag_shader_info = { - stage: "fragment", - code: frag_code, - entrypoint: "main0", - format: shader_type, - num_samplers: num_samplers, - num_textures: num_textures, - num_storage_buffers: 0, - num_uniform_buffers: 0 - } - - // Check shader cache - var vert_cache_key = `${vert}:vert` - var frag_cache_key = `${frag}:frag` - - var vert_shader = shader_cache[vert_cache_key] - if (!vert_shader) { - log.console(json.encode(vert_shader_info)) - vert_shader = new sdl_gpu.shader(device, vert_shader_info) - if (!vert_shader) { - log.error(`Failed to create vertex shader: ${vert}`) - return null - } - shader_cache[vert_cache_key] = vert_shader - } - - var frag_shader = shader_cache[frag_cache_key] - if (!frag_shader) { - frag_shader = new sdl_gpu.shader(device, frag_shader_info) - if (!frag_shader) { - log.error(`Failed to create fragment shader: ${frag}`) - return null - } - shader_cache[frag_cache_key] = frag_shader - } - - // Create graphics pipeline using composition - var pipeline_info = create_pipeline_config({ - vertex: vert_shader, - fragment: frag_shader, - blend: pipeline_config.blend, - target: pipeline_config.target, - label: pipeline_config.label - }) - - // Ensure target is properly set - if (!pipeline_info.target || !pipeline_info.target.color_targets) { - log.error("Pipeline target configuration is missing or invalid") - log.console("pipeline_config:", json.encode(pipeline_config)) - return null - } - - // Set up vertex input layout based on reflection - var vertex_stride = 0 - var vertex_attributes = [] - - // Build vertex attributes from reflection - if (vert_reflection.inputs) { - // Add attributes from reflection - for (var input of vert_reflection.inputs) { - var format = "float2" // default - var size = 8 - - if (input.type == "vec2") { - format = "float2" - size = 8 - } else if (input.type == "vec4") { - format = "float4" - size = 16 - } - - vertex_attributes.push({ - location: input.location, - buffer_slot: 0, - format: format, - offset: vertex_stride - }) - vertex_stride += size - } - } - - pipeline_info.vertex_buffer_descriptions = [{ - slot: 0, - pitch: vertex_stride, - input_rate: "vertex", - instance_step_rate: 0 - }] - - pipeline_info.vertex_attributes = vertex_attributes - - log.console("Creating pipeline with info:") - log.console(json.encode(pipeline_info)) - log.console("Target info:") - log.console(json.encode(pipeline_info.target)) - log.console("Has color_targets?", pipeline_info.target.color_targets ? "yes" : "no") - - var pipeline = new sdl_gpu.graphics_pipeline(device, pipeline_info) - if (!pipeline) { - log.error(`Failed to create graphics pipeline for ${vert}/${frag}`) - return null - } - - // Cache the pipeline - pipeline_cache[cache_key] = pipeline - - return pipeline -} - -// Load default sprite shaders -var sprite_gpu_pipeline = load_shader('sprite', 'sprite') - -// Public function to get shader pipelines -prosperon.get_shader_pipeline = function(vert, frag, pipeline_config) { - return load_shader(vert, frag, pipeline_config) -} - -// Export pipeline components for custom configs -prosperon.pipeline = { - depth_states: { - default: default_depth_state, - depth_test: { - compare: "less", - test: true, - write: true, - bias: 0, - bias_slope_scale: 0, - bias_clamp: 0 - } - }, - blend_states: { - disabled: disabled_blend_state, - alpha: alpha_blend_state, - additive: { - enabled: true, - src_rgb: "src_alpha", - dst_rgb: "one", - op_rgb: "add", - src_alpha: "one", - dst_alpha: "one", - op_alpha: "add" - } - }, - stencil_states: { - default: default_stencil_state - }, - create_config: create_pipeline_config +var usepipe +function load_pipeline(config) +{ + log.console(usepipe) + if (usepipe) return usepipe + config.vertex = make_shader(config.vertex).gpu + config.fragment = make_shader(config.fragment).gpu + log.console(json.encode(config)) + log.console("ANOTHER NEW PIPELINE") + log.console(config) + usepipe = new sdl_gpu.graphics_pipeline(device, config) + log.console(usepipe) + return usepipe } // Initialize ImGui with the window and renderer @@ -361,7 +230,7 @@ var io = use('io'); var rasterize = use('rasterize'); var time = use('time') var tilemap = use('tilemap') -var geometry = use('geometry') + var res = use('resources') var input = use('input') @@ -452,83 +321,6 @@ function create_pipeline_config(options) { return config } -// Sprite pipeline configuration -var sprite_pipeline_config = { - blend: alpha_blend_state, - target: { - color_targets: [{ - format: "rgba8", - blend: alpha_blend_state - }], - depth: "d32 float s8" // C code expects "depth" not "depth_stencil_format" - }, - label: "sprite pipeline" -} - -function updateCameraMatrix(cam) { - def win_w = logical.width - def win_h = logical.height - def view_w = (cam.size?.[0] ?? win_w) / cam.zoom - def view_h = (cam.size?.[1] ?? win_h) / cam.zoom - - def ox = cam.pos[0] - view_w * (cam.anchor?.[0] ?? 0) - def oy = cam.pos[1] - view_h * (cam.anchor?.[1] ?? 0) - - def vx = (cam.viewport?.x ?? 0) * win_w - def vy = (cam.viewport?.y ?? 0) * win_h - def vw = (cam.viewport?.width ?? 1) * win_w - def vh = (cam.viewport?.height ?? 1) * win_h - - def sx = vw / view_w - def sy = vh / view_h // flip-Y later - - /* affine matrix that SDL wants (Y going down) */ - cam.a = sx - cam.c = vx - sx * ox - cam.e = -sy // <-- minus = flip Y - cam.f = vy + vh + sy * oy - - /* convenience inverses */ - cam.ia = 1 / cam.a - cam.ic = -cam.c / cam.a - cam.ie = 1 / cam.e - cam.if = -cam.f / cam.e - - camera = cam -} - -//---- forward transform ---- -function worldToScreenPoint([x,y], camera) { - return { - x: camera.a * x + camera.c, - y: camera.e * y + camera.f - }; -} - -//---- inverse transform ---- -function screenToWorldPoint(pos, camera) { - return { - x: camera.ia * pos[0] + camera.ic, - y: camera.ie * pos[1] + camera.if - }; -} - -//---- rectangle (two corner) ---- -function worldToScreenRect({x,y,width,height}, camera) { - // map bottom-left and top-right - def x1 = camera.a * x + camera.c; - def y1 = camera.e * y + camera.f; - def x2 = camera.a * (x + width) + camera.c; - def y2 = camera.e * (y + height) + camera.f; - - return { - x:Math.min(x1,x2), - y:Math.min(y1,y2), - width:Math.abs(x2-x1), - height:Math.abs(y2-y1) - } -} - var gameactor var images = {} @@ -632,94 +424,121 @@ prosperon.input = function(fn) poll_input() } +var sprite_pipeline = { + vertex: "sprite.vert", + fragment: "sprite.frag", + cull: "none", + target: { + color_targets: [ + {format: device.swapchain_format(window), blend:disabled_blend_state} + ], + }, + vertex_buffer_descriptions: [ { slot:0, input_rate: "vertex", instance_step_rate: 0, + pitch: 8}, + {slot:1, input_rate:"vertex", instance_step_rate: 0, pitch: 8}, + {slot:2, input_rate:"vertex", instance_step_rate: 0, pitch: 16} + ], + vertex_attributes: [ + { location: 0, buffer_slot: 0, format: "float2", offset: 0}, + { location: 1, buffer_slot: 1, format: "float2", offset: 0}, + { location: 2, buffer_slot: 2, format: "float4", offset: 0} + ], + primitive: "triangle", + blend: alpha_blend_state +} + +var pipey = load_pipeline(sprite_pipeline) + prosperon.create_batch = function create_batch(draw_cmds, done) { - var cmd_buffer = device.acquire_cmd_buffer() - var swapchain_texture = cmd_buffer.acquire_swapchain(window) - var img = graphics.texture("pockle") - var gpu_tex = get_img_gpu(img) - var geom = geometry.sprites_to_data([{ - pos: {x: 0, y: 0}, - texture: img, - color: {r:1,g:1,b:1,a:1} - }]) + var pipeline = pipey - device.upload(cmd_buffer, [geom]) + var geom = geometry.make_rect_quad({x:-320,y:-180,width:640,height:360}) + geom.indices = geometry.make_quad_indices(1) - var pass = cmd_buffer.render_pass({ - color_targets: [{ - texture: swapchain_texture, - clear_color: {r:0.1, g:0.1, b:0.15, a:1}, - load_op: "clear", - store_op: "store" - }] + var cmd_buffer = device.acquire_cmd_buffer() + + cmd_buffer.push_vertex_uniform_data(0, Pblob) + + var pos_buffer = new sdl_gpu.buffer(device, { + vertex: true, + size: geom.xy.length/8 }) + var uv_buffer = new sdl_gpu.buffer(device, { + vertex: true, + size: geom.uv.length/8 + }) + var color_buffer = new sdl_gpu.buffer(device, { + vertex: true, + size: geom.color.length/8 + }) - if (!swapchain_texture) { - cmd_buffer.cancel() - } else { + var index_buffer = new sdl_gpu.buffer(device, { + index: true, + size: geom.indices.length/8 + }) + + var cpy_pass = cmd_buffer.copy_pass() + + upload(cpy_pass, pos_buffer, geom.xy) + upload(cpy_pass, uv_buffer, geom.uv) + upload(cpy_pass, color_buffer, geom.color) + upload(cpy_pass, index_buffer, geom.indices) + + if (!img.gpu) { + img.gpu = new sdl_gpu.texture(device, { + width: img.width, + height: img.height, + layers: 1, + mip_levels: 1, + samples: 0, + type: "2d", + format: "rgba8", + sampler: true, + }) + + var tbuf = new sdl_gpu.transfer_buffer(device, { + size: img.cpu.pixels.length/8, + usage: "upload" + }) + + tbuf.copy_blob(device, img.cpu.pixels) + + cpy_pass.upload_to_texture({ + transfer_buffer: tbuf, + offset: 0, + pixels_per_row: img.cpu.width, + rows_per_lay: img.cpu.height, + }, { + texture: img.gpu, + mip_level: 0, + layer: 0, + x: 0, y: 0, z: 0, + w: img.cpu.width, + h: img.cpu.height, + d: 1 + }, false); } - // Begin render pass - var render_pass = cmd_buffer.render_pass({ - color_targets: [{ - texture: swapchain_texture, - clear_color: {r: 0.1, g: 0.1, b: 0.15, a: 1.0}, - load_op: "clear", - store_op: "store" - }] - }) + cpy_pass.end() + + var pass = cmd_buffer.swapchain_pass(window) - render_pass.bind_pipeline(sprite_gpu_pipeline) - - // Set viewport - render_pass.viewport({ + pass.viewport({ x: 0, y: 0, - w: logical.width, - h: logical.height + width: 640, + height: 360 }) - // Process draw_image commands - for (var cmd of draw_cmds) { - if (cmd.cmd != "draw_image") continue - - var img = graphics.texture(cmd.image) - var gpu_tex = get_img_gpu(img) - - if (!gpu_tex) continue - - // Set up sprite dimensions - cmd.rect.width ??= img.width - cmd.rect.height ??= img.height - cmd.rect.width = cmd.rect.width * (cmd.scale?.x ?? 1) - cmd.rect.height = cmd.rect.height * (cmd.scale?.y ?? 1) - cmd.rect = worldToScreenRect(cmd.rect, camera) - - var geom = geometry.sprites_to_data([{ - pos: {x: cmd.rect.x, y: cmd.rect.y}, - texture: img, - color: {r:1,g:1,b:1,a:1} - }]) - - log.console(json.encode(geom)) - - render_pass.bind_buffers(0, [geom], device) - - // Bind texture and sampler - render_pass.bind_samplers(false, 0, [{ - texture: gpu_tex, - sampler: std_sampler - }]) - - // Draw the sprite - log.console("DRWA INDEX") - render_pass.draw(geom.num_vertices, 1, 0, 0, 0) // 6 vertices, 1 instance - log.console("DREW") - } + pass.bind_pipeline(pipeline) + pass.bind_buffers(0, [{buffer:pos_buffer,offset:0}, {buffer:uv_buffer, offset:0}, {buffer:color_buffer, offset:0}]) + pass.bind_index_buffer({buffer:index_buffer,offset:0}, 16) + pass.bind_samplers(false, 0, [{texture:img.gpu, sampler:std_sampler}]) + pass.draw_indexed(6, 1, 0, 0, 0) - render_pass.end() + pass.end() cmd_buffer.submit() if (done) done() diff --git a/source/cell.c b/source/cell.c index 70cd2613..8ae2d85e 100644 --- a/source/cell.c +++ b/source/cell.c @@ -153,8 +153,6 @@ void actor_free(cell_rt *actor) JS_FreeAtom(js, actor->actor_sym); SDL_RemoveTimer(actor->ar); - for (int i = 0; i < arrlen(actor->js_swapchains); i++) - JS_FreeValue(js, actor->js_swapchains[i]); /* Free timer callbacks stored in actor */ for (int i = 0; i < hmlen(actor->timers); i++) { @@ -162,7 +160,6 @@ void actor_free(cell_rt *actor) } hmfree(actor->timers); - arrfree(actor->js_swapchains); arrfree(actor->module_registry); /* Free all letters in the queue */ diff --git a/source/cell.h b/source/cell.h index 029bc08a..017b0426 100644 --- a/source/cell.h +++ b/source/cell.h @@ -65,7 +65,6 @@ mi_heap_t *heap; void *init_wota; ModuleEntry *module_registry; - JSValue *js_swapchains; /* Protects JSContext usage */ SDL_Mutex *mutex; /* for everything else */ diff --git a/source/jsffi.c b/source/jsffi.c index 55c591f1..72964fd0 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -1436,34 +1436,6 @@ JSC_CCALL(os_power_state, return JS_NULL; ) -JSC_CCALL(os_cull_sprites, - ret = JS_NewArray(js); - int n = 0; - - JSValue sprites = argv[0]; - shader_globals info = {0}; // TODO: get this as a JS object - rect camera_rect = {0}; - camera_rect.x = info.camera_pos_world.x - info.render_size.x/2.0; - camera_rect.y = info.camera_pos_world.y - info.render_size.y/2.0; - camera_rect.w = info.render_size.x; - camera_rect.h = info.render_size.y; - - int len = JS_ArrayLength(js,sprites); - - for (int i = 0; i < len; i++) { - JSValue sub = JS_GetPropertyUint32(js,sprites,i); - transform *t; - JS_GETATOM(js,t,sub,transform,transform) - - rect sprite = transform2rect(t); - if (SDL_HasRectIntersectionFloat(&sprite, &camera_rect)) { - JS_SetPropertyUint32(js,ret,n,JS_DupValue(js,sub)); - n++; - } - JS_FreeValue(js,sub); - } -) - static const JSCFunctionListEntry js_util_funcs[] = { MIST_FUNC_DEF(os, guid, 0), MIST_FUNC_DEF(os, insertion_sort, 2), @@ -1524,7 +1496,6 @@ static const JSCFunctionListEntry js_graphics_funcs[] = { MIST_FUNC_DEF(os, make_texture, 1), MIST_FUNC_DEF(os, make_gif, 1), MIST_FUNC_DEF(os, make_aseprite, 1), - MIST_FUNC_DEF(os, cull_sprites, 2), MIST_FUNC_DEF(os, make_font, 2), MIST_FUNC_DEF(os, make_line_prim, 5), MIST_FUNC_DEF(graphics, hsl_to_rgb, 3), diff --git a/source/jsffi.h b/source/jsffi.h index 5ff80669..360f0ba7 100644 --- a/source/jsffi.h +++ b/source/jsffi.h @@ -56,24 +56,6 @@ struct lrtb { typedef struct lrtb lrtb; typedef struct text_vert text_vert; -// Shader globals structure for camera transformations -#pragma pack(push, 1) -typedef struct shader_globals { - HMM_Mat4 world_to_projection; - HMM_Mat4 projection_to_world; - HMM_Mat4 world_to_view; - HMM_Mat4 view_to_projection; - HMM_Vec3 camera_pos_world; - HMM_Vec3 camera_dir_world; - float viewport_min_z; - float viewport_max_z; - HMM_Vec2 viewport_size; - HMM_Vec2 viewport_offset; - HMM_Vec2 render_size; - float time; -} shader_globals; -#pragma pack(pop) - // Common macros for property access #define JS_GETPROP(JS, TARGET, VALUE, PROP, TYPE) {\ JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#PROP); \ diff --git a/source/qjs_geometry.c b/source/qjs_geometry.c index 5aa26300..8d52eba0 100644 --- a/source/qjs_geometry.c +++ b/source/qjs_geometry.c @@ -971,6 +971,34 @@ JSC_CCALL(geometry_tilemap_to_data, free(index_data); ) +static void print_buffers(float *xy_data, float *uv_data, SDL_FColor *color_data, uint16_t *index_data, int vertex_count, int index_count) +{ + printf("=== GEOMETRY BUFFERS ===\n"); + + printf("XY Data (%d vertices):\n", vertex_count); + for (int i = 0; i < vertex_count; i++) { + printf(" Vertex %d: x=%.2f, y=%.2f\n", i, xy_data[i*2], xy_data[i*2+1]); + } + + printf("\nUV Data:\n"); + for (int i = 0; i < vertex_count; i++) { + printf(" Vertex %d: u=%.4f, v=%.4f\n", i, uv_data[i*2], uv_data[i*2+1]); + } + + printf("\nColor Data:\n"); + for (int i = 0; i < vertex_count; i++) { + printf(" Vertex %d: r=%.2f, g=%.2f, b=%.2f, a=%.2f\n", + i, color_data[i].r, color_data[i].g, color_data[i].b, color_data[i].a); + } + + printf("\nIndex Data (%d indices):\n", index_count); + for (int i = 0; i < index_count; i += 3) { + printf(" Triangle %d: %d, %d, %d\n", i/3, index_data[i], index_data[i+1], index_data[i+2]); + } + + printf("========================\n"); +} + JSC_CCALL(geometry_sprites_to_data, JSValue sprites_array = argv[0]; if (!JS_IsArray(js, sprites_array)) { @@ -1318,6 +1346,108 @@ JSC_CCALL(geometry_renderitem_clear, return JS_NULL; ) +JSC_CCALL(geometry_array_blob, + JSValue arr = argv[0]; + size_t len = JS_ArrayLength(js,arr); + float data[len]; + for (int i = 0; i < len; i++) { + JSValue val = JS_GetPropertyUint32(js,arr,i); + data[i] = js2number(js, val); + JS_FreeValue(js,val); + } + + return js_new_blob_stoned_copy(js, data, sizeof(float)*len); +) + +JSC_CCALL(geometry_make_quad_indices, + int quads; + if (JS_ToInt32(js, &quads, argv[0]) < 0) { + return JS_ThrowTypeError(js, "quads must be a number"); + } + + if (quads < 0) { + return JS_ThrowTypeError(js, "quads must be >= 0"); + } + + int index_count = quads * 6; + uint16_t *index_data = malloc(index_count * sizeof(uint16_t)); + + int index_idx = 0; + for (int i = 0; i < quads; i++) { + uint16_t base_idx = i * 4; + index_data[index_idx++] = base_idx + 0; + index_data[index_idx++] = base_idx + 1; + index_data[index_idx++] = base_idx + 2; + index_data[index_idx++] = base_idx + 1; + index_data[index_idx++] = base_idx + 3; + index_data[index_idx++] = base_idx + 2; + } + + JSValue result = js_new_blob_stoned_copy(js, index_data, index_count * sizeof(uint16_t)); + free(index_data); + return result; +) + +JSC_CCALL(geometry_make_rect_quad, + rect r = js2rect(js, argv[0]); + + // Optional UV rect (default to 0,0,1,1) + rect uv = {0, 0, 1, 1}; + if (argc > 1 && !JS_IsNull(argv[1])) { + uv = js2rect(js, argv[1]); + } + + // Optional color (default to white) + SDL_FColor color = {1.0f, 1.0f, 1.0f, 1.0f}; + if (argc > 2 && !JS_IsNull(argv[2])) { + HMM_Vec4 c = js2color(js, argv[2]); + color.r = c.r; + color.g = c.g; + color.b = c.b; + color.a = c.a; + } + + // Allocate buffers for 1 quad (4 vertices) + int vertex_count = 4; + int index_count = 6; + + float xy_data[vertex_count*2]; + float uv_data[vertex_count*2]; + SDL_FColor color_data[vertex_count]; + + // Set vertex positions (4 corners) + xy_data[0] = r.x; xy_data[1] = r.y; // bottom-left + xy_data[2] = r.x + r.w; xy_data[3] = r.y; // bottom-right + xy_data[4] = r.x; xy_data[5] = r.y + r.h; // top-left + xy_data[6] = r.x + r.w; xy_data[7] = r.y + r.h; // top-right + + // Set UV coordinates + uv_data[0] = uv.x; uv_data[1] = uv.y + uv.h; // bottom-left + uv_data[2] = uv.x + uv.w; uv_data[3] = uv.y + uv.h; // bottom-right + uv_data[4] = uv.x; uv_data[5] = uv.y; // top-left + uv_data[6] = uv.x + uv.w; uv_data[7] = uv.y; // top-right + + // Set colors + for (int i = 0; i < 4; i++) { + color_data[i] = color; + } + + // Create result object + ret = JS_NewObject(js); + + JSValue xy_blob = js_new_blob_stoned_copy(js, xy_data, vertex_count * 2 * sizeof(float)); + JSValue uv_blob = js_new_blob_stoned_copy(js, uv_data, vertex_count * 2 * sizeof(float)); + JSValue color_blob = js_new_blob_stoned_copy(js, color_data, vertex_count * sizeof(SDL_FColor)); + + JS_SetPropertyStr(js, ret, "xy", xy_blob); + JS_SetPropertyStr(js, ret, "xy_stride", JS_NewInt32(js, 2 * sizeof(float))); + JS_SetPropertyStr(js, ret, "uv", uv_blob); + JS_SetPropertyStr(js, ret, "uv_stride", JS_NewInt32(js, 2 * sizeof(float))); + JS_SetPropertyStr(js, ret, "color", color_blob); + JS_SetPropertyStr(js, ret, "color_stride", JS_NewInt32(js, sizeof(SDL_FColor))); + JS_SetPropertyStr(js, ret, "num_vertices", JS_NewInt32(js, vertex_count)); +) + static const JSCFunctionListEntry js_geometry_funcs[] = { MIST_FUNC_DEF(geometry, rect_intersection, 2), MIST_FUNC_DEF(geometry, rect_intersects, 2), @@ -1339,6 +1469,9 @@ static const JSCFunctionListEntry js_geometry_funcs[] = { MIST_FUNC_DEF(geometry, renderitem_push, 3), MIST_FUNC_DEF(geometry, renderitem_sort, 0), MIST_FUNC_DEF(geometry, renderitem_clear, 0), + MIST_FUNC_DEF(geometry, array_blob, 2), + MIST_FUNC_DEF(geometry, make_quad_indices, 1), + MIST_FUNC_DEF(geometry, make_rect_quad, 3), }; JSValue js_geometry_use(JSContext *js) { diff --git a/source/qjs_sdl_gpu.c b/source/qjs_sdl_gpu.c index 7ee86a39..666aadf9 100644 --- a/source/qjs_sdl_gpu.c +++ b/source/qjs_sdl_gpu.c @@ -10,39 +10,36 @@ #include "cell.h" // Macro for GPU wrapper classes that need cleanup -#define QJSCLASSGPUWRAPPER(WRAPPERTYPE, SDLTYPE, MEMBER) \ -JSClassID js_##SDLTYPE##_id; \ -static void js_##SDLTYPE##_finalizer(JSRuntime *rt, JSValue val) { \ - WRAPPERTYPE *wrapper = JS_GetOpaque(val, js_##SDLTYPE##_id); \ - SDLTYPE##_free(rt, wrapper); \ +#define QJSCLASSGPUWRAPPER(WRAPPERTYPE, SDLTYPE) \ +typedef struct { \ + SDL_GPUDevice *device; \ + SDL_##SDLTYPE *type; \ +} WRAPPERTYPE; \ +JSClassID js_SDL_##SDLTYPE##_id; \ +static void js_SDL_##SDLTYPE##_finalizer(JSRuntime *rt, JSValue val) { \ + WRAPPERTYPE *wrapper = JS_GetOpaque(val, js_SDL_##SDLTYPE##_id); \ + if (wrapper && wrapper->device && wrapper->type) \ + SDL_Release##SDLTYPE(wrapper->device, wrapper->type); \ + free(wrapper); \ } \ -static JSClassDef js_##SDLTYPE##_class = { \ +static JSClassDef js_SDL_##SDLTYPE##_class = { \ .class_name = #SDLTYPE, \ - .finalizer = js_##SDLTYPE##_finalizer, \ + .finalizer = js_SDL_##SDLTYPE##_finalizer, \ }; \ -SDLTYPE *js2##SDLTYPE(JSContext *js, JSValue val) { \ - if (JS_GetClassID(val) != js_##SDLTYPE##_id) return NULL; \ - WRAPPERTYPE *wrapper = JS_GetOpaque(val, js_##SDLTYPE##_id); \ - return wrapper ? wrapper->MEMBER : NULL; \ +SDL_##SDLTYPE *js2SDL_##SDLTYPE(JSContext *js, JSValue val) { \ + if (JS_GetClassID(val) != js_SDL_##SDLTYPE##_id) return NULL; \ + WRAPPERTYPE *wrapper = JS_GetOpaque(val, js_SDL_##SDLTYPE##_id); \ + return wrapper ? wrapper->type : NULL; \ } \ -JSValue SDLTYPE##2js(JSContext *js, WRAPPERTYPE *wrapper) { \ - JSValue j = JS_NewObjectClass(js, js_##SDLTYPE##_id); \ +JSValue SDL_##SDLTYPE##2js(JSContext *js, SDL_GPUDevice *device, SDL_##SDLTYPE *member) { \ + WRAPPERTYPE *wrapper = malloc(sizeof(WRAPPERTYPE)); \ + wrapper->device = device; \ + wrapper->type = member; \ + JSValue j = JS_NewObjectClass(js, js_SDL_##SDLTYPE##_id); \ JS_SetOpaque(j, wrapper); \ return j; \ } -#include "stb_dxt.h" - -// Include additional headers -#include "font.h" - -// Type array constants -#define JS_TYPED_ARRAY_FLOAT32 0 -#define JS_TYPED_ARRAY_UINT16 1 -#define JS_TYPED_ARRAY_UINT32 2 - -// External function declarations -extern SDL_Surface *js2SDL_Surface(JSContext *js, JSValue v); extern double js2number(JSContext *js, JSValue v); extern int JS_GETBOOL(JSContext *js, JSValue obj, const char *prop); extern double js_getnum_str(JSContext *js, JSValue obj, const char *str); @@ -53,198 +50,18 @@ const char *js2cstring(JSContext *js, JSValue v) return JS_ToCString(js, v); } -// Global GPU device and window removed - now passed as parameters - -// Wrapper structures that hold GPU device reference for proper cleanup -typedef struct { - SDL_GPUDevice *device; - SDL_GPUBuffer *buffer; -} gpu_buffer_wrapper; - -typedef struct { - SDL_GPUDevice *device; - SDL_GPUComputePipeline *pipeline; -} gpu_compute_pipeline_wrapper; - -typedef struct { - SDL_GPUDevice *device; - SDL_GPUGraphicsPipeline *pipeline; -} gpu_graphics_pipeline_wrapper; - -typedef struct { - SDL_GPUDevice *device; - SDL_GPUSampler *sampler; -} gpu_sampler_wrapper; - -typedef struct { - SDL_GPUDevice *device; - SDL_GPUShader *shader; -} gpu_shader_wrapper; - -typedef struct { - SDL_GPUDevice *device; - SDL_GPUTexture *texture; -} gpu_texture_wrapper; - -typedef struct { - SDL_GPUDevice *device; - SDL_GPUTransferBuffer *buffer; -} gpu_transfer_buffer_wrapper; - -typedef struct { - SDL_GPUDevice *device; - SDL_GPUFence *fence; -} gpu_fence_wrapper; - -typedef struct { - SDL_GPUDevice *device; - SDL_GPUCommandBuffer *command_buffer; -} gpu_command_buffer_wrapper; - // GPU Free functions void SDL_GPUDevice_free(JSRuntime *rt, SDL_GPUDevice *d) { SDL_DestroyGPUDevice(d); } -void SDL_GPUBuffer_free(JSRuntime *rt, gpu_buffer_wrapper *w) +void SDL_GPUCommandBuffer_free(JSRuntime *rt, void *w) { - if (w && w->device && w->buffer) { - SDL_ReleaseGPUBuffer(w->device, w->buffer); - } - free(w); } -void SDL_GPUTexture_free(JSRuntime *rt, gpu_texture_wrapper *w) +void gpu_command_buffer_wrapper_free(JSRuntime *rt, void *w) { - if (w && w->device && w->texture) { - SDL_ReleaseGPUTexture(w->device, w->texture); - } - free(w); -} - -void SDL_GPUTransferBuffer_free(JSRuntime *rt, gpu_transfer_buffer_wrapper *w) -{ - if (w && w->device && w->buffer) { - SDL_ReleaseGPUTransferBuffer(w->device, w->buffer); - } - free(w); -} - -void SDL_GPUSampler_free(JSRuntime *rt, gpu_sampler_wrapper *w) -{ - if (w && w->device && w->sampler) { - SDL_ReleaseGPUSampler(w->device, w->sampler); - } - free(w); -} - -void SDL_GPUShader_free(JSRuntime *rt, gpu_shader_wrapper *w) -{ - if (w && w->device && w->shader) { - SDL_ReleaseGPUShader(w->device, w->shader); - } - free(w); -} - -void SDL_GPUGraphicsPipeline_free(JSRuntime *rt, gpu_graphics_pipeline_wrapper *w) -{ - if (w && w->device && w->pipeline) { - SDL_ReleaseGPUGraphicsPipeline(w->device, w->pipeline); - } - free(w); -} - -void SDL_GPUComputePipeline_free(JSRuntime *rt, gpu_compute_pipeline_wrapper *w) -{ - if (w && w->device && w->pipeline) { - SDL_ReleaseGPUComputePipeline(w->device, w->pipeline); - } - free(w); -} - -void SDL_GPUFence_free(JSRuntime *rt, gpu_fence_wrapper *w) -{ - if (w && w->device && w->fence) { - SDL_ReleaseGPUFence(w->device, w->fence); - } - free(w); -} - -void SDL_GPUCommandBuffer_free(JSRuntime *rt, gpu_command_buffer_wrapper *w) -{ - // Command buffers are typically managed by SDL, no explicit release needed - free(w); -} - -// Wrapper free functions that use the device reference for proper cleanup -void gpu_buffer_wrapper_free(JSRuntime *rt, gpu_buffer_wrapper *w) -{ - if (w && w->device && w->buffer) { - SDL_ReleaseGPUBuffer(w->device, w->buffer); - } - free(w); -} - -void gpu_compute_pipeline_wrapper_free(JSRuntime *rt, gpu_compute_pipeline_wrapper *w) -{ - if (w && w->device && w->pipeline) { - SDL_ReleaseGPUComputePipeline(w->device, w->pipeline); - } - free(w); -} - -void gpu_graphics_pipeline_wrapper_free(JSRuntime *rt, gpu_graphics_pipeline_wrapper *w) -{ - if (w && w->device && w->pipeline) { - SDL_ReleaseGPUGraphicsPipeline(w->device, w->pipeline); - } - free(w); -} - -void gpu_sampler_wrapper_free(JSRuntime *rt, gpu_sampler_wrapper *w) -{ - if (w && w->device && w->sampler) { - SDL_ReleaseGPUSampler(w->device, w->sampler); - } - free(w); -} - -void gpu_shader_wrapper_free(JSRuntime *rt, gpu_shader_wrapper *w) -{ - if (w && w->device && w->shader) { - SDL_ReleaseGPUShader(w->device, w->shader); - } - free(w); -} - -void gpu_texture_wrapper_free(JSRuntime *rt, gpu_texture_wrapper *w) -{ - if (w && w->device && w->texture) { - SDL_ReleaseGPUTexture(w->device, w->texture); - } - free(w); -} - -void gpu_transfer_buffer_wrapper_free(JSRuntime *rt, gpu_transfer_buffer_wrapper *w) -{ - if (w && w->device && w->buffer) { - SDL_ReleaseGPUTransferBuffer(w->device, w->buffer); - } - free(w); -} - -void gpu_fence_wrapper_free(JSRuntime *rt, gpu_fence_wrapper *w) -{ - if (w && w->device && w->fence) { - SDL_ReleaseGPUFence(w->device, w->fence); - } - free(w); -} - -void gpu_command_buffer_wrapper_free(JSRuntime *rt, gpu_command_buffer_wrapper *w) -{ - free(w); } // Moved to jsffi.c - extern declaration @@ -253,124 +70,21 @@ void SDL_GPUComputePass_free(JSRuntime *rt, SDL_GPUComputePass *c) { } void SDL_GPUCopyPass_free(JSRuntime *rt, SDL_GPUCopyPass *c) { } void SDL_GPURenderPass_free(JSRuntime *rt, SDL_GPURenderPass *c) { } - // GPU Class definitions QJSCLASS(SDL_GPUDevice,) -QJSCLASSGPUWRAPPER(gpu_buffer_wrapper, SDL_GPUBuffer, buffer) -QJSCLASSGPUWRAPPER(gpu_compute_pipeline_wrapper, SDL_GPUComputePipeline, pipeline) -QJSCLASSGPUWRAPPER(gpu_graphics_pipeline_wrapper, SDL_GPUGraphicsPipeline, pipeline) -QJSCLASSGPUWRAPPER(gpu_sampler_wrapper, SDL_GPUSampler, sampler) -QJSCLASSGPUWRAPPER(gpu_shader_wrapper, SDL_GPUShader, shader) -QJSCLASSGPUWRAPPER(gpu_texture_wrapper, SDL_GPUTexture, texture) -QJSCLASSGPUWRAPPER(gpu_transfer_buffer_wrapper, SDL_GPUTransferBuffer, buffer) -QJSCLASS(SDL_GPUFence,) -QJSCLASSGPUWRAPPER(gpu_command_buffer_wrapper, SDL_GPUCommandBuffer, command_buffer) +QJSCLASSGPUWRAPPER(gpu_buffer_wrapper, GPUBuffer) +QJSCLASSGPUWRAPPER(gpu_compute_pipeline_wrapper, GPUComputePipeline) +QJSCLASSGPUWRAPPER(gpu_graphics_pipeline_wrapper, GPUGraphicsPipeline) +QJSCLASSGPUWRAPPER(gpu_sampler_wrapper, GPUSampler) +QJSCLASSGPUWRAPPER(gpu_shader_wrapper, GPUShader) +QJSCLASSGPUWRAPPER(gpu_texture_wrapper, GPUTexture) +QJSCLASSGPUWRAPPER(gpu_transfer_buffer_wrapper, GPUTransferBuffer) +QJSCLASSGPUWRAPPER(gpu_fence_wrapper, GPUFence) +QJSCLASS(SDL_GPUCommandBuffer,) QJSCLASS(SDL_GPUComputePass,) QJSCLASS(SDL_GPUCopyPass,) QJSCLASS(SDL_GPURenderPass,) -// Helper functions to create wrapper objects and extract SDL objects -JSValue gpu_buffer_wrapper2js_from_components(JSContext *js, SDL_GPUDevice *device, SDL_GPUBuffer *buffer) -{ - gpu_buffer_wrapper *wrapper = malloc(sizeof(gpu_buffer_wrapper)); - wrapper->device = device; - wrapper->buffer = buffer; - return SDL_GPUBuffer2js(js, wrapper); -} - - -JSValue gpu_texture_wrapper2js_from_components(JSContext *js, SDL_GPUDevice *device, SDL_GPUTexture *texture) -{ - gpu_texture_wrapper *wrapper = malloc(sizeof(gpu_texture_wrapper)); - wrapper->device = device; - wrapper->texture = texture; - return SDL_GPUTexture2js(js, wrapper); -} - - -// Helper functions for sampler -JSValue gpu_sampler_wrapper2js_from_components(JSContext *js, SDL_GPUDevice *device, SDL_GPUSampler *sampler) -{ - gpu_sampler_wrapper *wrapper = malloc(sizeof(gpu_sampler_wrapper)); - wrapper->device = device; - wrapper->sampler = sampler; - return SDL_GPUSampler2js(js, wrapper); -} - - -// Helper functions for shader -JSValue gpu_shader_wrapper2js_from_components(JSContext *js, SDL_GPUDevice *device, SDL_GPUShader *shader) -{ - gpu_shader_wrapper *wrapper = malloc(sizeof(gpu_shader_wrapper)); - wrapper->device = device; - wrapper->shader = shader; - return SDL_GPUShader2js(js, wrapper); -} - - -// Helper functions for graphics pipeline -JSValue gpu_graphics_pipeline_wrapper2js_from_components(JSContext *js, SDL_GPUDevice *device, SDL_GPUGraphicsPipeline *pipeline) -{ - gpu_graphics_pipeline_wrapper *wrapper = malloc(sizeof(gpu_graphics_pipeline_wrapper)); - wrapper->device = device; - wrapper->pipeline = pipeline; - return SDL_GPUGraphicsPipeline2js(js, wrapper); -} - - -// Helper functions for compute pipeline -JSValue gpu_compute_pipeline_wrapper2js_from_components(JSContext *js, SDL_GPUDevice *device, SDL_GPUComputePipeline *pipeline) -{ - gpu_compute_pipeline_wrapper *wrapper = malloc(sizeof(gpu_compute_pipeline_wrapper)); - wrapper->device = device; - wrapper->pipeline = pipeline; - return SDL_GPUComputePipeline2js(js, wrapper); -} - - -// Helper functions for transfer buffer -JSValue gpu_transfer_buffer_wrapper2js_from_components(JSContext *js, SDL_GPUDevice *device, SDL_GPUTransferBuffer *buffer) -{ - gpu_transfer_buffer_wrapper *wrapper = malloc(sizeof(gpu_transfer_buffer_wrapper)); - wrapper->device = device; - wrapper->buffer = buffer; - return SDL_GPUTransferBuffer2js(js, wrapper); -} - - -// Helper functions for fence -JSValue gpu_fence_wrapper2js_from_components(JSContext *js, SDL_GPUDevice *device, SDL_GPUFence *fence) -{ - gpu_fence_wrapper *wrapper = malloc(sizeof(gpu_fence_wrapper)); - wrapper->device = device; - wrapper->fence = fence; - return SDL_GPUFence2js(js, wrapper); -} - - -// Helper functions for command buffer -JSValue gpu_command_buffer_wrapper2js_from_components(JSContext *js, SDL_GPUDevice *device, SDL_GPUCommandBuffer *command_buffer) -{ - gpu_command_buffer_wrapper *wrapper = malloc(sizeof(gpu_command_buffer_wrapper)); - wrapper->device = device; - wrapper->command_buffer = command_buffer; - return SDL_GPUCommandBuffer2js(js, wrapper); -} - -// Override the default js2SDL_GPUCommandBuffer to work with our wrapper - -// Compatibility functions for the old naming scheme -#define SDL_GPUBuffer2js(js, buffer) gpu_buffer_wrapper2js_from_components(js, NULL, buffer) -#define SDL_GPUTexture2js(js, texture) gpu_texture_wrapper2js_from_components(js, NULL, texture) -#define SDL_GPUSampler2js(js, sampler) gpu_sampler_wrapper2js_from_components(js, NULL, sampler) -#define SDL_GPUShader2js(js, shader) gpu_shader_wrapper2js_from_components(js, NULL, shader) -#define SDL_GPUGraphicsPipeline2js(js, pipeline) gpu_graphics_pipeline_wrapper2js_from_components(js, NULL, pipeline) -#define SDL_GPUComputePipeline2js(js, pipeline) gpu_compute_pipeline_wrapper2js_from_components(js, NULL, pipeline) -#define SDL_GPUTransferBuffer2js(js, buffer) gpu_transfer_buffer_wrapper2js_from_components(js, NULL, buffer) -#define SDL_GPUFence2js(js, fence) gpu_fence_wrapper2js_from_components(js, NULL, fence) -#define SDL_GPUCommandBuffer2js(js, command_buffer) gpu_command_buffer_wrapper2js_from_components(js, NULL, command_buffer) - - // GPU type conversion functions SDL_GPUGraphicsPipelineTargetInfo js2SDL_GPUGraphicsPipelineTargetInfo(JSContext *js, JSValue v) { @@ -390,51 +104,47 @@ SDL_GPUSampleCount js2SDL_GPUSampleCount(JSContext *js, JSValue v) return SDL_GPU_SAMPLECOUNT_1; } -#define JS2ENUM(NAME, RETS, VALS) \ +// X-macro enum definition system +#define ENUM_MAPPING_TABLE(ENUM) \ + static const struct { int value; const char *name; } ENUM##_mapping[] + +#define JS2ENUM(NAME) \ int js2##NAME(JSContext *js, JSValue v) { \ - if (JS_IsNull(v)) return 0; \ + if (JS_IsNull(v)) return 0; \ const char *str = JS_ToCString(js, v); \ - int *rets = (RETS); \ - const char **vals = (VALS); \ - /* Compute how many entries are in the arrays */ \ - int n = (int)(sizeof((RETS)) / sizeof((RETS)[0])); \ - for(int i = 0; i < n; i++) \ - if(!strcmp(vals[i], str)) { \ + if (!str) return 0; \ + for(int i = 0; i < sizeof(NAME##_mapping)/sizeof(NAME##_mapping[0]); i++) \ + if(!strcmp(NAME##_mapping[i].name, str)) { \ JS_FreeCString(js, str); \ - return rets[i]; \ + return NAME##_mapping[i].value; \ } \ JS_FreeCString(js, str); \ - return 0; \ + return 0; \ +} \ +JSValue NAME##2js(JSContext *js, int enumval) { \ + for(int i = 0; i < sizeof(NAME##_mapping)/sizeof(NAME##_mapping[0]); i++) \ + if(NAME##_mapping[i].value == enumval) \ + return JS_NewString(js, NAME##_mapping[i].name); \ + return JS_NULL; \ } -// Enum conversion arrays -static int rets_SDL_GPUSwapchainComposition[] = { - SDL_GPU_SWAPCHAINCOMPOSITION_SDR, - SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR, - SDL_GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR, -// SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2084 +// Enum conversion tables using x-macro technique +ENUM_MAPPING_TABLE(SDL_GPUSwapchainComposition) = { + {SDL_GPU_SWAPCHAINCOMPOSITION_SDR, "sdr"}, + {SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR, "linear"}, + {SDL_GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR, "hdr"}, + {SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2084, "hdr10"} }; -static const char *vals_SDL_GPUSwapchainComposition[] = { - "sdr", - "linear", - "hdr", -// "hdr10" +JS2ENUM(SDL_GPUSwapchainComposition) + +ENUM_MAPPING_TABLE(SDL_FlipMode) = { + {SDL_FLIP_NONE, "none"}, + {SDL_FLIP_HORIZONTAL, "horizontal"}, + {SDL_FLIP_VERTICAL, "vertical"} }; -JS2ENUM(SDL_GPUSwapchainComposition, rets_SDL_GPUSwapchainComposition, vals_SDL_GPUSwapchainComposition) - -static int rets_SDL_FlipMode[] = { - SDL_FLIP_NONE, - SDL_FLIP_HORIZONTAL, - SDL_FLIP_VERTICAL -}; - -static const char *vals_SDL_FlipMode[] = { - "none", - "horizontal", - "vertical" -}; +JS2ENUM(SDL_FlipMode) SDL_FColor js2SDL_FColor(JSContext *js, JSValue v) { @@ -442,546 +152,260 @@ SDL_FColor js2SDL_FColor(JSContext *js, JSValue v) return (SDL_FColor){color.r,color.g,color.b,color.a}; } -JS2ENUM(SDL_FlipMode, rets_SDL_FlipMode, vals_SDL_FlipMode) - -/* ------------------------------------------------------- - 1) SDL_GPUBlendFactor - ------------------------------------------------------- */ - -static int rets_SDL_GPUBlendFactor[] = { - SDL_GPU_BLENDFACTOR_INVALID, - SDL_GPU_BLENDFACTOR_ZERO, - SDL_GPU_BLENDFACTOR_ONE, - SDL_GPU_BLENDFACTOR_SRC_COLOR, - SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_COLOR, - SDL_GPU_BLENDFACTOR_DST_COLOR, - SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_COLOR, - SDL_GPU_BLENDFACTOR_SRC_ALPHA, - SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, - SDL_GPU_BLENDFACTOR_DST_ALPHA, - SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_ALPHA, - SDL_GPU_BLENDFACTOR_CONSTANT_COLOR, - SDL_GPU_BLENDFACTOR_ONE_MINUS_CONSTANT_COLOR, - SDL_GPU_BLENDFACTOR_SRC_ALPHA_SATURATE -}; -static const char *vals_SDL_GPUBlendFactor[] = { - "invalid", - "zero", - "one", - "src_color", - "one_minus_src_color", - "dst_color", - "one_minus_dst_color", - "src_alpha", - "one_minus_src_alpha", - "dst_alpha", - "one_minus_dst_alpha", - "constant_color", - "one_minus_constant_color", - "src_alpha_saturate" +ENUM_MAPPING_TABLE(SDL_GPUBlendFactor) = { + {SDL_GPU_BLENDFACTOR_INVALID, "invalid"}, + {SDL_GPU_BLENDFACTOR_ZERO, "zero"}, + {SDL_GPU_BLENDFACTOR_ONE, "one"}, + {SDL_GPU_BLENDFACTOR_SRC_COLOR, "src_color"}, + {SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_COLOR, "one_minus_src_color"}, + {SDL_GPU_BLENDFACTOR_DST_COLOR, "dst_color"}, + {SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_COLOR, "one_minus_dst_color"}, + {SDL_GPU_BLENDFACTOR_SRC_ALPHA, "src_alpha"}, + {SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, "one_minus_src_alpha"}, + {SDL_GPU_BLENDFACTOR_DST_ALPHA, "dst_alpha"}, + {SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_ALPHA, "one_minus_dst_alpha"}, + {SDL_GPU_BLENDFACTOR_CONSTANT_COLOR, "constant_color"}, + {SDL_GPU_BLENDFACTOR_ONE_MINUS_CONSTANT_COLOR, "one_minus_constant_color"}, + {SDL_GPU_BLENDFACTOR_SRC_ALPHA_SATURATE, "src_alpha_saturate"} }; -JS2ENUM(SDL_GPUBlendFactor, rets_SDL_GPUBlendFactor, vals_SDL_GPUBlendFactor) +JS2ENUM(SDL_GPUBlendFactor) -/* ------------------------------------------------------- - 2) SDL_GPUBlendOp - ------------------------------------------------------- */ -static int rets_SDL_GPUBlendOp[] = { - SDL_GPU_BLENDOP_INVALID, - SDL_GPU_BLENDOP_ADD, - SDL_GPU_BLENDOP_SUBTRACT, - SDL_GPU_BLENDOP_REVERSE_SUBTRACT, - SDL_GPU_BLENDOP_MIN, - SDL_GPU_BLENDOP_MAX -}; -static const char *vals_SDL_GPUBlendOp[] = { - "invalid", - "add", - "subtract", - "reverse_subtract", - "min", - "max" +ENUM_MAPPING_TABLE(SDL_GPUBlendOp) = { + {SDL_GPU_BLENDOP_INVALID, "invalid"}, + {SDL_GPU_BLENDOP_ADD, "add"}, + {SDL_GPU_BLENDOP_SUBTRACT, "subtract"}, + {SDL_GPU_BLENDOP_REVERSE_SUBTRACT, "reverse_subtract"}, + {SDL_GPU_BLENDOP_MIN, "min"}, + {SDL_GPU_BLENDOP_MAX, "max"} }; -JS2ENUM(SDL_GPUBlendOp, rets_SDL_GPUBlendOp, vals_SDL_GPUBlendOp) +JS2ENUM(SDL_GPUBlendOp) -/* ------------------------------------------------------- - 3) SDL_GPUCompareOp - ------------------------------------------------------- */ -static int rets_SDL_GPUCompareOp[] = { - SDL_GPU_COMPAREOP_INVALID, - SDL_GPU_COMPAREOP_NEVER, - SDL_GPU_COMPAREOP_LESS, - SDL_GPU_COMPAREOP_EQUAL, - SDL_GPU_COMPAREOP_LESS_OR_EQUAL, - SDL_GPU_COMPAREOP_GREATER, - SDL_GPU_COMPAREOP_NOT_EQUAL, - SDL_GPU_COMPAREOP_GREATER_OR_EQUAL, - SDL_GPU_COMPAREOP_ALWAYS -}; -static const char *vals_SDL_GPUCompareOp[] = { - "invalid", - "never", - "less", - "equal", - "less_or_equal", - "greater", - "not_equal", - "greater_or_equal", - "always" + +ENUM_MAPPING_TABLE(SDL_GPUCompareOp) = { + {SDL_GPU_COMPAREOP_INVALID, "invalid"}, + {SDL_GPU_COMPAREOP_NEVER, "never"}, + {SDL_GPU_COMPAREOP_LESS, "less"}, + {SDL_GPU_COMPAREOP_EQUAL, "equal"}, + {SDL_GPU_COMPAREOP_LESS_OR_EQUAL, "less_or_equal"}, + {SDL_GPU_COMPAREOP_GREATER, "greater"}, + {SDL_GPU_COMPAREOP_NOT_EQUAL, "not_equal"}, + {SDL_GPU_COMPAREOP_GREATER_OR_EQUAL, "greater_or_equal"}, + {SDL_GPU_COMPAREOP_ALWAYS, "always"} }; -JS2ENUM(SDL_GPUCompareOp, rets_SDL_GPUCompareOp, vals_SDL_GPUCompareOp) +JS2ENUM(SDL_GPUCompareOp) -/* ------------------------------------------------------- - 4) SDL_GPUCullMode - ------------------------------------------------------- */ -static int rets_SDL_GPUCullMode[] = { - SDL_GPU_CULLMODE_NONE, - SDL_GPU_CULLMODE_FRONT, - SDL_GPU_CULLMODE_BACK -}; -static const char *vals_SDL_GPUCullMode[] = { - "none", - "front", - "back" +ENUM_MAPPING_TABLE(SDL_GPUCullMode) = { + {SDL_GPU_CULLMODE_NONE, "none"}, + {SDL_GPU_CULLMODE_FRONT, "front"}, + {SDL_GPU_CULLMODE_BACK, "back"} }; -JS2ENUM(SDL_GPUCullMode, rets_SDL_GPUCullMode, vals_SDL_GPUCullMode) +JS2ENUM(SDL_GPUCullMode) -/* ------------------------------------------------------- - 5) SDL_GPUFillMode - ------------------------------------------------------- */ -static int rets_SDL_GPUFillMode[] = { - SDL_GPU_FILLMODE_FILL, - SDL_GPU_FILLMODE_LINE -}; -static const char *vals_SDL_GPUFillMode[] = { - "fill", - "line" +ENUM_MAPPING_TABLE(SDL_GPUFillMode) = { + {SDL_GPU_FILLMODE_FILL, "fill"}, + {SDL_GPU_FILLMODE_LINE, "line"} }; -JS2ENUM(SDL_GPUFillMode, rets_SDL_GPUFillMode, vals_SDL_GPUFillMode) +JS2ENUM(SDL_GPUFillMode) -/* ------------------------------------------------------- - 6) SDL_GPUFilter - ------------------------------------------------------- */ -static int rets_SDL_GPUFilter[] = { - SDL_GPU_FILTER_NEAREST, - SDL_GPU_FILTER_LINEAR -}; -static const char *vals_SDL_GPUFilter[] = { - "nearest", - "linear" +ENUM_MAPPING_TABLE(SDL_GPUFilter) = { + {SDL_GPU_FILTER_NEAREST, "nearest"}, + {SDL_GPU_FILTER_LINEAR, "linear"} }; -JS2ENUM(SDL_GPUFilter, rets_SDL_GPUFilter, vals_SDL_GPUFilter) +JS2ENUM(SDL_GPUFilter) -/* ------------------------------------------------------- - 7) SDL_GPUFrontFace - ------------------------------------------------------- */ -static int rets_SDL_GPUFrontFace[] = { - SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE, - SDL_GPU_FRONTFACE_CLOCKWISE -}; -static const char *vals_SDL_GPUFrontFace[] = { - "counter_clockwise", - "clockwise" +ENUM_MAPPING_TABLE(SDL_GPUFrontFace) = { + {SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE, "counter_clockwise"}, + {SDL_GPU_FRONTFACE_CLOCKWISE, "clockwise"} }; -JS2ENUM(SDL_GPUFrontFace, rets_SDL_GPUFrontFace, vals_SDL_GPUFrontFace) +JS2ENUM(SDL_GPUFrontFace) -/* ------------------------------------------------------- - 8) SDL_GPULoadOp - ------------------------------------------------------- */ -static int rets_SDL_GPULoadOp[] = { - SDL_GPU_LOADOP_LOAD, - SDL_GPU_LOADOP_CLEAR, - SDL_GPU_LOADOP_DONT_CARE -}; -static const char *vals_SDL_GPULoadOp[] = { - "load", - "clear", - "dont_care" +ENUM_MAPPING_TABLE(SDL_GPULoadOp) = { + {SDL_GPU_LOADOP_LOAD, "load"}, + {SDL_GPU_LOADOP_CLEAR, "clear"}, + {SDL_GPU_LOADOP_DONT_CARE, "dont_care"} }; -JS2ENUM(SDL_GPULoadOp, rets_SDL_GPULoadOp, vals_SDL_GPULoadOp) +JS2ENUM(SDL_GPULoadOp) -/* ------------------------------------------------------- - 9) SDL_GPUPresentMode - ------------------------------------------------------- */ -static int rets_SDL_GPUPresentMode[] = { - SDL_GPU_PRESENTMODE_VSYNC, - SDL_GPU_PRESENTMODE_IMMEDIATE, - SDL_GPU_PRESENTMODE_MAILBOX -}; -static const char *vals_SDL_GPUPresentMode[] = { - "vsync", - "immediate", - "mailbox" +ENUM_MAPPING_TABLE(SDL_GPUPresentMode) = { + {SDL_GPU_PRESENTMODE_VSYNC, "vsync"}, + {SDL_GPU_PRESENTMODE_IMMEDIATE, "immediate"}, + {SDL_GPU_PRESENTMODE_MAILBOX, "mailbox"} }; -JS2ENUM(SDL_GPUPresentMode, rets_SDL_GPUPresentMode, vals_SDL_GPUPresentMode) +JS2ENUM(SDL_GPUPresentMode) -/* ------------------------------------------------------- - 10) SDL_GPUPrimitiveType - ------------------------------------------------------- */ -static int rets_SDL_GPUPrimitiveType[] = { - SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, - SDL_GPU_PRIMITIVETYPE_TRIANGLESTRIP, - SDL_GPU_PRIMITIVETYPE_LINELIST, - SDL_GPU_PRIMITIVETYPE_LINESTRIP, - SDL_GPU_PRIMITIVETYPE_POINTLIST -}; -static const char *vals_SDL_GPUPrimitiveType[] = { - "triangle", - "trianglestrip", - "line", - "linestrip", - "point" +ENUM_MAPPING_TABLE(SDL_GPUPrimitiveType) = { + {SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, "triangle"}, + {SDL_GPU_PRIMITIVETYPE_TRIANGLESTRIP, "trianglestrip"}, + {SDL_GPU_PRIMITIVETYPE_LINELIST, "line"}, + {SDL_GPU_PRIMITIVETYPE_LINESTRIP, "linestrip"}, + {SDL_GPU_PRIMITIVETYPE_POINTLIST, "point"} }; -JS2ENUM(SDL_GPUPrimitiveType, rets_SDL_GPUPrimitiveType, vals_SDL_GPUPrimitiveType) +JS2ENUM(SDL_GPUPrimitiveType) -/* ------------------------------------------------------- - 11) SDL_GPUSamplerAddressMode - ------------------------------------------------------- */ -static int rets_SDL_GPUSamplerAddressMode[] = { - SDL_GPU_SAMPLERADDRESSMODE_REPEAT, - SDL_GPU_SAMPLERADDRESSMODE_MIRRORED_REPEAT, - SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE -}; -static const char *vals_SDL_GPUSamplerAddressMode[] = { - "repeat", - "mirrored_repeat", - "clamp" +ENUM_MAPPING_TABLE(SDL_GPUSamplerAddressMode) = { + {SDL_GPU_SAMPLERADDRESSMODE_REPEAT, "repeat"}, + {SDL_GPU_SAMPLERADDRESSMODE_MIRRORED_REPEAT, "mirrored_repeat"}, + {SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, "clamp"} }; -JS2ENUM(SDL_GPUSamplerAddressMode, rets_SDL_GPUSamplerAddressMode, vals_SDL_GPUSamplerAddressMode) +JS2ENUM(SDL_GPUSamplerAddressMode) -/* ------------------------------------------------------- - 12) SDL_GPUSamplerMipmapMode - ------------------------------------------------------- */ -static int rets_SDL_GPUSamplerMipmapMode[] = { - SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, - SDL_GPU_SAMPLERMIPMAPMODE_LINEAR -}; -static const char *vals_SDL_GPUSamplerMipmapMode[] = { - "nearest", - "linear" +ENUM_MAPPING_TABLE(SDL_GPUSamplerMipmapMode) = { + {SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, "nearest"}, + {SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, "linear"} }; -JS2ENUM(SDL_GPUSamplerMipmapMode, rets_SDL_GPUSamplerMipmapMode, vals_SDL_GPUSamplerMipmapMode) +JS2ENUM(SDL_GPUSamplerMipmapMode) -/* ------------------------------------------------------- - 13) SDL_GPUStencilOp - ------------------------------------------------------- */ -static int rets_SDL_GPUStencilOp[] = { - SDL_GPU_STENCILOP_INVALID, - SDL_GPU_STENCILOP_KEEP, - SDL_GPU_STENCILOP_ZERO, - SDL_GPU_STENCILOP_REPLACE, - SDL_GPU_STENCILOP_INCREMENT_AND_CLAMP, - SDL_GPU_STENCILOP_DECREMENT_AND_CLAMP, - SDL_GPU_STENCILOP_INVERT, - SDL_GPU_STENCILOP_INCREMENT_AND_WRAP, - SDL_GPU_STENCILOP_DECREMENT_AND_WRAP -}; -static const char *vals_SDL_GPUStencilOp[] = { - "invalid", - "keep", - "zero", - "replace", - "increment_and_clamp", - "decrement_and_clamp", - "invert", - "increment_and_wrap", - "decrement_and_wrap" +ENUM_MAPPING_TABLE(SDL_GPUStencilOp) = { + {SDL_GPU_STENCILOP_INVALID, "invalid"}, + {SDL_GPU_STENCILOP_KEEP, "keep"}, + {SDL_GPU_STENCILOP_ZERO, "zero"}, + {SDL_GPU_STENCILOP_REPLACE, "replace"}, + {SDL_GPU_STENCILOP_INCREMENT_AND_CLAMP, "increment_and_clamp"}, + {SDL_GPU_STENCILOP_DECREMENT_AND_CLAMP, "decrement_and_clamp"}, + {SDL_GPU_STENCILOP_INVERT, "invert"}, + {SDL_GPU_STENCILOP_INCREMENT_AND_WRAP, "increment_and_wrap"}, + {SDL_GPU_STENCILOP_DECREMENT_AND_WRAP, "decrement_and_wrap"} }; -JS2ENUM(SDL_GPUStencilOp, rets_SDL_GPUStencilOp, vals_SDL_GPUStencilOp) +JS2ENUM(SDL_GPUStencilOp) -static int rets_SDL_GPUTextureType[] = { - SDL_GPU_TEXTURETYPE_2D, /**< The texture is a 2-dimensional image. */ - SDL_GPU_TEXTURETYPE_2D_ARRAY, /**< The texture is a 2-dimensional array image. */ - SDL_GPU_TEXTURETYPE_3D, /**< The texture is a 3-dimensional image. */ - SDL_GPU_TEXTURETYPE_CUBE, /**< The texture is a cube image. */ - SDL_GPU_TEXTURETYPE_CUBE_ARRAY /**< The texture is a cube array image. */ +ENUM_MAPPING_TABLE(SDL_GPUTextureType) = { + {SDL_GPU_TEXTURETYPE_2D, "2d"}, + {SDL_GPU_TEXTURETYPE_2D_ARRAY, "2d array"}, + {SDL_GPU_TEXTURETYPE_3D, "3d"}, + {SDL_GPU_TEXTURETYPE_CUBE, "cube"}, + {SDL_GPU_TEXTURETYPE_CUBE_ARRAY, "cube array"} }; -static const char *vals_SDL_GPUTextureType[] = { - "2d", - "2d array", - "3d", - "cube", - "cube array" +JS2ENUM(SDL_GPUTextureType) + +ENUM_MAPPING_TABLE(SDL_GPUStoreOp) = { + {SDL_GPU_STOREOP_STORE, "store"}, + {SDL_GPU_STOREOP_DONT_CARE, "dont_care"}, + {SDL_GPU_STOREOP_RESOLVE, "resolve"}, + {SDL_GPU_STOREOP_RESOLVE_AND_STORE, "resolve_and_store"} }; -JS2ENUM(SDL_GPUTextureType, rets_SDL_GPUTextureType, vals_SDL_GPUTextureType) +JS2ENUM(SDL_GPUStoreOp) -/* ------------------------------------------------------- - 14) SDL_GPUStoreOp - ------------------------------------------------------- */ -static int rets_SDL_GPUStoreOp[] = { - SDL_GPU_STOREOP_STORE, - SDL_GPU_STOREOP_DONT_CARE, - SDL_GPU_STOREOP_RESOLVE, - SDL_GPU_STOREOP_RESOLVE_AND_STORE -}; - -static const char *vals_SDL_GPUStoreOp[] = { - "store", - "dont_care", - "resolve", - "resolve_and_store" -}; - -JS2ENUM(SDL_GPUStoreOp, rets_SDL_GPUStoreOp, vals_SDL_GPUStoreOp) - -/* ------------------------------------------------------- - X) SDL_GPUTextureType - ------------------------------------------------------- */ -static int rets_SDL_GPUTextureFormat[] = { - SDL_GPU_TEXTUREFORMAT_INVALID, - - /* Unsigned Normalized Float Color Formats */ - SDL_GPU_TEXTUREFORMAT_A8_UNORM, - SDL_GPU_TEXTUREFORMAT_R8_UNORM, - SDL_GPU_TEXTUREFORMAT_R8G8_UNORM, - SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, - SDL_GPU_TEXTUREFORMAT_R16_UNORM, - SDL_GPU_TEXTUREFORMAT_R16G16_UNORM, - SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM, - SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM, - SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM, - SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM, - SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM, - SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM, - /* Compressed Unsigned Normalized Float Color Formats */ - SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM, - SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM, - SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM, - SDL_GPU_TEXTUREFORMAT_BC4_R_UNORM, - SDL_GPU_TEXTUREFORMAT_BC5_RG_UNORM, - SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM, - /* Compressed Signed Float Color Formats */ - SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT, - /* Compressed Unsigned Float Color Formats */ - SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT, - /* Signed Normalized Float Color Formats */ - SDL_GPU_TEXTUREFORMAT_R8_SNORM, - SDL_GPU_TEXTUREFORMAT_R8G8_SNORM, - SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM, - SDL_GPU_TEXTUREFORMAT_R16_SNORM, - SDL_GPU_TEXTUREFORMAT_R16G16_SNORM, - SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM, - /* Signed Float Color Formats */ - SDL_GPU_TEXTUREFORMAT_R16_FLOAT, - SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT, - SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT, - SDL_GPU_TEXTUREFORMAT_R32_FLOAT, - SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT, - SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT, - /* Unsigned Float Color Formats */ - SDL_GPU_TEXTUREFORMAT_R11G11B10_UFLOAT, - /* Unsigned Integer Color Formats */ - SDL_GPU_TEXTUREFORMAT_R8_UINT, - SDL_GPU_TEXTUREFORMAT_R8G8_UINT, - SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT, - SDL_GPU_TEXTUREFORMAT_R16_UINT, - SDL_GPU_TEXTUREFORMAT_R16G16_UINT, - SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT, - SDL_GPU_TEXTUREFORMAT_R32_UINT, - SDL_GPU_TEXTUREFORMAT_R32G32_UINT, - SDL_GPU_TEXTUREFORMAT_R32G32B32A32_UINT, - /* Signed Integer Color Formats */ - SDL_GPU_TEXTUREFORMAT_R8_INT, - SDL_GPU_TEXTUREFORMAT_R8G8_INT, - SDL_GPU_TEXTUREFORMAT_R8G8B8A8_INT, - SDL_GPU_TEXTUREFORMAT_R16_INT, - SDL_GPU_TEXTUREFORMAT_R16G16_INT, - SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT, - SDL_GPU_TEXTUREFORMAT_R32_INT, - SDL_GPU_TEXTUREFORMAT_R32G32_INT, - SDL_GPU_TEXTUREFORMAT_R32G32B32A32_INT, - /* SRGB Unsigned Normalized Color Formats */ - SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB, - /* Compressed SRGB Unsigned Normalized Color Formats */ - SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB, - /* Depth Formats */ - SDL_GPU_TEXTUREFORMAT_D16_UNORM, - SDL_GPU_TEXTUREFORMAT_D24_UNORM, - SDL_GPU_TEXTUREFORMAT_D32_FLOAT, - SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT, - SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT, - /* Compressed ASTC Normalized Float Color Formats*/ - SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM, - SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM, - /* Compressed SRGB ASTC Normalized Float Color Formats*/ - SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB, - SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB, - /* Compressed ASTC Signed Float Color Formats*/ - SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT, - SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT -}; - -static const char *vals_SDL_GPUTextureFormat[] = { - "invalid", - "a8", - "r8", - "rg8", - "rgba8", - "r16", - "rg16", - "rgba16", - "r10g10b10a2", - "b5g6r5", - "b5g5r5a1", - "b4g4r4a4", - "b8g8r8a8", - - "bc1", - "bc2", - "bc3", - "bc4", - "bc5", - "bc7", - "bc6h float", - "bc6h ufloat", - - "r8 snorm", - "rg8 snorm", - "rgba8 snorm", - "r16 snorm", - "rg16 snorm", - "rgba16 snorm", - - "r16 float", - "rg16 float", - "rgba16 float", - "r32 float", - "rg32 float", - "rgba32 float", - - "r11g11b10", - - "r8 uint", - "rg8 uint", - "rgba8 uint", - "r16 uint", - "rg16 uint", - "rgba16 uint", - "r32 uint", - "rg32 uint", - "rgba32 uint", - - "r8 int", - "rg8 int", - "rgba8 int", - "r16 int", - "rg16 int", - "rgba16 int", - "r32 int", - "rg32 int", - "rgba32 int", - - "rgba8 srgb", - "b8g8r8a8 srgb", - "bc1 srgb", - "bc2 srgb", - "bc3 srgb", - "bc7 srgb", - - "d16", - "d24", - "d32 float", - "d24 s8", - "d32 float s8", - - "astc 4x4", - "astc 5x4", - "astc 5x5", - "astc 6x5", - "astc 6x6", - "astc 8x5", - "astc 8x6", - "astc 8x8", - "astc 10x5", - "astc 10x6", - "astc 10x8", - "astc 10x10", - "astc 12x10", - "astc 12x12", - - "astc 4x4 srgb", - "astc 5x4 srgb", - "astc 5x5 srgb", - "astc 6x5 srgb", - "astc 6x6 srgb", - "astc 8x5 srgb", - "astc 8x6 srgb", - "astc 8x8 srgb", - "astc 10x5 srgb", - "astc 10x6 srgb", - "astc 10x8 srgb", - "astc 10x10 srgb", - "astc 12x10 srgb", - "astc 12x12 srgb", - - "astc 4x4 float", - "astc 5x4 float", - "astc 5x5 float", - "astc 6x5 float", - "astc 6x6 float", - "astc 8x5 float", - "astc 8x6 float", - "astc 8x8 float", - "astc 10x5 float", - "astc 10x6 float", - "astc 10x8 float", - "astc 10x10 float", - "astc 12x10 float", - "astc 12x12 float" +ENUM_MAPPING_TABLE(SDL_GPUTextureFormat) = { + {SDL_GPU_TEXTUREFORMAT_INVALID, "invalid"}, + {SDL_GPU_TEXTUREFORMAT_A8_UNORM, "a8"}, + {SDL_GPU_TEXTUREFORMAT_R8_UNORM, "r8"}, + {SDL_GPU_TEXTUREFORMAT_R8G8_UNORM, "rg8"}, + {SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, "rgba8"}, + {SDL_GPU_TEXTUREFORMAT_R16_UNORM, "r16"}, + {SDL_GPU_TEXTUREFORMAT_R16G16_UNORM, "rg16"}, + {SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM, "rgba16"}, + {SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM, "r10g10b10a2"}, + {SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM, "b5g6r5"}, + {SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM, "b5g5r5a1"}, + {SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM, "b4g4r4a4"}, + {SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM, "b8g8r8a8"}, + {SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM, "bc1"}, + {SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM, "bc2"}, + {SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM, "bc3"}, + {SDL_GPU_TEXTUREFORMAT_BC4_R_UNORM, "bc4"}, + {SDL_GPU_TEXTUREFORMAT_BC5_RG_UNORM, "bc5"}, + {SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM, "bc7"}, + {SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT, "bc6h float"}, + {SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT, "bc6h ufloat"}, + {SDL_GPU_TEXTUREFORMAT_R8_SNORM, "r8 snorm"}, + {SDL_GPU_TEXTUREFORMAT_R8G8_SNORM, "rg8 snorm"}, + {SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM, "rgba8 snorm"}, + {SDL_GPU_TEXTUREFORMAT_R16_SNORM, "r16 snorm"}, + {SDL_GPU_TEXTUREFORMAT_R16G16_SNORM, "rg16 snorm"}, + {SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM, "rgba16 snorm"}, + {SDL_GPU_TEXTUREFORMAT_R16_FLOAT, "r16 float"}, + {SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT, "rg16 float"}, + {SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT, "rgba16 float"}, + {SDL_GPU_TEXTUREFORMAT_R32_FLOAT, "r32 float"}, + {SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT, "rg32 float"}, + {SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT, "rgba32 float"}, + {SDL_GPU_TEXTUREFORMAT_R11G11B10_UFLOAT, "r11g11b10"}, + {SDL_GPU_TEXTUREFORMAT_R8_UINT, "r8 uint"}, + {SDL_GPU_TEXTUREFORMAT_R8G8_UINT, "rg8 uint"}, + {SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT, "rgba8 uint"}, + {SDL_GPU_TEXTUREFORMAT_R16_UINT, "r16 uint"}, + {SDL_GPU_TEXTUREFORMAT_R16G16_UINT, "rg16 uint"}, + {SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT, "rgba16 uint"}, + {SDL_GPU_TEXTUREFORMAT_R32_UINT, "r32 uint"}, + {SDL_GPU_TEXTUREFORMAT_R32G32_UINT, "rg32 uint"}, + {SDL_GPU_TEXTUREFORMAT_R32G32B32A32_UINT, "rgba32 uint"}, + {SDL_GPU_TEXTUREFORMAT_R8_INT, "r8 int"}, + {SDL_GPU_TEXTUREFORMAT_R8G8_INT, "rg8 int"}, + {SDL_GPU_TEXTUREFORMAT_R8G8B8A8_INT, "rgba8 int"}, + {SDL_GPU_TEXTUREFORMAT_R16_INT, "r16 int"}, + {SDL_GPU_TEXTUREFORMAT_R16G16_INT, "rg16 int"}, + {SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT, "rgba16 int"}, + {SDL_GPU_TEXTUREFORMAT_R32_INT, "r32 int"}, + {SDL_GPU_TEXTUREFORMAT_R32G32_INT, "rg32 int"}, + {SDL_GPU_TEXTUREFORMAT_R32G32B32A32_INT, "rgba32 int"}, + {SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB, "rgba8 srgb"}, + {SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB, "b8g8r8a8 srgb"}, + {SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB, "bc1 srgb"}, + {SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB, "bc2 srgb"}, + {SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB, "bc3 srgb"}, + {SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB, "bc7 srgb"}, + {SDL_GPU_TEXTUREFORMAT_D16_UNORM, "d16"}, + {SDL_GPU_TEXTUREFORMAT_D24_UNORM, "d24"}, + {SDL_GPU_TEXTUREFORMAT_D32_FLOAT, "d32 float"}, + {SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT, "d24 s8"}, + {SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT, "d32 float s8"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM, "astc 4x4"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM, "astc 5x4"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM, "astc 5x5"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM, "astc 6x5"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM, "astc 6x6"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM, "astc 8x5"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM, "astc 8x6"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM, "astc 8x8"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM, "astc 10x5"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM, "astc 10x6"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM, "astc 10x8"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM, "astc 10x10"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM, "astc 12x10"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM, "astc 12x12"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB, "astc 4x4 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB, "astc 5x4 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB, "astc 5x5 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB, "astc 6x5 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB, "astc 6x6 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB, "astc 8x5 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB, "astc 8x6 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB, "astc 8x8 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB, "astc 10x5 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB, "astc 10x6 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB, "astc 10x8 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB, "astc 10x10 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB, "astc 12x10 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB, "astc 12x12 srgb"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT, "astc 4x4 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT, "astc 5x4 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT, "astc 5x5 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT, "astc 6x5 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT, "astc 6x6 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT, "astc 8x5 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT, "astc 8x6 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT, "astc 8x8 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT, "astc 10x5 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT, "astc 10x6 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT, "astc 10x8 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT, "astc 10x10 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT, "astc 12x10 float"}, + {SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT, "astc 12x12 float"} }; SDL_GPUColorTargetInfo js2SDL_GPUColorTargetInfo(JSContext *js, JSValue v) @@ -1006,7 +430,15 @@ SDL_GPUTextureSamplerBinding js2SDL_GPUTextureSamplerBinding(JSContext *js, JSVa return b; } -JS2ENUM(SDL_GPUTextureFormat, rets_SDL_GPUTextureFormat, vals_SDL_GPUTextureFormat) +SDL_GPUBufferBinding js2SDL_GPUBufferBinding(JSContext *js, JSValue v) +{ + SDL_GPUBufferBinding binding = {0}; + JS_GETPROP(js, binding.buffer, v, buffer, SDL_GPUBuffer) + JS_GETPROP(js, binding.offset, v, offset, number) + return binding; +} + +JS2ENUM(SDL_GPUTextureFormat) SDL_GPUColorTargetBlendState js2SDL_GPUColorTargetBlendState(JSContext *js, JSValue v) { @@ -1014,28 +446,73 @@ SDL_GPUColorTargetBlendState js2SDL_GPUColorTargetBlendState(JSContext *js, JSVa JS_GETPROP(js,state.src_color_blendfactor,v,src_rgb,SDL_GPUBlendFactor); JS_GETPROP(js,state.dst_color_blendfactor,v,dst_rgb,SDL_GPUBlendFactor); JS_GETPROP(js,state.src_alpha_blendfactor,v,src_alpha,SDL_GPUBlendFactor); - JS_GETPROP(js,state.dst_alpha_blendfactor,v,src_alpha,SDL_GPUBlendFactor); + JS_GETPROP(js,state.dst_alpha_blendfactor,v,dst_alpha,SDL_GPUBlendFactor); JS_GETPROP(js,state.color_blend_op,v,op_rgb,SDL_GPUBlendOp) JS_GETPROP(js,state.alpha_blend_op,v,op_alpha,SDL_GPUBlendOp) JS_GETPROP(js,state.enable_blend,v,enabled,bool) return state; } -SDL_GPUShaderFormat js2SDL_GPUShaderFormat(JSContext *js, JSValue v) -{ - const char *format_str = JS_ToCString(js, v); - SDL_GPUShaderFormat format = SDL_GPU_SHADERFORMAT_SPIRV; // default to SPIR-V - if (format_str) { - if (!strcmp(format_str, "private")) format = SDL_GPU_SHADERFORMAT_PRIVATE; - else if (!strcmp(format_str, "spv")) format = SDL_GPU_SHADERFORMAT_SPIRV; - else if (!strcmp(format_str, "dxbc")) format = SDL_GPU_SHADERFORMAT_DXBC; - else if (!strcmp(format_str, "dxil")) format = SDL_GPU_SHADERFORMAT_DXIL; - else if (!strcmp(format_str, "msl")) format = SDL_GPU_SHADERFORMAT_MSL; - else if (!strcmp(format_str, "metallib")) format = SDL_GPU_SHADERFORMAT_METALLIB; - JS_FreeCString(js, format_str); - } - return format; -} +ENUM_MAPPING_TABLE(SDL_GPUShaderFormat) = { + {SDL_GPU_SHADERFORMAT_PRIVATE, "private"}, + {SDL_GPU_SHADERFORMAT_SPIRV, "spv"}, + {SDL_GPU_SHADERFORMAT_DXBC, "dxbc"}, + {SDL_GPU_SHADERFORMAT_DXIL, "dxil"}, + {SDL_GPU_SHADERFORMAT_MSL, "msl"}, + {SDL_GPU_SHADERFORMAT_METALLIB, "metallib"} +}; + +JS2ENUM(SDL_GPUShaderFormat) + +ENUM_MAPPING_TABLE(SDL_GPUVertexInputRate) = { + {SDL_GPU_VERTEXINPUTRATE_VERTEX, "vertex"}, + {SDL_GPU_VERTEXINPUTRATE_INSTANCE, "instance"} +}; + +JS2ENUM(SDL_GPUVertexInputRate) + +ENUM_MAPPING_TABLE(SDL_GPUTransferBufferUsage) = { + {SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, "upload"}, + {SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD, "download"} +}; + +JS2ENUM(SDL_GPUTransferBufferUsage) + +ENUM_MAPPING_TABLE(SDL_GPUVertexElementFormat) = { + {SDL_GPU_VERTEXELEMENTFORMAT_INVALID, "invalid"}, + {SDL_GPU_VERTEXELEMENTFORMAT_INT, "int"}, + {SDL_GPU_VERTEXELEMENTFORMAT_INT2, "int2"}, + {SDL_GPU_VERTEXELEMENTFORMAT_INT3, "int3"}, + {SDL_GPU_VERTEXELEMENTFORMAT_INT4, "int4"}, + {SDL_GPU_VERTEXELEMENTFORMAT_UINT, "uint"}, + {SDL_GPU_VERTEXELEMENTFORMAT_UINT2, "uint2"}, + {SDL_GPU_VERTEXELEMENTFORMAT_UINT3, "uint3"}, + {SDL_GPU_VERTEXELEMENTFORMAT_UINT4, "uint4"}, + {SDL_GPU_VERTEXELEMENTFORMAT_FLOAT, "float"}, + {SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2, "float2"}, + {SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, "float3"}, + {SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4, "float4"}, + {SDL_GPU_VERTEXELEMENTFORMAT_BYTE2, "byte2"}, + {SDL_GPU_VERTEXELEMENTFORMAT_BYTE4, "byte4"}, + {SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2, "ubyte2"}, + {SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4, "ubyte4"}, + {SDL_GPU_VERTEXELEMENTFORMAT_BYTE2_NORM, "byte2_norm"}, + {SDL_GPU_VERTEXELEMENTFORMAT_BYTE4_NORM, "byte4_norm"}, + {SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2_NORM, "ubyte2_norm"}, + {SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM, "ubyte4_norm"}, + {SDL_GPU_VERTEXELEMENTFORMAT_SHORT2, "short2"}, + {SDL_GPU_VERTEXELEMENTFORMAT_SHORT4, "short4"}, + {SDL_GPU_VERTEXELEMENTFORMAT_USHORT2, "ushort2"}, + {SDL_GPU_VERTEXELEMENTFORMAT_USHORT4, "ushort4"}, + {SDL_GPU_VERTEXELEMENTFORMAT_SHORT2_NORM, "short2_norm"}, + {SDL_GPU_VERTEXELEMENTFORMAT_SHORT4_NORM, "short4_norm"}, + {SDL_GPU_VERTEXELEMENTFORMAT_USHORT2_NORM, "ushort2_norm"}, + {SDL_GPU_VERTEXELEMENTFORMAT_USHORT4_NORM, "ushort4_norm"}, + {SDL_GPU_VERTEXELEMENTFORMAT_HALF2, "half2"}, + {SDL_GPU_VERTEXELEMENTFORMAT_HALF4, "half4"} +}; + +JS2ENUM(SDL_GPUVertexElementFormat) SDL_GPUColorTargetDescription js2SDL_GPUColorTargetDescription(JSContext *js, JSValue v) { @@ -1069,49 +546,11 @@ SDL_GPUStencilOpState js2SDL_GPUStencilOpState(JSContext *js, JSValue v) return state; } - -// Unpacks a typed array javascript object. If it has a gpu property, returns it, too. Otherwise, if requested, makes one. -void *gpu_buffer_unpack(JSContext *js, SDL_GPUDevice *device, JSValue buffer, size_t *size, void **send_data, SDL_GPUBuffer **send_gpu) -{ - size_t msize; - // Use blob system for array buffer data - void *data = js_get_blob_data(js, &msize, buffer); - if (!data) { - // If not a blob, try to get data from buffer property - JSValue buf_val = JS_GetPropertyStr(js, buffer, "buffer"); - data = js_get_blob_data(js, &msize, buf_val); - JS_FreeValue(js, buf_val); - } - if (size) *size = msize; - if (send_gpu) { - JSValue gpu = JS_GetPropertyStr(js,buffer,"gpu"); - *send_gpu = js2SDL_GPUBuffer(js,gpu); - if (!*send_gpu) { - JSValue idx = JS_GetPropertyStr(js,buffer, "index"); - Uint32 usage = JS_ToBool(js,idx) ? SDL_GPU_BUFFERUSAGE_INDEX : SDL_GPU_BUFFERUSAGE_VERTEX; - JS_FreeValue(js,idx); - *send_gpu = SDL_CreateGPUBuffer(device, &(SDL_GPUBufferCreateInfo) { .usage=usage,.size=msize}); - if (!*send_gpu) printf("COULDN'T MAKE GPU BUFFER: %s\n", SDL_GetError()); - JS_SetPropertyStr(js, buffer, "gpu", SDL_GPUBuffer2js(js,*send_gpu)); - } - JS_FreeValue(js,gpu); - } - - if (send_data) - *send_data = data; - return data; -} - -// GPU buffer management functions -// Moved to jsffi.c - extern declaration -extern void free_gpu_buffer(JSRuntime *rt, void *opaque, void *ptr); - -// GPU API JSC_CCALL(gpu_claim_window, SDL_GPUDevice *gpu = js2SDL_GPUDevice(js,self); SDL_Window *win = js2SDL_Window(js, argv[0]); if (!SDL_ClaimWindowForGPUDevice(gpu,win)) - printf("couldn't claim: %s\n", SDL_GetError()); + return JS_ThrowInternalError(js, "couldn't claim window for GPU device: %s", SDL_GetError()); ) JSC_CCALL(gpu_set_swapchain, @@ -1121,273 +560,6 @@ JSC_CCALL(gpu_set_swapchain, return JS_ThrowReferenceError(js, "Could not set: %s\n", SDL_GetError()); ) -JSC_CCALL(cmd_acquire_swapchain, - SDL_GPUCommandBuffer *cmds = js2SDL_GPUCommandBuffer(js, self); - SDL_Window *window = js2SDL_Window(js, argv[0]); - Uint32 w,h; - SDL_GPUTexture *texture; - SDL_AcquireGPUSwapchainTexture(cmds, window, &texture, &w, &h); - if (!texture) return JS_NULL; - JSValue swap = JS_NULL; - - JSValue *js_swapchains = ((cell_rt*)JS_GetContextOpaque(js))->js_swapchains; - - for (int i = 0; i < arrlen(js_swapchains); i++) { - if (js2SDL_GPUTexture(js,js_swapchains[i]) == texture) { - swap = js_swapchains[i]; - break; - } - } - - if (JS_IsNull(swap)) { - swap = SDL_GPUTexture2js(js,texture); - arrput(js_swapchains,swap); - } - - JS_SetPropertyStr(js,swap,"width", number2js(js,w)); - JS_SetPropertyStr(js,swap,"height", number2js(js,h)); - return JS_DupValue(js,swap); -) - -JSC_CCALL(cmd_swapchain_pass, - SDL_GPUCommandBuffer *cmds = js2SDL_GPUCommandBuffer(js, self); - SDL_Window *window = js2SDL_Window(js, argv[0]); - SDL_GPUColorTargetInfo info = {0}; - Uint32 w, h; - SDL_AcquireGPUSwapchainTexture(cmds, window, &info.texture, &w,&h); - info.load_op = SDL_GPU_LOADOP_CLEAR; - info.store_op = SDL_GPU_STOREOP_STORE; - colorf c = js2color(js,argv[1]); - info.clear_color = (SDL_FColor){c.r,c.g,c.b,c.a}; - SDL_GPURenderPass *pass = SDL_BeginGPURenderPass( - cmds, - &info, - 1, - NULL - ); - if (!pass) return JS_ThrowReferenceError(js, "Unable to create swapchain pass: %s", SDL_GetError()); - JSValue jspass = SDL_GPURenderPass2js(js,pass); - JS_SetPropertyStr(js,jspass,"size", vec22js(js,(HMM_Vec2){w,h})); - return jspass; -) - -JSC_CCALL(gpu_load_texture, - SDL_GPUDevice *gpu = js2SDL_GPUDevice(js, self); - SDL_Surface *surf = js2SDL_Surface(js, argv[0]); - if (!surf) return JS_ThrowReferenceError(js, "Surface was not a surface."); - - int compression_level = js2number(js,argv[1]); - if (compression_level < 0) compression_level = 0; - if (compression_level > 2) compression_level = 2; - - int dofree = 0; - - SDL_PixelFormat sfmt = surf->format; - const SDL_PixelFormatDetails *pdetails = SDL_GetPixelFormatDetails(sfmt); - -if (!pdetails) { - // If we can't get pixel format details, fall back to converting to RGBA8888 - surf = SDL_ConvertSurface(surf, SDL_PIXELFORMAT_RGBA8888); - dofree = 1; - sfmt = SDL_PIXELFORMAT_RGBA8888; - pdetails = SDL_GetPixelFormatDetails(sfmt); - if (!pdetails) { - // Should never happen with RGBA8888, but just in case - return JS_ThrowReferenceError(js, "Unable to get pixel format details."); - } -} - -// Check if format has alpha -bool has_alpha = (pdetails->Amask != 0); - -// Choose a GPU format that closely matches the surface's format -SDL_GPUTextureFormat chosen_format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; - -switch (sfmt) { - case SDL_PIXELFORMAT_RGBA32: - case SDL_PIXELFORMAT_RGBX8888: - case SDL_PIXELFORMAT_XRGB8888: - case SDL_PIXELFORMAT_XBGR8888: - chosen_format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; - break; - - case SDL_PIXELFORMAT_RGBA4444: - case SDL_PIXELFORMAT_ABGR4444: - case SDL_PIXELFORMAT_ARGB4444: - case SDL_PIXELFORMAT_BGRA4444: - // 4-4-4-4 format - chosen_format = SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM; - break; - - case SDL_PIXELFORMAT_RGB565: - case SDL_PIXELFORMAT_BGR565: - // 5-6-5 format - chosen_format = SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM; - break; - - case SDL_PIXELFORMAT_RGBA5551: - case SDL_PIXELFORMAT_ARGB1555: - case SDL_PIXELFORMAT_BGRA5551: - case SDL_PIXELFORMAT_ABGR1555: - // 5-5-5-1 format - chosen_format = SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM; - break; - - default: - surf = SDL_ConvertSurface(surf, SDL_PIXELFORMAT_RGBA32); - dofree = 1; - sfmt = SDL_PIXELFORMAT_RGBA32; - pdetails = SDL_GetPixelFormatDetails(sfmt); - chosen_format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; - has_alpha = true; - break; -} - -// If compression_level > 0, we override format with BC1/BC3 -bool compress = (compression_level > 0); -int stb_mode = STB_DXT_NORMAL; -SDL_GPUTextureFormat compressed_format = chosen_format; - -if (compress) { - if (has_alpha) - compressed_format = SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM; // DXT5 - else - compressed_format = SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM; // DXT1 - - if (compression_level > 1) stb_mode = STB_DXT_HIGHQUAL; -} - -SDL_GPUTexture *tex = SDL_CreateGPUTexture(gpu, &(SDL_GPUTextureCreateInfo) { - .type = SDL_GPU_TEXTURETYPE_2D, - .format = compress ? compressed_format : chosen_format, - .width = surf->w, - .height = surf->h, - .layer_count_or_depth = 1, - .num_levels = 1, - .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER -}); - -const void *pixel_data = surf->pixels; -size_t pixel_data_size = surf->pitch * surf->h; -unsigned char *upload_data = NULL; -size_t upload_size = pixel_data_size; - -if (compress) { - // Compress with stb_dxt - int block_width = (surf->w + 3) / 4; - int block_height = (surf->h + 3) / 4; - int block_size = (compressed_format == SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM) ? 8 : 16; - int blocks_count = block_width * block_height; - - unsigned char *compressed_data = (unsigned char*)malloc(blocks_count * block_size); - if (!compressed_data) { - if (dofree) SDL_DestroySurface(surf); - return JS_ThrowOutOfMemory(js); - } - - const unsigned char *src_pixels = (const unsigned char *)pixel_data; - for (int by = 0; by < block_height; ++by) { - for (int bx = 0; bx < block_width; ++bx) { - unsigned char block_rgba[4*4*4]; - memset(block_rgba, 0, sizeof(block_rgba)); - - for (int y = 0; y < 4; ++y) { - for (int x = 0; x < 4; ++x) { - int sx = bx*4 + x; - int sy = by*4 + y; - if (sx < surf->w && sy < surf->h) { - const unsigned char *pixel = src_pixels + sy * surf->pitch + sx * pdetails->bytes_per_pixel; - Uint32 pixelValue = 0; - // Copy pixel data into a Uint32 for SDL_GetRGBA-like extraction - // We'll use masks/shifts from pdetails - memcpy(&pixelValue, pixel, pdetails->bytes_per_pixel); - - // Extract RGBA - unsigned char r = (pixelValue & pdetails->Rmask) >> pdetails->Rshift; - unsigned char g = (pixelValue & pdetails->Gmask) >> pdetails->Gshift; - unsigned char b = (pixelValue & pdetails->Bmask) >> pdetails->Bshift; - unsigned char a = pdetails->Amask ? ((pixelValue & pdetails->Amask) >> pdetails->Ashift) : 255; - - // If bits are not fully 8-bit, scale them: - // pdetails->Rbits (etc.) give how many bits each channel uses - int Rmax = (1 << pdetails->Rbits) - 1; - int Gmax = (1 << pdetails->Gbits) - 1; - int Bmax = (1 << pdetails->Bbits) - 1; - int Amax = pdetails->Abits ? ((1 << pdetails->Abits) - 1) : 255; - - if (pdetails->Rbits < 8) r = (r * 255) / Rmax; - if (pdetails->Gbits < 8) g = (g * 255) / Gmax; - if (pdetails->Bbits < 8) b = (b * 255) / Bmax; - if (pdetails->Amask && pdetails->Abits < 8) a = (a * 255) / Amax; - - // Set block pixel - block_rgba[(y*4+x)*4+0] = r; - block_rgba[(y*4+x)*4+1] = g; - block_rgba[(y*4+x)*4+2] = b; - block_rgba[(y*4+x)*4+3] = a; - } - } - } - - unsigned char *dest_block = compressed_data + (by * block_width + bx)*block_size; - int alpha = (compressed_format == SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM) ? 1 : 0; - stb_compress_dxt_block(dest_block, block_rgba, alpha, stb_mode); - } - } - - upload_data = compressed_data; - upload_size = blocks_count * block_size; - } else { - // No compression, upload directly - upload_data = (unsigned char*)pixel_data; - upload_size = pixel_data_size; - } - - SDL_GPUTransferBuffer *tex_buffer = SDL_CreateGPUTransferBuffer( - gpu, - &(SDL_GPUTransferBufferCreateInfo) { - .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, - .size = upload_size - }); - void *tex_ptr = SDL_MapGPUTransferBuffer(gpu, tex_buffer, false); - memcpy(tex_ptr, upload_data, upload_size); - SDL_UnmapGPUTransferBuffer(gpu, tex_buffer); - - SDL_GPUCommandBuffer *uploadcmd = SDL_AcquireGPUCommandBuffer(gpu); - SDL_GPUCopyPass *copypass = SDL_BeginGPUCopyPass(uploadcmd); - SDL_UploadToGPUTexture( - copypass, - &(SDL_GPUTextureTransferInfo) { - .transfer_buffer = tex_buffer, - .offset = 0 - }, - &(SDL_GPUTextureRegion) { - .texture = tex, - .w = surf->w, - .h = surf->h, - .d = 1 - }, - false -); - - SDL_EndGPUCopyPass(copypass); - SDL_SubmitGPUCommandBuffer(uploadcmd); - SDL_ReleaseGPUTransferBuffer(gpu, tex_buffer); - - if (compress) { - free(upload_data); - } - - ret = SDL_GPUTexture2js(js, tex); - JS_SetPropertyStr(js, ret, "width", number2js(js, surf->w)); - JS_SetPropertyStr(js, ret, "height", number2js(js, surf->h)); - JS_SetPropertyStr(js,ret,"dim", vec22js(js,(HMM_Vec2){surf->w,surf->h})); - - if (dofree) SDL_DestroySurface(surf); - -) - -// Standalone graphics pipeline constructor: new sdl_gpu.graphics_pipeline(device, config) static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { if (argc < 2) return JS_ThrowTypeError(js, "graphics pipeline constructor requires device and config parameters"); @@ -1401,9 +573,6 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst SDL_GPUGraphicsPipelineCreateInfo info = {0}; - // --------------------------------------------------- - // 2. Retrieve vertex buffer descriptions array - // --------------------------------------------------- JSValue vbd_val = JS_GetPropertyStr(js, pipe, "vertex_buffer_descriptions"); Uint32 vbd_len = JS_ArrayLength(js,vbd_val); SDL_GPUVertexBufferDescription vbd[vbd_len]; @@ -1415,27 +584,17 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst JSValue rate_val = JS_GetPropertyStr(js, elem, "input_rate"); JSValue step_val = JS_GetPropertyStr(js, elem, "instance_step_rate"); - // Slot Uint32 slot = 0; JS_ToUint32(js, &slot, slot_val); JS_FreeValue(js, slot_val); - // Pitch Uint32 pitch = 0; JS_ToUint32(js, &pitch, pitch_val); JS_FreeValue(js, pitch_val); - // Input Rate - const char *rate_str = JS_ToCString(js, rate_val); - SDL_GPUVertexInputRate input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX; - if (rate_str) { - if (!strcmp(rate_str, "vertex")) input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX; - else if (!strcmp(rate_str, "instance")) input_rate = SDL_GPU_VERTEXINPUTRATE_INSTANCE; - JS_FreeCString(js, rate_str); - } + SDL_GPUVertexInputRate input_rate = js2SDL_GPUVertexInputRate(js, rate_val); JS_FreeValue(js, rate_val); - // Instance Step Rate Uint32 step_rate = 0; JS_ToUint32(js, &step_rate, step_val); JS_FreeValue(js, step_val); @@ -1444,14 +603,12 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst vbd[i].pitch = pitch; vbd[i].input_rate = input_rate; vbd[i].instance_step_rate = step_rate; + printf("slot %d, pitch %d ...\n", vbd[i].slot, vbd[i].pitch); } JS_FreeValue(js, elem); } JS_FreeValue(js, vbd_val); - // --------------------------------------------------- - // 3. Retrieve vertex attributes array - // --------------------------------------------------- JSValue vat_val = JS_GetPropertyStr(js, pipe, "vertex_attributes"); Uint32 vat_len = JS_ArrayLength(js,vat_val); @@ -1464,31 +621,17 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst JSValue fmt_val = JS_GetPropertyStr(js, elem, "format"); JSValue off_val = JS_GetPropertyStr(js, elem, "offset"); - // location Uint32 location = 0; JS_ToUint32(js, &location, loc_val); JS_FreeValue(js, loc_val); - // buffer_slot Uint32 buffer_slot = 0; JS_ToUint32(js, &buffer_slot, slot_val); JS_FreeValue(js, slot_val); - // format - const char *fmt_str = JS_ToCString(js, fmt_val); - SDL_GPUVertexElementFormat format = -1; // TODO: Check for error (if this is still -1) - if (fmt_str) { - // Map from string to SDL_GPUVertexElementFormat - if (!strcmp(fmt_str, "float2")) format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2; - else if (!strcmp(fmt_str, "float3")) format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3; - else if (!strcmp(fmt_str, "float4")) format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4; - else if (!strcmp(fmt_str, "color")) - format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4; - JS_FreeCString(js, fmt_str); - } + SDL_GPUVertexElementFormat format = js2SDL_GPUVertexElementFormat(js, fmt_val); JS_FreeValue(js, fmt_val); - // offset Uint32 offset = 0; JS_ToUint32(js, &offset, off_val); JS_FreeValue(js, off_val); @@ -1509,19 +652,15 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst .num_vertex_attributes = vat_len }; - // Vertex Shader JS_GETPROP(js,info.vertex_shader, pipe, vertex,SDL_GPUShader) JS_GETPROP(js, info.fragment_shader, pipe, fragment, SDL_GPUShader) - // Primitive Type JS_GETPROP(js, info.primitive_type, pipe, primitive, SDL_GPUPrimitiveType) - // Rasterizer State JS_GETPROP(js, info.rasterizer_state.fill_mode, pipe, fill, SDL_GPUFillMode) JS_GETPROP(js, info.rasterizer_state.cull_mode, pipe, cull, SDL_GPUCullMode) JS_GETPROP(js, info.rasterizer_state.front_face, pipe, face, SDL_GPUFrontFace) - // Depth Stencil State JSValue depth_val = JS_GetPropertyStr(js, pipe, "depth"); if (JS_IsObject(depth_val)) { JS_GETPROP(js,info.depth_stencil_state.compare_op, depth_val, compare, SDL_GPUCompareOp) @@ -1533,7 +672,6 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst } JS_FreeValue(js, depth_val); - // Stencil State JSValue stencil_val = JS_GetPropertyStr(js, pipe, "stencil"); if (JS_IsObject(stencil_val)) { JS_GETPROP(js,info.depth_stencil_state.enable_stencil_test, stencil_val, enabled, bool) @@ -1579,9 +717,9 @@ static JSValue js_gpu_graphics_pipeline_constructor(JSContext *js, JSValueConst // Create the pipeline SDL_GPUGraphicsPipeline *pipeline = SDL_CreateGPUGraphicsPipeline(gpu, &info); - if (!pipeline) return JS_ThrowInternalError(js, "Failed to create GPU pipeline"); + if (!pipeline) return JS_ThrowInternalError(js, "Failed to create GPU pipeline: %s", SDL_GetError()); - return gpu_graphics_pipeline_wrapper2js_from_components(js, gpu, pipeline); + return SDL_GPUGraphicsPipeline2js(js, gpu, pipeline); } // Standalone sampler constructor: new sdl_gpu.sampler(device, config) @@ -1612,110 +750,9 @@ static JSValue js_gpu_sampler_constructor(JSContext *js, JSValueConst self, int SDL_GPUSampler *sdl_sampler = SDL_CreateGPUSampler(gpu, &info); if (!sdl_sampler) return JS_ThrowInternalError(js, "Failed to create GPU sampler: %s", SDL_GetError()); - return gpu_sampler_wrapper2js_from_components(js, gpu, sdl_sampler); + return SDL_GPUSampler2js(js, gpu, sdl_sampler); } - -JSC_CCALL(gpu_texture, - SDL_GPUDevice *gpu = js2SDL_GPUDevice(js,self); - SDL_GPUTextureCreateInfo info = {0}; - JSValue fmt = argv[0]; - JS_GETPROP(js, info.width, fmt, width, number) - JS_GETPROP(js, info.height, fmt, height, number) - JS_GETPROP(js, info.layer_count_or_depth, fmt, layers, number) - JS_GETPROP(js, info.num_levels, fmt, mip_levels, number) - JS_GETPROP(js, info.sample_count, fmt, samples, number) - JS_GETPROP(js, info.type, fmt, type, SDL_GPUTextureType) - JS_GETPROP(js, info.format, fmt, format, SDL_GPUTextureFormat) - if (JS_GETBOOL(js,fmt,"sampler")) - info.usage |= SDL_GPU_TEXTUREUSAGE_SAMPLER; - if (JS_GETBOOL(js,fmt,"color_target")) - info.usage |= SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; - if (JS_GETBOOL(js,fmt,"depth_target")) - info.usage |= SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET; - if (JS_GETBOOL(js,fmt,"read")) - info.usage |= (SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ | SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ); - if (JS_GETBOOL(js,fmt,"write")) - info.usage |= SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE; - if (JS_GETBOOL(js,fmt,"readwrite")) - info.usage |= SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE; - - SDL_GPUTexture *tex = SDL_CreateGPUTexture(gpu,&info); - if (!tex) return JS_ThrowReferenceError(js, "Unable to create texture: %s", SDL_GetError()); - JSValue jstex = SDL_GPUTexture2js(js,tex); - JS_SetPropertyStr(js,jstex,"width", number2js(js,info.width)); - JS_SetPropertyStr(js,jstex,"height", number2js(js,info.height)); - JS_SetPropertyStr(js,jstex,"dim", vec22js(js,(HMM_Vec2){info.width, info.height})); - return jstex; -) - -JSC_CCALL(gpu_buffer, - SDL_GPUDevice *gpu = js2SDL_GPUDevice(js,self); - SDL_GPUBufferCreateInfo info = {0}; - JSValue config = argv[0]; - - // Get size - this is required - JS_GETPROP(js, info.size, config, size, number) - if (info.size == 0) return JS_ThrowTypeError(js, "Buffer size must be greater than 0"); - - // Parse usage flags - if (JS_GETBOOL(js, config, "vertex")) - info.usage |= SDL_GPU_BUFFERUSAGE_VERTEX; - if (JS_GETBOOL(js, config, "index")) - info.usage |= SDL_GPU_BUFFERUSAGE_INDEX; - if (JS_GETBOOL(js, config, "indirect")) - info.usage |= SDL_GPU_BUFFERUSAGE_INDIRECT; - if (JS_GETBOOL(js, config, "graphics_storage_read")) - info.usage |= SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ; - if (JS_GETBOOL(js, config, "compute_storage_read")) - info.usage |= SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ; - if (JS_GETBOOL(js, config, "compute_storage_write")) - info.usage |= SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE; - - // If no usage flags were set, throw an error - if (info.usage == 0) return JS_ThrowTypeError(js, "Buffer must have at least one usage flag"); - - SDL_GPUBuffer *buffer = SDL_CreateGPUBuffer(gpu, &info); - if (!buffer) return JS_ThrowReferenceError(js, "Unable to create buffer: %s", SDL_GetError()); - - return gpu_buffer_wrapper2js_from_components(js, gpu, buffer); -) - -JSC_CCALL(gpu_transfer_buffer, - SDL_GPUDevice *gpu = js2SDL_GPUDevice(js,self); - SDL_GPUTransferBufferCreateInfo info = {0}; - JSValue config = argv[0]; - - // Get size - this is required - JS_GETPROP(js, info.size, config, size, number) - if (info.size == 0) return JS_ThrowTypeError(js, "Transfer buffer size must be greater than 0"); - - // Get usage - this is required - JSValue usage_val = JS_GetPropertyStr(js, config, "usage"); - if (JS_IsString(usage_val)) { - const char *usage_str = JS_ToCString(js, usage_val); - if (strcmp(usage_str, "upload") == 0) { - info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; - } else if (strcmp(usage_str, "download") == 0) { - info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD; - } else { - JS_FreeCString(js, usage_str); - JS_FreeValue(js, usage_val); - return JS_ThrowTypeError(js, "Invalid transfer buffer usage. Must be 'upload' or 'download'"); - } - JS_FreeCString(js, usage_str); - } else { - JS_FreeValue(js, usage_val); - return JS_ThrowTypeError(js, "Transfer buffer usage must be specified as 'upload' or 'download'"); - } - JS_FreeValue(js, usage_val); - - SDL_GPUTransferBuffer *buffer = SDL_CreateGPUTransferBuffer(gpu, &info); - if (!buffer) return JS_ThrowReferenceError(js, "Unable to create transfer buffer: %s", SDL_GetError()); - - return gpu_transfer_buffer_wrapper2js_from_components(js, gpu, buffer); -) - JSC_CCALL(gpu_driver, SDL_GPUDevice *gpu = js2SDL_GPUDevice(js,self); ret = JS_NewString(js, SDL_GetGPUDeviceDriver(gpu)); @@ -1764,136 +801,20 @@ static JSValue js_gpu_shader_constructor(JSContext *js, JSValueConst self, int a info.code = code_data; info.props = 0; // No extension properties by default - JS_FreeCString(js,info.entrypoint); - SDL_GPUShader *shader = SDL_CreateGPUShader(gpu, &info); + + JS_FreeCString(js,info.entrypoint); if (!shader) return JS_ThrowReferenceError(js, "Unable to create shader: %s", SDL_GetError()); - return gpu_shader_wrapper2js_from_components(js, gpu, shader); + return SDL_GPUShader2js(js, gpu, shader); } JSC_CCALL(gpu_acquire_cmd_buffer, SDL_GPUDevice *gpu = js2SDL_GPUDevice(js, self); SDL_GPUCommandBuffer *cb = SDL_AcquireGPUCommandBuffer(gpu); if (!cb) return JS_ThrowReferenceError(js,"Unable to acquire command buffer: %s", SDL_GetError()); - return gpu_command_buffer_wrapper2js_from_components(js, gpu, cb); -) - -/* takes argv - 0: a command buffer to write to - 1: a buffer or array of buffers to upload - 2: an optional transfer buffer to use; if undefined a temporary one is used -*/ -JSC_CCALL(gpu_upload, - JSValue js_cmd = argv[0]; - JSValue js_buffers = argv[1]; - JSValue js_transfer = argv[2]; - - SDL_GPUDevice *gpu = js2SDL_GPUDevice(js, self); - if (!gpu) - return JS_ThrowTypeError(js, "Invalid GPU device"); - - SDL_GPUCommandBuffer *cmds = js2SDL_GPUCommandBuffer(js, js_cmd); - if (!cmds) - return JS_ThrowTypeError(js, "Invalid command buffer"); - - if (!JS_IsArray(js, js_buffers)) - return JS_ThrowTypeError(js, "buffers must be an array"); - - size_t len = JS_ArrayLength(js, js_buffers); - if (len == 0) - return JS_DupValue(js, js_transfer); // No data to upload, just return existing transfer buffer - - struct { - SDL_GPUBuffer *gpu_buffer; - void *data; - size_t size; - } *items = malloc(sizeof(*items) * len); - - if (!items) - return JS_ThrowOutOfMemory(js); - - size_t total_size_needed = 0; - - for (size_t i = 0; i < len; i++) { - JSValue js_buf = JS_GetPropertyUint32(js, js_buffers, i); - - if (JS_IsNull(js_buf)) - continue; - - gpu_buffer_unpack(js, gpu, js_buf, &items[i].size, &items[i].data, &items[i].gpu_buffer); - total_size_needed += items[i].size; - JS_FreeValue(js, js_buf); - } - - SDL_GPUTransferBuffer *transfer = js2SDL_GPUTransferBuffer(js,js_transfer); - if (transfer) { - // ensure it's large enough - size_t transfer_size = js_getnum_str(js,js_transfer, "size"); - if (transfer_size < total_size_needed) { - total_size_needed *= 1.5; - transfer = SDL_CreateGPUTransferBuffer( gpu, &(SDL_GPUTransferBufferCreateInfo){ - .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, - .size = total_size_needed - } - ); - ret = SDL_GPUTransferBuffer2js(js,transfer); - JS_SetPropertyStr(js,ret,"size", number2js(js,total_size_needed)); - } else - ret = JS_DupValue(js,js_transfer); // supplied transfer buffer is fine so we use it - } else { - transfer = SDL_CreateGPUTransferBuffer( gpu, &(SDL_GPUTransferBufferCreateInfo){ - .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, - .size = total_size_needed - } - ); - ret = SDL_GPUTransferBuffer2js(js,transfer); - JS_SetPropertyStr(js,ret,"size", number2js(js,total_size_needed)); - } - - SDL_GPUCopyPass *copy_pass = SDL_BeginGPUCopyPass(cmds); - if (!copy_pass) { - free(items); - return JS_ThrowReferenceError(js, "Failed to begin copy pass"); - } - - void *mapped_data = SDL_MapGPUTransferBuffer(gpu, transfer, false); - if (!mapped_data) { - SDL_EndGPUCopyPass(copy_pass); - free(items); - return JS_ThrowReferenceError(js, "Failed to map transfer buffer: %s", SDL_GetError()); - } - - // Copy all data into the mapped transfer buffer - size_t current_offset = 0; - for (size_t i = 0; i < len; i++) { - memcpy((char*)mapped_data + current_offset, items[i].data, items[i].size); - current_offset += items[i].size; - } - SDL_UnmapGPUTransferBuffer(gpu, transfer); - - // Issue uploads for each item - current_offset = 0; - for (size_t i = 0; i < len; i++) { - SDL_UploadToGPUBuffer( - copy_pass, - &(SDL_GPUTransferBufferLocation){ - .transfer_buffer = transfer, - .offset = current_offset - }, - &(SDL_GPUBufferRegion){ - .buffer = items[i].gpu_buffer, - .offset = 0, - .size = items[i].size - }, - false - ); - current_offset += items[i].size; - } - - SDL_EndGPUCopyPass(copy_pass); - free(items); + return SDL_GPUCommandBuffer2js(js, cb); ) JSC_CCALL(gpu_wait_for_fences, @@ -1951,7 +872,6 @@ static JSValue js_gpu_compute_pipeline_constructor(JSContext *js, JSValueConst s JS_GETPROP(js,info.threadcount_z,pipe,threadcount_z,number) JS_GETPROP(js,info.entrypoint,pipe,entrypoint,cstring) - JSValue shader = JS_GetPropertyStr(js,pipe,"shader"); info.code = js_get_blob_data(js,&info.code_size, shader); JS_FreeValue(js,shader); @@ -1959,7 +879,7 @@ static JSValue js_gpu_compute_pipeline_constructor(JSContext *js, JSValueConst s SDL_GPUComputePipeline *pipeline = SDL_CreateGPUComputePipeline(gpu, &info); JS_FreeCString(js,info.entrypoint); if (!pipeline) return JS_ThrowReferenceError(js,"Could not create compute pipeline: %s", SDL_GetError()); - return gpu_compute_pipeline_wrapper2js_from_components(js, gpu, pipeline); + return SDL_GPUComputePipeline2js(js, gpu, pipeline); } // Standalone buffer constructor: new sdl_gpu.buffer(device, config) @@ -1990,16 +910,14 @@ static JSValue js_gpu_buffer_constructor(JSContext *js, JSValueConst self, int a if (JS_GETBOOL(js, config, "compute_storage_write")) info.usage |= SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE; - // If no usage flags were set, throw an error if (info.usage == 0) return JS_ThrowTypeError(js, "Buffer must have at least one usage flag"); SDL_GPUBuffer *buffer = SDL_CreateGPUBuffer(gpu, &info); if (!buffer) return JS_ThrowReferenceError(js, "Unable to create buffer: %s", SDL_GetError()); - return gpu_buffer_wrapper2js_from_components(js, gpu, buffer); + return SDL_GPUBuffer2js(js, gpu, buffer); } -// Standalone transfer buffer constructor: new sdl_gpu.transfer_buffer(device, config) static JSValue js_gpu_transfer_buffer_constructor(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) { if (argc < 2) return JS_ThrowTypeError(js, "transfer_buffer constructor requires device and config parameters"); @@ -2013,30 +931,12 @@ static JSValue js_gpu_transfer_buffer_constructor(JSContext *js, JSValueConst se JS_GETPROP(js, info.size, config, size, number) if (info.size == 0) return JS_ThrowTypeError(js, "Transfer buffer size must be greater than 0"); - // Get usage - this is required - JSValue usage_val = JS_GetPropertyStr(js, config, "usage"); - if (JS_IsString(usage_val)) { - const char *usage_str = JS_ToCString(js, usage_val); - if (strcmp(usage_str, "upload") == 0) { - info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; - } else if (strcmp(usage_str, "download") == 0) { - info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD; - } else { - JS_FreeCString(js, usage_str); - JS_FreeValue(js, usage_val); - return JS_ThrowTypeError(js, "Invalid transfer buffer usage. Must be 'upload' or 'download'"); - } - JS_FreeCString(js, usage_str); - } else { - JS_FreeValue(js, usage_val); - return JS_ThrowTypeError(js, "Transfer buffer usage must be specified as 'upload' or 'download'"); - } - JS_FreeValue(js, usage_val); + JS_GETPROP(js, info.usage, config, usage, SDL_GPUTransferBufferUsage) SDL_GPUTransferBuffer *buffer = SDL_CreateGPUTransferBuffer(gpu, &info); if (!buffer) return JS_ThrowReferenceError(js, "Unable to create transfer buffer: %s", SDL_GetError()); - return gpu_transfer_buffer_wrapper2js_from_components(js, gpu, buffer); + return SDL_GPUTransferBuffer2js(js, gpu, buffer); } // Standalone texture constructor: new sdl_gpu.texture(device, config) @@ -2074,31 +974,25 @@ static JSValue js_gpu_texture_constructor(JSContext *js, JSValueConst self, int SDL_GPUTexture *tex = SDL_CreateGPUTexture(gpu, &info); if (!tex) return JS_ThrowReferenceError(js, "Unable to create texture: %s", SDL_GetError()); - JSValue jstex = gpu_texture_wrapper2js_from_components(js, gpu, tex); + JSValue jstex = SDL_GPUTexture2js(js, gpu, tex); JS_SetPropertyStr(js, jstex, "width", number2js(js, info.width)); JS_SetPropertyStr(js, jstex, "height", number2js(js, info.height)); JS_SetPropertyStr(js, jstex, "dim", vec22js(js, (HMM_Vec2){info.width, info.height})); return jstex; } -JSC_CCALL(gpu_get_swapchain_texture_format, - SDL_GPUDevice *gpu = js2SDL_GPUDevice(js, self); - SDL_Window *window = js2SDL_Window(js, argv[0]); - SDL_GPUTextureFormat format = SDL_GetGPUSwapchainTextureFormat(gpu, window); - return JS_NewInt32(js, format); +JSC_CCALL(gpu_swapchain_format, + SDL_GPUDevice *dev = js2SDL_GPUDevice(js, self); + SDL_Window *win = js2SDL_Window(js, argv[0]); + return SDL_GPUTextureFormat2js(js, SDL_GetGPUSwapchainTextureFormat(dev, win)); ) static const JSCFunctionListEntry js_SDL_GPUDevice_funcs[] = { MIST_FUNC_DEF(gpu, claim_window, 1), MIST_FUNC_DEF(gpu, set_swapchain, 3), - MIST_FUNC_DEF(gpu, load_texture, 2), - MIST_FUNC_DEF(gpu, texture, 1), - MIST_FUNC_DEF(gpu, buffer, 1), - MIST_FUNC_DEF(gpu, transfer_buffer, 1), - MIST_FUNC_DEF(gpu, get_swapchain_texture_format, 1), + MIST_FUNC_DEF(gpu, swapchain_format, 1), MIST_FUNC_DEF(gpu, driver, 0), MIST_FUNC_DEF(gpu, acquire_cmd_buffer, 0), - MIST_FUNC_DEF(gpu, upload, 3), MIST_FUNC_DEF(gpu, wait_for_fences, 2), MIST_FUNC_DEF(gpu, query_fence, 1), MIST_FUNC_DEF(gpu, shader_format, 0), @@ -2106,19 +1000,21 @@ static const JSCFunctionListEntry js_SDL_GPUDevice_funcs[] = { JSC_CCALL(renderpass_bind_pipeline, SDL_GPURenderPass *r = js2SDL_GPURenderPass(js,self); + if (!r) return JS_ThrowInternalError(js, "Invalid render pass"); SDL_GPUGraphicsPipeline *pipe = js2SDL_GPUGraphicsPipeline(js,argv[0]); + if (!pipe) return JS_ThrowInternalError(js, "Invalid graphics pipeline"); SDL_BindGPUGraphicsPipeline(r,pipe); ) JSC_CCALL(renderpass_draw_indexed, SDL_GPURenderPass *pass = js2SDL_GPURenderPass(js,self); - printf("DRAWING INDEX\n"); + if (!pass) return JS_ThrowInternalError(js, "Invalid render pass"); SDL_DrawGPUIndexedPrimitives(pass, js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3]), js2number(js,argv[4])); - printf("DRAW!!!\n"); ) JSC_CCALL(renderpass_draw, SDL_GPURenderPass *pass = js2SDL_GPURenderPass(js,self); + if (!pass) return JS_ThrowInternalError(js, "Invalid render pass"); SDL_DrawGPUPrimitives(pass, js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3])); ) @@ -2126,13 +1022,11 @@ JSC_CCALL(renderpass_bind_buffers, SDL_GPURenderPass *pass = js2SDL_GPURenderPass(js,self); int first = js2number(js,argv[0]); JSValue buffers = argv[1]; - SDL_GPUDevice *gpu = js2SDL_GPUDevice(js, argv[2]); int len = JS_ArrayLength(js,buffers); SDL_GPUBufferBinding bindings[len]; for (int i = 0; i < len; i++) { JSValue buffer = JS_GetPropertyUint32(js,buffers,i); - bindings[i].offset = 0; - gpu_buffer_unpack(js, gpu, buffer, NULL, NULL,&bindings[i].buffer); + bindings[i] = js2SDL_GPUBufferBinding(js, buffer); JS_FreeValue(js,buffer); } @@ -2145,19 +1039,14 @@ JSC_CCALL(renderpass_bind_buffers, JSC_CCALL(renderpass_bind_index_buffer, SDL_GPURenderPass *pass = js2SDL_GPURenderPass(js,self); - SDL_GPUDevice *gpu = js2SDL_GPUDevice(js, argv[1]); - SDL_GPUBufferBinding bind; - bind.offset = 0; - gpu_buffer_unpack(js, gpu, argv[0], NULL, NULL, &bind.buffer); - int elen; - JSValue b = argv[0]; - JS_GETPROP(js, elen, b, elen, number) - - SDL_BindGPUIndexBuffer(pass,&bind,elen == 2 ? SDL_GPU_INDEXELEMENTSIZE_16BIT : SDL_GPU_INDEXELEMENTSIZE_32BIT); + SDL_GPUBufferBinding bind = js2SDL_GPUBufferBinding(js, argv[0]); + int elen = js2number(js,argv[1]); + SDL_BindGPUIndexBuffer(pass,&bind,elen == 16 ? SDL_GPU_INDEXELEMENTSIZE_16BIT : SDL_GPU_INDEXELEMENTSIZE_32BIT); ) JSC_CCALL(renderpass_end, SDL_GPURenderPass *pass = js2SDL_GPURenderPass(js,self); + if (!pass) return JS_ThrowInternalError(js, "Invalid render pass"); SDL_EndGPURenderPass(pass); ) @@ -2169,12 +1058,7 @@ JSC_CCALL(renderpass_bind_samplers, SDL_GPUTextureSamplerBinding binds[num]; for (int i = 0; i < num; i++) { JSValue val = JS_GetPropertyUint32(js,arr,i); - JSValue tex = JS_GetPropertyStr(js,val,"texture"); - JSValue smp = JS_GetPropertyStr(js,val,"sampler"); - binds[i].texture = js2SDL_GPUTexture(js,tex); - binds[i].sampler = js2SDL_GPUSampler(js,smp); - JS_FreeValue(js,tex); - JS_FreeValue(js,smp); + binds[i] = js2SDL_GPUTextureSamplerBinding(js, val); JS_FreeValue(js,val); } int vertex = JS_ToBool(js,argv[0]); @@ -2224,12 +1108,7 @@ JSC_CCALL(renderpass_bind_vertex_samplers, SDL_GPUTextureSamplerBinding binds[num]; for (int i = 0; i < num; i++) { JSValue val = JS_GetPropertyUint32(js,arr,i); - JSValue tex = JS_GetPropertyStr(js,val,"texture"); - JSValue smp = JS_GetPropertyStr(js,val,"sampler"); - binds[i].texture = js2SDL_GPUTexture(js,tex); - binds[i].sampler = js2SDL_GPUSampler(js,smp); - JS_FreeValue(js,tex); - JS_FreeValue(js,smp); + binds[i] = js2SDL_GPUTextureSamplerBinding(js,val); JS_FreeValue(js,val); } SDL_BindGPUVertexSamplers(pass, first_slot, binds, num); @@ -2243,12 +1122,7 @@ JSC_CCALL(renderpass_bind_fragment_samplers, SDL_GPUTextureSamplerBinding binds[num]; for (int i = 0; i < num; i++) { JSValue val = JS_GetPropertyUint32(js,arr,i); - JSValue tex = JS_GetPropertyStr(js,val,"texture"); - JSValue smp = JS_GetPropertyStr(js,val,"sampler"); - binds[i].texture = js2SDL_GPUTexture(js,tex); - binds[i].sampler = js2SDL_GPUSampler(js,smp); - JS_FreeValue(js,tex); - JS_FreeValue(js,smp); + binds[i] = js2SDL_GPUTextureSamplerBinding(js,val); JS_FreeValue(js,val); } SDL_BindGPUFragmentSamplers(pass, first_slot, binds, num); @@ -2269,6 +1143,12 @@ JSC_CCALL(renderpass_bind_vertex_buffers, SDL_BindGPUVertexBuffers(pass, first_slot, binds, num); ) +JSC_CCALL(renderpass_set_stencil_reference, + SDL_GPURenderPass *pass = js2SDL_GPURenderPass(js, self); + Uint8 ref = js2number(js,argv[0]); + SDL_SetGPUStencilReference(pass, ref); +) + static const JSCFunctionListEntry js_SDL_GPURenderPass_funcs[] = { MIST_FUNC_DEF(renderpass, bind_pipeline, 1), MIST_FUNC_DEF(renderpass, viewport, 1), @@ -2276,6 +1156,7 @@ static const JSCFunctionListEntry js_SDL_GPURenderPass_funcs[] = { MIST_FUNC_DEF(renderpass, draw, 4), MIST_FUNC_DEF(renderpass, draw_indexed, 5), MIST_FUNC_DEF(renderpass, end, 0), + MIST_FUNC_DEF(renderpass, set_stencil_reference, 1), MIST_FUNC_DEF(renderpass, bind_index_buffer, 1), MIST_FUNC_DEF(renderpass, bind_buffers, 2), MIST_FUNC_DEF(renderpass, bind_samplers, 3), @@ -2343,33 +1224,6 @@ JSC_CCALL(cmd_copy_pass, return SDL_GPUCopyPass2js(js, pass); ) -JSC_CCALL(cmd_bind_vertex_buffer, - SDL_GPUCommandBuffer *cmds = js2SDL_GPUCommandBuffer(js, self); - int slot; - JS_ToInt32(js, &slot, argv[0]); - SDL_GPUBuffer *buffer = js2SDL_GPUBuffer(js, argv[1]); - size_t offset = 0; - if (argc > 2) JS_ToIndex(js, &offset, argv[2]); - SDL_BindGPUVertexBuffers(cmds, slot, &(SDL_GPUBufferBinding){.buffer = buffer, .offset = offset}, 1); -) - -JSC_CCALL(cmd_bind_index_buffer, - SDL_GPUCommandBuffer *cmds = js2SDL_GPUCommandBuffer(js, self); - SDL_GPUBuffer *buffer = js2SDL_GPUBuffer(js, argv[0]); - size_t offset = 0; - if (argc > 1) JS_ToIndex(js, &offset, argv[1]); - SDL_BindGPUIndexBuffer(cmds, &(SDL_GPUBufferBinding){.buffer = buffer, .offset = offset}, SDL_GPU_INDEXELEMENTSIZE_16BIT); -) - -JSC_CCALL(cmd_bind_fragment_sampler, - SDL_GPUCommandBuffer *cmds = js2SDL_GPUCommandBuffer(js, self); - int slot; - JS_ToInt32(js, &slot, argv[0]); - SDL_GPUTexture *tex = js2SDL_GPUTexture(js, argv[1]); - SDL_GPUSampler *sampler = js2SDL_GPUSampler(js, argv[2]); - SDL_BindGPUFragmentSamplers(cmds, slot, &(SDL_GPUTextureSamplerBinding){.texture = tex, .sampler = sampler}, 1); -) - JSC_CCALL(cmd_push_vertex_uniform_data, SDL_GPUCommandBuffer *cmds = js2SDL_GPUCommandBuffer(js, self); int slot; @@ -2399,31 +1253,7 @@ JSC_CCALL(cmd_push_compute_uniform_data, JSC_CCALL(cmd_submit, SDL_GPUCommandBuffer *cmds = js2SDL_GPUCommandBuffer(js,self); - SDL_GPUFence *fence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmds); - return SDL_GPUFence2js(js,fence); -) - -JSC_CCALL(cmd_hud, - SDL_GPUCommandBuffer *cmds = js2SDL_GPUCommandBuffer(js,self); - HMM_Vec2 size = js2vec2(js,argv[0]); - HMM_Mat4 proj = HMM_Orthographic_RH_NO(0,size.x,0,size.y,-1,1); - shader_globals data = {0}; - data.world_to_projection = proj; - data.projection_to_world = HMM_InvGeneralM4(proj); - data.viewport_min_z = -1, - data.viewport_max_z = 1; - data.render_size = size; - data.view_to_projection = proj; - data.viewport_size = (HMM_Vec2){1,1}; - data.viewport_offset = (HMM_Vec2){0,0}; - data.time = SDL_GetTicksNS() / 1000000000.0f; - SDL_PushGPUVertexUniformData(cmds, js2number(js,argv[1]), &data, sizeof(data)); -) - -JSC_CCALL(cmd_camera, -// SDL_GPUCommandBuffer *cmds = js2SDL_GPUCommandBuffer(js, self); -// shader_globals data = camera_globals(js, argv[0]); -// SDL_PushGPUVertexUniformData(cmds, js2number(js,argv[1]), &data, sizeof(data)); + SDL_SubmitGPUCommandBuffer(cmds); ) JSC_SCALL(cmd_push_debug_group, @@ -2490,6 +1320,33 @@ JSC_CCALL(cmd_cancel, SDL_CancelGPUCommandBuffer(cmd); ) +JSC_CCALL(cmd_swapchain_pass, + SDL_GPUCommandBuffer *cmdbuf = js2SDL_GPUCommandBuffer(js, self); + SDL_Window *window = js2SDL_Window(js, argv[0]); + + SDL_GPUTexture* swapchainTexture; + if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, window, &swapchainTexture, NULL, NULL)) { + return JS_ThrowReferenceError(js, "WaitAndAcquireGPUSwapchainTexture failed: %s", SDL_GetError()); + } + + if (swapchainTexture == NULL) { + return JS_ThrowReferenceError(js, "Failed to acquire swapchain texture"); + } + + SDL_GPUColorTargetInfo colorTargetInfo = { 0 }; + colorTargetInfo.texture = swapchainTexture; + colorTargetInfo.clear_color = (SDL_FColor){ 0.0f, 0.0f, 0.0f, 1.0f }; + colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR; + colorTargetInfo.store_op = SDL_GPU_STOREOP_STORE; + + SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL); + if (!renderPass) { + return JS_ThrowReferenceError(js, "Failed to begin render pass: %s", SDL_GetError()); + } + + return SDL_GPURenderPass2js(js, renderPass); +) + JSC_CCALL(cmd_compute_pass, SDL_GPUCommandBuffer *cmd = js2SDL_GPUCommandBuffer(js,self); JSValue textures = argv[0]; @@ -2517,46 +1374,27 @@ JSC_CCALL(cmd_compute_pass, return SDL_GPUComputePass2js(js,pass); ) -JSC_CCALL(cmd_wait_and_acquire_swapchain_texture, - SDL_GPUCommandBuffer *cmds = js2SDL_GPUCommandBuffer(js, self); - SDL_Window *window = js2SDL_Window(js, argv[0]); - - SDL_GPUTexture *swapchain_texture; - Uint32 width, height; - - bool result = SDL_WaitAndAcquireGPUSwapchainTexture(cmds, window, &swapchain_texture, &width, &height); - if (!result) return JS_ThrowReferenceError(js, "Failed to acquire swapchain texture: %s", SDL_GetError()); - - if (swapchain_texture) { - JSValue texture_obj = SDL_GPUTexture2js(js, swapchain_texture); - JS_SetPropertyStr(js, texture_obj, "width", JS_NewUint32(js, width)); - JS_SetPropertyStr(js, texture_obj, "height", JS_NewUint32(js, height)); - return texture_obj; - } - - return JS_NULL; +JSC_CCALL(cmd_generate_mipmaps, + SDL_GPUCommandBuffer *cmd = js2SDL_GPUCommandBuffer(js,self); + SDL_GPUTexture *tex = js2SDL_GPUTexture(js,argv[0]); + SDL_GenerateMipmapsForGPUTexture(cmd,tex); ) static const JSCFunctionListEntry js_SDL_GPUCommandBuffer_funcs[] = { MIST_FUNC_DEF(cmd, render_pass, 1), MIST_FUNC_DEF(cmd, copy_pass, 0), MIST_FUNC_DEF(cmd, compute_pass, 2), - MIST_FUNC_DEF(cmd, swapchain_pass, 1), - MIST_FUNC_DEF(cmd, acquire_swapchain,0), - MIST_FUNC_DEF(cmd, bind_vertex_buffer, 2), - MIST_FUNC_DEF(cmd, bind_index_buffer, 1), - MIST_FUNC_DEF(cmd, bind_fragment_sampler, 3), MIST_FUNC_DEF(cmd, push_vertex_uniform_data, 2), MIST_FUNC_DEF(cmd, push_fragment_uniform_data, 2), MIST_FUNC_DEF(cmd, push_compute_uniform_data, 2), + MIST_FUNC_DEF(cmd, generate_mipmaps, 1), MIST_FUNC_DEF(cmd, submit, 0), MIST_FUNC_DEF(cmd, cancel, 0), - MIST_FUNC_DEF(cmd, camera, 2), - MIST_FUNC_DEF(cmd, hud, 2), MIST_FUNC_DEF(cmd, push_debug_group, 1), MIST_FUNC_DEF(cmd, pop_debug_group, 0), MIST_FUNC_DEF(cmd, debug_label, 1), MIST_FUNC_DEF(cmd, blit, 1), + MIST_FUNC_DEF(cmd, swapchain_pass, 1), }; JSC_CCALL(copypass_end, @@ -2605,15 +1443,25 @@ JSC_CCALL(copypass_upload_to_texture, JS_GETPROP(js, texture_region.h, texture_region_val, h, number) JS_GETPROP(js, texture_region.d, texture_region_val, d, number) - bool cycle = argc > 2 ? JS_ToBool(js, argv[2]) : false; + bool cycle = JS_ToBool(js, argv[2]); SDL_UploadToGPUTexture(pass, &transfer_info, &texture_region, cycle); ) +JSC_CCALL(copypass_buffer_to_buffer, + SDL_GPUCopyPass *pass = js2SDL_GPUCopyPass(js,self); + SDL_GPUBuffer *b1 = js2SDL_GPUBuffer(js,argv[0]); + SDL_GPUBuffer *b2 = js2SDL_GPUBuffer(js,argv[1]); + size_t size = js2number(js,argv[2]); + bool cycle = js2bool(js,argv[3]); + SDL_CopyGPUBufferToBuffer(pass,b1,b2,size,cycle); +) + static const JSCFunctionListEntry js_SDL_GPUCopyPass_funcs[] = { MIST_FUNC_DEF(copypass, end, 0), MIST_FUNC_DEF(copypass, upload_to_buffer, 3), MIST_FUNC_DEF(copypass, upload_to_texture, 3), + MIST_FUNC_DEF(copypass, buffer_to_buffer, 4), }; JSC_SCALL(buffer_name, @@ -2647,11 +1495,9 @@ JSC_CCALL(transferbuffer_copy_blob, void *blob_data = js_get_blob_data(js, &blob_size, blob); if (!blob_data) return JS_ThrowTypeError(js, "copy_blob: Expected a blob"); - // Map the transfer buffer void *mapped_data = SDL_MapGPUTransferBuffer(gpu, buffer, false); if (!mapped_data) return JS_ThrowReferenceError(js, "copy_blob: Failed to map transfer buffer: %s", SDL_GetError()); - // Copy blob data to mapped buffer SDL_memcpy(mapped_data, blob_data, blob_size); // Unmap the transfer buffer @@ -2716,7 +1562,7 @@ JSC_CCALL(compute_storage_buffers, b[i] = js2SDL_GPUBuffer(js,s); JS_FreeValue(js,s); } - SDL_BindGPUComputeStorageTextures(pass,js2number(js,argv[1]),b,n); + SDL_BindGPUComputeStorageBuffers(pass,js2number(js,argv[1]),b,n); ) static const JSCFunctionListEntry js_SDL_GPUComputePass_funcs[] = { @@ -2729,11 +1575,6 @@ static const JSCFunctionListEntry js_SDL_GPUComputePass_funcs[] = { }; // Empty function arrays for classes with no methods yet -static const JSCFunctionListEntry js_SDL_GPUGraphicsPipeline_funcs[] = {}; -static const JSCFunctionListEntry js_SDL_GPUComputePipeline_funcs[] = {}; -static const JSCFunctionListEntry js_SDL_GPUSampler_funcs[] = {}; -static const JSCFunctionListEntry js_SDL_GPUShader_funcs[] = {}; - // GPU device constructor function static JSValue js_gpu_constructor(JSContext *js, JSValueConst new_target, int argc, JSValueConst *argv) @@ -2753,10 +1594,8 @@ static JSValue js_gpu_constructor(JSContext *js, JSValueConst new_target, int ar JS_FreeValue(js, val); \ } while(0) - // Set boolean properties SET_BOOL_PROP("debug", SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN); SET_BOOL_PROP("lowpower", SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN); - // SET_BOOL_PROP("verbose", SDL_PROP_GPU_DEVICE_CREATE_VERBOSE_BOOLEAN); // Not available in current SDL // Shader format properties SET_BOOL_PROP("shaders_private", SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN); @@ -2766,12 +1605,6 @@ static JSValue js_gpu_constructor(JSContext *js, JSValueConst new_target, int ar SET_BOOL_PROP("shaders_msl", SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN); SET_BOOL_PROP("shaders_metallib", SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN); - // Vulkan-specific properties - uncomment when available in SDL - // SET_BOOL_PROP("vulkan_shaderclipdistance", SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SHADERCLIPDISTANCE_BOOLEAN); - // SET_BOOL_PROP("vulkan_depthclamp", SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DEPTHCLAMP_BOOLEAN); - // SET_BOOL_PROP("vulkan_drawindirectfirst", SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DRAWINDIRECTFIRST_BOOLEAN); - // SET_BOOL_PROP("vulkan_sampleranisotropy", SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SAMPLERANISOTROPY_BOOLEAN); - #undef SET_BOOL_PROP // Handle string properties @@ -2820,19 +1653,20 @@ JSValue js_sdl_gpu_use(JSContext *js) // Initialize classes QJSCLASSPREP_FUNCS(SDL_GPUDevice) - QJSCLASSPREP_NO_FUNCS(SDL_GPUBuffer) - QJSCLASSPREP_NO_FUNCS(SDL_GPUComputePipeline) - QJSCLASSPREP_NO_FUNCS(SDL_GPUGraphicsPipeline) - QJSCLASSPREP_NO_FUNCS(SDL_GPUSampler) - QJSCLASSPREP_NO_FUNCS(SDL_GPUShader) + QJSCLASSPREP_FUNCS(SDL_GPUBuffer) QJSCLASSPREP_FUNCS(SDL_GPUTexture) QJSCLASSPREP_FUNCS(SDL_GPUTransferBuffer) - QJSCLASSPREP_NO_FUNCS(SDL_GPUFence) QJSCLASSPREP_FUNCS(SDL_GPUCommandBuffer) QJSCLASSPREP_FUNCS(SDL_GPUComputePass) QJSCLASSPREP_FUNCS(SDL_GPUCopyPass) QJSCLASSPREP_FUNCS(SDL_GPURenderPass) + QJSCLASSPREP_NO_FUNCS(SDL_GPUFence) + QJSCLASSPREP_NO_FUNCS(SDL_GPUComputePipeline) + QJSCLASSPREP_NO_FUNCS(SDL_GPUGraphicsPipeline) + QJSCLASSPREP_NO_FUNCS(SDL_GPUSampler) + QJSCLASSPREP_NO_FUNCS(SDL_GPUShader) + // Create GPU constructor JSValue gpu_ctor = JS_NewCFunction2(js, js_gpu_constructor, "gpu", 1, JS_CFUNC_constructor, 0);