[gl canvas] allow multiple textures per batch

This commit is contained in:
martinfouilleul 2023-07-27 20:07:07 +02:00
parent c983c39f44
commit b05caf984c
4 changed files with 114 additions and 50 deletions

View File

@ -30,7 +30,8 @@ typedef struct mg_gl_path
vec4 box; vec4 box;
vec4 clip; vec4 clip;
mg_gl_cmd cmd; mg_gl_cmd cmd;
u8 pad[12]; int textureID;
u8 pad[8];
} mg_gl_path; } mg_gl_path;
enum _mg_gl_seg_kind{ enum _mg_gl_seg_kind{
@ -125,6 +126,7 @@ enum {
MG_GL_INPUT_BUFFERS_COUNT = 3, MG_GL_INPUT_BUFFERS_COUNT = 3,
MG_GL_TILE_SIZE = 16, MG_GL_TILE_SIZE = 16,
MG_GL_MSAA_COUNT = 8, MG_GL_MSAA_COUNT = 8,
MG_GL_MAX_IMAGES_PER_BATCH = 8,
}; };
typedef struct mg_gl_mapped_buffer typedef struct mg_gl_mapped_buffer
@ -186,6 +188,7 @@ typedef struct mg_gl_canvas_backend
int maxTileQueueCount; int maxTileQueueCount;
int maxSegmentCount; int maxSegmentCount;
int currentImageIndex;
} mg_gl_canvas_backend; } mg_gl_canvas_backend;
static void mg_update_path_extents(vec4* extents, vec2 p) static void mg_update_path_extents(vec4* extents, vec2 p)
@ -362,6 +365,12 @@ void mg_gl_canvas_encode_path(mg_gl_canvas_backend* backend, mg_primitive* primi
path->uvTransform[9] = uvTransform.m[5]; path->uvTransform[9] = uvTransform.m[5];
path->uvTransform[10] = 1; path->uvTransform[10] = 1;
path->uvTransform[11] = 0; path->uvTransform[11] = 0;
path->textureID = backend->currentImageIndex;
}
else
{
path->textureID = -1;
} }
int nTilesX = ((path->box.z - path->box.x)*scale - 1) / MG_GL_TILE_SIZE + 1; int nTilesX = ((path->box.z - path->box.x)*scale - 1) / MG_GL_TILE_SIZE + 1;
@ -1043,7 +1052,7 @@ void mg_gl_grow_buffer_if_needed(GLuint buffer, i32 wantedSize, const char* name
void mg_gl_render_batch(mg_gl_canvas_backend* backend, void mg_gl_render_batch(mg_gl_canvas_backend* backend,
mg_wgl_surface* surface, mg_wgl_surface* surface,
mg_image_data* image, mg_image* images,
int tileSize, int tileSize,
int nTilesX, int nTilesX,
int nTilesY, int nTilesY,
@ -1220,18 +1229,7 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
glUniform1i(0, tileSize); glUniform1i(0, tileSize);
glUniform1f(1, scale); glUniform1f(1, scale);
glUniform1i(2, pathCount); glUniform1i(2, pathCount);
glUniform1i(3, backend->pathBatchStart);
// if there's an image, don't cull solid tiles
if(image)
{
glUniform1i(3, 0);
}
else
{
glUniform1i(3, 1);
}
glUniform1i(4, backend->pathBatchStart);
glDispatchCompute(nTilesX, nTilesY, 1); glDispatchCompute(nTilesX, nTilesY, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
@ -1269,20 +1267,21 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
glBindImageTexture(0, backend->outTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); glBindImageTexture(0, backend->outTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
if(image) for(int i=0; i<MG_GL_MAX_IMAGES_PER_BATCH; i++)
{ {
mg_gl_image* glImage = (mg_gl_image*)image; if(images[i].h)
glActiveTexture(GL_TEXTURE1); {
glBindTexture(GL_TEXTURE_2D, glImage->texture); mg_gl_image* image = (mg_gl_image*)mg_image_data_from_handle(images[i]);
glUniform1ui(2, 1); if(image)
} {
else glActiveTexture(GL_TEXTURE1+i);
{ glBindTexture(GL_TEXTURE_2D, image->texture);
glUniform1ui(2, 0); }
}
} }
glUniform1i(3, backend->pathBatchStart); glUniform1i(2, backend->pathBatchStart);
glUniform1ui(4, maxWorkGroupCount); glUniform1ui(3, maxWorkGroupCount);
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, backend->rasterDispatchBuffer); glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, backend->rasterDispatchBuffer);
glDispatchComputeIndirect(0); glDispatchComputeIndirect(0);
@ -1397,28 +1396,53 @@ void mg_gl_canvas_render(mg_canvas_backend* interface,
//NOTE: encode and render batches //NOTE: encode and render batches
vec2 currentPos = {0}; vec2 currentPos = {0};
mg_image currentImage = mg_image_nil(); mg_image images[MG_GL_MAX_IMAGES_PER_BATCH] = {0};
int imageCount = 0;
backend->eltCount = 0; backend->eltCount = 0;
for(int primitiveIndex = 0; primitiveIndex < primitiveCount; primitiveIndex++) for(int primitiveIndex = 0; primitiveIndex < primitiveCount; primitiveIndex++)
{ {
mg_primitive* primitive = &primitives[primitiveIndex]; mg_primitive* primitive = &primitives[primitiveIndex];
if(primitiveIndex && (primitive->attributes.image.h != currentImage.h)) if(primitive->attributes.image.h != 0)
{ {
mg_image_data* imageData = mg_image_data_from_handle(currentImage); backend->currentImageIndex = -1;
for(int i=0; i<imageCount; i++)
{
if(images[i].h == primitive->attributes.image.h)
{
backend->currentImageIndex = i;
}
}
if(backend->currentImageIndex <= 0)
{
if(imageCount<MG_GL_MAX_IMAGES_PER_BATCH)
{
images[imageCount] = primitive->attributes.image;
backend->currentImageIndex = imageCount;
imageCount++;
}
else
{
mg_gl_render_batch(backend,
surface,
images,
tileSize,
nTilesX,
nTilesY,
viewportSize,
scale);
mg_gl_render_batch(backend, images[0] = primitive->attributes.image;
surface, backend->currentImageIndex = 0;
imageData, imageCount = 1;
tileSize, }
nTilesX, }
nTilesY, }
viewportSize, else
scale); {
backend->currentImageIndex = -1;
} }
currentImage = primitive->attributes.image;
if(primitive->path.count) if(primitive->path.count)
{ {
@ -1470,10 +1494,9 @@ void mg_gl_canvas_render(mg_canvas_backend* interface,
} }
} }
mg_image_data* imageData = mg_image_data_from_handle(currentImage);
mg_gl_render_batch(backend, mg_gl_render_batch(backend,
surface, surface,
imageData, images,
tileSize, tileSize,
nTilesX, nTilesX,
nTilesY, nTilesY,
@ -1661,10 +1684,10 @@ mg_canvas_backend* gl_canvas_backend_create(mg_wgl_surface* surface)
//NOTE(martin): setup interface functions //NOTE(martin): setup interface functions
backend->interface.destroy = mg_gl_canvas_destroy; backend->interface.destroy = mg_gl_canvas_destroy;
backend->interface.render = mg_gl_canvas_render;
backend->interface.imageCreate = mg_gl_canvas_image_create; backend->interface.imageCreate = mg_gl_canvas_image_create;
backend->interface.imageDestroy = mg_gl_canvas_image_destroy; backend->interface.imageDestroy = mg_gl_canvas_image_destroy;
backend->interface.imageUploadRegion = mg_gl_canvas_image_upload_region; backend->interface.imageUploadRegion = mg_gl_canvas_image_upload_region;
backend->interface.render = mg_gl_canvas_render;
surface->interface.prepare((mg_surface_data*)surface); surface->interface.prepare((mg_surface_data*)surface);

View File

@ -34,6 +34,7 @@ struct mg_gl_path
vec4 box; vec4 box;
vec4 clip; vec4 clip;
int cmd; int cmd;
int textureID;
}; };
struct mg_gl_path_elt struct mg_gl_path_elt

View File

@ -43,8 +43,7 @@ layout(binding = 6) coherent restrict buffer screenTilesCountBufferSSBO
layout(location = 0) uniform int tileSize; layout(location = 0) uniform int tileSize;
layout(location = 1) uniform float scale; layout(location = 1) uniform float scale;
layout(location = 2) uniform int pathCount; layout(location = 2) uniform int pathCount;
layout(location = 3) uniform int cullSolidTiles; layout(location = 3) uniform int pathBufferStart;
layout(location = 4) uniform int pathBufferStart;
void main() void main()
{ {
@ -130,7 +129,7 @@ void main()
tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_FILL; tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_FILL;
if( pathBuffer.elements[pathBufferStart + pathIndex].color.a == 1 if( pathBuffer.elements[pathBufferStart + pathIndex].color.a == 1
&& cullSolidTiles != 0) && pathBuffer.elements[pathBufferStart + pathIndex].textureID < 0)
{ {
screenTilesBuffer.elements[tileIndex].first = pathOpIndex; screenTilesBuffer.elements[tileIndex].first = pathOpIndex;
} }

View File

@ -32,12 +32,19 @@ layout(binding = 4) restrict readonly buffer screenTilesCountBufferSSBO
layout(location = 0) uniform float scale; layout(location = 0) uniform float scale;
layout(location = 1) uniform int msaaSampleCount; layout(location = 1) uniform int msaaSampleCount;
layout(location = 2) uniform uint useTexture; layout(location = 2) uniform int pathBufferStart;
layout(location = 3) uniform int pathBufferStart; layout(location = 3) uniform uint maxWorkGroupCount;
layout(location = 4) uniform uint maxWorkGroupCount;
layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture; layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture;
layout(binding = 1) uniform sampler2D srcTexture;
layout(binding = 1) uniform sampler2D srcTexture0;
layout(binding = 2) uniform sampler2D srcTexture1;
layout(binding = 3) uniform sampler2D srcTexture2;
layout(binding = 4) uniform sampler2D srcTexture3;
layout(binding = 5) uniform sampler2D srcTexture4;
layout(binding = 6) uniform sampler2D srcTexture5;
layout(binding = 7) uniform sampler2D srcTexture6;
layout(binding = 8) uniform sampler2D srcTexture7;
void main() void main()
{ {
@ -146,15 +153,49 @@ void main()
vec4 nextColor = pathBuffer.elements[pathBufferStart + pathIndex].color; vec4 nextColor = pathBuffer.elements[pathBufferStart + pathIndex].color;
nextColor.rgb *= nextColor.a; nextColor.rgb *= nextColor.a;
if(useTexture != 0) int textureID = pathBuffer.elements[pathBufferStart+pathIndex].textureID;
if(textureID >= 0)
{ {
vec4 texColor = vec4(0); vec4 texColor = vec4(0);
for(int sampleIndex = 0; sampleIndex<srcSampleCount; sampleIndex++) for(int sampleIndex = 0; sampleIndex<srcSampleCount; sampleIndex++)
{ {
vec2 sampleCoord = imgSampleCoords[sampleIndex]; vec2 sampleCoord = imgSampleCoords[sampleIndex];
vec3 ph = vec3(sampleCoord.xy, 1); vec3 ph = vec3(sampleCoord.xy, 1);
vec2 uv = (pathBuffer.elements[pathBufferStart + pathIndex].uvTransform * ph).xy; vec2 uv = (pathBuffer.elements[pathBufferStart + pathIndex].uvTransform * ph).xy;
texColor += texture(srcTexture, uv);
if(textureID == 0)
{
texColor += texture(srcTexture0, uv);
}
else if(textureID == 1)
{
texColor += texture(srcTexture1, uv);
}
else if(textureID == 2)
{
texColor += texture(srcTexture2, uv);
}
else if(textureID == 3)
{
texColor += texture(srcTexture3, uv);
}
else if(textureID == 4)
{
texColor += texture(srcTexture4, uv);
}
else if(textureID == 5)
{
texColor += texture(srcTexture5, uv);
}
else if(textureID == 6)
{
texColor += texture(srcTexture6, uv);
}
else if(textureID == 7)
{
texColor += texture(srcTexture7, uv);
}
} }
texColor /= srcSampleCount; texColor /= srcSampleCount;
texColor.rgb *= texColor.a; texColor.rgb *= texColor.a;