[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 clip;
mg_gl_cmd cmd;
u8 pad[12];
int textureID;
u8 pad[8];
} mg_gl_path;
enum _mg_gl_seg_kind{
@ -125,6 +126,7 @@ enum {
MG_GL_INPUT_BUFFERS_COUNT = 3,
MG_GL_TILE_SIZE = 16,
MG_GL_MSAA_COUNT = 8,
MG_GL_MAX_IMAGES_PER_BATCH = 8,
};
typedef struct mg_gl_mapped_buffer
@ -186,6 +188,7 @@ typedef struct mg_gl_canvas_backend
int maxTileQueueCount;
int maxSegmentCount;
int currentImageIndex;
} mg_gl_canvas_backend;
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[10] = 1;
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;
@ -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,
mg_wgl_surface* surface,
mg_image_data* image,
mg_image* images,
int tileSize,
int nTilesX,
int nTilesY,
@ -1220,18 +1229,7 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
glUniform1i(0, tileSize);
glUniform1f(1, scale);
glUniform1i(2, pathCount);
// if there's an image, don't cull solid tiles
if(image)
{
glUniform1i(3, 0);
}
else
{
glUniform1i(3, 1);
}
glUniform1i(4, backend->pathBatchStart);
glUniform1i(3, backend->pathBatchStart);
glDispatchCompute(nTilesX, nTilesY, 1);
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);
if(image)
for(int i=0; i<MG_GL_MAX_IMAGES_PER_BATCH; i++)
{
mg_gl_image* glImage = (mg_gl_image*)image;
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, glImage->texture);
glUniform1ui(2, 1);
}
else
{
glUniform1ui(2, 0);
if(images[i].h)
{
mg_gl_image* image = (mg_gl_image*)mg_image_data_from_handle(images[i]);
if(image)
{
glActiveTexture(GL_TEXTURE1+i);
glBindTexture(GL_TEXTURE_2D, image->texture);
}
}
}
glUniform1i(3, backend->pathBatchStart);
glUniform1ui(4, maxWorkGroupCount);
glUniform1i(2, backend->pathBatchStart);
glUniform1ui(3, maxWorkGroupCount);
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, backend->rasterDispatchBuffer);
glDispatchComputeIndirect(0);
@ -1397,28 +1396,53 @@ void mg_gl_canvas_render(mg_canvas_backend* interface,
//NOTE: encode and render batches
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;
for(int primitiveIndex = 0; primitiveIndex < primitiveCount; 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,
surface,
imageData,
tileSize,
nTilesX,
nTilesY,
viewportSize,
scale);
images[0] = primitive->attributes.image;
backend->currentImageIndex = 0;
imageCount = 1;
}
}
}
else
{
backend->currentImageIndex = -1;
}
currentImage = primitive->attributes.image;
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,
surface,
imageData,
images,
tileSize,
nTilesX,
nTilesY,
@ -1661,10 +1684,10 @@ mg_canvas_backend* gl_canvas_backend_create(mg_wgl_surface* surface)
//NOTE(martin): setup interface functions
backend->interface.destroy = mg_gl_canvas_destroy;
backend->interface.render = mg_gl_canvas_render;
backend->interface.imageCreate = mg_gl_canvas_image_create;
backend->interface.imageDestroy = mg_gl_canvas_image_destroy;
backend->interface.imageUploadRegion = mg_gl_canvas_image_upload_region;
backend->interface.render = mg_gl_canvas_render;
surface->interface.prepare((mg_surface_data*)surface);

View File

@ -34,6 +34,7 @@ struct mg_gl_path
vec4 box;
vec4 clip;
int cmd;
int textureID;
};
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 = 1) uniform float scale;
layout(location = 2) uniform int pathCount;
layout(location = 3) uniform int cullSolidTiles;
layout(location = 4) uniform int pathBufferStart;
layout(location = 3) uniform int pathBufferStart;
void main()
{
@ -130,7 +129,7 @@ void main()
tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_FILL;
if( pathBuffer.elements[pathBufferStart + pathIndex].color.a == 1
&& cullSolidTiles != 0)
&& pathBuffer.elements[pathBufferStart + pathIndex].textureID < 0)
{
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 = 1) uniform int msaaSampleCount;
layout(location = 2) uniform uint useTexture;
layout(location = 3) uniform int pathBufferStart;
layout(location = 4) uniform uint maxWorkGroupCount;
layout(location = 2) uniform int pathBufferStart;
layout(location = 3) uniform uint maxWorkGroupCount;
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()
{
@ -146,15 +153,49 @@ void main()
vec4 nextColor = pathBuffer.elements[pathBufferStart + pathIndex].color;
nextColor.rgb *= nextColor.a;
if(useTexture != 0)
int textureID = pathBuffer.elements[pathBufferStart+pathIndex].textureID;
if(textureID >= 0)
{
vec4 texColor = vec4(0);
for(int sampleIndex = 0; sampleIndex<srcSampleCount; sampleIndex++)
{
vec2 sampleCoord = imgSampleCoords[sampleIndex];
vec3 ph = vec3(sampleCoord.xy, 1);
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.rgb *= texColor.a;