Finished first draft for VEFontCache font provider hookup for sokol_gfx (untested)
This commit is contained in:
		| @@ -116,13 +116,6 @@ font_key_from_label :: #force_inline proc( label : string ) -> u64 { | ||||
| 	return hash | ||||
| } | ||||
|  | ||||
| // ve_fontcache_configure_snap | ||||
| configure_snap :: proc( ctx : ^Context, snap_width, snap_height : u32 ) { | ||||
| 	assert( ctx != nil ) | ||||
| 	ctx.snap_width  = snap_width | ||||
| 	ctx.snap_height = snap_height | ||||
| } | ||||
|  | ||||
| // For a provided alpha value, | ||||
| // allows the function to calculate the position of a point along the curve at any given fraction of its total length | ||||
| // ve_fontcache_eval_bezier (quadratic) | ||||
| @@ -358,6 +351,13 @@ shutdown :: proc( ctx : ^Context ) | ||||
| 	shaper_shutdown( & shaper_ctx ) | ||||
| } | ||||
|  | ||||
| // ve_fontcache_configure_snap | ||||
| configure_snap :: proc( ctx : ^Context, snap_width, snap_height : u32 ) { | ||||
| 	assert( ctx != nil ) | ||||
| 	ctx.snap_width  = snap_width | ||||
| 	ctx.snap_height = snap_height | ||||
| } | ||||
|  | ||||
| // ve_fontcache_load | ||||
| load_font :: proc( ctx : ^Context, label : string, data : []byte, size_px : f32 ) -> FontID | ||||
| { | ||||
|   | ||||
| @@ -6,7 +6,7 @@ DrawCall :: struct { | ||||
| 	end_index         : u32, | ||||
| 	clear_before_draw : b32, | ||||
| 	region            : AtlasRegionKind, | ||||
| 	colour            : [4]f32, | ||||
| 	colour            : Colour, | ||||
| } | ||||
|  | ||||
| DrawCall_Default :: DrawCall { | ||||
| @@ -25,11 +25,11 @@ DrawList :: struct { | ||||
| } | ||||
|  | ||||
| FrameBufferPass :: enum u32 { | ||||
| 	None             = 0, | ||||
| 	Glyph            = 1, | ||||
| 	Atlas            = 2, | ||||
| 	Target           = 3, | ||||
| 	Target_Unchanged = 4, | ||||
| 	None            = 0, | ||||
| 	Glyph           = 1, | ||||
| 	Atlas           = 2, | ||||
| 	Target          = 3, | ||||
| 	Target_Uncached = 4, | ||||
| } | ||||
|  | ||||
| GlyphDrawBuffer :: struct { | ||||
| @@ -127,7 +127,7 @@ directly_draw_massive_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph : Gly | ||||
| 	call : DrawCall | ||||
| 	{ | ||||
| 		using call | ||||
| 		pass        = .Target_Unchanged | ||||
| 		pass        = .Target_Uncached | ||||
| 		colour      = ctx.colour | ||||
| 		start_index = u32(ctx.draw_list.indices.num) | ||||
| 		blit_quad( & ctx.draw_list, dst, dst + { dst_width, dst_height }, glyph_position, glyph_position + glyph_size ) | ||||
| @@ -200,7 +200,7 @@ draw_cached_glyph :: proc( ctx : ^Context, entry : ^Entry, glyph_index : Glyph, | ||||
| 	call := DrawCall_Default | ||||
| 	{ | ||||
| 		using call | ||||
| 		pass        = .Target_Unchanged | ||||
| 		pass        = .Target_Uncached | ||||
| 		colour      = ctx.colour | ||||
| 		start_index = cast(u32) ctx.draw_list.indices.num | ||||
|  | ||||
|   | ||||
| @@ -88,7 +88,7 @@ shaper_shape_from_text :: proc( ctx : ^ShaperContext, info : ^ShaperInfo, output | ||||
| 		// script = HB_SCRIPT_LATIN | ||||
| 		harfbuzz.buffer_set_script( buffer, script ) | ||||
| 		harfbuzz.buffer_set_direction( buffer, harfbuzz.script_get_horizontal_direction( script )) | ||||
| 		harfbuzz.set_language( buffer, harfbuzz.language_get_default() ) | ||||
| 		harfbuzz.buffer_set_language( buffer, harfbuzz.language_get_default() ) | ||||
|  | ||||
| 		// Perform the actual shaping of this run using HarfBuzz. | ||||
| 		harfbuzz.shape( font, buffer, nil, 0 ) | ||||
|   | ||||
| @@ -177,8 +177,8 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem | ||||
| 		sokol_app.client_init() | ||||
|  | ||||
| 		window := & state.app_window | ||||
| 		window.extent.x = sokol_app.widthf() | ||||
| 		window.extent.y = sokol_app.heightf() | ||||
| 		window.extent.x = cast(f32) i32(sokol_app.widthf() * 0.5) | ||||
| 		window.extent.y = cast(f32) i32(sokol_app.heightf() * 0.5) | ||||
|  | ||||
| 		// TODO(Ed): We don't need monitor tracking until we have multi-window support (which I don't think I'll do for this prototype) | ||||
| 		// Sokol doesn't provide it. | ||||
|   | ||||
| @@ -27,11 +27,13 @@ sokol_app_frame_callback :: proc "c" () { | ||||
| 	window := & state.app_window | ||||
| 	// if	int(window.extent.x) != int(sokol_width) || int(window.extent.y) != int(sokol_height) { | ||||
| 		window.resized = true | ||||
| 		window.extent.x = sokol_width  * 0.5 | ||||
| 		window.extent.y = sokol_height * 0.5 | ||||
| 		window.extent.x = cast(f32) i32(sokol_width  * 0.5) | ||||
| 		window.extent.y = cast(f32) i32(sokol_height * 0.5) | ||||
| 		// log("sokol_app: Event-based frame callback triggered (detected a resize") | ||||
| 	// } | ||||
|  | ||||
| 	font_provider_reload() | ||||
|  | ||||
| 	// sokol_app is the only good reference for a frame-time at this point. | ||||
| 	sokol_delta_ms := sokol_app.frame_delta() | ||||
| 	sokol_delta_ns := transmute(Duration) sokol_delta_ms * MS_To_NS | ||||
|   | ||||
							
								
								
									
										190
									
								
								code/sectr/engine/render_vefc.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								code/sectr/engine/render_vefc.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| package sectr | ||||
|  | ||||
| import ve         "codebase:font/VEFontCache" | ||||
| import sokol_gfx  "thirdparty:sokol/gfx" | ||||
| import sokol_glue "thirdparty:sokol/glue" | ||||
|  | ||||
| PassActions :: struct { | ||||
| 	bg_clear_black : sokol_gfx.Pass_Action, | ||||
|  | ||||
| } | ||||
|  | ||||
| RenderState :: struct { | ||||
| 	pass_actions : PassActions, | ||||
| } | ||||
|  | ||||
| // TODO(Ed) : Review this and put into space.odin when ready | ||||
| ortho :: proc(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32) -> [4][4]f32 { | ||||
|     result: [4][4]f32 | ||||
|     result[0][0] = 2.0 / (right - left) | ||||
|     result[1][1] = 2.0 / (top - bottom) | ||||
|     result[2][2] = -2.0 / (far - near) | ||||
|     result[3][0] = -(right + left) / (right - left) | ||||
|     result[3][1] = -(top + bottom) / (top - bottom) | ||||
|     result[3][2] = -(far + near) / (far - near) | ||||
|     result[3][3] = 1.0 | ||||
|     return result | ||||
| } | ||||
|  | ||||
| render :: proc() | ||||
| { | ||||
| 	Bindings    :: sokol_gfx.Bindings | ||||
| 	Range       :: sokol_gfx.Range | ||||
| 	ShaderStage :: sokol_gfx.Shader_Stage | ||||
|  | ||||
| 	state := get_state(); using state | ||||
| 	using render_data | ||||
|  | ||||
| 	do_nothing : bool | ||||
| 	do_nothing = false | ||||
|  | ||||
| 	// The below are most likely limited to a "depth layer" and so | ||||
| 	// different depth layers need different draw pass combos (of the 3 constructive passes) | ||||
| 	// Will need to profile how expensive it is for batching with the UI box rendering | ||||
| 	// since the the text is correlated with the box rendering | ||||
|  | ||||
| 	font_provider := & state.font_provider_data | ||||
| 	using font_provider | ||||
| 	// ve_ctx := & font_provider.ve_font_cache | ||||
|  | ||||
| 	// "Draw text" using immediate mode api | ||||
| 	{ | ||||
| 		// text_test_str := str_fmt("frametime: %v", frametime_avg_ms) | ||||
| 		text_test_str := str_fmt("HELLO VE FONT CACHE!!!!!") | ||||
|  | ||||
| 		// font_provider := & state.font_provider_data | ||||
| 		fdef := hmap_chained_get( font_cache, default_font.key ) | ||||
|  | ||||
| 		ve.draw_text( & ve_font_cache, fdef.ve_id, text_test_str, {30, 30}, Vec2{1, 1} ) | ||||
| 	} | ||||
|  | ||||
| 	// Process the draw calls for drawing text | ||||
| 	{ | ||||
| 		draw_list := ve.get_draw_list( & ve_font_cache ) | ||||
|  | ||||
| 		sokol_gfx.update_buffer( draw_list_vbuf, Range{ draw_list.vertices.data, draw_list.vertices.num }) | ||||
| 		sokol_gfx.update_buffer( draw_list_ibuf, Range{ draw_list.indices.data,  draw_list.indices.num  }) | ||||
|  | ||||
| 		for & draw_call in array_to_slice(draw_list.calls) | ||||
| 		{ | ||||
| 			if (draw_call.end_index - draw_call.start_index) == 0 do continue | ||||
|  | ||||
| 			switch draw_call.pass | ||||
| 			{ | ||||
| 				// 1. Do the glyph rendering pass | ||||
| 				// Glyphs are first rendered to an intermediate 2k x 512px R8 texture | ||||
| 				case .Glyph: | ||||
| 					width  := ve_font_cache.atlas.buffer_width | ||||
| 					height := ve_font_cache.atlas.buffer_height | ||||
|  | ||||
| 					pass := glyph_pass | ||||
| 					if draw_call.clear_before_draw { | ||||
| 						pass.action.colors[0].load_action   = .CLEAR | ||||
| 						pass.action.colors[0].clear_value.a = 1.0 | ||||
| 					} | ||||
| 					sokol_gfx.begin_pass( pass ) | ||||
|  | ||||
| 					sokol_gfx.apply_viewport( 0,0, width, height, origin_top_left = true ) | ||||
| 					sokol_gfx.apply_scissor_rect( 0,0, width, height, origin_top_left = true ) | ||||
|  | ||||
| 					sokol_gfx.apply_pipeline( glyph_pipeline ) | ||||
|  | ||||
| 					bindings := Bindings { | ||||
| 						vertex_buffers = { | ||||
| 							0 = draw_list_vbuf, | ||||
| 						}, | ||||
| 						vertex_buffer_offsets = { | ||||
| 							0 = 0, | ||||
| 						}, | ||||
| 						index_buffer        = draw_list_ibuf, | ||||
| 						index_buffer_offset = i32(draw_call.start_index), | ||||
| 						fs = {}, | ||||
| 					} | ||||
| 					sokol_gfx.apply_bindings( bindings ) | ||||
|  | ||||
| 				// 2. Do the atlas rendering pass | ||||
| 				// A simple 16-tap box downsample shader is then used to blit from this intermediate texture to the final atlas location | ||||
| 				case .Atlas: | ||||
| 					width  := ve_font_cache.atlas.width | ||||
| 					height := ve_font_cache.atlas.height | ||||
|  | ||||
| 					pass := atlas_pass | ||||
| 					if draw_call.clear_before_draw { | ||||
| 						pass.action.colors[0].load_action = .CLEAR | ||||
| 						// pass.action.colors[0].clear_value.a = 0.0 | ||||
| 					} | ||||
| 					sokol_gfx.begin_pass( pass ) | ||||
|  | ||||
| 					sokol_gfx.apply_viewport( 0, 0, width, height, origin_top_left = true ) | ||||
| 					sokol_gfx.apply_scissor_rect( 0, 0, width, height, origin_top_left = true ) | ||||
|  | ||||
| 					sokol_gfx.apply_pipeline( atlas_pipeline ) | ||||
|  | ||||
| 					fs_uniform := Ve_Blit_Atlas_Fs_Params { region = cast(i32) draw_call.region } | ||||
| 					sokol_gfx.apply_uniforms( ShaderStage.FS, SLOT_ve_blit_atlas_fs_params, Range { & fs_uniform, size_of(fs_uniform) }) | ||||
|  | ||||
| 					sokol_gfx.apply_bindings(Bindings { | ||||
| 						vertex_buffers = { | ||||
| 							0 = draw_list_vbuf, | ||||
| 						}, | ||||
| 						vertex_buffer_offsets = { | ||||
| 							0 = 0, | ||||
| 						}, | ||||
| 						index_buffer        = draw_list_ibuf, | ||||
| 						index_buffer_offset = i32(draw_call.start_index), | ||||
| 						fs = { | ||||
| 							images   = { SLOT_ve_blit_atlas_src_texture = glyph_rt_color, }, | ||||
| 							samplers = { SLOT_ve_blit_atlas_src_sampler = gfx_sampler,   }, | ||||
| 						}, | ||||
| 					}) | ||||
|  | ||||
| 				// 3. Use the atlas to then render the text. | ||||
| 				case .None: fallthrough | ||||
| 				case .Target: fallthrough | ||||
| 				case .Target_Uncached: | ||||
| 					width  := u32(app_window.extent.x * 2) | ||||
| 					height := u32(app_window.extent.y * 2) | ||||
|  | ||||
| 					pass := atlas_pass | ||||
| 					if ! draw_call.clear_before_draw { | ||||
| 						pass.action.colors[0].load_action = .LOAD | ||||
| 						// pass.action.colors[0].clear_value.a = 0.0 | ||||
| 					} | ||||
| 					pass.swapchain = sokol_glue.swapchain() | ||||
| 					sokol_gfx.begin_pass( pass ) | ||||
|  | ||||
| 					sokol_gfx.apply_viewport( 0, 0, width, height, origin_top_left = true ) | ||||
| 					sokol_gfx.apply_scissor_rect( 0, 0, width, height, origin_top_left = true ) | ||||
|  | ||||
| 					sokol_gfx.apply_pipeline( screen_pipeline ) | ||||
|  | ||||
| 					fs_uniform := Ve_Draw_Text_Fs_Params { down_sample = 0, colour = {1, 1, 1, 1} } | ||||
| 					sokol_gfx.apply_uniforms( ShaderStage.FS, SLOT_ve_blit_atlas_fs_params, Range { & fs_uniform, size_of(fs_uniform) }) | ||||
|  | ||||
| 					src_rt := draw_call.pass == .Target_Uncached ? glyph_rt_color : atlas_rt_color | ||||
|  | ||||
| 					sokol_gfx.apply_bindings(Bindings { | ||||
| 						vertex_buffers = { | ||||
| 							0 = draw_list_vbuf, | ||||
| 						}, | ||||
| 						vertex_buffer_offsets = { | ||||
| 							0 = 0, | ||||
| 						}, | ||||
| 						index_buffer        = draw_list_ibuf, | ||||
| 						index_buffer_offset = i32(draw_call.start_index), | ||||
| 						fs = { | ||||
| 							images   = { SLOT_ve_draw_text_src_texture = src_rt, }, | ||||
| 							samplers = { SLOT_ve_draw_text_src_sampler = gfx_sampler,   }, | ||||
| 						}, | ||||
| 					}) | ||||
| 			} | ||||
|  | ||||
| 			num_indices := draw_call.end_index - draw_call.start_index | ||||
| 			sokol_gfx.draw( 0, num_indices, 1 ) | ||||
|  | ||||
| 			sokol_gfx.end_pass() | ||||
| 		} | ||||
|  | ||||
| 		sokol_gfx.commit() | ||||
| 	} | ||||
| } | ||||
| @@ -1,8 +1,9 @@ | ||||
| package sectr | ||||
|  | ||||
| import "core:os" | ||||
| import ve        "codebase:font/VEFontCache" | ||||
| import sokol_gfx "thirdparty:sokol/gfx" | ||||
| import ve         "codebase:font/VEFontCache" | ||||
| import sokol_gfx  "thirdparty:sokol/gfx" | ||||
| import sokol_glue "thirdparty:sokol/glue" | ||||
|  | ||||
|  | ||||
| Font_Provider_Use_Freetype :: false | ||||
| @@ -30,11 +31,32 @@ FontProviderData :: struct | ||||
| 	ve_font_cache : ve.Context, | ||||
| 	font_cache    : HMapChained(FontDef), | ||||
|  | ||||
| 	gfx_bindings  : sokol_gfx.Bindings, | ||||
| 	gfx_pipeline  : sokol_gfx.Pipeline, | ||||
| 	gfx_v_buffer  : sokol_gfx.Buffer, | ||||
| 	gfx_uv_buffer : sokol_gfx.Buffer, | ||||
| 	gfx_sampler   : sokol_gfx.Sampler, | ||||
| 	gfx_sampler : sokol_gfx.Sampler, | ||||
|  | ||||
| 	draw_list_vbuf : sokol_gfx.Buffer, | ||||
| 	draw_list_ibuf : sokol_gfx.Buffer, | ||||
|  | ||||
| 	glyph_shader  : sokol_gfx.Shader, | ||||
| 	atlas_shader  : sokol_gfx.Shader, | ||||
| 	screen_shader : sokol_gfx.Shader, | ||||
|  | ||||
| 	// 2k x 512, R8 | ||||
| 	glyph_rt_color   : sokol_gfx.Image, | ||||
| 	// glyph_rt_resolve : sokol_gfx.Image, | ||||
| 	// glyph_rt_depth   : sokol_gfx.Image, | ||||
|  | ||||
| 	// 4k x 2k, R8 | ||||
| 	atlas_rt_color   : sokol_gfx.Image, | ||||
| 	// atlas_rt_resolve : sokol_gfx.Image, | ||||
| 	// atlas_rt_depth   : sokol_gfx.Image, | ||||
|  | ||||
| 	glyph_pipeline  : sokol_gfx.Pipeline, | ||||
| 	atlas_pipeline  : sokol_gfx.Pipeline, | ||||
| 	screen_pipeline : sokol_gfx.Pipeline, | ||||
|  | ||||
| 	glyph_pass  : sokol_gfx.Pass, | ||||
| 	atlas_pass  : sokol_gfx.Pass, | ||||
| 	screen_pass : sokol_gfx.Pass, | ||||
| } | ||||
|  | ||||
| font_provider_startup :: proc() | ||||
| @@ -51,7 +73,317 @@ font_provider_startup :: proc() | ||||
| 	ve.init( & provider_data.ve_font_cache, .STB_TrueType, allocator = persistent_slab_allocator() ) | ||||
| 	log("VEFontCached initialized") | ||||
|  | ||||
| 	ve.configure_snap( & provider_data.ve_font_cache, u32(state.app_window.extent.x * 2.0), u32(state.app_window.extent.y * 2.0) ) | ||||
|  | ||||
| 	// TODO(Ed): Setup sokol hookup for VEFontCache | ||||
| 	{ | ||||
| 		AttachmentDesc          :: sokol_gfx.Attachment_Desc | ||||
| 		BlendFactor             :: sokol_gfx.Blend_Factor | ||||
| 		BlendOp                 :: sokol_gfx.Blend_Op | ||||
| 		BlendState              :: sokol_gfx.Blend_State | ||||
| 		BorderColor             :: sokol_gfx.Border_Color | ||||
| 		BufferDesciption        :: sokol_gfx.Buffer_Desc | ||||
| 		BufferUsage             :: sokol_gfx.Usage | ||||
| 		BufferType              :: sokol_gfx.Buffer_Type | ||||
| 		ColorTargetState        :: sokol_gfx.Color_Target_State | ||||
| 		Filter                  :: sokol_gfx.Filter | ||||
| 		ImageDesc               :: sokol_gfx.Image_Desc | ||||
| 		PassAction              :: sokol_gfx.Pass_Action | ||||
| 		Range                   :: sokol_gfx.Range | ||||
| 		SamplerDescription      :: sokol_gfx.Sampler_Desc | ||||
| 		Wrap                    :: sokol_gfx.Wrap | ||||
| 		VertexAttributeState    :: sokol_gfx.Vertex_Attr_State | ||||
| 		VertexBufferLayoutState :: sokol_gfx.Vertex_Buffer_Layout_State | ||||
| 		VertexIndexType         :: sokol_gfx.Index_Type | ||||
| 		VertexFormat            :: sokol_gfx.Vertex_Format | ||||
| 		VertexLayoutState       :: sokol_gfx.Vertex_Layout_State | ||||
| 		VertexStep              :: sokol_gfx.Vertex_Step | ||||
|  | ||||
| 		using provider_data | ||||
| 		backend := sokol_gfx.query_backend() | ||||
| 		app_env := sokol_glue.environment() | ||||
|  | ||||
| 		glyph_shader  = sokol_gfx.make_shader(ve_render_glyph_shader_desc(backend) ) | ||||
| 		atlas_shader  = sokol_gfx.make_shader(ve_blit_atlas_shader_desc(backend) ) | ||||
| 		screen_shader = sokol_gfx.make_shader(ve_draw_text_shader_desc(backend) ) | ||||
|  | ||||
| 		draw_list_vbuf = sokol_gfx.make_buffer( BufferDesciption { | ||||
| 			size  = size_of([4]f32) * Kilo * 128, | ||||
| 			usage = BufferUsage.STREAM, | ||||
| 			type  = BufferType.VERTEXBUFFER, | ||||
| 		}) | ||||
|  | ||||
| 		draw_list_ibuf = sokol_gfx.make_buffer( BufferDesciption { | ||||
| 			size  = size_of(u32) * Kilo * 32, | ||||
| 			usage = BufferUsage.STREAM, | ||||
| 			type  = BufferType.INDEXBUFFER, | ||||
| 		}) | ||||
|  | ||||
| 		gfx_sampler = sokol_gfx.make_sampler( SamplerDescription { | ||||
| 			min_filter    = Filter.NEAREST, | ||||
| 			mag_filter    = Filter.NEAREST, | ||||
| 			mipmap_filter = Filter.NONE, | ||||
| 			wrap_u        = Wrap.CLAMP_TO_EDGE, | ||||
| 			wrap_v        = Wrap.CLAMP_TO_EDGE, | ||||
| 			border_color  = BorderColor.OPAQUE_BLACK, | ||||
| 		}) | ||||
|  | ||||
| 		// glyph_pipeline | ||||
| 		{ | ||||
| 			vs_layout : VertexLayoutState | ||||
| 			{ | ||||
| 				using vs_layout | ||||
| 				attrs[ATTR_ve_render_glyph_vs_v_position] = VertexAttributeState { | ||||
| 					format       = VertexFormat.FLOAT2, | ||||
| 					offset       = 0, | ||||
| 					buffer_index = 0, | ||||
| 				} | ||||
| 				attrs[ATTR_ve_render_glyph_vs_v_texture] = VertexAttributeState { | ||||
| 					format       = VertexFormat.FLOAT2, | ||||
| 					offset       = size_of(Vec2), | ||||
| 					buffer_index = 0, | ||||
| 				} | ||||
| 				buffers[0] = VertexBufferLayoutState { | ||||
| 					stride    = size_of(Vec2) * 2, | ||||
| 					step_func = VertexStep.PER_VERTEX | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			color_target := ColorTargetState { | ||||
| 				pixel_format = .R8, | ||||
| 				// write_mask   = | ||||
| 				blend = BlendState { | ||||
| 					enabled = true, | ||||
| 					src_factor_rgb   = .ONE_MINUS_DST_COLOR, | ||||
| 					dst_factor_rgb   = .ONE_MINUS_SRC_COLOR, | ||||
| 					op_rgb           = BlendOp.ADD, | ||||
| 					src_factor_alpha = BlendFactor.ONE, | ||||
| 					dst_factor_alpha = BlendFactor.ZERO, | ||||
| 					op_alpha         = BlendOp.ADD, | ||||
| 				}, | ||||
| 			} | ||||
|  | ||||
| 			glyph_pipeline = sokol_gfx.make_pipeline({ | ||||
| 				shader       = glyph_shader, | ||||
| 				layout       = vs_layout, | ||||
| 				index_type   = VertexIndexType.UINT32, | ||||
| 				colors       = { | ||||
| 					0 = color_target, | ||||
| 				}, | ||||
| 				color_count  = 1, | ||||
| 				// sample_count = 1, | ||||
| 				// label = | ||||
| 			}) | ||||
| 		} | ||||
|  | ||||
| 		// glyph_pass | ||||
| 		{ | ||||
| 			glyph_rt_color = sokol_gfx.make_image( ImageDesc { | ||||
| 				type          = ._2D, | ||||
| 				render_target = true, | ||||
| 				width         = i32(ve_font_cache.atlas.buffer_width), | ||||
| 				height        = i32(ve_font_cache.atlas.buffer_height), | ||||
| 				num_slices    = 1, | ||||
| 				num_mipmaps   = 1, | ||||
| 				usage         = .STREAM, | ||||
| 				pixel_format  = .R8, | ||||
| 				sample_count  = app_env.defaults.sample_count, | ||||
| 				// TODO(Ed): Setup labels for debug tracing/logging | ||||
| 				// label         =  | ||||
| 			}) | ||||
|  | ||||
| 			color_attach := AttachmentDesc { | ||||
| 				image     = glyph_rt_color, | ||||
| 				// mip_level = 1, | ||||
| 			} | ||||
|  | ||||
| 			glyph_attachments := sokol_gfx.make_attachments({ | ||||
| 				colors = { | ||||
| 					0 = color_attach, | ||||
| 				}, | ||||
| 			}) | ||||
|  | ||||
| 			glyph_action := PassAction { | ||||
| 				colors = { | ||||
| 					0 = { | ||||
| 						load_action  = .DONTCARE, | ||||
| 						store_action = .STORE, | ||||
| 						clear_value  = {0,0,0,1}, | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			glyph_pass = sokol_gfx.Pass { | ||||
| 				action      = glyph_action, | ||||
| 				attachments = glyph_attachments, | ||||
| 				// label = | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// atlas_pipeline | ||||
| 		{ | ||||
| 			vs_layout : VertexLayoutState | ||||
| 			{ | ||||
| 				using vs_layout | ||||
| 				attrs[ATTR_ve_blit_atlas_vs_v_position] = VertexAttributeState { | ||||
| 					format       = VertexFormat.FLOAT2, | ||||
| 					offset       = 0, | ||||
| 					buffer_index = 0, | ||||
| 				} | ||||
| 				attrs[ATTR_ve_blit_atlas_vs_v_texture] = VertexAttributeState { | ||||
| 					format       = VertexFormat.FLOAT2, | ||||
| 					offset       = size_of(Vec2), | ||||
| 					buffer_index = 0, | ||||
| 				} | ||||
| 				buffers[0] = VertexBufferLayoutState { | ||||
| 					stride    = size_of(Vec2) * 2, | ||||
| 					step_func = VertexStep.PER_VERTEX | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			color_target := ColorTargetState { | ||||
| 				pixel_format = .R8, | ||||
| 				// write_mask   = | ||||
| 				blend = BlendState { | ||||
| 					enabled = true, | ||||
| 					src_factor_rgb   = .SRC_ALPHA, | ||||
| 					dst_factor_rgb   = .ONE_MINUS_SRC_ALPHA, | ||||
| 					op_rgb           = BlendOp.ADD, | ||||
| 					src_factor_alpha = BlendFactor.ONE, | ||||
| 					dst_factor_alpha = BlendFactor.ZERO, | ||||
| 					op_alpha         = BlendOp.ADD, | ||||
| 				}, | ||||
| 			} | ||||
|  | ||||
| 			atlas_pipeline = sokol_gfx.make_pipeline({ | ||||
| 				shader     = atlas_shader, | ||||
| 				layout     = vs_layout, | ||||
| 				index_type = VertexIndexType.UINT32, | ||||
| 				colors     = { | ||||
| 					0 = color_target, | ||||
| 				}, | ||||
| 				color_count  = 1, | ||||
| 				sample_count = 1, | ||||
| 			}) | ||||
| 		} | ||||
|  | ||||
| 		// atlas_pass | ||||
| 		{ | ||||
| 			atlas_rt_color = sokol_gfx.make_image( ImageDesc { | ||||
| 				type          = ._2D, | ||||
| 				render_target = true, | ||||
| 				width         = i32(ve_font_cache.atlas.buffer_width), | ||||
| 				height        = i32(ve_font_cache.atlas.buffer_height), | ||||
| 				num_slices    = 1, | ||||
| 				num_mipmaps   = 1, | ||||
| 				usage         = .STREAM, | ||||
| 				pixel_format  = .R8, | ||||
| 				sample_count  = app_env.defaults.sample_count, | ||||
| 				// TODO(Ed): Setup labels for debug tracing/logging | ||||
| 				// label         =  | ||||
| 			}) | ||||
|  | ||||
| 			color_attach := AttachmentDesc { | ||||
| 				image     = atlas_rt_color, | ||||
| 				// mip_level = 1, | ||||
| 			} | ||||
|  | ||||
| 			atlas_attachments := sokol_gfx.make_attachments({ | ||||
| 				colors = { | ||||
| 					0 = color_attach, | ||||
| 				}, | ||||
| 			}) | ||||
|  | ||||
| 			atlas_action := PassAction { | ||||
| 				colors = { | ||||
| 					0 = { | ||||
| 						load_action  = .LOAD, | ||||
| 						store_action = .STORE, | ||||
| 						clear_value  = {0,0,0,1}, | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			atlas_pass = sokol_gfx.Pass { | ||||
| 				action      = atlas_action, | ||||
| 				attachments = atlas_attachments, | ||||
| 				// label = | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// screen pipeline | ||||
| 		{ | ||||
| 			vs_layout : VertexLayoutState | ||||
| 			{ | ||||
| 				using vs_layout | ||||
| 				attrs[ATTR_ve_draw_text_vs_v_position] = VertexAttributeState { | ||||
| 					format       = VertexFormat.FLOAT2, | ||||
| 					offset       = 0, | ||||
| 					buffer_index = 0, | ||||
| 				} | ||||
| 				attrs[ATTR_ve_draw_text_vs_v_texture] = VertexAttributeState { | ||||
| 					format       = VertexFormat.FLOAT2, | ||||
| 					offset       = size_of(Vec2), | ||||
| 					buffer_index = 0, | ||||
| 				} | ||||
| 				buffers[0] = VertexBufferLayoutState { | ||||
| 					stride    = size_of(Vec2) * 2, | ||||
| 					step_func = VertexStep.PER_VERTEX | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			color_target := ColorTargetState { | ||||
| 				// pixel_format = .R8, | ||||
| 				// write_mask   = | ||||
| 				blend = BlendState { | ||||
| 					enabled = true, | ||||
| 					src_factor_rgb   = .SRC_ALPHA, | ||||
| 					dst_factor_rgb   = .ONE_MINUS_SRC_ALPHA, | ||||
| 					op_rgb           = BlendOp.ADD, | ||||
| 					src_factor_alpha = BlendFactor.ONE, | ||||
| 					dst_factor_alpha = BlendFactor.ZERO, | ||||
| 					op_alpha         = BlendOp.ADD, | ||||
| 				}, | ||||
| 			} | ||||
|  | ||||
| 			screen_pipeline = sokol_gfx.make_pipeline({ | ||||
| 				shader     = screen_shader, | ||||
| 				layout     = vs_layout, | ||||
| 				index_type = VertexIndexType.UINT32, | ||||
| 				colors     = { | ||||
| 					0 = color_target, | ||||
| 				}, | ||||
| 				color_count  = 1, | ||||
| 				sample_count = 1, | ||||
| 			}) | ||||
| 		} | ||||
|  | ||||
| 		// screen_pass | ||||
| 		{ | ||||
| 			screen_action := PassAction { | ||||
| 				colors = { | ||||
| 					0 = { | ||||
| 						load_action  = .CLEAR, | ||||
| 						store_action = .STORE, | ||||
| 						clear_value  = {0,0,0,0}, | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			screen_pass = sokol_gfx.Pass { | ||||
| 				action = screen_action, | ||||
| 				// label = | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| font_provider_reload :: proc() | ||||
| { | ||||
| 	state         := get_state() | ||||
| 	provider_data := & state.font_provider_data | ||||
|  | ||||
| 	ve.configure_snap( & provider_data.ve_font_cache, u32(state.app_window.extent.x * 2.0), u32(state.app_window.extent.y) ) | ||||
| } | ||||
|  | ||||
| font_provider_shutdown :: proc() | ||||
| @@ -92,7 +424,7 @@ font_load :: proc(path_file : string, | ||||
| 	verify( set_error == AllocatorError.None, "Failed to add new font entry to cache" ) | ||||
|  | ||||
| 	// TODO(Ed): Load even sizes from 8px to upper bound. | ||||
| 	def.ve_id = ve.load_font( & provider_data.ve_font_cache, desired_id, font_data, default_size ) | ||||
| 	def.ve_id = ve.load_font( & provider_data.ve_font_cache, desired_id, font_data, 36.0 ) | ||||
|  | ||||
| 	fid := FontID { key, desired_id } | ||||
| 	return fid | ||||
|   | ||||
		Reference in New Issue
	
	Block a user