diff options
| author | quou <quou@disroot.org> | 2024-12-30 12:44:28 +1100 | 
|---|---|---|
| committer | quou <quou@disroot.org> | 2024-12-30 14:11:22 +1100 | 
| commit | e8baea58dd5c92b62c4eef1b5c1ca9648f44e7d7 (patch) | |
| tree | e0e9685b8ae53e7984258965b8ad486d1781c8a3 | |
| parent | 90eed5c3684a6dd751afc2bcb7ae0ac919c143a8 (diff) | |
ui renderer clipping
| -rw-r--r-- | pipeline.cpp | 78 | ||||
| -rw-r--r-- | ui.cpp | 91 | ||||
| -rw-r--r-- | ui.hpp | 19 | ||||
| -rw-r--r-- | 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  } @@ -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);  } @@ -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; @@ -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 && |