[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];
int pathIndex;
int localEltIndex;
mg_gl_seg_kind kind;
u8 pad[4];
} mg_gl_path_elt;
enum {
@ -105,7 +104,6 @@ typedef struct mg_gl_encoding_context
mg_gl_path* pathBufferData;
mg_gl_path_elt* elementBufferData;
int pathIndex;
int localEltIndex;
mg_primitive* primitive;
vec4 pathScreenExtents;
vec4 pathUserExtents;
@ -195,8 +193,6 @@ void mg_gl_canvas_encode_element(mg_gl_encoding_context* context, mg_path_elt_ty
break;
}
glElt->localEltIndex = context->localEltIndex;
for(int i=0; i<count; 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);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->pathBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->segmentCountBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->segmentBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileOpBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, backend->screenTilesBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->segmentBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->tileOpBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->screenTilesBuffer);
glUniform1f(0, scale);
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++)
{
context.localEltIndex = segCount;
mg_path_elt* elt = &pathElements[primitive->path.startIndex + eltIndex];
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);
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
glGenBuffers(1, &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);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->segmentBuffer);

View File

@ -36,7 +36,6 @@ struct mg_gl_path_elt
{
vec2 p[4];
int pathIndex;
int localEltIndex;
int kind;
};
@ -44,13 +43,12 @@ struct mg_gl_segment
{
int kind;
int pathIndex;
int config; //TODO pack these
int config;
int windingIncrement;
vec4 box;
mat3 implicitMatrix;
float sign;
vec2 hullVertex;
int debugID;
float sign;
};
struct mg_gl_path_queue
@ -62,10 +60,9 @@ struct mg_gl_path_queue
struct mg_gl_tile_op
{
int kind;
int index;
int next;
bool crossRight;
int windingOffset;
int index;
int windingOffsetOrCrossRight;
};
struct mg_gl_tile_queue
@ -75,7 +72,6 @@ struct mg_gl_tile_queue
int last;
};
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));

View File

@ -82,7 +82,7 @@ void main()
tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_START;
tileOpBuffer.elements[pathOpIndex].next = -1;
tileOpBuffer.elements[pathOpIndex].index = pathIndex;
tileOpBuffer.elements[pathOpIndex].windingOffset = windingOffset;
tileOpBuffer.elements[pathOpIndex].windingOffsetOrCrossRight = windingOffset;
vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
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].next = -1;
tileOpBuffer.elements[pathOpIndex].index = pathIndex;
tileOpBuffer.elements[pathOpIndex].windingOffset = windingOffset;
tileOpBuffer.elements[pathOpIndex].windingOffsetOrCrossRight = windingOffset;
if(lastOpIndex < 0)
{

View File

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

View File

@ -106,7 +106,7 @@ void bin_to_tiles(int segIndex)
tileOpBuffer.elements[tileOpIndex].kind = MG_GL_OP_SEGMENT;
tileOpBuffer.elements[tileOpIndex].index = segIndex;
tileOpBuffer.elements[tileOpIndex].crossRight = false;
tileOpBuffer.elements[tileOpIndex].windingOffsetOrCrossRight = 0;
tileOpBuffer.elements[tileOpIndex].next = -1;
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.
if(crossR)
{
tileOpBuffer.elements[tileOpIndex].crossRight = true;
tileOpBuffer.elements[tileOpIndex].windingOffsetOrCrossRight = 1;
}
}
}