Compare commits

..

6 Commits

5 changed files with 90 additions and 20 deletions

View File

@@ -321,6 +321,10 @@ layout :: proc(layer: ^renderer.Layer) {
border_color = {0, 0, 0, 1}, border_color = {0, 0, 0, 1},
border_width = 10, border_width = 10,
) )
renderer.prepare_quad(layer, test_quad) renderer.prepare_quad(layer, test_quad)
text_ok, text := renderer.text(0, "Raw Text", {bounds.x + 80, bounds.y + 80})
if text_ok {
renderer.prepare_text(layer, text)
}
} }

View File

@@ -13,8 +13,8 @@ fi
# Convert GLSL to SPIRV # Convert GLSL to SPIRV
echo "Converting GLSL shaders to SPIRV..." echo "Converting GLSL shaders to SPIRV..."
mkdir -p renderer/res/shaders/compiled mkdir -p res/shaders/compiled
cd renderer/res/shaders/raw || exit cd res/shaders/raw || exit
glslangValidator -V quad.vert -o ../compiled/quad.vert.spv glslangValidator -V quad.vert -o ../compiled/quad.vert.spv
glslangValidator -V quad.frag -o ../compiled/quad.frag.spv glslangValidator -V quad.frag -o ../compiled/quad.frag.spv
glslangValidator -V text.vert -o ../compiled/text.vert.spv glslangValidator -V text.vert -o ../compiled/text.vert.spv

View File

@@ -211,7 +211,7 @@ draw_quads :: proc(
) { ) {
using global using global
if layer.quad_len == 0 { if layer.quad_instance_len == 0 {
return return
} }

View File

@@ -33,6 +33,7 @@ Global :: struct {
tmp_quads: [dynamic]Quad, tmp_quads: [dynamic]Quad,
max_tmp_quads: int, max_tmp_quads: int,
clay_mem: [^]u8, clay_mem: [^]u8,
clay_z_index: i16,
odin_context: runtime.Context, odin_context: runtime.Context,
quad_pipeline: QuadPipeline, quad_pipeline: QuadPipeline,
text_pipeline: TextPipeline, text_pipeline: TextPipeline,
@@ -68,6 +69,7 @@ clear_global :: proc() {
using global using global
curr_layer_index = 0 curr_layer_index = 0
clay_z_index = 0
clear(&layers) clear(&layers)
clear(&scissors) clear(&scissors)
clear(&tmp_text) clear(&tmp_text)
@@ -86,7 +88,7 @@ Rectangle :: struct {
Layer :: struct { Layer :: struct {
bounds: Rectangle, bounds: Rectangle,
quad_instance_start: u32, quad_instance_start: u32,
quad_len: u32, quad_instance_len: u32,
text_instance_start: u32, text_instance_start: u32,
text_instance_len: u32, text_instance_len: u32,
text_vertex_start: u32, text_vertex_start: u32,
@@ -184,19 +186,20 @@ begin_prepare :: proc(bounds: Rectangle) -> ^Layer {
} }
/// Creates a new layer /// Creates a new layer
new_layer :: proc(old_layer: ^Layer, bounds: Rectangle) -> ^Layer { new_layer :: proc(prev_layer: ^Layer, bounds: Rectangle) -> ^Layer {
using global using global
layer := Layer { layer := Layer {
bounds = bounds, bounds = bounds,
quad_instance_start = old_layer.quad_instance_start + old_layer.quad_len, quad_instance_start = prev_layer.quad_instance_start + prev_layer.quad_instance_len,
text_instance_start = old_layer.text_instance_start + old_layer.text_instance_len, text_instance_start = prev_layer.text_instance_start + prev_layer.text_instance_len,
text_vertex_start = old_layer.text_vertex_start + old_layer.text_vertex_len, text_vertex_start = prev_layer.text_vertex_start + prev_layer.text_vertex_len,
text_index_start = old_layer.text_index_start + old_layer.text_instance_len, text_index_start = prev_layer.text_index_start + prev_layer.text_index_len,
scissor_start = old_layer.scissor_start + old_layer.scissor_len, scissor_start = prev_layer.scissor_start + prev_layer.scissor_len,
scissor_len = 1, scissor_len = 1,
} }
append(&layers, layer) append(&layers, layer)
curr_layer_index += 1 curr_layer_index += 1
log.debug("Added new layer; curr index", curr_layer_index)
scissor := Scissor { scissor := Scissor {
bounds = sdl.Rect { bounds = sdl.Rect {
@@ -227,10 +230,26 @@ prepare_quad :: proc(layer: ^Layer, quad: Quad) {
using global using global
append(&tmp_quads, quad) append(&tmp_quads, quad)
layer.quad_len += 1 layer.quad_instance_len += 1
scissors[layer.scissor_start + layer.scissor_len - 1].quad_len += 1 scissors[layer.scissor_start + layer.scissor_len - 1].quad_len += 1
} }
// TODO need to make sure no overlap with clay render command IDs
prepare_text :: proc(layer: ^Layer, text: Text) {
using global
data := sdl_ttf.GetGPUTextDrawData(text.ref)
if data == nil {
log.error("Failed to find GPUTextDrawData for sdl_text")
}
append(&tmp_text, text)
layer.text_instance_len += 1
layer.text_vertex_len += u32(data.num_vertices)
layer.text_index_len += u32(data.num_indices)
scissors[layer.scissor_start + layer.scissor_len - 1].text_len += 1
}
// ====== Clay-specific processing ====== // ====== Clay-specific processing ======
ClayBatch :: struct { ClayBatch :: struct {
bounds: Rectangle, bounds: Rectangle,
@@ -239,7 +258,7 @@ ClayBatch :: struct {
/// Upload data to the GPU /// Upload data to the GPU
prepare_clay_batch :: proc( prepare_clay_batch :: proc(
layer: ^Layer, base_layer: ^Layer,
mouse_pos: [2]f32, mouse_pos: [2]f32,
mouse_flags: sdl.MouseButtonFlags, mouse_flags: sdl.MouseButtonFlags,
mouse_wheel_delta: [2]f32, mouse_wheel_delta: [2]f32,
@@ -250,14 +269,17 @@ prepare_clay_batch :: proc(
// Update clay internals // Update clay internals
clay.SetPointerState( clay.SetPointerState(
clay.Vector2{mouse_pos.x - layer.bounds.x, mouse_pos.y - layer.bounds.y}, clay.Vector2{mouse_pos.x - base_layer.bounds.x, mouse_pos.y - base_layer.bounds.y},
.LEFT in mouse_flags, .LEFT in mouse_flags,
) )
clay.UpdateScrollContainers(true, transmute(clay.Vector2)mouse_wheel_delta, frame_time) clay.UpdateScrollContainers(true, transmute(clay.Vector2)mouse_wheel_delta, frame_time)
layer := base_layer
// Parse render commands // Parse render commands
for i in 0 ..< int(batch.cmds.length) { for i in 0 ..< int(batch.cmds.length) {
render_command := clay.RenderCommandArray_Get(&batch.cmds, cast(i32)i) render_command := clay.RenderCommandArray_Get(&batch.cmds, cast(i32)i)
// Translate bounding box of the primitive by the layer position // Translate bounding box of the primitive by the layer position
bounds := Rectangle { bounds := Rectangle {
x = render_command.boundingBox.x + layer.bounds.x, x = render_command.boundingBox.x + layer.bounds.x,
@@ -266,6 +288,18 @@ prepare_clay_batch :: proc(
h = render_command.boundingBox.height, h = render_command.boundingBox.height,
} }
if render_command.zIndex > clay_z_index {
log.debug(
"Higher zIndex found, creating new layer & setting z_index to",
render_command.zIndex,
)
layer = new_layer(layer, bounds)
// Update bounds to new layer offset
bounds.x = render_command.boundingBox.x + layer.bounds.x
bounds.y = render_command.boundingBox.y + layer.bounds.y
clay_z_index = render_command.zIndex
}
switch (render_command.commandType) { switch (render_command.commandType) {
case clay.RenderCommandType.None: case clay.RenderCommandType.None:
case clay.RenderCommandType.Text: case clay.RenderCommandType.Text:
@@ -347,7 +381,7 @@ prepare_clay_batch :: proc(
} }
append(&tmp_quads, quad) append(&tmp_quads, quad)
layer.quad_len += 1 layer.quad_instance_len += 1
scissors[layer.scissor_start + layer.scissor_len - 1].quad_len += 1 scissors[layer.scissor_start + layer.scissor_len - 1].quad_len += 1
case clay.RenderCommandType.Border: case clay.RenderCommandType.Border:
render_data := render_command.renderData.border render_data := render_command.renderData.border
@@ -363,7 +397,7 @@ prepare_clay_batch :: proc(
// Technically these should be drawn on top of everything else including children, but // Technically these should be drawn on top of everything else including children, but
// for our use case we can just chuck these in with the quad pipeline // for our use case we can just chuck these in with the quad pipeline
append(&tmp_quads, quad) append(&tmp_quads, quad)
layer.quad_len += 1 layer.quad_instance_len += 1
scissors[layer.scissor_start + layer.scissor_len - 1].quad_len += 1 scissors[layer.scissor_start + layer.scissor_len - 1].quad_len += 1
case clay.RenderCommandType.Custom: case clay.RenderCommandType.Custom:
} }
@@ -386,6 +420,7 @@ draw :: proc(device: ^sdl.GPUDevice, window: ^sdl.Window, cmd_buffer: ^sdl.GPUCo
} }
for &layer, index in layers { for &layer, index in layers {
log.debug("Drawing layer", index)
draw_quads( draw_quads(
device, device,
window, window,

View File

@@ -61,6 +61,38 @@ Text :: struct {
color: [4]f32, color: [4]f32,
} }
text :: proc(
id: u32,
txt: cstring,
pos: [2]f32,
color: [4]f32 = {0.0, 0.0, 0.0, 1.0},
font_id: u16 = JETBRAINS_MONO_REGULAR,
font_size: u16 = 44,
) -> (bool, Text) {
using global
sdl_text := text_pipeline.cache[id]
if sdl_text == nil {
sdl_text = sdl_ttf.CreateText(text_pipeline.engine, get_font(font_id, font_size), txt, 0)
text_pipeline.cache[id] = sdl_text
} else {
//TODO if IDs are always unique and never change the underlying text
// can get rid of this
_ = sdl_ttf.SetTextString(sdl_text, txt, 0)
}
if sdl_text == nil {
log.error("Could not create SDL text:", sdl.GetError())
return false, Text {}
} else {
return true, Text {
sdl_text,
pos,
color,
}
}
}
// For upload // For upload
TextVert :: struct { TextVert :: struct {
pos_uv: [4]f32, pos_uv: [4]f32,
@@ -383,9 +415,8 @@ draw_text :: proc(
atlas: ^sdl.GPUTexture atlas: ^sdl.GPUTexture
layer_text := tmp_text[layer.text_instance_start:layer.text_instance_start + layer_text := tmp_text[layer.text_instance_start:][:layer.text_instance_len]
layer.text_instance_len] index_offset: u32 = layer.text_index_start
index_offset: u32 = layer.text_instance_start
vertex_offset: i32 = i32(layer.text_vertex_start) vertex_offset: i32 = i32(layer.text_vertex_start)
instance_offset: u32 = layer.text_instance_start instance_offset: u32 = layer.text_instance_start
@@ -396,7 +427,7 @@ draw_text :: proc(
sdl.SetGPUScissor(render_pass, scissor.bounds) sdl.SetGPUScissor(render_pass, scissor.bounds)
for &text in layer_text[scissor.text_start:scissor.text_start + scissor.text_len] { for &text in layer_text[scissor.text_start:][:scissor.text_len] {
data := sdl_ttf.GetGPUTextDrawData(text.ref) data := sdl_ttf.GetGPUTextDrawData(text.ref)
for data != nil { for data != nil {