simple gles tiled renderer
This commit is contained in:
parent
8faf588bee
commit
e59f2b152b
|
@ -1,7 +1,8 @@
|
||||||
|
|
||||||
if not exist bin mkdir bin
|
if not exist bin mkdir bin
|
||||||
|
|
||||||
call python scripts\embed_text.py src\gles_canvas_shaders\gles_canvas_fragment.glsl src\gles_canvas_shaders\gles_canvas_vertex.glsl --output src\gles_canvas_shaders.h
|
set gles_shaders=src\gles_canvas_shaders\gles_canvas_fragment.glsl src\gles_canvas_shaders\gles_canvas_vertex.glsl src\gles_canvas_shaders\gles_canvas_tile.glsl
|
||||||
|
call python scripts\embed_text.py %gles_shaders% --output src\gles_canvas_shaders.h
|
||||||
|
|
||||||
set INCLUDES=/I src /I src/util /I src/platform /I ext /I ext/angle_headers
|
set INCLUDES=/I src /I src/util /I src/platform /I ext /I ext/angle_headers
|
||||||
cl /we4013 /Zi /Zc:preprocessor /DMG_IMPLEMENTS_BACKEND_GLES /std:c11 %INCLUDES% /c /Fo:bin/milepost.obj src/milepost.c
|
cl /we4013 /Zi /Zc:preprocessor /DMG_IMPLEMENTS_BACKEND_GLES /std:c11 %INCLUDES% /c /Fo:bin/milepost.obj src/milepost.c
|
||||||
|
|
|
@ -56,8 +56,9 @@ int main()
|
||||||
LogLevel(LOG_LEVEL_DEBUG);
|
LogLevel(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
mp_init();
|
mp_init();
|
||||||
|
mp_clock_init(); //TODO put that in mp_init()?
|
||||||
|
|
||||||
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600};
|
mp_rect rect = {.x = 100, .y = 100, .w = 810, .h = 610};
|
||||||
mp_window window = mp_window_create(rect, "test", 0);
|
mp_window window = mp_window_create(rect, "test", 0);
|
||||||
|
|
||||||
//NOTE: create surface
|
//NOTE: create surface
|
||||||
|
@ -78,11 +79,15 @@ int main()
|
||||||
mp_window_focus(window);
|
mp_window_focus(window);
|
||||||
|
|
||||||
f32 x = 400, y = 300;
|
f32 x = 400, y = 300;
|
||||||
// f32 dx = 5, dy = 5;
|
f32 dx = 5, dy = 5;
|
||||||
f32 dx = 0, dy = 0;
|
// f32 dx = 0, dy = 0;
|
||||||
|
|
||||||
|
f64 frameTime = 0;
|
||||||
|
|
||||||
while(!mp_should_quit())
|
while(!mp_should_quit())
|
||||||
{
|
{
|
||||||
|
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
|
||||||
|
|
||||||
mp_pump_events(0);
|
mp_pump_events(0);
|
||||||
mp_event event = {0};
|
mp_event event = {0};
|
||||||
while(mp_next_event(&event))
|
while(mp_next_event(&event))
|
||||||
|
@ -163,11 +168,14 @@ int main()
|
||||||
mg_circle_fill(x, y, 200);
|
mg_circle_fill(x, y, 200);
|
||||||
|
|
||||||
// smile
|
// smile
|
||||||
|
|
||||||
|
f32 frown = frameTime > 0.033 ? 100 : 0;
|
||||||
|
|
||||||
mg_set_color_rgba(0, 0, 0, 1);
|
mg_set_color_rgba(0, 0, 0, 1);
|
||||||
|
|
||||||
mg_set_width(20);
|
mg_set_width(20);
|
||||||
mg_move_to(x-100, y-100);
|
mg_move_to(x-100, y-100);
|
||||||
mg_cubic_to(x-50, y-50, x+50, y-50, x+100, y-100);
|
mg_cubic_to(x-50, y-150+frown, x+50, y-150+frown, x+100, y-100);
|
||||||
mg_stroke();
|
mg_stroke();
|
||||||
|
|
||||||
// eyes
|
// eyes
|
||||||
|
@ -179,11 +187,23 @@ int main()
|
||||||
mg_set_font(font);
|
mg_set_font(font);
|
||||||
mg_set_font_size(12);
|
mg_set_font_size(12);
|
||||||
mg_move_to(50, 50);
|
mg_move_to(50, 50);
|
||||||
mg_text_outlines(str8_lit("Milepost vector graphics test program..."));
|
|
||||||
|
str8 text = str8_pushf(mem_scratch(),
|
||||||
|
"Milepost vector graphics test program (frame time = %fs, fps = %f)...",
|
||||||
|
frameTime,
|
||||||
|
1./frameTime);
|
||||||
|
mg_text_outlines(text);
|
||||||
mg_fill();
|
mg_fill();
|
||||||
|
|
||||||
|
/*
|
||||||
|
mg_set_color_rgba(1, 1, 0, 1);
|
||||||
|
mg_rectangle_fill(8, 8, 100, 50);
|
||||||
|
*/
|
||||||
mg_flush();
|
mg_flush();
|
||||||
mg_surface_present(surface);
|
mg_surface_present(surface);
|
||||||
|
|
||||||
|
mem_arena_clear(mem_scratch());
|
||||||
|
frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_terminate();
|
mp_terminate();
|
||||||
|
|
|
@ -20,7 +20,10 @@ typedef struct mg_gles_canvas_backend
|
||||||
GLint dummyVertexBuffer;
|
GLint dummyVertexBuffer;
|
||||||
GLint vertexBuffer;
|
GLint vertexBuffer;
|
||||||
GLint indexBuffer;
|
GLint indexBuffer;
|
||||||
GLint program;
|
GLint tileCounterBuffer;
|
||||||
|
GLint tileArrayBuffer;
|
||||||
|
GLint tileProgram;
|
||||||
|
GLint drawProgram;
|
||||||
|
|
||||||
char* indexMapping;
|
char* indexMapping;
|
||||||
char* vertexMapping;
|
char* vertexMapping;
|
||||||
|
@ -78,6 +81,9 @@ enum {
|
||||||
MG_GLES_CANVAS_DEFAULT_BUFFER_LENGTH = 1<<20,
|
MG_GLES_CANVAS_DEFAULT_BUFFER_LENGTH = 1<<20,
|
||||||
MG_GLES_CANVAS_VERTEX_BUFFER_SIZE = MG_GLES_CANVAS_DEFAULT_BUFFER_LENGTH * LAYOUT_VERTEX_SIZE,
|
MG_GLES_CANVAS_VERTEX_BUFFER_SIZE = MG_GLES_CANVAS_DEFAULT_BUFFER_LENGTH * LAYOUT_VERTEX_SIZE,
|
||||||
MG_GLES_CANVAS_INDEX_BUFFER_SIZE = MG_GLES_CANVAS_DEFAULT_BUFFER_LENGTH * LAYOUT_INT_SIZE,
|
MG_GLES_CANVAS_INDEX_BUFFER_SIZE = MG_GLES_CANVAS_DEFAULT_BUFFER_LENGTH * LAYOUT_INT_SIZE,
|
||||||
|
MG_GLES_CANVAS_TILE_COUNTER_BUFFER_SIZE = 65536,
|
||||||
|
MG_GLES_CANVAS_TILE_ARRAY_SIZE = 4096,
|
||||||
|
MG_GLES_CANVAS_TILE_ARRAY_BUFFER_SIZE = MG_GLES_CANVAS_TILE_COUNTER_BUFFER_SIZE * MG_GLES_CANVAS_TILE_ARRAY_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
void mg_gles_canvas_update_vertex_layout(mg_gles_canvas_backend* backend)
|
void mg_gles_canvas_update_vertex_layout(mg_gles_canvas_backend* backend)
|
||||||
|
@ -115,7 +121,6 @@ void mg_gles_canvas_begin(mg_canvas_backend* interface)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
glUseProgram(backend->program);
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
|
@ -156,11 +161,44 @@ void mg_gles_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u3
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->indexBuffer);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->indexBuffer);
|
||||||
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
|
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
|
||||||
|
|
||||||
|
mp_rect frame = mg_surface_get_frame(backend->surface);
|
||||||
|
|
||||||
|
const int tileSize = 16;
|
||||||
|
const int tileCountX = (frame.w + tileSize - 1)/tileSize;
|
||||||
|
const int tileCountY = (frame.h + tileSize - 1)/tileSize;
|
||||||
|
const int tileArraySize = 4096;
|
||||||
|
|
||||||
|
//TODO: ensure there's enough space in tile buffer
|
||||||
|
|
||||||
|
//NOTE: we first distribute triangles into tiles:
|
||||||
|
glUseProgram(backend->tileProgram);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->vertexBuffer);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->indexBuffer);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->tileCounterBuffer);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileArrayBuffer);
|
||||||
|
|
||||||
|
glUniform1ui(0, indexCount);
|
||||||
|
glUniform2ui(1, tileCountX, tileCountY);
|
||||||
|
glUniform1ui(2, tileSize);
|
||||||
|
glUniform1ui(3, tileArraySize);
|
||||||
|
|
||||||
|
glDispatchCompute(tileCountX, tileCountY, 1);
|
||||||
|
|
||||||
|
//TODO: then we fire the fragment shader that will select only triangles in its tile
|
||||||
|
// glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
|
|
||||||
|
glUseProgram(backend->drawProgram);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, backend->dummyVertexBuffer);
|
glBindBuffer(GL_ARRAY_BUFFER, backend->dummyVertexBuffer);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->vertexBuffer);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->vertexBuffer);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->indexBuffer);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->indexBuffer);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->tileCounterBuffer);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileArrayBuffer);
|
||||||
|
|
||||||
glUniform1i(0, indexCount);
|
glUniform1ui(0, indexCount);
|
||||||
|
glUniform2ui(1, tileCountX, tileCountY);
|
||||||
|
glUniform1ui(2, tileSize);
|
||||||
|
glUniform1ui(3, tileArraySize);
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
|
||||||
|
@ -235,31 +273,60 @@ mg_canvas_backend* mg_gles_canvas_create(mg_surface surface)
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->indexBuffer);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->indexBuffer);
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GLES_CANVAS_INDEX_BUFFER_SIZE, 0, GL_DYNAMIC_DRAW);
|
glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GLES_CANVAS_INDEX_BUFFER_SIZE, 0, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
glGenBuffers(1, &backend->tileCounterBuffer);
|
||||||
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->tileCounterBuffer);
|
||||||
|
glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GLES_CANVAS_TILE_COUNTER_BUFFER_SIZE, 0, GL_DYNAMIC_COPY);
|
||||||
|
|
||||||
|
glGenBuffers(1, &backend->tileArrayBuffer);
|
||||||
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->tileArrayBuffer);
|
||||||
|
glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GLES_CANVAS_TILE_ARRAY_BUFFER_SIZE, 0, GL_DYNAMIC_COPY);
|
||||||
|
|
||||||
glGenBuffers(1, &backend->dummyVertexBuffer);
|
glGenBuffers(1, &backend->dummyVertexBuffer);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, backend->dummyVertexBuffer);
|
glBindBuffer(GL_ARRAY_BUFFER, backend->dummyVertexBuffer);
|
||||||
|
|
||||||
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
//NOTE: create tile program
|
||||||
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
{
|
||||||
backend->program = glCreateProgram();
|
GLuint tileShader = glCreateShader(GL_COMPUTE_SHADER);
|
||||||
|
backend->tileProgram = glCreateProgram();
|
||||||
|
|
||||||
compile_shader(vertexShader, gles_canvas_vertex);
|
compile_shader(tileShader, gles_canvas_tile);
|
||||||
compile_shader(fragmentShader, gles_canvas_fragment);
|
|
||||||
|
|
||||||
glAttachShader(backend->program, vertexShader);
|
glAttachShader(backend->tileProgram, tileShader);
|
||||||
glAttachShader(backend->program, fragmentShader);
|
glLinkProgram(backend->tileProgram);
|
||||||
glLinkProgram(backend->program);
|
|
||||||
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
glGetProgramiv(backend->program, GL_LINK_STATUS, &status);
|
glGetProgramiv(backend->tileProgram, GL_LINK_STATUS, &status);
|
||||||
if(!status)
|
if(!status)
|
||||||
{
|
{
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
int size = 0;
|
int size = 0;
|
||||||
glGetProgramInfoLog(backend->program, 256, &size, buffer);
|
glGetProgramInfoLog(backend->tileProgram, 256, &size, buffer);
|
||||||
printf("link error: %.*s\n", size, buffer);
|
printf("link error: %.*s\n", size, buffer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
//NOTE: create draw program
|
||||||
|
{
|
||||||
|
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
backend->drawProgram = glCreateProgram();
|
||||||
|
|
||||||
glUseProgram(backend->program);
|
compile_shader(vertexShader, gles_canvas_vertex);
|
||||||
|
compile_shader(fragmentShader, gles_canvas_fragment);
|
||||||
|
|
||||||
|
glAttachShader(backend->drawProgram, vertexShader);
|
||||||
|
glAttachShader(backend->drawProgram, fragmentShader);
|
||||||
|
glLinkProgram(backend->drawProgram);
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
glGetProgramiv(backend->drawProgram, GL_LINK_STATUS, &status);
|
||||||
|
if(!status)
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
int size = 0;
|
||||||
|
glGetProgramInfoLog(backend->drawProgram, 256, &size, buffer);
|
||||||
|
printf("link error: %.*s\n", size, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mg_gles_canvas_update_vertex_layout(backend);
|
mg_gles_canvas_update_vertex_layout(backend);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
*
|
*
|
||||||
* file: gles_canvas_shaders.h
|
* file: gles_canvas_shaders.h
|
||||||
* note: string literals auto-generated by embed_text.py
|
* note: string literals auto-generated by embed_text.py
|
||||||
* date: 02/022023
|
* date: 03/022023
|
||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
#ifndef __GLES_CANVAS_SHADERS_H__
|
#ifndef __GLES_CANVAS_SHADERS_H__
|
||||||
|
@ -33,10 +33,22 @@ const char* gles_canvas_fragment =
|
||||||
" uint elements[];\n"
|
" uint elements[];\n"
|
||||||
"} indexBuffer ;\n"
|
"} indexBuffer ;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"layout(location = 0) uniform int indexCount;\n"
|
"layout(binding = 2) coherent buffer tileCounterBufferSSBO {\n"
|
||||||
|
" uint elements[];\n"
|
||||||
|
"} tileCounterBuffer ;\n"
|
||||||
|
"\n"
|
||||||
|
"layout(binding = 3) coherent buffer tileArrayBufferSSBO {\n"
|
||||||
|
" uint elements[];\n"
|
||||||
|
"} tileArrayBuffer ;\n"
|
||||||
|
"\n"
|
||||||
|
"layout(location = 0) uniform uint indexCount;\n"
|
||||||
|
"layout(location = 1) uniform uvec2 tileCount;\n"
|
||||||
|
"layout(location = 2) uniform uint tileSize;\n"
|
||||||
|
"layout(location = 3) uniform uint tileArraySize;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"layout(location = 0) out vec4 fragColor;\n"
|
"layout(location = 0) out vec4 fragColor;\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"\n"
|
||||||
"bool is_top_left(ivec2 a, ivec2 b)\n"
|
"bool is_top_left(ivec2 a, ivec2 b)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" return( (a.y == b.y && b.x < a.x)\n"
|
" return( (a.y == b.y && b.x < a.x)\n"
|
||||||
|
@ -50,6 +62,10 @@ const char* gles_canvas_fragment =
|
||||||
"\n"
|
"\n"
|
||||||
"void main()\n"
|
"void main()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
" uvec2 tileCoord = uvec2(gl_FragCoord.xy)/tileSize;\n"
|
||||||
|
" uint tileIndex = tileCoord.y * tileCount.x + tileCoord.x;\n"
|
||||||
|
" uint tileCounter = tileCounterBuffer.elements[tileIndex];\n"
|
||||||
|
"\n"
|
||||||
" const float subPixelFactor = 16.;\n"
|
" const float subPixelFactor = 16.;\n"
|
||||||
" const int sampleCount = 8;\n"
|
" const int sampleCount = 8;\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -63,6 +79,30 @@ const char* gles_canvas_fragment =
|
||||||
" centerPoint + ivec2(3, -7),\n"
|
" centerPoint + ivec2(3, -7),\n"
|
||||||
" centerPoint + ivec2(7, 7));\n"
|
" centerPoint + ivec2(7, 7));\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"\n"
|
||||||
|
" //DEBUG\n"
|
||||||
|
"/*\n"
|
||||||
|
" if( int(gl_FragCoord.x - 0.5) % 16 == 0\n"
|
||||||
|
" ||int(gl_FragCoord.y - 0.5) % 16 == 0)\n"
|
||||||
|
" {\n"
|
||||||
|
" fragColor = vec4(0, 0, 0, 1);\n"
|
||||||
|
" }\n"
|
||||||
|
" else if(tileCounterBuffer.elements[tileIndex] == 2u)\n"
|
||||||
|
" {\n"
|
||||||
|
" fragColor = vec4(1, 1, 0, 1);\n"
|
||||||
|
" }\n"
|
||||||
|
" else if(tileCounter != 0u)\n"
|
||||||
|
" {\n"
|
||||||
|
" fragColor = vec4(0, 1, 0, 1);\n"
|
||||||
|
" }\n"
|
||||||
|
" else\n"
|
||||||
|
" {\n"
|
||||||
|
" fragColor = vec4(1, 0, 0, 1);\n"
|
||||||
|
" }\n"
|
||||||
|
" return;\n"
|
||||||
|
"//*/\n"
|
||||||
|
" //----\n"
|
||||||
|
"\n"
|
||||||
" vec4 sampleColor[sampleCount];\n"
|
" vec4 sampleColor[sampleCount];\n"
|
||||||
" vec4 currentColor[sampleCount];\n"
|
" vec4 currentColor[sampleCount];\n"
|
||||||
" int currentZIndex[sampleCount];\n"
|
" int currentZIndex[sampleCount];\n"
|
||||||
|
@ -76,11 +116,13 @@ const char* gles_canvas_fragment =
|
||||||
" currentColor[i] = vec4(0, 0, 0, 0);\n"
|
" currentColor[i] = vec4(0, 0, 0, 0);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" for(int triangleIndex=0; triangleIndex<indexCount; triangleIndex+=3)\n"
|
" for(uint tileArrayIndex=0u; tileArrayIndex < tileCounter; tileArrayIndex++)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
|
" uint triangleIndex = tileArrayBuffer.elements[tileArraySize * tileIndex + tileArrayIndex];\n"
|
||||||
|
"\n"
|
||||||
" uint i0 = indexBuffer.elements[triangleIndex];\n"
|
" uint i0 = indexBuffer.elements[triangleIndex];\n"
|
||||||
" uint i1 = indexBuffer.elements[triangleIndex+1];\n"
|
" uint i1 = indexBuffer.elements[triangleIndex+1u];\n"
|
||||||
" uint i2 = indexBuffer.elements[triangleIndex+2];\n"
|
" uint i2 = indexBuffer.elements[triangleIndex+2u];\n"
|
||||||
"\n"
|
"\n"
|
||||||
" ivec2 p0 = ivec2(vertexBuffer.elements[i0].pos * subPixelFactor + vec2(0.5, 0.5));\n"
|
" ivec2 p0 = ivec2(vertexBuffer.elements[i0].pos * subPixelFactor + vec2(0.5, 0.5));\n"
|
||||||
" ivec2 p1 = ivec2(vertexBuffer.elements[i1].pos * subPixelFactor + vec2(0.5, 0.5));\n"
|
" ivec2 p1 = ivec2(vertexBuffer.elements[i1].pos * subPixelFactor + vec2(0.5, 0.5));\n"
|
||||||
|
@ -169,4 +211,83 @@ const char* gles_canvas_vertex =
|
||||||
" gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f);\n"
|
" gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
|
//NOTE: string imported from src\gles_canvas_shaders\gles_canvas_tile.glsl
|
||||||
|
const char* gles_canvas_tile =
|
||||||
|
"#version 310 es\n"
|
||||||
|
"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
|
||||||
|
"\n"
|
||||||
|
"precision mediump float;\n"
|
||||||
|
"layout(std430) buffer;\n"
|
||||||
|
"\n"
|
||||||
|
"struct vertex {\n"
|
||||||
|
" vec2 pos;\n"
|
||||||
|
" vec4 cubic;\n"
|
||||||
|
" vec2 uv;\n"
|
||||||
|
" vec4 color;\n"
|
||||||
|
" vec4 clip;\n"
|
||||||
|
" int zIndex;\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"layout(binding = 0) buffer vertexBufferSSBO {\n"
|
||||||
|
" vertex elements[];\n"
|
||||||
|
"} vertexBuffer ;\n"
|
||||||
|
"\n"
|
||||||
|
"layout(binding = 1) buffer indexBufferSSBO {\n"
|
||||||
|
" uint elements[];\n"
|
||||||
|
"} indexBuffer ;\n"
|
||||||
|
"\n"
|
||||||
|
"layout(binding = 2) coherent buffer tileCounterBufferSSBO {\n"
|
||||||
|
" uint elements[];\n"
|
||||||
|
"} tileCounterBuffer ;\n"
|
||||||
|
"\n"
|
||||||
|
"layout(binding = 3) coherent buffer tileArrayBufferSSBO {\n"
|
||||||
|
" uint elements[];\n"
|
||||||
|
"} tileArrayBuffer ;\n"
|
||||||
|
"\n"
|
||||||
|
"layout(location = 0) uniform uint indexCount;\n"
|
||||||
|
"layout(location = 1) uniform uvec2 tileCount;\n"
|
||||||
|
"layout(location = 2) uniform uint tileSize;\n"
|
||||||
|
"layout(location = 3) uniform uint tileArraySize;\n"
|
||||||
|
"\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" uint tileIndex = gl_WorkGroupID.y * tileCount.x + gl_WorkGroupID.x;\n"
|
||||||
|
" uint tileArrayOffset = tileArraySize * tileIndex;\n"
|
||||||
|
"\n"
|
||||||
|
" vec4 tileBox = vec4(gl_WorkGroupID.x * tileSize,\n"
|
||||||
|
" gl_WorkGroupID.y * tileSize,\n"
|
||||||
|
" gl_WorkGroupID.x * tileSize + tileSize,\n"
|
||||||
|
" gl_WorkGroupID.y * tileSize + tileSize);\n"
|
||||||
|
"\n"
|
||||||
|
" uint tileCounter = 0u;\n"
|
||||||
|
"\n"
|
||||||
|
" for(uint triangleIndex = 0u; triangleIndex < indexCount; triangleIndex += 3u)\n"
|
||||||
|
" {\n"
|
||||||
|
" uint i0 = indexBuffer.elements[triangleIndex];\n"
|
||||||
|
" uint i1 = indexBuffer.elements[triangleIndex+1u];\n"
|
||||||
|
" uint i2 = indexBuffer.elements[triangleIndex+2u];\n"
|
||||||
|
"\n"
|
||||||
|
" vec2 p0 = vertexBuffer.elements[i0].pos;\n"
|
||||||
|
" vec2 p1 = vertexBuffer.elements[i1].pos;\n"
|
||||||
|
" vec2 p2 = vertexBuffer.elements[i2].pos;\n"
|
||||||
|
"\n"
|
||||||
|
" vec4 bbox = vec4(min(min(p0.x, p1.x), p2.x),\n"
|
||||||
|
" min(min(p0.y, p1.y), p2.y),\n"
|
||||||
|
" max(max(p0.x, p1.x), p2.x),\n"
|
||||||
|
" max(max(p0.y, p1.y), p2.y));\n"
|
||||||
|
"\n"
|
||||||
|
" if(!( bbox.x > tileBox.z\n"
|
||||||
|
" || bbox.z < tileBox.x\n"
|
||||||
|
" || bbox.y > tileBox.w\n"
|
||||||
|
" || bbox.w < tileBox.y))\n"
|
||||||
|
" {\n"
|
||||||
|
" tileArrayBuffer.elements[tileArrayOffset + tileCounter] = triangleIndex;\n"
|
||||||
|
" tileCounter++;\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
" tileCounterBuffer.elements[tileIndex] = tileCounter;\n"
|
||||||
|
"\n"
|
||||||
|
"// tileCounterBuffer.elements[tileIndex] = 1u;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
#endif // __GLES_CANVAS_SHADERS_H__
|
#endif // __GLES_CANVAS_SHADERS_H__
|
||||||
|
|
|
@ -20,10 +20,22 @@ layout(binding = 1) buffer indexBufferSSBO {
|
||||||
uint elements[];
|
uint elements[];
|
||||||
} indexBuffer ;
|
} indexBuffer ;
|
||||||
|
|
||||||
layout(location = 0) uniform int indexCount;
|
layout(binding = 2) coherent buffer tileCounterBufferSSBO {
|
||||||
|
uint elements[];
|
||||||
|
} tileCounterBuffer ;
|
||||||
|
|
||||||
|
layout(binding = 3) coherent buffer tileArrayBufferSSBO {
|
||||||
|
uint elements[];
|
||||||
|
} tileArrayBuffer ;
|
||||||
|
|
||||||
|
layout(location = 0) uniform uint indexCount;
|
||||||
|
layout(location = 1) uniform uvec2 tileCount;
|
||||||
|
layout(location = 2) uniform uint tileSize;
|
||||||
|
layout(location = 3) uniform uint tileArraySize;
|
||||||
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
|
|
||||||
bool is_top_left(ivec2 a, ivec2 b)
|
bool is_top_left(ivec2 a, ivec2 b)
|
||||||
{
|
{
|
||||||
return( (a.y == b.y && b.x < a.x)
|
return( (a.y == b.y && b.x < a.x)
|
||||||
|
@ -37,6 +49,10 @@ int orient2d(ivec2 a, ivec2 b, ivec2 p)
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
uvec2 tileCoord = uvec2(gl_FragCoord.xy)/tileSize;
|
||||||
|
uint tileIndex = tileCoord.y * tileCount.x + tileCoord.x;
|
||||||
|
uint tileCounter = tileCounterBuffer.elements[tileIndex];
|
||||||
|
|
||||||
const float subPixelFactor = 16.;
|
const float subPixelFactor = 16.;
|
||||||
const int sampleCount = 8;
|
const int sampleCount = 8;
|
||||||
|
|
||||||
|
@ -50,6 +66,30 @@ void main()
|
||||||
centerPoint + ivec2(3, -7),
|
centerPoint + ivec2(3, -7),
|
||||||
centerPoint + ivec2(7, 7));
|
centerPoint + ivec2(7, 7));
|
||||||
|
|
||||||
|
|
||||||
|
//DEBUG
|
||||||
|
/*
|
||||||
|
if( int(gl_FragCoord.x - 0.5) % 16 == 0
|
||||||
|
||int(gl_FragCoord.y - 0.5) % 16 == 0)
|
||||||
|
{
|
||||||
|
fragColor = vec4(0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
else if(tileCounterBuffer.elements[tileIndex] == 2u)
|
||||||
|
{
|
||||||
|
fragColor = vec4(1, 1, 0, 1);
|
||||||
|
}
|
||||||
|
else if(tileCounter != 0u)
|
||||||
|
{
|
||||||
|
fragColor = vec4(0, 1, 0, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fragColor = vec4(1, 0, 0, 1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
//*/
|
||||||
|
//----
|
||||||
|
|
||||||
vec4 sampleColor[sampleCount];
|
vec4 sampleColor[sampleCount];
|
||||||
vec4 currentColor[sampleCount];
|
vec4 currentColor[sampleCount];
|
||||||
int currentZIndex[sampleCount];
|
int currentZIndex[sampleCount];
|
||||||
|
@ -63,11 +103,13 @@ void main()
|
||||||
currentColor[i] = vec4(0, 0, 0, 0);
|
currentColor[i] = vec4(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int triangleIndex=0; triangleIndex<indexCount; triangleIndex+=3)
|
for(uint tileArrayIndex=0u; tileArrayIndex < tileCounter; tileArrayIndex++)
|
||||||
{
|
{
|
||||||
|
uint triangleIndex = tileArrayBuffer.elements[tileArraySize * tileIndex + tileArrayIndex];
|
||||||
|
|
||||||
uint i0 = indexBuffer.elements[triangleIndex];
|
uint i0 = indexBuffer.elements[triangleIndex];
|
||||||
uint i1 = indexBuffer.elements[triangleIndex+1];
|
uint i1 = indexBuffer.elements[triangleIndex+1u];
|
||||||
uint i2 = indexBuffer.elements[triangleIndex+2];
|
uint i2 = indexBuffer.elements[triangleIndex+2u];
|
||||||
|
|
||||||
ivec2 p0 = ivec2(vertexBuffer.elements[i0].pos * subPixelFactor + vec2(0.5, 0.5));
|
ivec2 p0 = ivec2(vertexBuffer.elements[i0].pos * subPixelFactor + vec2(0.5, 0.5));
|
||||||
ivec2 p1 = ivec2(vertexBuffer.elements[i1].pos * subPixelFactor + vec2(0.5, 0.5));
|
ivec2 p1 = ivec2(vertexBuffer.elements[i1].pos * subPixelFactor + vec2(0.5, 0.5));
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
precision mediump float;
|
||||||
|
layout(std430) buffer;
|
||||||
|
|
||||||
|
struct vertex {
|
||||||
|
vec2 pos;
|
||||||
|
vec4 cubic;
|
||||||
|
vec2 uv;
|
||||||
|
vec4 color;
|
||||||
|
vec4 clip;
|
||||||
|
int zIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 0) buffer vertexBufferSSBO {
|
||||||
|
vertex elements[];
|
||||||
|
} vertexBuffer ;
|
||||||
|
|
||||||
|
layout(binding = 1) buffer indexBufferSSBO {
|
||||||
|
uint elements[];
|
||||||
|
} indexBuffer ;
|
||||||
|
|
||||||
|
layout(binding = 2) coherent buffer tileCounterBufferSSBO {
|
||||||
|
uint elements[];
|
||||||
|
} tileCounterBuffer ;
|
||||||
|
|
||||||
|
layout(binding = 3) coherent buffer tileArrayBufferSSBO {
|
||||||
|
uint elements[];
|
||||||
|
} tileArrayBuffer ;
|
||||||
|
|
||||||
|
layout(location = 0) uniform uint indexCount;
|
||||||
|
layout(location = 1) uniform uvec2 tileCount;
|
||||||
|
layout(location = 2) uniform uint tileSize;
|
||||||
|
layout(location = 3) uniform uint tileArraySize;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint tileIndex = gl_WorkGroupID.y * tileCount.x + gl_WorkGroupID.x;
|
||||||
|
uint tileArrayOffset = tileArraySize * tileIndex;
|
||||||
|
|
||||||
|
vec4 tileBox = vec4(gl_WorkGroupID.x * tileSize,
|
||||||
|
gl_WorkGroupID.y * tileSize,
|
||||||
|
gl_WorkGroupID.x * tileSize + tileSize,
|
||||||
|
gl_WorkGroupID.y * tileSize + tileSize);
|
||||||
|
|
||||||
|
uint tileCounter = 0u;
|
||||||
|
|
||||||
|
for(uint triangleIndex = 0u; triangleIndex < indexCount; triangleIndex += 3u)
|
||||||
|
{
|
||||||
|
uint i0 = indexBuffer.elements[triangleIndex];
|
||||||
|
uint i1 = indexBuffer.elements[triangleIndex+1u];
|
||||||
|
uint i2 = indexBuffer.elements[triangleIndex+2u];
|
||||||
|
|
||||||
|
vec2 p0 = vertexBuffer.elements[i0].pos;
|
||||||
|
vec2 p1 = vertexBuffer.elements[i1].pos;
|
||||||
|
vec2 p2 = vertexBuffer.elements[i2].pos;
|
||||||
|
|
||||||
|
vec4 bbox = vec4(min(min(p0.x, p1.x), p2.x),
|
||||||
|
min(min(p0.y, p1.y), p2.y),
|
||||||
|
max(max(p0.x, p1.x), p2.x),
|
||||||
|
max(max(p0.y, p1.y), p2.y));
|
||||||
|
|
||||||
|
if(!( bbox.x > tileBox.z
|
||||||
|
|| bbox.z < tileBox.x
|
||||||
|
|| bbox.y > tileBox.w
|
||||||
|
|| bbox.w < tileBox.y))
|
||||||
|
{
|
||||||
|
tileArrayBuffer.elements[tileArrayOffset + tileCounter] = triangleIndex;
|
||||||
|
tileCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tileCounterBuffer.elements[tileIndex] = tileCounter;
|
||||||
|
|
||||||
|
// tileCounterBuffer.elements[tileIndex] = 1u;
|
||||||
|
}
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#if defined(OS_WIN64)
|
#if defined(OS_WIN64)
|
||||||
#include"platform/win32_base_allocator.c"
|
#include"platform/win32_base_allocator.c"
|
||||||
|
#include"platform/win32_clock.c"
|
||||||
//TODO
|
//TODO
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(OS_MACOS)
|
||||||
#include"platform/unix_base_allocator.c"
|
#include"platform/unix_base_allocator.c"
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/************************************************************//**
|
||||||
|
*
|
||||||
|
* @file: win32_clock.c
|
||||||
|
* @author: Martin Fouilleul
|
||||||
|
* @date: 03/02/2023
|
||||||
|
* @revision:
|
||||||
|
*
|
||||||
|
*****************************************************************/
|
||||||
|
#include<profileapi.h>
|
||||||
|
|
||||||
|
#include"typedefs.h"
|
||||||
|
#include"platform_clock.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static u64 __performanceCounterFreq = 0;
|
||||||
|
|
||||||
|
void mp_clock_init()
|
||||||
|
{
|
||||||
|
LARGE_INTEGER freq;
|
||||||
|
QueryPerformanceFrequency(&freq);
|
||||||
|
__performanceCounterFreq = freq.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
f64 mp_get_time(mp_clock_kind clock)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER counter;
|
||||||
|
QueryPerformanceCounter(&counter);
|
||||||
|
|
||||||
|
f64 time = __performanceCounterFreq ? (counter.QuadPart / (f64)__performanceCounterFreq) : 0;
|
||||||
|
return(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
|
@ -518,7 +518,7 @@ mp_window mp_window_create(mp_rect rect, const char* title, mp_window_style styl
|
||||||
|
|
||||||
HWND windowHandle = CreateWindow("ApplicationWindowClass", "Test Window",
|
HWND windowHandle = CreateWindow("ApplicationWindowClass", "Test Window",
|
||||||
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
800, 600,
|
rect.w, rect.h,
|
||||||
0, 0, windowClass.hInstance, 0);
|
0, 0, windowClass.hInstance, 0);
|
||||||
|
|
||||||
if(!windowHandle)
|
if(!windowHandle)
|
||||||
|
|
|
@ -41,21 +41,27 @@ void mg_gles_surface_prepare(mg_surface_data* interface)
|
||||||
|
|
||||||
void mg_gles_surface_present(mg_surface_data* interface)
|
void mg_gles_surface_present(mg_surface_data* interface)
|
||||||
{
|
{
|
||||||
|
|
||||||
//TODO: eglSwapBuffers seem to never block in macOS (ie eglSwapInterval doesn't seem to have any effect)
|
|
||||||
// We need to use a CVDisplayLink to time this if we want surface present to block
|
|
||||||
|
|
||||||
mg_gles_surface* surface = (mg_gles_surface*)interface;
|
mg_gles_surface* surface = (mg_gles_surface*)interface;
|
||||||
eglSwapBuffers(surface->eglDisplay, surface->eglSurface);
|
eglSwapBuffers(surface->eglDisplay, surface->eglSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void mg_gles_surface_set_frame(mg_surface_data* interface, mp_rect frame);
|
void mg_gles_surface_set_frame(mg_surface_data* interface, mp_rect frame);
|
||||||
mp_rect mg_gles_surface_get_frame(mg_surface_data* interface);
|
|
||||||
void mg_gles_surface_set_hidden(mg_surface_data* interface, bool hidden);
|
void mg_gles_surface_set_hidden(mg_surface_data* interface, bool hidden);
|
||||||
bool mg_gles_surface_get_hidden(mg_surface_data* interface);
|
bool mg_gles_surface_get_hidden(mg_surface_data* interface);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mp_rect mg_gles_surface_get_frame(mg_surface_data* interface)
|
||||||
|
{
|
||||||
|
mg_gles_surface* surface = (mg_gles_surface*)interface;
|
||||||
|
RECT rect = {0};
|
||||||
|
GetClientRect(surface->hWnd, &rect);
|
||||||
|
|
||||||
|
mp_rect res = {rect.left, rect.bottom, rect.right - rect.left, rect.bottom - rect.top};
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
mg_surface mg_gles_surface_create_for_window(mp_window window)
|
mg_surface mg_gles_surface_create_for_window(mp_window window)
|
||||||
{
|
{
|
||||||
mg_surface res = mg_surface_nil();
|
mg_surface res = mg_surface_nil();
|
||||||
|
@ -69,8 +75,8 @@ mg_surface mg_gles_surface_create_for_window(mp_window window)
|
||||||
surface->interface.destroy = mg_gles_surface_destroy;
|
surface->interface.destroy = mg_gles_surface_destroy;
|
||||||
surface->interface.prepare = mg_gles_surface_prepare;
|
surface->interface.prepare = mg_gles_surface_prepare;
|
||||||
surface->interface.present = mg_gles_surface_present;
|
surface->interface.present = mg_gles_surface_present;
|
||||||
/*TODO
|
|
||||||
surface->interface.getFrame = mg_gles_surface_get_frame;
|
surface->interface.getFrame = mg_gles_surface_get_frame;
|
||||||
|
/*TODO
|
||||||
surface->interface.setFrame = mg_gles_surface_set_frame;
|
surface->interface.setFrame = mg_gles_surface_set_frame;
|
||||||
surface->interface.getHidden = mg_gles_surface_get_hidden;
|
surface->interface.getHidden = mg_gles_surface_get_hidden;
|
||||||
surface->interface.setHidden = mg_gles_surface_set_hidden;
|
surface->interface.setHidden = mg_gles_surface_set_hidden;
|
||||||
|
@ -117,7 +123,8 @@ mg_surface mg_gles_surface_create_for_window(mp_window window)
|
||||||
surface->eglContext = eglCreateContext(surface->eglDisplay, surface->eglConfig, EGL_NO_CONTEXT, contextAttributes);
|
surface->eglContext = eglCreateContext(surface->eglDisplay, surface->eglConfig, EGL_NO_CONTEXT, contextAttributes);
|
||||||
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
|
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
|
||||||
|
|
||||||
eglSwapInterval(surface->eglDisplay, 1);
|
//TODO: reactivate this when finished testing!
|
||||||
|
// eglSwapInterval(surface->eglDisplay, 1);
|
||||||
|
|
||||||
res = mg_surface_alloc_handle((mg_surface_data*)surface);
|
res = mg_surface_alloc_handle((mg_surface_data*)surface);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue