[gl canvas] allow multiple textures per batch
This commit is contained in:
parent
c983c39f44
commit
b05caf984c
105
src/gl_canvas.c
105
src/gl_canvas.c
|
@ -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);
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ struct mg_gl_path
|
|||
vec4 box;
|
||||
vec4 clip;
|
||||
int cmd;
|
||||
int textureID;
|
||||
};
|
||||
|
||||
struct mg_gl_path_elt
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue