From e8baea58dd5c92b62c4eef1b5c1ca9648f44e7d7 Mon Sep 17 00:00:00 2001 From: quou Date: Mon, 30 Dec 2024 12:44:28 +1100 Subject: ui renderer clipping --- pipeline.cpp | 78 +++++++++++++++++++++++++++------------------------ ui.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- ui.hpp | 19 +++++++++---- video.hpp | 2 ++ 4 files changed, 135 insertions(+), 55 deletions(-) diff --git a/pipeline.cpp b/pipeline.cpp index 79bfc1d..cccd1c5 100644 --- a/pipeline.cpp +++ b/pipeline.cpp @@ -244,57 +244,61 @@ void Pipeline_Builder::vertex_format(Vertex_Format_Id vf) { } Pipeline& Pipeline_Builder::build() { + validate(); + pip->hash(); + return *pip; +} + +void Pipeline::hash() { #define h(n, v) \ n = fnv1a64_2(n, (uint8_t*)&v, sizeof v) - validate(); - pip->pipeline_hash = fnv1a64(0, 0); - h(pip->pipeline_hash, pip->vertex_format); - h(pip->pipeline_hash, pip->shader); - h(pip->pipeline_hash, pip->descriptor_count); - h(pip->pipeline_hash, pip->viewport[0]); - h(pip->pipeline_hash, pip->viewport[1]); - h(pip->pipeline_hash, pip->viewport[2]); - h(pip->pipeline_hash, pip->viewport[3]); - h(pip->pipeline_hash, pip->scissor[0]); - h(pip->pipeline_hash, pip->scissor[1]); - h(pip->pipeline_hash, pip->scissor[2]); - h(pip->pipeline_hash, pip->scissor[3]); - h(pip->pipeline_hash, pip->depth_test); - h(pip->pipeline_hash, pip->depth_write); - h(pip->pipeline_hash, pip->depth_mode); - h(pip->pipeline_hash, pip->blend_enable); - h(pip->pipeline_hash, pip->blend_mode); - h(pip->pipeline_hash, pip->blend_mode_alpha); - h(pip->pipeline_hash, pip->blend_src); - h(pip->pipeline_hash, pip->blend_dst); - h(pip->pipeline_hash, pip->blend_src_alpha); - h(pip->pipeline_hash, pip->blend_dst_alpha); - h(pip->pipeline_hash, pip->cull_mode); + pipeline_hash = fnv1a64(0, 0); + h(pipeline_hash, vertex_format); + h(pipeline_hash, shader); + h(pipeline_hash, descriptor_count); + h(pipeline_hash, viewport[0]); + h(pipeline_hash, viewport[1]); + h(pipeline_hash, viewport[2]); + h(pipeline_hash, viewport[3]); + h(pipeline_hash, scissor[0]); + h(pipeline_hash, scissor[1]); + h(pipeline_hash, scissor[2]); + h(pipeline_hash, scissor[3]); + h(pipeline_hash, depth_test); + h(pipeline_hash, depth_write); + h(pipeline_hash, depth_mode); + h(pipeline_hash, blend_enable); + h(pipeline_hash, blend_mode); + h(pipeline_hash, blend_mode_alpha); + h(pipeline_hash, blend_src); + h(pipeline_hash, blend_dst); + h(pipeline_hash, blend_src_alpha); + h(pipeline_hash, blend_dst_alpha); + h(pipeline_hash, cull_mode); { - int i, e = pip->descriptor_count; - pip->descriptor_resource_hash = fnv1a64(0, 0); + int i, e = descriptor_count; + descriptor_resource_hash = fnv1a64(0, 0); for (i = 0; i < e; i++) { - Descriptor* d = &pip->descriptors[i]; - h(pip->pipeline_hash, d->type); - h(pip->pipeline_hash, d->slot); - h(pip->descriptor_resource_hash, d->type); - h(pip->descriptor_resource_hash, d->slot); + Descriptor* d = &descriptors[i]; + h(pipeline_hash, d->type); + h(pipeline_hash, d->slot); + h(descriptor_resource_hash, d->type); + h(descriptor_resource_hash, d->slot); switch (d->type) { case Descriptor::Type::texture: { auto td = (Texture_Descriptor*)d->payload; - h(pip->descriptor_resource_hash, td->sampler); - h(pip->descriptor_resource_hash, td->texture); + h(descriptor_resource_hash, td->sampler); + h(descriptor_resource_hash, td->texture); } break; case Descriptor::Type::constant_buffer: { auto cd = (Constant_Buffer_Descriptor*)d->payload; - h(pip->descriptor_resource_hash, cd->buffer); - h(pip->descriptor_resource_hash, cd->size); - h(pip->descriptor_resource_hash, cd->offset); + h(descriptor_resource_hash, cd->buffer); + h(descriptor_resource_hash, cd->size); + h(descriptor_resource_hash, cd->offset); } break; } } } - return *pip; #undef h } diff --git a/ui.cpp b/ui.cpp index 2060a78..5814204 100644 --- a/ui.cpp +++ b/ui.cpp @@ -129,6 +129,9 @@ UI::Colour::Colour(unsigned rgb, uint8_t a): b((rgb) & 0xff), a(a) {} +UI::Rect::Rect(int x, int y, int w, int h): + x(x), y(y), w(w), h(h) {} + void UI::Vertex_Buffer::init(Device* dev) { buf.init( dev, @@ -138,6 +141,7 @@ void UI::Vertex_Buffer::init(Device* dev) { ); init_indices(dev); usage = 0; + start = 0; next = 0; } @@ -199,6 +203,7 @@ void UI::Vertex_Buffer::add_quad( ) { Vertex* verts; int index = usage * 4; + int* scissor = ui->pipeline->scissor; float r, g, b, a; if (usage >= vertex_buffer_count) { if (!next) { @@ -208,6 +213,35 @@ void UI::Vertex_Buffer::add_quad( next->add_quad(ui, x, y, w, h, u0, v0, u1, v1, col); return; } + if ( + clip.x < scissor[0] || + clip.y < scissor[1] || + clip.x + clip.w > scissor[0] + scissor[2] || + clip.y + clip.h > scissor[1] + scissor[3] || + (( + clip.x != scissor[0] || + clip.y != scissor[1] || + clip.w != scissor[2] || + clip.h != scissor[3] + ) && ( + x < clip.x || + y < clip.y || + x + w > clip.x + clip.w || + y + h > clip.y + clip.h + )) + ) { + ui->mesh.draw( + ui, + ui->device->get_ctx(), + *ui->pipeline, + *ui->render_pass + ); + scissor[0] = clip.x; + scissor[1] = clip.y; + scissor[2] = clip.w; + scissor[3] = clip.h; + ui->pipeline->hash(); + } r = col.r_f(); g = col.g_f(); b = col.b_f(); @@ -254,17 +288,44 @@ void UI::Vertex_Buffer::add_text( const char* txt, Colour col ) { - for (; *txt; txt++) - add_char(ui, x += 10, y, *txt, col); + for (; *txt; txt++, x += 10) + add_char(ui, x, y, *txt, col); } void UI::Vertex_Buffer::update_buffer(Context& ctx) { buf.update(ctx); +} + +void UI::Vertex_Buffer::reset(const Rect& c) { + start = 0; + usage = 0; + dirty = true; + clip = c; + if (next) + next->reset(c); +} + +void UI::Vertex_Buffer::set_clip(const Rect& r) { + clip = r; if (next) - next->update_buffer(ctx); + next->set_clip(r); } -void UI::Vertex_Buffer::draw(UI* ui, Context& ctx, Pipeline& pip, Render_Pass& rp) { +void UI::Vertex_Buffer::draw( + UI* ui, + Context& ctx, + Pipeline& pip, + Render_Pass& rp +) { + if (usage == start) { + if (next) + next->draw(ui, ctx, pip, rp); + return; + } + if (dirty) { + update_buffer(ctx); + dirty = false; + } Vertex_Buffer_Binding binding[] = {{ .id = buf.gpuonly, .offset = 0, @@ -277,12 +338,13 @@ void UI::Vertex_Buffer::draw(UI* ui, Context& ctx, Pipeline& pip, Render_Pass& r Draw d{}; d.verts = binding; d.inds = indb; - d.vertex_count = usage * 6; + d.vertex_count = (usage - start) * 6; d.instance_count = 1; + d.first_vertex = start * 6; ctx.submit(d, pip, rp); if (next) next->draw(ui, ctx, pip, rp); - usage = 0; + start = usage; } UI* UI::create(Device* dev, Arena* a, Shader_Id sh) { @@ -345,7 +407,6 @@ void UI::update(Arena* s) { } void UI::render(Arena* s, Texture_Id target) { - int i, c = 2000; Context& ctx = device->get_ctx(); Texture& t = device->get_texture(target); UI_CBuffer* config = (UI_CBuffer*)cbuffer.map(device); @@ -358,12 +419,10 @@ void UI::render(Arena* s, Texture_Id target) { cbuffer.unmap(device); cbuffer.update(ctx); - mesh.add_text(this, 10, 10, "Hello, world!", 0xff00ff); - Pipeline_Builder pb(s, device); pb.begin_rp(); pb.rp_target(device->get_backbuffer(), Clear_Mode::restore); - Render_Pass& pass = pb.build_rp(); + render_pass = &pb.build_rp(); pb.begin(); pb.shader(shader); @@ -375,8 +434,14 @@ void UI::render(Arena* s, Texture_Id target) { ); pb.cbuffer(shader_info.config_binding, cbuffer.gpuonly); pb.texture(shader_info.atlas_binding, atlas, sampler); - Pipeline& pip = pb.build(); + pipeline = &pb.build(); - mesh.update_buffer(ctx); - mesh.draw(this, ctx, pip, pass); + mesh.reset(Rect(0, 0, t.w, t.h)); + mesh.add_text(this, 10, 10, "Hello, world!", 0xffffff); + mesh.add_text(this, 10, 30, "Hello, world!", 0xffffff); + mesh.set_clip(Rect(0, 0, 35, 100)); + mesh.add_text(this, 10, 50, "Hello, world!", 0xffffff); + mesh.set_clip(Rect(0, 0, t.w, t.h)); + mesh.add_text(this, 10, 70, "Hello, world!", 0xffffff); + mesh.draw(this, ctx, *pipeline, *render_pass); } diff --git a/ui.hpp b/ui.hpp index 4dc0dd9..2b671ae 100644 --- a/ui.hpp +++ b/ui.hpp @@ -19,15 +19,26 @@ struct UI { float a_f() { return (float)a / 255.0f; }; }; + struct Rect { + int x, y, w, h; + + Rect() = default; + Rect(int x, int y, int w, int h); + }; + struct Vertex_Buffer { + Rect clip; + bool dirty; Staged_Buffer buf; Buffer_Id indices; - int usage; + int start, usage; void init(Device* dev); void init_indices(Device* dev); void destroy(UI* ui); void update_buffer(Context& ctx); + void reset(const Rect& clip); + void set_clip(const Rect& clip); void add_quad( UI* ui, @@ -66,10 +77,6 @@ struct UI { Vertex_Buffer* next; }; - struct Rect { - int x, y, w, h; - }; - Heap* heap; Device* device; Texture_Id atlas; @@ -78,6 +85,8 @@ struct UI { Sampler_Id sampler; Staged_Buffer cbuffer; Vertex_Buffer mesh; + Pipeline* pipeline; + Render_Pass* render_pass; struct UI_CBuffer { m4f projection; diff --git a/video.hpp b/video.hpp index 37a7315..2148d8f 100644 --- a/video.hpp +++ b/video.hpp @@ -128,6 +128,8 @@ struct Pipeline { Descriptor descriptors[pipeline_max_descriptors]; int descriptor_count; + void hash(); + bool pipeline_eq(const Pipeline& other) const { return shader == other.shader && -- cgit v1.2.3-54-g00ecf