[gl, canvas]

- Haul path color and texture sampling outside of per-sample loop
- Pack gl input structs a bit
- Set correct hint flags for glBufferData()
This commit is contained in:
martinfouilleul 2023-07-07 15:45:06 +02:00
parent 9bfae2c4e8
commit 59fdc27ac6
5 changed files with 41 additions and 57 deletions

View File

@ -44,9 +44,8 @@ typedef struct mg_gl_path_elt
{ {
vec2 p[4]; vec2 p[4];
int pathIndex; int pathIndex;
int localEltIndex;
mg_gl_seg_kind kind; mg_gl_seg_kind kind;
u8 pad[4];
} mg_gl_path_elt; } mg_gl_path_elt;
enum { enum {
@ -105,7 +104,6 @@ typedef struct mg_gl_encoding_context
mg_gl_path* pathBufferData; mg_gl_path* pathBufferData;
mg_gl_path_elt* elementBufferData; mg_gl_path_elt* elementBufferData;
int pathIndex; int pathIndex;
int localEltIndex;
mg_primitive* primitive; mg_primitive* primitive;
vec4 pathScreenExtents; vec4 pathScreenExtents;
vec4 pathUserExtents; vec4 pathUserExtents;
@ -195,8 +193,6 @@ void mg_gl_canvas_encode_element(mg_gl_encoding_context* context, mg_path_elt_ty
break; break;
} }
glElt->localEltIndex = context->localEltIndex;
for(int i=0; i<count; i++) for(int i=0; i<count; i++)
{ {
mg_update_path_extents(&context->pathUserExtents, p[i]); mg_update_path_extents(&context->pathUserExtents, p[i]);
@ -998,10 +994,9 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
glUseProgram(backend->raster); glUseProgram(backend->raster);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->pathBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->pathBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->segmentCountBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->segmentBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->segmentBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->tileOpBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileOpBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->screenTilesBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, backend->screenTilesBuffer);
glUniform1f(0, scale); glUniform1f(0, scale);
glUniform1i(1, backend->msaaCount); glUniform1i(1, backend->msaaCount);
@ -1126,8 +1121,6 @@ void mg_gl_canvas_render(mg_canvas_backend* interface,
(eltIndex < primitive->path.count) && (primitive->path.startIndex + eltIndex < eltCount); (eltIndex < primitive->path.count) && (primitive->path.startIndex + eltIndex < eltCount);
eltIndex++) eltIndex++)
{ {
context.localEltIndex = segCount;
mg_path_elt* elt = &pathElements[primitive->path.startIndex + eltIndex]; mg_path_elt* elt = &pathElements[primitive->path.startIndex + eltIndex];
if(elt->type != MG_PATH_MOVE) if(elt->type != MG_PATH_MOVE)
@ -1453,12 +1446,12 @@ mg_canvas_backend* gl_canvas_backend_create(mg_wgl_surface* surface)
glGenBuffers(1, &backend->pathBuffer); glGenBuffers(1, &backend->pathBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->pathBuffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->pathBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GL_PATH_BUFFER_SIZE, 0, GL_DYNAMIC_COPY); glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GL_PATH_BUFFER_SIZE, 0, GL_STREAM_DRAW);
//TODO change flags //TODO change flags
glGenBuffers(1, &backend->elementBuffer); glGenBuffers(1, &backend->elementBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->elementBuffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->elementBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GL_ELEMENT_BUFFER_SIZE, 0, GL_DYNAMIC_COPY); glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GL_ELEMENT_BUFFER_SIZE, 0, GL_STREAM_DRAW);
glGenBuffers(1, &backend->segmentBuffer); glGenBuffers(1, &backend->segmentBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->segmentBuffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->segmentBuffer);

View File

@ -36,7 +36,6 @@ struct mg_gl_path_elt
{ {
vec2 p[4]; vec2 p[4];
int pathIndex; int pathIndex;
int localEltIndex;
int kind; int kind;
}; };
@ -44,13 +43,12 @@ struct mg_gl_segment
{ {
int kind; int kind;
int pathIndex; int pathIndex;
int config; //TODO pack these int config;
int windingIncrement; int windingIncrement;
vec4 box; vec4 box;
mat3 implicitMatrix; mat3 implicitMatrix;
float sign;
vec2 hullVertex; vec2 hullVertex;
int debugID; float sign;
}; };
struct mg_gl_path_queue struct mg_gl_path_queue
@ -62,10 +60,9 @@ struct mg_gl_path_queue
struct mg_gl_tile_op struct mg_gl_tile_op
{ {
int kind; int kind;
int index;
int next; int next;
bool crossRight; int index;
int windingOffset; int windingOffsetOrCrossRight;
}; };
struct mg_gl_tile_queue struct mg_gl_tile_queue
@ -75,7 +72,6 @@ struct mg_gl_tile_queue
int last; int last;
}; };
float ccw(vec2 a, vec2 b, vec2 c) float ccw(vec2 a, vec2 b, vec2 c)
{ {
return((b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x)); return((b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x));

View File

@ -82,7 +82,7 @@ void main()
tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_START; tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_START;
tileOpBuffer.elements[pathOpIndex].next = -1; tileOpBuffer.elements[pathOpIndex].next = -1;
tileOpBuffer.elements[pathOpIndex].index = pathIndex; tileOpBuffer.elements[pathOpIndex].index = pathIndex;
tileOpBuffer.elements[pathOpIndex].windingOffset = windingOffset; tileOpBuffer.elements[pathOpIndex].windingOffsetOrCrossRight = windingOffset;
vec4 clip = pathBuffer.elements[pathIndex].clip * scale; vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
vec4 tileBox = vec4(tileCoord.x, tileCoord.y, tileCoord.x+1, tileCoord.y+1); vec4 tileBox = vec4(tileCoord.x, tileCoord.y, tileCoord.x+1, tileCoord.y+1);
@ -114,7 +114,7 @@ void main()
tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_START; tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_START;
tileOpBuffer.elements[pathOpIndex].next = -1; tileOpBuffer.elements[pathOpIndex].next = -1;
tileOpBuffer.elements[pathOpIndex].index = pathIndex; tileOpBuffer.elements[pathOpIndex].index = pathIndex;
tileOpBuffer.elements[pathOpIndex].windingOffset = windingOffset; tileOpBuffer.elements[pathOpIndex].windingOffsetOrCrossRight = windingOffset;
if(lastOpIndex < 0) if(lastOpIndex < 0)
{ {

View File

@ -9,22 +9,17 @@ layout(binding = 0) restrict readonly buffer pathBufferSSBO
mg_gl_path elements[]; mg_gl_path elements[];
} pathBuffer; } pathBuffer;
layout(binding = 1) restrict readonly buffer segmentCountBufferSSBO layout(binding = 1) restrict readonly buffer segmentBufferSSBO
{
int elements[];
} segmentCountBuffer;
layout(binding = 2) restrict readonly buffer segmentBufferSSBO
{ {
mg_gl_segment elements[]; mg_gl_segment elements[];
} segmentBuffer; } segmentBuffer;
layout(binding = 3) restrict readonly buffer tileOpBufferSSBO layout(binding = 2) restrict readonly buffer tileOpBufferSSBO
{ {
mg_gl_tile_op elements[]; mg_gl_tile_op elements[];
} tileOpBuffer; } tileOpBuffer;
layout(binding = 4) restrict readonly buffer screenTilesBufferSSBO layout(binding = 3) restrict readonly buffer screenTilesBufferSSBO
{ {
int elements[]; int elements[];
} screenTilesBuffer; } screenTilesBuffer;
@ -91,8 +86,17 @@ void main()
if(op.kind == MG_GL_OP_START) if(op.kind == MG_GL_OP_START)
{ {
vec4 clip = pathBuffer.elements[pathIndex].clip * scale; vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
vec4 pathColor = pathBuffer.elements[pathIndex].color; vec4 nextColor = pathBuffer.elements[pathIndex].color;
pathColor.rgb *= pathColor.a; nextColor.rgb *= nextColor.a;
if(useTexture != 0)
{
vec3 ph = vec3(centerCoord.xy, 1);
vec2 uv = (pathBuffer.elements[pathIndex].uvTransform * ph).xy;
vec4 texColor = texture(srcTexture, uv);
texColor.rgb *= texColor.a;
nextColor *= texColor;
}
for(int sampleIndex = 0; sampleIndex<sampleCount; sampleIndex++) for(int sampleIndex = 0; sampleIndex<sampleCount; sampleIndex++)
{ {
@ -107,19 +111,10 @@ void main()
||(pathBuffer.elements[pathIndex].cmd == MG_GL_STROKE && (winding[sampleIndex] != 0)); ||(pathBuffer.elements[pathIndex].cmd == MG_GL_STROKE && (winding[sampleIndex] != 0));
if(filled) if(filled)
{ {
vec4 nextColor = pathColor;
if(useTexture != 0)
{
vec3 ph = vec3(sampleCoord.xy, 1);
vec2 uv = (pathBuffer.elements[pathIndex].uvTransform * ph).xy;
vec4 texColor = texture(srcTexture, uv);
texColor.rgb *= texColor.a;
nextColor *= texColor;
}
color[sampleIndex] = color[sampleIndex]*(1-nextColor.a) + nextColor; color[sampleIndex] = color[sampleIndex]*(1-nextColor.a) + nextColor;
} }
} }
winding[sampleIndex] = op.windingOffset; winding[sampleIndex] = op.windingOffsetOrCrossRight;
} }
pathIndex = op.index; pathIndex = op.index;
} }
@ -139,7 +134,7 @@ void main()
winding[sampleIndex] += seg.windingIncrement; winding[sampleIndex] += seg.windingIncrement;
} }
if(op.crossRight) if(op.windingOffsetOrCrossRight != 0)
{ {
if( (seg.config == MG_GL_BR || seg.config == MG_GL_TL) if( (seg.config == MG_GL_BR || seg.config == MG_GL_TL)
&&(sampleCoord.y > seg.box.w)) &&(sampleCoord.y > seg.box.w))
@ -159,8 +154,17 @@ void main()
vec4 clip = pathBuffer.elements[pathIndex].clip * scale; vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
vec4 pixelColor = vec4(0); vec4 pixelColor = vec4(0);
vec4 pathColor = pathBuffer.elements[pathIndex].color; vec4 nextColor = pathBuffer.elements[pathIndex].color;
pathColor.rgb *= pathColor.a; nextColor.rgb *= nextColor.a;
if(useTexture != 0)
{
vec3 ph = vec3(centerCoord.xy, 1);
vec2 uv = (pathBuffer.elements[pathIndex].uvTransform * ph).xy;
vec4 texColor = texture(srcTexture, uv);
texColor.rgb *= texColor.a;
nextColor *= texColor;
}
for(int sampleIndex=0; sampleIndex<sampleCount; sampleIndex++) for(int sampleIndex=0; sampleIndex<sampleCount; sampleIndex++)
{ {
@ -175,15 +179,6 @@ void main()
||(pathBuffer.elements[pathIndex].cmd == MG_GL_STROKE && (winding[sampleIndex] != 0)); ||(pathBuffer.elements[pathIndex].cmd == MG_GL_STROKE && (winding[sampleIndex] != 0));
if(filled) if(filled)
{ {
vec4 nextColor = pathColor;
if(useTexture != 0)
{
vec3 ph = vec3(sampleCoord.xy, 1);
vec2 uv = (pathBuffer.elements[pathIndex].uvTransform * ph).xy;
vec4 texColor = texture(srcTexture, uv);
texColor.rgb *= texColor.a;
nextColor *= texColor;
}
color[sampleIndex] = color[sampleIndex]*(1-nextColor.a) + nextColor; color[sampleIndex] = color[sampleIndex]*(1-nextColor.a) + nextColor;
} }
} }

View File

@ -106,7 +106,7 @@ void bin_to_tiles(int segIndex)
tileOpBuffer.elements[tileOpIndex].kind = MG_GL_OP_SEGMENT; tileOpBuffer.elements[tileOpIndex].kind = MG_GL_OP_SEGMENT;
tileOpBuffer.elements[tileOpIndex].index = segIndex; tileOpBuffer.elements[tileOpIndex].index = segIndex;
tileOpBuffer.elements[tileOpIndex].crossRight = false; tileOpBuffer.elements[tileOpIndex].windingOffsetOrCrossRight = 0;
tileOpBuffer.elements[tileOpIndex].next = -1; tileOpBuffer.elements[tileOpIndex].next = -1;
int tileQueueIndex = pathQueue.tileQueues + y*pathArea.z + x; int tileQueueIndex = pathQueue.tileQueues + y*pathArea.z + x;
@ -126,7 +126,7 @@ void bin_to_tiles(int segIndex)
//NOTE: if the segment crosses the right boundary, mark it. //NOTE: if the segment crosses the right boundary, mark it.
if(crossR) if(crossR)
{ {
tileOpBuffer.elements[tileOpIndex].crossRight = true; tileOpBuffer.elements[tileOpIndex].windingOffsetOrCrossRight = 1;
} }
} }
} }