From 36678c11279e54e61abd06b34b717777f541a552 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Tue, 26 Nov 2024 10:50:26 -0500 Subject: [PATCH] Fixes for nov 7 breaking changes to sokol_gfx --- .../engine/client_api_sokol_callbacks.odin | 4 +- code/sectr/engine/render.odin | 27 ++--- code/sectr/font/provider.odin | 4 +- code/sectr/font/render_sokol.odin | 12 +-- code/sectr/shaders/ve_blit_atlas.odin | 96 +++++++++--------- code/sectr/shaders/ve_blit_atlas.shdc.glsl | 6 +- code/sectr/shaders/ve_draw_text.odin | 96 +++++++++--------- code/sectr/shaders/ve_draw_text.shdc.glsl | 6 +- code/sectr/shaders/ve_render_glyph.odin | 39 +++---- docs/input sys design.pur | Bin 79671 -> 79695 bytes scripts/compile_shaders.ps1 | 1 - 11 files changed, 145 insertions(+), 146 deletions(-) diff --git a/code/sectr/engine/client_api_sokol_callbacks.odin b/code/sectr/engine/client_api_sokol_callbacks.odin index b7bb485..f4afd28 100644 --- a/code/sectr/engine/client_api_sokol_callbacks.odin +++ b/code/sectr/engine/client_api_sokol_callbacks.odin @@ -52,7 +52,7 @@ sokol_app_cleanup_callback :: proc "c" () { log("sokol_app: Confirmed cleanup") } -sokol_app_alloc :: proc "c" ( size : u64, user_data : rawptr ) -> rawptr { +sokol_app_alloc :: proc "c" ( size : uint, user_data : rawptr ) -> rawptr { context = get_state().sokol_context block, error := alloc( int(size), allocator = persistent_slab_allocator() ) ensure(error == AllocatorError.None, "sokol_app allocation failed") @@ -235,7 +235,7 @@ sokol_app_event_callback :: proc "c" (sokol_event : ^sokol_app.Event) #region("Sokol GFX") -sokol_gfx_alloc :: proc "c" ( size : u64, user_data : rawptr ) -> rawptr { +sokol_gfx_alloc :: proc "c" ( size : uint, user_data : rawptr ) -> rawptr { context = get_state().sokol_context block, error := alloc( int(size), allocator = persistent_slab_allocator() ) ensure(error == AllocatorError.None, "sokol_gfx allocation failed") diff --git a/code/sectr/engine/render.odin b/code/sectr/engine/render.odin index 9c36ca1..3daa5f3 100644 --- a/code/sectr/engine/render.odin +++ b/code/sectr/engine/render.odin @@ -223,7 +223,7 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State debug_text("Mouse Position (Workspace View): %0.2f", screen_to_ws_view_pos(input.mouse.pos) ) } - if false + if true { ui := & project.workspace.ui @@ -243,7 +243,7 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State } } - if false + if true { ui := & screen_ui @@ -260,7 +260,7 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State } } - if false { + if true { state.config.font_size_canvas_scalar = 1.5 zoom_adjust_size := 16 * state.project.workspace.cam.zoom over_sample := f32(state.config.font_size_canvas_scalar) @@ -301,8 +301,8 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render : vbuf_layer_slice, ibuf_layer_slice, calls_layer_slice := ve.get_draw_list_layer( ve_ctx ) - vbuf_ve_range := Range{ raw_data(vbuf_layer_slice), cast(u64) len(vbuf_layer_slice) * size_of(ve.Vertex) } - ibuf_ve_range := Range{ raw_data(ibuf_layer_slice), cast(u64) len(ibuf_layer_slice) * size_of(u32) } + vbuf_ve_range := Range{ raw_data(vbuf_layer_slice), cast(uint) len(vbuf_layer_slice) * size_of(ve.Vertex) } + ibuf_ve_range := Range{ raw_data(ibuf_layer_slice), cast(uint) len(ibuf_layer_slice) * size_of(u32) } gfx.append_buffer( draw_list_vbuf, vbuf_ve_range ) gfx.append_buffer( draw_list_ibuf, ibuf_ve_range ) @@ -353,7 +353,6 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render : }, index_buffer = draw_list_ibuf, index_buffer_offset = 0,//i32(draw_call.start_index) * size_of(u32), - fs = {}, } gfx.apply_bindings( bindings ) @@ -381,7 +380,7 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render : gfx.apply_pipeline( atlas_pipeline ) fs_uniform := Ve_Blit_Atlas_Fs_Params { region = cast(i32) draw_call.region } - gfx.apply_uniforms( ShaderStage.FS, SLOT_ve_blit_atlas_fs_params, Range { & fs_uniform, size_of(Ve_Blit_Atlas_Fs_Params) }) + gfx.apply_uniforms( UB_ve_blit_atlas_fs_params, Range { & fs_uniform, size_of(Ve_Blit_Atlas_Fs_Params) }) gfx.apply_bindings(Bindings { vertex_buffers = { @@ -392,10 +391,8 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render : }, index_buffer = draw_list_ibuf, index_buffer_offset = 0,//i32(draw_call.start_index) * size_of(u32), - fs = { - images = { SLOT_ve_blit_atlas_src_texture = glyph_rt_color, }, - samplers = { SLOT_ve_blit_atlas_src_sampler = glyph_rt_sampler, }, - }, + images = { IMG_ve_blit_atlas_src_texture = glyph_rt_color, }, + samplers = { SMP_ve_blit_atlas_src_sampler = glyph_rt_sampler, }, }) // 3. Use the atlas to then render the text. @@ -428,7 +425,7 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render : src_rt = glyph_rt_color src_sampler = glyph_rt_sampler } - gfx.apply_uniforms( ShaderStage.FS, SLOT_ve_draw_text_fs_params, Range { & fs_target_uniform, size_of(Ve_Draw_Text_Fs_Params) }) + gfx.apply_uniforms( UB_ve_draw_text_fs_params, Range { & fs_target_uniform, size_of(Ve_Draw_Text_Fs_Params) }) gfx.apply_bindings(Bindings { vertex_buffers = { @@ -439,10 +436,8 @@ render_text_layer :: proc( screen_extent : Vec2, ve_ctx : ^ve.Context, render : }, index_buffer = draw_list_ibuf, index_buffer_offset = 0,//i32(draw_call.start_index) * size_of(u32), - fs = { - images = { SLOT_ve_draw_text_src_texture = src_rt, }, - samplers = { SLOT_ve_draw_text_src_sampler = src_sampler, }, - }, + images = { IMG_ve_draw_text_src_texture = src_rt, }, + samplers = { SMP_ve_draw_text_src_sampler = src_sampler, }, }) } diff --git a/code/sectr/font/provider.odin b/code/sectr/font/provider.odin index abf5bdf..2e6348d 100644 --- a/code/sectr/font/provider.odin +++ b/code/sectr/font/provider.odin @@ -23,7 +23,7 @@ FontID :: struct { FontDef :: struct { path_file : string, default_size : i32, - size_table : [Font_Largest_Px_Size / Font_Size_Interval] ve.FontID, + size_table : [Font_Largest_Px_Size / Font_Size_Interval] ve.Font_ID, } FontProviderContext :: struct @@ -114,7 +114,7 @@ font_load :: proc(path_file : string, Font_Use_Default_Size :: f32(0.0) -font_provider_resolve_draw_id :: proc( id : FontID, size := Font_Use_Default_Size ) -> (ve_id :ve.FontID, resolved_size : i32) +font_provider_resolve_draw_id :: proc( id : FontID, size := Font_Use_Default_Size ) -> (ve_id :ve.Font_ID, resolved_size : i32) { provider_data := get_state().font_provider_ctx; using provider_data diff --git a/code/sectr/font/render_sokol.odin b/code/sectr/font/render_sokol.odin index 06642e1..d76269c 100644 --- a/code/sectr/font/render_sokol.odin +++ b/code/sectr/font/render_sokol.odin @@ -87,12 +87,12 @@ font_provider_setup_sokol_gfx_objects :: proc( ctx : ^VE_RenderData, ve_ctx : ve vs_layout : VertexLayoutState { using vs_layout - attrs[ATTR_ve_render_glyph_vs_v_position] = VertexAttributeState { + attrs[ATTR_ve_render_glyph_v_position] = VertexAttributeState { format = VertexFormat.FLOAT2, offset = 0, buffer_index = 0, } - attrs[ATTR_ve_render_glyph_vs_v_texture] = VertexAttributeState { + attrs[ATTR_ve_render_glyph_v_texture] = VertexAttributeState { format = VertexFormat.FLOAT2, offset = size_of(Vec2), buffer_index = 0, @@ -226,12 +226,12 @@ font_provider_setup_sokol_gfx_objects :: proc( ctx : ^VE_RenderData, ve_ctx : ve vs_layout : VertexLayoutState { using vs_layout - attrs[ATTR_ve_blit_atlas_vs_v_position] = VertexAttributeState { + attrs[ATTR_ve_blit_atlas_v_position] = VertexAttributeState { format = VertexFormat.FLOAT2, offset = 0, buffer_index = 0, } - attrs[ATTR_ve_blit_atlas_vs_v_texture] = VertexAttributeState { + attrs[ATTR_ve_blit_atlas_v_texture] = VertexAttributeState { format = VertexFormat.FLOAT2, offset = size_of(Vec2), buffer_index = 0, @@ -365,12 +365,12 @@ font_provider_setup_sokol_gfx_objects :: proc( ctx : ^VE_RenderData, ve_ctx : ve vs_layout : VertexLayoutState { using vs_layout - attrs[ATTR_ve_draw_text_vs_v_position] = VertexAttributeState { + attrs[ATTR_ve_draw_text_v_position] = VertexAttributeState { format = VertexFormat.FLOAT2, offset = 0, buffer_index = 0, } - attrs[ATTR_ve_draw_text_vs_v_texture] = VertexAttributeState { + attrs[ATTR_ve_draw_text_v_texture] = VertexAttributeState { format = VertexFormat.FLOAT2, offset = size_of(Vec2), buffer_index = 0, diff --git a/code/sectr/shaders/ve_blit_atlas.odin b/code/sectr/shaders/ve_blit_atlas.odin index 62100df..864ec75 100644 --- a/code/sectr/shaders/ve_blit_atlas.odin +++ b/code/sectr/shaders/ve_blit_atlas.odin @@ -12,31 +12,29 @@ import sg "thirdparty:sokol/gfx" ========= Shader program: 've_blit_atlas': Get shader desc: ve_blit_atlas_shader_desc(sg.query_backend()) - Vertex shader: ve_blit_atlas_vs - Attributes: - ATTR_ve_blit_atlas_vs_v_position => 0 - ATTR_ve_blit_atlas_vs_v_texture => 1 - Fragment shader: ve_blit_atlas_fs - Uniform block 've_blit_atlas_fs_params': - Odin struct: Ve_Blit_Atlas_Fs_Params - Bind slot: SLOT_ve_blit_atlas_fs_params => 0 - Image 've_blit_atlas_src_texture': - Image type: ._2D - Sample type: .FLOAT - Multisampled: false - Bind slot: SLOT_ve_blit_atlas_src_texture => 0 - Sampler 've_blit_atlas_src_sampler': - Type: .FILTERING - Bind slot: SLOT_ve_blit_atlas_src_sampler => 0 - Image Sampler Pair 've_blit_atlas_src_texture_ve_blit_atlas_src_sampler': - Image: ve_blit_atlas_src_texture - Sampler: ve_blit_atlas_src_sampler + Vertex Shader: ve_blit_atlas_vs + Fragment Shader: ve_blit_atlas_fs + Attributes: + ATTR_ve_blit_atlas_v_position => 0 + ATTR_ve_blit_atlas_v_texture => 1 + Bindings: + Uniform block 've_blit_atlas_fs_params': + Odin struct: Ve_Blit_Atlas_Fs_Params + Bind slot: UB_ve_blit_atlas_fs_params => 0 + Image 've_blit_atlas_src_texture': + Image type: ._2D + Sample type: .FLOAT + Multisampled: false + Bind slot: IMG_ve_blit_atlas_src_texture => 0 + Sampler 've_blit_atlas_src_sampler': + Type: .FILTERING + Bind slot: SMP_ve_blit_atlas_src_sampler => 0 */ -ATTR_ve_blit_atlas_vs_v_position :: 0 -ATTR_ve_blit_atlas_vs_v_texture :: 1 -SLOT_ve_blit_atlas_fs_params :: 0 -SLOT_ve_blit_atlas_src_texture :: 0 -SLOT_ve_blit_atlas_src_sampler :: 0 +ATTR_ve_blit_atlas_v_position :: 0 +ATTR_ve_blit_atlas_v_texture :: 1 +UB_ve_blit_atlas_fs_params :: 0 +IMG_ve_blit_atlas_src_texture :: 0 +SMP_ve_blit_atlas_src_sampler :: 0 Ve_Blit_Atlas_Fs_Params :: struct #align(16) { using _: struct #packed { region: i32, @@ -78,7 +76,7 @@ Ve_Blit_Atlas_Fs_Params :: struct #align(16) { return stage_output; } */ -@(private) +@(private="file") ve_blit_atlas_vs_source_hlsl4 := [705]u8 { 0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c, 0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69, @@ -201,7 +199,7 @@ ve_blit_atlas_vs_source_hlsl4 := [705]u8 { return stage_output; } */ -@(private) +@(private="file") ve_blit_atlas_fs_source_hlsl4 := [2140]u8 { 0x63,0x62,0x75,0x66,0x66,0x65,0x72,0x20,0x76,0x65,0x5f,0x62,0x6c,0x69,0x74,0x5f, 0x61,0x74,0x6c,0x61,0x73,0x5f,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x20, @@ -343,27 +341,31 @@ ve_blit_atlas_shader_desc :: proc (backend: sg.Backend) -> sg.Shader_Desc { desc.label = "ve_blit_atlas_shader" #partial switch backend { case .D3D11: - desc.attrs[0].sem_name = "TEXCOORD" - desc.attrs[0].sem_index = 0 - desc.attrs[1].sem_name = "TEXCOORD" - desc.attrs[1].sem_index = 1 - desc.vs.source = transmute(cstring)&ve_blit_atlas_vs_source_hlsl4 - desc.vs.d3d11_target = "vs_4_0" - desc.vs.entry = "main" - desc.fs.source = transmute(cstring)&ve_blit_atlas_fs_source_hlsl4 - desc.fs.d3d11_target = "ps_4_0" - desc.fs.entry = "main" - desc.fs.uniform_blocks[0].size = 16 - desc.fs.uniform_blocks[0].layout = .STD140 - desc.fs.images[0].used = true - desc.fs.images[0].multisampled = false - desc.fs.images[0].image_type = ._2D - desc.fs.images[0].sample_type = .FLOAT - desc.fs.samplers[0].used = true - desc.fs.samplers[0].sampler_type = .FILTERING - desc.fs.image_sampler_pairs[0].used = true - desc.fs.image_sampler_pairs[0].image_slot = 0 - desc.fs.image_sampler_pairs[0].sampler_slot = 0 + desc.vertex_func.source = transmute(cstring)&ve_blit_atlas_vs_source_hlsl4 + desc.vertex_func.d3d11_target = "vs_4_0" + desc.vertex_func.entry = "main" + desc.fragment_func.source = transmute(cstring)&ve_blit_atlas_fs_source_hlsl4 + desc.fragment_func.d3d11_target = "ps_4_0" + desc.fragment_func.entry = "main" + desc.attrs[0].hlsl_sem_name = "TEXCOORD" + desc.attrs[0].hlsl_sem_index = 0 + desc.attrs[1].hlsl_sem_name = "TEXCOORD" + desc.attrs[1].hlsl_sem_index = 1 + desc.uniform_blocks[0].stage = .FRAGMENT + desc.uniform_blocks[0].layout = .STD140 + desc.uniform_blocks[0].size = 16 + desc.uniform_blocks[0].hlsl_register_b_n = 0 + desc.images[0].stage = .FRAGMENT + desc.images[0].multisampled = false + desc.images[0].image_type = ._2D + desc.images[0].sample_type = .FLOAT + desc.images[0].hlsl_register_t_n = 0 + desc.samplers[0].stage = .FRAGMENT + desc.samplers[0].sampler_type = .FILTERING + desc.samplers[0].hlsl_register_s_n = 0 + desc.image_sampler_pairs[0].stage = .FRAGMENT + desc.image_sampler_pairs[0].image_slot = 0 + desc.image_sampler_pairs[0].sampler_slot = 0 } return desc } diff --git a/code/sectr/shaders/ve_blit_atlas.shdc.glsl b/code/sectr/shaders/ve_blit_atlas.shdc.glsl index 2108f34..8b07b6f 100644 --- a/code/sectr/shaders/ve_blit_atlas.shdc.glsl +++ b/code/sectr/shaders/ve_blit_atlas.shdc.glsl @@ -11,10 +11,10 @@ in vec2 uv; out vec4 frag_color; -uniform texture2D ve_blit_atlas_src_texture; -uniform sampler ve_blit_atlas_src_sampler; +layout(binding = 0) uniform texture2D ve_blit_atlas_src_texture; +layout(binding = 0) uniform sampler ve_blit_atlas_src_sampler; -uniform ve_blit_atlas_fs_params { +layout(binding = 0) uniform ve_blit_atlas_fs_params { int region; }; diff --git a/code/sectr/shaders/ve_draw_text.odin b/code/sectr/shaders/ve_draw_text.odin index 334627a..ec9179e 100644 --- a/code/sectr/shaders/ve_draw_text.odin +++ b/code/sectr/shaders/ve_draw_text.odin @@ -12,31 +12,29 @@ import sg "thirdparty:sokol/gfx" ========= Shader program: 've_draw_text': Get shader desc: ve_draw_text_shader_desc(sg.query_backend()) - Vertex shader: ve_draw_text_vs - Attributes: - ATTR_ve_draw_text_vs_v_position => 0 - ATTR_ve_draw_text_vs_v_texture => 1 - Fragment shader: ve_draw_text_fs - Uniform block 've_draw_text_fs_params': - Odin struct: Ve_Draw_Text_Fs_Params - Bind slot: SLOT_ve_draw_text_fs_params => 0 - Image 've_draw_text_src_texture': - Image type: ._2D - Sample type: .FLOAT - Multisampled: false - Bind slot: SLOT_ve_draw_text_src_texture => 0 - Sampler 've_draw_text_src_sampler': - Type: .FILTERING - Bind slot: SLOT_ve_draw_text_src_sampler => 0 - Image Sampler Pair 've_draw_text_src_texture_ve_draw_text_src_sampler': - Image: ve_draw_text_src_texture - Sampler: ve_draw_text_src_sampler + Vertex Shader: ve_draw_text_vs + Fragment Shader: ve_draw_text_fs + Attributes: + ATTR_ve_draw_text_v_position => 0 + ATTR_ve_draw_text_v_texture => 1 + Bindings: + Uniform block 've_draw_text_fs_params': + Odin struct: Ve_Draw_Text_Fs_Params + Bind slot: UB_ve_draw_text_fs_params => 0 + Image 've_draw_text_src_texture': + Image type: ._2D + Sample type: .FLOAT + Multisampled: false + Bind slot: IMG_ve_draw_text_src_texture => 0 + Sampler 've_draw_text_src_sampler': + Type: .FILTERING + Bind slot: SMP_ve_draw_text_src_sampler => 0 */ -ATTR_ve_draw_text_vs_v_position :: 0 -ATTR_ve_draw_text_vs_v_texture :: 1 -SLOT_ve_draw_text_fs_params :: 0 -SLOT_ve_draw_text_src_texture :: 0 -SLOT_ve_draw_text_src_sampler :: 0 +ATTR_ve_draw_text_v_position :: 0 +ATTR_ve_draw_text_v_texture :: 1 +UB_ve_draw_text_fs_params :: 0 +IMG_ve_draw_text_src_texture :: 0 +SMP_ve_draw_text_src_sampler :: 0 Ve_Draw_Text_Fs_Params :: struct #align(16) { using _: struct #packed { down_sample: i32, @@ -79,7 +77,7 @@ Ve_Draw_Text_Fs_Params :: struct #align(16) { return stage_output; } */ -@(private) +@(private="file") ve_draw_text_vs_source_hlsl4 := [724]u8 { 0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c, 0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69, @@ -170,7 +168,7 @@ ve_draw_text_vs_source_hlsl4 := [724]u8 { return stage_output; } */ -@(private) +@(private="file") ve_draw_text_fs_source_hlsl4 := [1296]u8 { 0x63,0x62,0x75,0x66,0x66,0x65,0x72,0x20,0x76,0x65,0x5f,0x64,0x72,0x61,0x77,0x5f, 0x74,0x65,0x78,0x74,0x5f,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x20,0x3a, @@ -260,27 +258,31 @@ ve_draw_text_shader_desc :: proc (backend: sg.Backend) -> sg.Shader_Desc { desc.label = "ve_draw_text_shader" #partial switch backend { case .D3D11: - desc.attrs[0].sem_name = "TEXCOORD" - desc.attrs[0].sem_index = 0 - desc.attrs[1].sem_name = "TEXCOORD" - desc.attrs[1].sem_index = 1 - desc.vs.source = transmute(cstring)&ve_draw_text_vs_source_hlsl4 - desc.vs.d3d11_target = "vs_4_0" - desc.vs.entry = "main" - desc.fs.source = transmute(cstring)&ve_draw_text_fs_source_hlsl4 - desc.fs.d3d11_target = "ps_4_0" - desc.fs.entry = "main" - desc.fs.uniform_blocks[0].size = 32 - desc.fs.uniform_blocks[0].layout = .STD140 - desc.fs.images[0].used = true - desc.fs.images[0].multisampled = false - desc.fs.images[0].image_type = ._2D - desc.fs.images[0].sample_type = .FLOAT - desc.fs.samplers[0].used = true - desc.fs.samplers[0].sampler_type = .FILTERING - desc.fs.image_sampler_pairs[0].used = true - desc.fs.image_sampler_pairs[0].image_slot = 0 - desc.fs.image_sampler_pairs[0].sampler_slot = 0 + desc.vertex_func.source = transmute(cstring)&ve_draw_text_vs_source_hlsl4 + desc.vertex_func.d3d11_target = "vs_4_0" + desc.vertex_func.entry = "main" + desc.fragment_func.source = transmute(cstring)&ve_draw_text_fs_source_hlsl4 + desc.fragment_func.d3d11_target = "ps_4_0" + desc.fragment_func.entry = "main" + desc.attrs[0].hlsl_sem_name = "TEXCOORD" + desc.attrs[0].hlsl_sem_index = 0 + desc.attrs[1].hlsl_sem_name = "TEXCOORD" + desc.attrs[1].hlsl_sem_index = 1 + desc.uniform_blocks[0].stage = .FRAGMENT + desc.uniform_blocks[0].layout = .STD140 + desc.uniform_blocks[0].size = 32 + desc.uniform_blocks[0].hlsl_register_b_n = 0 + desc.images[0].stage = .FRAGMENT + desc.images[0].multisampled = false + desc.images[0].image_type = ._2D + desc.images[0].sample_type = .FLOAT + desc.images[0].hlsl_register_t_n = 0 + desc.samplers[0].stage = .FRAGMENT + desc.samplers[0].sampler_type = .FILTERING + desc.samplers[0].hlsl_register_s_n = 0 + desc.image_sampler_pairs[0].stage = .FRAGMENT + desc.image_sampler_pairs[0].image_slot = 0 + desc.image_sampler_pairs[0].sampler_slot = 0 } return desc } diff --git a/code/sectr/shaders/ve_draw_text.shdc.glsl b/code/sectr/shaders/ve_draw_text.shdc.glsl index 404ce9f..291face 100644 --- a/code/sectr/shaders/ve_draw_text.shdc.glsl +++ b/code/sectr/shaders/ve_draw_text.shdc.glsl @@ -19,10 +19,10 @@ void main() in vec2 uv; out vec4 frag_color; -uniform texture2D ve_draw_text_src_texture; -uniform sampler ve_draw_text_src_sampler; +layout(binding = 0) uniform texture2D ve_draw_text_src_texture; +layout(binding = 0) uniform sampler ve_draw_text_src_sampler; -uniform ve_draw_text_fs_params { +layout(binding = 0) uniform ve_draw_text_fs_params { int down_sample; vec4 colour; }; diff --git a/code/sectr/shaders/ve_render_glyph.odin b/code/sectr/shaders/ve_render_glyph.odin index cce323a..3f34bb0 100644 --- a/code/sectr/shaders/ve_render_glyph.odin +++ b/code/sectr/shaders/ve_render_glyph.odin @@ -12,14 +12,15 @@ import sg "thirdparty:sokol/gfx" ========= Shader program: 've_render_glyph': Get shader desc: ve_render_glyph_shader_desc(sg.query_backend()) - Vertex shader: ve_render_glyph_vs - Attributes: - ATTR_ve_render_glyph_vs_v_position => 0 - ATTR_ve_render_glyph_vs_v_texture => 1 - Fragment shader: ve_render_glyph_fs + Vertex Shader: ve_render_glyph_vs + Fragment Shader: ve_render_glyph_fs + Attributes: + ATTR_ve_render_glyph_v_position => 0 + ATTR_ve_render_glyph_v_texture => 1 + Bindings: */ -ATTR_ve_render_glyph_vs_v_position :: 0 -ATTR_ve_render_glyph_vs_v_texture :: 1 +ATTR_ve_render_glyph_v_position :: 0 +ATTR_ve_render_glyph_v_texture :: 1 /* static float4 gl_Position; static float2 uv; @@ -55,7 +56,7 @@ ATTR_ve_render_glyph_vs_v_texture :: 1 return stage_output; } */ -@(private) +@(private="file") ve_render_glyph_vs_source_hlsl4 := [705]u8 { 0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c, 0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69, @@ -131,7 +132,7 @@ ve_render_glyph_vs_source_hlsl4 := [705]u8 { return stage_output; } */ -@(private) +@(private="file") ve_render_glyph_fs_source_hlsl4 := [427]u8 { 0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72, 0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63, @@ -166,16 +167,16 @@ ve_render_glyph_shader_desc :: proc (backend: sg.Backend) -> sg.Shader_Desc { desc.label = "ve_render_glyph_shader" #partial switch backend { case .D3D11: - desc.attrs[0].sem_name = "TEXCOORD" - desc.attrs[0].sem_index = 0 - desc.attrs[1].sem_name = "TEXCOORD" - desc.attrs[1].sem_index = 1 - desc.vs.source = transmute(cstring)&ve_render_glyph_vs_source_hlsl4 - desc.vs.d3d11_target = "vs_4_0" - desc.vs.entry = "main" - desc.fs.source = transmute(cstring)&ve_render_glyph_fs_source_hlsl4 - desc.fs.d3d11_target = "ps_4_0" - desc.fs.entry = "main" + desc.vertex_func.source = transmute(cstring)&ve_render_glyph_vs_source_hlsl4 + desc.vertex_func.d3d11_target = "vs_4_0" + desc.vertex_func.entry = "main" + desc.fragment_func.source = transmute(cstring)&ve_render_glyph_fs_source_hlsl4 + desc.fragment_func.d3d11_target = "ps_4_0" + desc.fragment_func.entry = "main" + desc.attrs[0].hlsl_sem_name = "TEXCOORD" + desc.attrs[0].hlsl_sem_index = 0 + desc.attrs[1].hlsl_sem_name = "TEXCOORD" + desc.attrs[1].hlsl_sem_index = 1 } return desc } diff --git a/docs/input sys design.pur b/docs/input sys design.pur index 89d89cfebc7f6d78554ff862bb7779e76de2f349..d93f680a307d765ce8a62825b535a0b16fa6ef78 100644 GIT binary patch delta 11590 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