summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pipeline.cpp78
-rw-r--r--ui.cpp91
-rw-r--r--ui.hpp19
-rw-r--r--video.hpp2
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 &&