[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 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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue