mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 17:05:38 +00:00
gpu/shaders: update piet-gpu
Changes: - faster implementation of RGBA output - fix stroked clips and images Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+3
-3
File diff suppressed because one or more lines are too long
@@ -48,13 +48,13 @@ void main() {
|
|||||||
if (element_ix < conf.n_elements) {
|
if (element_ix < conf.n_elements) {
|
||||||
AnnotatedTag tag = Annotated_tag(conf.anno_alloc, ref);
|
AnnotatedTag tag = Annotated_tag(conf.anno_alloc, ref);
|
||||||
switch (tag.tag) {
|
switch (tag.tag) {
|
||||||
|
case Annotated_Image:
|
||||||
|
case Annotated_BeginClip:
|
||||||
case Annotated_Color:
|
case Annotated_Color:
|
||||||
if (fill_mode_from_flags(tag.flags) != MODE_NONZERO) {
|
if (fill_mode_from_flags(tag.flags) != MODE_NONZERO) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Fall through.
|
// Fall through.
|
||||||
case Annotated_Image:
|
|
||||||
case Annotated_BeginClip:
|
|
||||||
PathRef path_ref = PathRef(conf.tile_alloc.offset + element_ix * Path_size);
|
PathRef path_ref = PathRef(conf.tile_alloc.offset + element_ix * Path_size);
|
||||||
Path path = Path_read(conf.tile_alloc, path_ref);
|
Path path = Path_read(conf.tile_alloc, path_ref);
|
||||||
sh_row_width[th_ix] = path.bbox.z - path.bbox.x;
|
sh_row_width[th_ix] = path.bbox.z - path.bbox.x;
|
||||||
|
|||||||
+37
-44
@@ -91,6 +91,23 @@ bool alloc_cmd(inout Alloc cmd_alloc, inout CmdRef cmd_ref, inout uint cmd_limit
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_fill(Alloc alloc, inout CmdRef cmd_ref, uint flags, Tile tile, float linewidth) {
|
||||||
|
if (fill_mode_from_flags(flags) == MODE_NONZERO) {
|
||||||
|
if (tile.tile.offset != 0) {
|
||||||
|
CmdFill cmd_fill = CmdFill(tile.tile.offset, tile.backdrop);
|
||||||
|
Cmd_Fill_write(alloc, cmd_ref, cmd_fill);
|
||||||
|
cmd_ref.offset += 4 + CmdFill_size;
|
||||||
|
} else {
|
||||||
|
Cmd_Solid_write(alloc, cmd_ref);
|
||||||
|
cmd_ref.offset += 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CmdStroke cmd_stroke = CmdStroke(tile.tile.offset, 0.5 * linewidth);
|
||||||
|
Cmd_Stroke_write(alloc, cmd_ref, cmd_stroke);
|
||||||
|
cmd_ref.offset += 4 + CmdStroke_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
if (mem_error != NO_ERROR) {
|
if (mem_error != NO_ERROR) {
|
||||||
return;
|
return;
|
||||||
@@ -135,6 +152,12 @@ void main() {
|
|||||||
uint part_start_ix = 0;
|
uint part_start_ix = 0;
|
||||||
uint ready_ix = 0;
|
uint ready_ix = 0;
|
||||||
|
|
||||||
|
// Leave room for the fine rasterizer scratch allocation.
|
||||||
|
Alloc scratch_alloc = slice_mem(cmd_alloc, 0, Alloc_size);
|
||||||
|
cmd_ref.offset += Alloc_size;
|
||||||
|
|
||||||
|
uint num_begin_slots = 0;
|
||||||
|
uint begin_slot = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
for (uint i = 0; i < N_SLICE; i++) {
|
for (uint i = 0; i < N_SLICE; i++) {
|
||||||
sh_bitmaps[i][th_ix] = 0;
|
sh_bitmaps[i][th_ix] = 0;
|
||||||
@@ -320,20 +343,7 @@ void main() {
|
|||||||
if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) {
|
if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (fill_mode_from_flags(tag.flags) == MODE_NONZERO) {
|
write_fill(cmd_alloc, cmd_ref, tag.flags, tile, fill.linewidth);
|
||||||
if (tile.tile.offset != 0) {
|
|
||||||
CmdFill cmd_fill = CmdFill(tile.tile.offset, tile.backdrop);
|
|
||||||
Cmd_Fill_write(cmd_alloc, cmd_ref, cmd_fill);
|
|
||||||
cmd_ref.offset += 4 + CmdFill_size;
|
|
||||||
} else {
|
|
||||||
Cmd_Solid_write(cmd_alloc, cmd_ref);
|
|
||||||
cmd_ref.offset += 4;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CmdStroke cmd_stroke = CmdStroke(tile.tile.offset, 0.5 * fill.linewidth);
|
|
||||||
Cmd_Stroke_write(cmd_alloc, cmd_ref, cmd_stroke);
|
|
||||||
cmd_ref.offset += 4 + CmdStroke_size;
|
|
||||||
}
|
|
||||||
Cmd_Color_write(cmd_alloc, cmd_ref, CmdColor(fill.rgba_color));
|
Cmd_Color_write(cmd_alloc, cmd_ref, CmdColor(fill.rgba_color));
|
||||||
cmd_ref.offset += 4 + CmdColor_size;
|
cmd_ref.offset += 4 + CmdColor_size;
|
||||||
break;
|
break;
|
||||||
@@ -344,20 +354,7 @@ void main() {
|
|||||||
if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) {
|
if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (fill_mode_from_flags(tag.flags) == MODE_NONZERO) {
|
write_fill(cmd_alloc, cmd_ref, tag.flags, tile, fill_img.linewidth);
|
||||||
if (tile.tile.offset != 0) {
|
|
||||||
CmdFill cmd_fill = CmdFill(tile.tile.offset, tile.backdrop);
|
|
||||||
Cmd_Fill_write(cmd_alloc, cmd_ref, cmd_fill);
|
|
||||||
cmd_ref.offset += 4 + CmdFill_size;
|
|
||||||
} else {
|
|
||||||
Cmd_Solid_write(cmd_alloc, cmd_ref);
|
|
||||||
cmd_ref.offset += 4;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CmdStroke cmd_stroke = CmdStroke(tile.tile.offset, 0.5 * fill_img.linewidth);
|
|
||||||
Cmd_Stroke_write(cmd_alloc, cmd_ref, cmd_stroke);
|
|
||||||
cmd_ref.offset += 4 + CmdStroke_size;
|
|
||||||
}
|
|
||||||
Cmd_Image_write(cmd_alloc, cmd_ref, CmdImage(fill_img.index, fill_img.offset));
|
Cmd_Image_write(cmd_alloc, cmd_ref, CmdImage(fill_img.index, fill_img.offset));
|
||||||
cmd_ref.offset += 4 + CmdImage_size;
|
cmd_ref.offset += 4 + CmdImage_size;
|
||||||
break;
|
break;
|
||||||
@@ -373,27 +370,14 @@ void main() {
|
|||||||
if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) {
|
if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (fill_mode_from_flags(tag.flags) == MODE_NONZERO) {
|
write_fill(cmd_alloc, cmd_ref, tag.flags, tile, begin_clip.linewidth);
|
||||||
if (tile.tile.offset != 0) {
|
|
||||||
CmdFill cmd_fill = CmdFill(tile.tile.offset, tile.backdrop);
|
|
||||||
Cmd_Fill_write(cmd_alloc, cmd_ref, cmd_fill);
|
|
||||||
cmd_ref.offset += 4 + CmdFill_size;
|
|
||||||
} else {
|
|
||||||
// TODO: here is where a bunch of optimization magic should happen
|
|
||||||
float alpha = tile.backdrop == 0 ? 0.0 : 1.0;
|
|
||||||
Cmd_Alpha_write(cmd_alloc, cmd_ref, CmdAlpha(alpha));
|
|
||||||
cmd_ref.offset += 4 + CmdAlpha_size;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CmdStroke cmd_stroke = CmdStroke(tile.tile.offset, 0.5 * begin_clip.linewidth);
|
|
||||||
Cmd_Stroke_write(cmd_alloc, cmd_ref, cmd_stroke);
|
|
||||||
cmd_ref.offset += 4 + CmdStroke_size;
|
|
||||||
}
|
|
||||||
Cmd_BeginClip_write(cmd_alloc, cmd_ref);
|
Cmd_BeginClip_write(cmd_alloc, cmd_ref);
|
||||||
cmd_ref.offset += 4;
|
cmd_ref.offset += 4;
|
||||||
if (clip_depth < 32) {
|
if (clip_depth < 32) {
|
||||||
clip_one_mask &= ~(1 << clip_depth);
|
clip_one_mask &= ~(1 << clip_depth);
|
||||||
}
|
}
|
||||||
|
begin_slot++;
|
||||||
|
num_begin_slots = max(num_begin_slots, begin_slot);
|
||||||
}
|
}
|
||||||
clip_depth++;
|
clip_depth++;
|
||||||
break;
|
break;
|
||||||
@@ -405,6 +389,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
Cmd_Solid_write(cmd_alloc, cmd_ref);
|
Cmd_Solid_write(cmd_alloc, cmd_ref);
|
||||||
cmd_ref.offset += 4;
|
cmd_ref.offset += 4;
|
||||||
|
begin_slot--;
|
||||||
Cmd_EndClip_write(cmd_alloc, cmd_ref);
|
Cmd_EndClip_write(cmd_alloc, cmd_ref);
|
||||||
cmd_ref.offset += 4;
|
cmd_ref.offset += 4;
|
||||||
}
|
}
|
||||||
@@ -432,5 +417,13 @@ void main() {
|
|||||||
}
|
}
|
||||||
if (bin_tile_x + tile_x < conf.width_in_tiles && bin_tile_y + tile_y < conf.height_in_tiles) {
|
if (bin_tile_x + tile_x < conf.width_in_tiles && bin_tile_y + tile_y < conf.height_in_tiles) {
|
||||||
Cmd_End_write(cmd_alloc, cmd_ref);
|
Cmd_End_write(cmd_alloc, cmd_ref);
|
||||||
|
if (num_begin_slots > 0) {
|
||||||
|
// Write scratch allocation: one state per BeginClip per rasterizer chunk.
|
||||||
|
uint scratch_size = num_begin_slots * TILE_WIDTH_PX * TILE_HEIGHT_PX * CLIP_STATE_SIZE * 4;
|
||||||
|
MallocResult scratch = malloc(scratch_size);
|
||||||
|
// Ignore scratch.failed; we don't use the allocation and kernel4
|
||||||
|
// checks for memory overflow before using it.
|
||||||
|
alloc_write(scratch_alloc, scratch_alloc.offset, scratch.alloc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-77
@@ -13,9 +13,12 @@
|
|||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
|
|
||||||
#define CHUNK 8
|
#define CHUNK_X 2
|
||||||
#define CHUNK_DY (TILE_HEIGHT_PX / CHUNK)
|
#define CHUNK_Y 4
|
||||||
layout(local_size_x = TILE_WIDTH_PX, local_size_y = CHUNK_DY) in;
|
#define CHUNK CHUNK_X * CHUNK_Y
|
||||||
|
#define CHUNK_DX (TILE_WIDTH_PX / CHUNK_X)
|
||||||
|
#define CHUNK_DY (TILE_HEIGHT_PX / CHUNK_Y)
|
||||||
|
layout(local_size_x = CHUNK_DX, local_size_y = CHUNK_DY) in;
|
||||||
|
|
||||||
layout(set = 0, binding = 1) readonly buffer ConfigBuf {
|
layout(set = 0, binding = 1) readonly buffer ConfigBuf {
|
||||||
Config conf;
|
Config conf;
|
||||||
@@ -32,36 +35,6 @@ layout(rgba8, set = 0, binding = 3) uniform readonly image2D images[1];
|
|||||||
#include "ptcl.h"
|
#include "ptcl.h"
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
|
|
||||||
#define BLEND_STACK_SIZE 4
|
|
||||||
|
|
||||||
// Layout of a clip scratch frame:
|
|
||||||
// Each frame is WIDTH * HEIGHT ClipStates, then a link reference.
|
|
||||||
|
|
||||||
struct ClipState {
|
|
||||||
uint srgb;
|
|
||||||
float area;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Link offset and frame size in 32-bit words.
|
|
||||||
#define CLIP_STATE_SIZE 2
|
|
||||||
#define CLIP_LINK_OFFSET (TILE_WIDTH_PX * TILE_HEIGHT_PX * CLIP_STATE_SIZE)
|
|
||||||
#define CLIP_BUF_SIZE (CLIP_LINK_OFFSET + 1)
|
|
||||||
|
|
||||||
shared MallocResult sh_clip_alloc;
|
|
||||||
|
|
||||||
// Allocate a scratch buffer for clipping.
|
|
||||||
MallocResult alloc_clip_buf(uint link) {
|
|
||||||
if (gl_LocalInvocationID.x == 0 && gl_LocalInvocationID.y == 0) {
|
|
||||||
MallocResult m = malloc(CLIP_BUF_SIZE * 4);
|
|
||||||
if (!m.failed) {
|
|
||||||
write_mem(m.alloc, (m.alloc.offset >> 2) + CLIP_LINK_OFFSET, link);
|
|
||||||
}
|
|
||||||
sh_clip_alloc = m;
|
|
||||||
}
|
|
||||||
barrier();
|
|
||||||
return sh_clip_alloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 tosRGB(vec3 rgb) {
|
vec3 tosRGB(vec3 rgb) {
|
||||||
bvec3 cutoff = greaterThanEqual(rgb, vec3(0.0031308));
|
bvec3 cutoff = greaterThanEqual(rgb, vec3(0.0031308));
|
||||||
vec3 below = vec3(12.92)*rgb;
|
vec3 below = vec3(12.92)*rgb;
|
||||||
@@ -90,10 +63,14 @@ uint packsRGB(vec4 rgba) {
|
|||||||
return packUnorm4x8(rgba.wzyx);
|
return packUnorm4x8(rgba.wzyx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uvec2 chunk_offset(uint i) {
|
||||||
|
return uvec2(i % CHUNK_X * CHUNK_DX, i / CHUNK_X * CHUNK_DY);
|
||||||
|
}
|
||||||
|
|
||||||
vec4[CHUNK] fillImage(uvec2 xy, CmdImage cmd_img) {
|
vec4[CHUNK] fillImage(uvec2 xy, CmdImage cmd_img) {
|
||||||
vec4 rgba[CHUNK];
|
vec4 rgba[CHUNK];
|
||||||
for (uint i = 0; i < CHUNK; i++) {
|
for (uint i = 0; i < CHUNK; i++) {
|
||||||
ivec2 uv = ivec2(xy.x, xy.y + i * CHUNK_DY) + cmd_img.offset;
|
ivec2 uv = ivec2(xy + chunk_offset(i)) + cmd_img.offset;
|
||||||
#ifdef ENABLE_IMAGE_INDICES
|
#ifdef ENABLE_IMAGE_INDICES
|
||||||
vec4 fg_rgba = imageLoad(images[cmd_img.index], uv);
|
vec4 fg_rgba = imageLoad(images[cmd_img.index], uv);
|
||||||
#else
|
#else
|
||||||
@@ -114,23 +91,24 @@ void main() {
|
|||||||
Alloc cmd_alloc = slice_mem(conf.ptcl_alloc, tile_ix * PTCL_INITIAL_ALLOC, PTCL_INITIAL_ALLOC);
|
Alloc cmd_alloc = slice_mem(conf.ptcl_alloc, tile_ix * PTCL_INITIAL_ALLOC, PTCL_INITIAL_ALLOC);
|
||||||
CmdRef cmd_ref = CmdRef(cmd_alloc.offset);
|
CmdRef cmd_ref = CmdRef(cmd_alloc.offset);
|
||||||
|
|
||||||
uvec2 xy_uint = uvec2(gl_GlobalInvocationID.x, gl_LocalInvocationID.y + TILE_HEIGHT_PX * gl_WorkGroupID.y);
|
// Read scrach space allocation, written first in the command list.
|
||||||
|
Alloc scratch_alloc = alloc_read(cmd_alloc, cmd_ref.offset);
|
||||||
|
cmd_ref.offset += Alloc_size;
|
||||||
|
|
||||||
|
uvec2 xy_uint = uvec2(gl_LocalInvocationID.x + TILE_WIDTH_PX * gl_WorkGroupID.x, gl_LocalInvocationID.y + TILE_HEIGHT_PX * gl_WorkGroupID.y);
|
||||||
vec2 xy = vec2(xy_uint);
|
vec2 xy = vec2(xy_uint);
|
||||||
vec4 rgba[CHUNK];
|
vec4 rgba[CHUNK];
|
||||||
ClipState blend_stack[BLEND_STACK_SIZE][CHUNK];
|
|
||||||
uint blend_spill = 0;
|
|
||||||
uint blend_sp = 0;
|
|
||||||
Alloc clip_tos = new_alloc(0, 0);
|
|
||||||
for (uint i = 0; i < CHUNK; i++) {
|
for (uint i = 0; i < CHUNK; i++) {
|
||||||
rgba[i] = vec4(0.0);
|
rgba[i] = vec4(0.0);
|
||||||
#ifdef ENABLE_IMAGE_INDICES
|
#ifdef ENABLE_IMAGE_INDICES
|
||||||
if (xy_uint.x < 1024 && xy_uint.y < 1024) {
|
if (xy_uint.x < 1024 && xy_uint.y < 1024) {
|
||||||
rgba[i] = imageLoad(images[gl_WorkGroupID.x / 64], ivec2(xy_uint.x, xy_uint.y + CHUNK_DY * i)/4);
|
rgba[i] = imageLoad(images[gl_WorkGroupID.x / 64], ivec2(xy_uint + chunk_offset(i))/4);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
float area[CHUNK];
|
float area[CHUNK];
|
||||||
|
uint clip_depth = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
uint tag = Cmd_tag(cmd_alloc, cmd_ref).tag;
|
uint tag = Cmd_tag(cmd_alloc, cmd_ref).tag;
|
||||||
if (tag == Cmd_End) {
|
if (tag == Cmd_End) {
|
||||||
@@ -148,7 +126,7 @@ void main() {
|
|||||||
vec2 line_vec = seg.vector;
|
vec2 line_vec = seg.vector;
|
||||||
for (uint k = 0; k < CHUNK; k++) {
|
for (uint k = 0; k < CHUNK; k++) {
|
||||||
vec2 dpos = xy + vec2(0.5, 0.5) - seg.origin;
|
vec2 dpos = xy + vec2(0.5, 0.5) - seg.origin;
|
||||||
dpos.y += float(k * CHUNK_DY);
|
dpos += vec2(chunk_offset(k));
|
||||||
float t = clamp(dot(line_vec, dpos) / dot(line_vec, line_vec), 0.0, 1.0);
|
float t = clamp(dot(line_vec, dpos) / dot(line_vec, line_vec), 0.0, 1.0);
|
||||||
df[k] = min(df[k], length(line_vec * t - dpos));
|
df[k] = min(df[k], length(line_vec * t - dpos));
|
||||||
}
|
}
|
||||||
@@ -167,7 +145,7 @@ void main() {
|
|||||||
do {
|
do {
|
||||||
TileSeg seg = TileSeg_read(new_alloc(tile_seg_ref.offset, TileSeg_size), tile_seg_ref);
|
TileSeg seg = TileSeg_read(new_alloc(tile_seg_ref.offset, TileSeg_size), tile_seg_ref);
|
||||||
for (uint k = 0; k < CHUNK; k++) {
|
for (uint k = 0; k < CHUNK; k++) {
|
||||||
vec2 my_xy = vec2(xy.x, xy.y + float(k * CHUNK_DY));
|
vec2 my_xy = xy + vec2(chunk_offset(k));
|
||||||
vec2 start = seg.origin - my_xy;
|
vec2 start = seg.origin - my_xy;
|
||||||
vec2 end = start + seg.vector;
|
vec2 end = start + seg.vector;
|
||||||
vec2 window = clamp(vec2(start.y, end.y), 0.0, 1.0);
|
vec2 window = clamp(vec2(start.y, end.y), 0.0, 1.0);
|
||||||
@@ -223,47 +201,29 @@ void main() {
|
|||||||
cmd_ref.offset += 4 + CmdImage_size;
|
cmd_ref.offset += 4 + CmdImage_size;
|
||||||
break;
|
break;
|
||||||
case Cmd_BeginClip:
|
case Cmd_BeginClip:
|
||||||
uint blend_slot = blend_sp % BLEND_STACK_SIZE;
|
uint base_ix = (scratch_alloc.offset >> 2) + CLIP_STATE_SIZE * (clip_depth * TILE_WIDTH_PX * TILE_HEIGHT_PX +
|
||||||
if (blend_sp == blend_spill + BLEND_STACK_SIZE) {
|
gl_LocalInvocationID.x + TILE_WIDTH_PX * gl_LocalInvocationID.y);
|
||||||
// spill to scratch buffer
|
|
||||||
MallocResult m = alloc_clip_buf(clip_tos.offset);
|
|
||||||
if (m.failed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
clip_tos = m.alloc;
|
|
||||||
uint base_ix = (clip_tos.offset >> 2) + CLIP_STATE_SIZE * (gl_LocalInvocationID.x + TILE_WIDTH_PX * gl_LocalInvocationID.y);
|
|
||||||
for (uint k = 0; k < CHUNK; k++) {
|
|
||||||
uint srgb = blend_stack[blend_slot][k].srgb;
|
|
||||||
uint area = floatBitsToUint(blend_stack[blend_slot][k].area);
|
|
||||||
write_mem(clip_tos, base_ix + 0 + k * CLIP_STATE_SIZE * TILE_WIDTH_PX * CHUNK_DY, srgb);
|
|
||||||
write_mem(clip_tos, base_ix + 1 + k * CLIP_STATE_SIZE * TILE_WIDTH_PX * CHUNK_DY, area);
|
|
||||||
}
|
|
||||||
blend_spill++;
|
|
||||||
}
|
|
||||||
for (uint k = 0; k < CHUNK; k++) {
|
for (uint k = 0; k < CHUNK; k++) {
|
||||||
blend_stack[blend_slot][k] = ClipState(packsRGB(rgba[k]), clamp(abs(area[k]), 0.0, 1.0));
|
uvec2 offset = chunk_offset(k);
|
||||||
|
uint srgb = packsRGB(vec4(rgba[k]));
|
||||||
|
float alpha = clamp(abs(area[k]), 0.0, 1.0);
|
||||||
|
write_mem(scratch_alloc, base_ix + 0 + CLIP_STATE_SIZE * (offset.x + offset.y * TILE_WIDTH_PX), srgb);
|
||||||
|
write_mem(scratch_alloc, base_ix + 1 + CLIP_STATE_SIZE * (offset.x + offset.y * TILE_WIDTH_PX), floatBitsToUint(alpha));
|
||||||
rgba[k] = vec4(0.0);
|
rgba[k] = vec4(0.0);
|
||||||
}
|
}
|
||||||
blend_sp++;
|
clip_depth++;
|
||||||
cmd_ref.offset += 4;
|
cmd_ref.offset += 4;
|
||||||
break;
|
break;
|
||||||
case Cmd_EndClip:
|
case Cmd_EndClip:
|
||||||
blend_slot = (blend_sp - 1) % BLEND_STACK_SIZE;
|
clip_depth--;
|
||||||
if (blend_sp == blend_spill) {
|
base_ix = (scratch_alloc.offset >> 2) + CLIP_STATE_SIZE * (clip_depth * TILE_WIDTH_PX * TILE_HEIGHT_PX +
|
||||||
uint base_ix = (clip_tos.offset >> 2) + CLIP_STATE_SIZE * (gl_LocalInvocationID.x + TILE_WIDTH_PX * gl_LocalInvocationID.y);
|
gl_LocalInvocationID.x + TILE_WIDTH_PX * gl_LocalInvocationID.y);
|
||||||
for (uint k = 0; k < CHUNK; k++) {
|
|
||||||
uint srgb = read_mem(clip_tos, base_ix + 0 + k * CLIP_STATE_SIZE * TILE_WIDTH_PX * CHUNK_DY);
|
|
||||||
uint area = read_mem(clip_tos, base_ix + 1 + k * CLIP_STATE_SIZE * TILE_WIDTH_PX * CHUNK_DY);
|
|
||||||
ClipState state = ClipState(srgb, uintBitsToFloat(area));
|
|
||||||
blend_stack[blend_slot][k] = state;
|
|
||||||
}
|
|
||||||
clip_tos.offset = read_mem(clip_tos, (clip_tos.offset >> 2) + CLIP_LINK_OFFSET);
|
|
||||||
blend_spill--;
|
|
||||||
}
|
|
||||||
blend_sp--;
|
|
||||||
for (uint k = 0; k < CHUNK; k++) {
|
for (uint k = 0; k < CHUNK; k++) {
|
||||||
vec4 bg = unpacksRGB(blend_stack[blend_slot][k].srgb);
|
uvec2 offset = chunk_offset(k);
|
||||||
vec4 fg = rgba[k] * area[k] * blend_stack[blend_slot][k].area;
|
uint srgb = read_mem(scratch_alloc, base_ix + 0 + CLIP_STATE_SIZE * (offset.x + offset.y * TILE_WIDTH_PX));
|
||||||
|
uint alpha = read_mem(scratch_alloc, base_ix + 1 + CLIP_STATE_SIZE * (offset.x + offset.y * TILE_WIDTH_PX));
|
||||||
|
vec4 bg = unpacksRGB(srgb);
|
||||||
|
vec4 fg = rgba[k] * area[k] * uintBitsToFloat(alpha);
|
||||||
rgba[k] = bg * (1.0 - fg.a) + fg;
|
rgba[k] = bg * (1.0 - fg.a) + fg;
|
||||||
}
|
}
|
||||||
cmd_ref.offset += 4;
|
cmd_ref.offset += 4;
|
||||||
@@ -276,6 +236,6 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (uint i = 0; i < CHUNK; i++) {
|
for (uint i = 0; i < CHUNK; i++) {
|
||||||
imageStore(image, ivec2(xy_uint.x, xy_uint.y + CHUNK_DY * i), vec4(tosRGB(rgba[i].rgb), rgba[i].a));
|
imageStore(image, ivec2(xy_uint + chunk_offset(i)), vec4(tosRGB(rgba[i].rgb), rgba[i].a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-1
@@ -21,7 +21,11 @@ layout(set = 0, binding = 0) buffer Memory {
|
|||||||
#define ERR_OUT_OF_BOUNDS 2
|
#define ERR_OUT_OF_BOUNDS 2
|
||||||
#define ERR_UNALIGNED_ACCESS 3
|
#define ERR_UNALIGNED_ACCESS 3
|
||||||
|
|
||||||
|
#ifdef MEM_DEBUG
|
||||||
|
#define Alloc_size 16
|
||||||
|
#else
|
||||||
#define Alloc_size 8
|
#define Alloc_size 8
|
||||||
|
#endif
|
||||||
|
|
||||||
// Alloc represents a memory allocation.
|
// Alloc represents a memory allocation.
|
||||||
struct Alloc {
|
struct Alloc {
|
||||||
@@ -39,7 +43,7 @@ struct MallocResult {
|
|||||||
bool failed;
|
bool failed;
|
||||||
};
|
};
|
||||||
|
|
||||||
// new_alloc synthesizes an Alloc when its offset and size are derived.
|
// new_alloc synthesizes an Alloc from an offset and size.
|
||||||
Alloc new_alloc(uint offset, uint size) {
|
Alloc new_alloc(uint offset, uint size) {
|
||||||
Alloc a;
|
Alloc a;
|
||||||
a.offset = offset;
|
a.offset = offset;
|
||||||
@@ -118,3 +122,21 @@ Alloc slice_mem(Alloc a, uint offset, uint size) {
|
|||||||
#endif
|
#endif
|
||||||
return new_alloc(a.offset + offset, size);
|
return new_alloc(a.offset + offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// alloc_write writes alloc to memory at offset bytes.
|
||||||
|
void alloc_write(Alloc a, uint offset, Alloc alloc) {
|
||||||
|
write_mem(a, offset >> 2, alloc.offset);
|
||||||
|
#ifdef MEM_DEBUG
|
||||||
|
write_mem(a, (offset >> 2) + 1, alloc.size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// alloc_read reads an Alloc from memory at offset bytes.
|
||||||
|
Alloc alloc_read(Alloc a, uint offset) {
|
||||||
|
Alloc alloc;
|
||||||
|
alloc.offset = read_mem(a, offset >> 2);
|
||||||
|
#ifdef MEM_DEBUG
|
||||||
|
alloc.size = read_mem(a, (offset >> 2) + 1);
|
||||||
|
#endif
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|||||||
+4
-1
@@ -42,7 +42,10 @@ struct Config {
|
|||||||
#define MODE_NONZERO 0
|
#define MODE_NONZERO 0
|
||||||
#define MODE_STROKE 1
|
#define MODE_STROKE 1
|
||||||
|
|
||||||
|
// Size of kernel4 clip state, in words.
|
||||||
|
#define CLIP_STATE_SIZE 2
|
||||||
|
|
||||||
// fill_mode_from_flags extracts the fill mode from tag flags.
|
// fill_mode_from_flags extracts the fill mode from tag flags.
|
||||||
uint fill_mode_from_flags(uint flags) {
|
uint fill_mode_from_flags(uint flags) {
|
||||||
return flags & 0x1;
|
return flags & 0x1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user