canvas renderer: parallel tiling pass and sorting pass
This commit is contained in:
		
							parent
							
								
									e59f2b152b
								
							
						
					
					
						commit
						fd836c00dd
					
				| 
						 | 
				
			
			@ -1,10 +1,12 @@
 | 
			
		|||
.DS_Store
 | 
			
		||||
*.dSYM
 | 
			
		||||
bin/*
 | 
			
		||||
*.metallib
 | 
			
		||||
 | 
			
		||||
*.pdb
 | 
			
		||||
*.exe
 | 
			
		||||
*.ilk
 | 
			
		||||
*.vs
 | 
			
		||||
*.obj
 | 
			
		||||
.DS_Store
 | 
			
		||||
*.dSYM
 | 
			
		||||
bin/*
 | 
			
		||||
*.metallib
 | 
			
		||||
 | 
			
		||||
*.pdb
 | 
			
		||||
*.exe
 | 
			
		||||
*.ilk
 | 
			
		||||
*.vs
 | 
			
		||||
*.obj
 | 
			
		||||
 | 
			
		||||
src/gles_canvas_shaders.h
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
 | 
			
		||||
if not exist bin mkdir bin
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
set gles_shaders=src\gles_canvas_shaders\gles_canvas_blit_vertex.glsl src\gles_canvas_shaders\gles_canvas_blit_fragment.glsl src\gles_canvas_shaders\gles_canvas_clear_counters.glsl src\gles_canvas_shaders\gles_canvas_tile.glsl src\gles_canvas_shaders\gles_canvas_sort.glsl src\gles_canvas_shaders\gles_canvas_draw.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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -183,6 +183,7 @@ int main()
 | 
			
		|||
			mg_ellipse_fill(x+70, y+50, 30, 50);
 | 
			
		||||
 | 
			
		||||
			// text
 | 
			
		||||
//*
 | 
			
		||||
			mg_set_color_rgba(0, 0, 1, 1);
 | 
			
		||||
			mg_set_font(font);
 | 
			
		||||
			mg_set_font_size(12);
 | 
			
		||||
| 
						 | 
				
			
			@ -193,12 +194,21 @@ int main()
 | 
			
		|||
			                      frameTime,
 | 
			
		||||
			                      1./frameTime);
 | 
			
		||||
			mg_text_outlines(text);
 | 
			
		||||
//*/
 | 
			
		||||
			mg_fill();
 | 
			
		||||
 | 
			
		||||
//*
 | 
			
		||||
			printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n",
 | 
			
		||||
			                      frameTime,
 | 
			
		||||
			                      1./frameTime);
 | 
			
		||||
//*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
			mg_set_color_rgba(1, 1, 0, 1);
 | 
			
		||||
			mg_rectangle_fill(8, 8, 100, 50);
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			mg_flush();
 | 
			
		||||
		mg_surface_present(surface);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,8 +22,13 @@ typedef struct mg_gles_canvas_backend
 | 
			
		|||
	GLint indexBuffer;
 | 
			
		||||
	GLint tileCounterBuffer;
 | 
			
		||||
	GLint tileArrayBuffer;
 | 
			
		||||
	GLint clearCounterProgram;
 | 
			
		||||
	GLint tileProgram;
 | 
			
		||||
	GLint sortProgram;
 | 
			
		||||
	GLint drawProgram;
 | 
			
		||||
	GLint blitProgram;
 | 
			
		||||
 | 
			
		||||
	GLint outTexture;
 | 
			
		||||
 | 
			
		||||
	char* indexMapping;
 | 
			
		||||
	char* vertexMapping;
 | 
			
		||||
| 
						 | 
				
			
			@ -170,8 +175,16 @@ void mg_gles_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u3
 | 
			
		|||
 | 
			
		||||
	//TODO: ensure there's enough space in tile buffer
 | 
			
		||||
 | 
			
		||||
	//NOTE: first clear counters
 | 
			
		||||
/*
 | 
			
		||||
	glUseProgram(backend->clearCounterProgram);
 | 
			
		||||
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->tileCounterBuffer);
 | 
			
		||||
	glDispatchCompute(tileCountX*tileCountY, 1, 1);
 | 
			
		||||
*/
 | 
			
		||||
	//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);
 | 
			
		||||
| 
						 | 
				
			
			@ -182,26 +195,55 @@ void mg_gles_canvas_draw_batch(mg_canvas_backend* interface, u32 vertexCount, u3
 | 
			
		|||
	glUniform1ui(2, tileSize);
 | 
			
		||||
	glUniform1ui(3, tileArraySize);
 | 
			
		||||
 | 
			
		||||
	glDispatchCompute(tileCountX, tileCountY, 1);
 | 
			
		||||
	glDispatchCompute(indexCount/3, 1, 1);
 | 
			
		||||
*/
 | 
			
		||||
	//NOTE: next we sort triangles in each tile
 | 
			
		||||
/*
 | 
			
		||||
	glUseProgram(backend->sortProgram);
 | 
			
		||||
 | 
			
		||||
	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, 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);
 | 
			
		||||
	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);
 | 
			
		||||
*/
 | 
			
		||||
/*
 | 
			
		||||
	glBindImageTexture(0, backend->outTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
 | 
			
		||||
 | 
			
		||||
	glUniform1ui(0, indexCount);
 | 
			
		||||
	glUniform2ui(1, tileCountX, tileCountY);
 | 
			
		||||
	glUniform1ui(2, tileSize);
 | 
			
		||||
	glUniform1ui(3, tileArraySize);
 | 
			
		||||
*/
 | 
			
		||||
	glDispatchCompute(tileCountX, tileCountY, 1);
 | 
			
		||||
 | 
			
		||||
	//NOTE: now blit out texture to surface
 | 
			
		||||
/*
 | 
			
		||||
	glUseProgram(backend->blitProgram);
 | 
			
		||||
	glBindBuffer(GL_ARRAY_BUFFER, backend->dummyVertexBuffer);
 | 
			
		||||
	glActiveTexture(GL_TEXTURE0);
 | 
			
		||||
	glBindTexture(GL_TEXTURE_2D, backend->outTexture);
 | 
			
		||||
	glUniform1i(0, 0);
 | 
			
		||||
 | 
			
		||||
	glDrawArrays(GL_TRIANGLES, 0, 6);
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
	mg_gles_canvas_update_vertex_layout(backend);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +259,7 @@ void mg_gles_canvas_atlas_upload(mg_canvas_backend* interface, mp_rect rect, u8*
 | 
			
		|||
	//TODO
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void compile_shader(GLuint shader, const char* source)
 | 
			
		||||
static void mg_gles_compile_shader(GLuint shader, const char* source)
 | 
			
		||||
{
 | 
			
		||||
	glShaderSource(shader, 1, &source, 0);
 | 
			
		||||
	glCompileShader(shader);
 | 
			
		||||
| 
						 | 
				
			
			@ -284,12 +326,40 @@ mg_canvas_backend* mg_gles_canvas_create(mg_surface surface)
 | 
			
		|||
		glGenBuffers(1, &backend->dummyVertexBuffer);
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, backend->dummyVertexBuffer);
 | 
			
		||||
 | 
			
		||||
		mp_rect frame = mg_surface_get_frame(backend->surface);
 | 
			
		||||
		glGenTextures(1, &backend->outTexture);
 | 
			
		||||
		glBindTexture(GL_TEXTURE_2D, backend->outTexture);
 | 
			
		||||
		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, frame.w, frame.h);
 | 
			
		||||
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
			
		||||
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
			
		||||
 | 
			
		||||
		//NOTE: create clear program
 | 
			
		||||
		{
 | 
			
		||||
			GLuint clearShader = glCreateShader(GL_COMPUTE_SHADER);
 | 
			
		||||
			backend->clearCounterProgram = glCreateProgram();
 | 
			
		||||
 | 
			
		||||
			mg_gles_compile_shader(clearShader, gles_canvas_clear_counters);
 | 
			
		||||
 | 
			
		||||
			glAttachShader(backend->clearCounterProgram, clearShader);
 | 
			
		||||
			glLinkProgram(backend->clearCounterProgram);
 | 
			
		||||
 | 
			
		||||
			int status = 0;
 | 
			
		||||
			glGetProgramiv(backend->clearCounterProgram, GL_LINK_STATUS, &status);
 | 
			
		||||
			if(!status)
 | 
			
		||||
			{
 | 
			
		||||
				char buffer[256];
 | 
			
		||||
				int size = 0;
 | 
			
		||||
				glGetProgramInfoLog(backend->clearCounterProgram, 256, &size, buffer);
 | 
			
		||||
				printf("link error in gl_canvas_clear_counters: %.*s\n", size, buffer);
 | 
			
		||||
				exit(-1);
 | 
			
		||||
 			}
 | 
			
		||||
		}
 | 
			
		||||
		//NOTE: create tile program
 | 
			
		||||
		{
 | 
			
		||||
			GLuint tileShader = glCreateShader(GL_COMPUTE_SHADER);
 | 
			
		||||
			backend->tileProgram = glCreateProgram();
 | 
			
		||||
 | 
			
		||||
			compile_shader(tileShader, gles_canvas_tile);
 | 
			
		||||
			mg_gles_compile_shader(tileShader, gles_canvas_tile);
 | 
			
		||||
 | 
			
		||||
			glAttachShader(backend->tileProgram, tileShader);
 | 
			
		||||
			glLinkProgram(backend->tileProgram);
 | 
			
		||||
| 
						 | 
				
			
			@ -301,20 +371,40 @@ mg_canvas_backend* mg_gles_canvas_create(mg_surface surface)
 | 
			
		|||
				char buffer[256];
 | 
			
		||||
				int size = 0;
 | 
			
		||||
				glGetProgramInfoLog(backend->tileProgram, 256, &size, buffer);
 | 
			
		||||
				printf("link error: %.*s\n", size, buffer);
 | 
			
		||||
				printf("link error in gl_canvas_tile: %.*s\n", size, buffer);
 | 
			
		||||
				exit(-1);
 | 
			
		||||
 			}
 | 
			
		||||
		}
 | 
			
		||||
		//NOTE: create sort program
 | 
			
		||||
		{
 | 
			
		||||
			GLuint sortShader = glCreateShader(GL_COMPUTE_SHADER);
 | 
			
		||||
			backend->sortProgram = glCreateProgram();
 | 
			
		||||
 | 
			
		||||
			mg_gles_compile_shader(sortShader, gles_canvas_sort);
 | 
			
		||||
 | 
			
		||||
			glAttachShader(backend->sortProgram, sortShader);
 | 
			
		||||
			glLinkProgram(backend->sortProgram);
 | 
			
		||||
 | 
			
		||||
			int status = 0;
 | 
			
		||||
			glGetProgramiv(backend->sortProgram, GL_LINK_STATUS, &status);
 | 
			
		||||
			if(!status)
 | 
			
		||||
			{
 | 
			
		||||
				char buffer[256];
 | 
			
		||||
				int size = 0;
 | 
			
		||||
				glGetProgramInfoLog(backend->sortProgram, 256, &size, buffer);
 | 
			
		||||
				printf("link error gl_canvas_sort: %.*s\n", size, buffer);
 | 
			
		||||
				exit(-1);
 | 
			
		||||
 			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//NOTE: create draw program
 | 
			
		||||
		{
 | 
			
		||||
			GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
 | 
			
		||||
			GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
 | 
			
		||||
			GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
 | 
			
		||||
			backend->drawProgram = glCreateProgram();
 | 
			
		||||
 | 
			
		||||
			compile_shader(vertexShader, gles_canvas_vertex);
 | 
			
		||||
			compile_shader(fragmentShader, gles_canvas_fragment);
 | 
			
		||||
			mg_gles_compile_shader(shader, gles_canvas_draw);
 | 
			
		||||
 | 
			
		||||
			glAttachShader(backend->drawProgram, vertexShader);
 | 
			
		||||
			glAttachShader(backend->drawProgram, fragmentShader);
 | 
			
		||||
			glAttachShader(backend->drawProgram, shader);
 | 
			
		||||
			glLinkProgram(backend->drawProgram);
 | 
			
		||||
 | 
			
		||||
			int status = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -324,7 +414,33 @@ mg_canvas_backend* mg_gles_canvas_create(mg_surface surface)
 | 
			
		|||
				char buffer[256];
 | 
			
		||||
				int size = 0;
 | 
			
		||||
				glGetProgramInfoLog(backend->drawProgram, 256, &size, buffer);
 | 
			
		||||
				printf("link error: %.*s\n", size, buffer);
 | 
			
		||||
				printf("link error gl_canvas_draw: %.*s\n", size, buffer);
 | 
			
		||||
				exit(-1);
 | 
			
		||||
 			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//NOTE: create blit program
 | 
			
		||||
		{
 | 
			
		||||
			GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
 | 
			
		||||
			GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
 | 
			
		||||
			backend->blitProgram = glCreateProgram();
 | 
			
		||||
 | 
			
		||||
			mg_gles_compile_shader(vertexShader, gles_canvas_blit_vertex);
 | 
			
		||||
			mg_gles_compile_shader(fragmentShader, gles_canvas_blit_fragment);
 | 
			
		||||
 | 
			
		||||
			glAttachShader(backend->blitProgram, vertexShader);
 | 
			
		||||
			glAttachShader(backend->blitProgram, fragmentShader);
 | 
			
		||||
			glLinkProgram(backend->blitProgram);
 | 
			
		||||
 | 
			
		||||
			int status = 0;
 | 
			
		||||
			glGetProgramiv(backend->blitProgram, GL_LINK_STATUS, &status);
 | 
			
		||||
			if(!status)
 | 
			
		||||
			{
 | 
			
		||||
				char buffer[256];
 | 
			
		||||
				int size = 0;
 | 
			
		||||
				glGetProgramInfoLog(backend->blitProgram, 256, &size, buffer);
 | 
			
		||||
				printf("link error gl_canvas_blit: %.*s\n", size, buffer);
 | 
			
		||||
				exit(-1);
 | 
			
		||||
 			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,293 +0,0 @@
 | 
			
		|||
/*********************************************************************
 | 
			
		||||
*
 | 
			
		||||
*	file: gles_canvas_shaders.h
 | 
			
		||||
*	note: string literals auto-generated by embed_text.py
 | 
			
		||||
*	date: 03/022023
 | 
			
		||||
*
 | 
			
		||||
**********************************************************************/
 | 
			
		||||
#ifndef __GLES_CANVAS_SHADERS_H__
 | 
			
		||||
#define __GLES_CANVAS_SHADERS_H__
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//NOTE: string imported from src\gles_canvas_shaders\gles_canvas_fragment.glsl
 | 
			
		||||
const char* gles_canvas_fragment = 
 | 
			
		||||
"#version 310 es\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"
 | 
			
		||||
"layout(location = 0) out vec4 fragColor;\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"bool is_top_left(ivec2 a, ivec2 b)\n"
 | 
			
		||||
"{\n"
 | 
			
		||||
"	return( (a.y == b.y && b.x < a.x)\n"
 | 
			
		||||
"	      ||(b.y < a.y));\n"
 | 
			
		||||
"}\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"int orient2d(ivec2 a, ivec2 b, ivec2 p)\n"
 | 
			
		||||
"{\n"
 | 
			
		||||
"	return((b.x-a.x)*(p.y-a.y) - (b.y-a.y)*(p.x-a.x));\n"
 | 
			
		||||
"}\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"void main()\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 int sampleCount = 8;\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"	ivec2 centerPoint = ivec2(round(gl_FragCoord.xy * subPixelFactor));\n"
 | 
			
		||||
"	ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(1, 3),\n"
 | 
			
		||||
"	                                                     centerPoint + ivec2(-1, -3),\n"
 | 
			
		||||
"	                                                     centerPoint + ivec2(5, -1),\n"
 | 
			
		||||
"	                                                     centerPoint + ivec2(-3, 5),\n"
 | 
			
		||||
"	                                                     centerPoint + ivec2(-5, -5),\n"
 | 
			
		||||
"	                                                     centerPoint + ivec2(-7, 1),\n"
 | 
			
		||||
"	                                                     centerPoint + ivec2(3, -7),\n"
 | 
			
		||||
"	                                                     centerPoint + ivec2(7, 7));\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 currentColor[sampleCount];\n"
 | 
			
		||||
"    int currentZIndex[sampleCount];\n"
 | 
			
		||||
"    int flipCount[sampleCount];\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"    for(int i=0; i<sampleCount; i++)\n"
 | 
			
		||||
"    {\n"
 | 
			
		||||
"		currentZIndex[i] = -1;\n"
 | 
			
		||||
"		flipCount[i] = 0;\n"
 | 
			
		||||
"		sampleColor[i] = vec4(0, 0, 0, 0);\n"
 | 
			
		||||
"		currentColor[i] = vec4(0, 0, 0, 0);\n"
 | 
			
		||||
"    }\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"    for(uint tileArrayIndex=0u; tileArrayIndex < tileCounter; tileArrayIndex++)\n"
 | 
			
		||||
"    {\n"
 | 
			
		||||
"    	uint triangleIndex = tileArrayBuffer.elements[tileArraySize * tileIndex + tileArrayIndex];\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"		uint i0 = indexBuffer.elements[triangleIndex];\n"
 | 
			
		||||
"		uint i1 = indexBuffer.elements[triangleIndex+1u];\n"
 | 
			
		||||
"		uint i2 = indexBuffer.elements[triangleIndex+2u];\n"
 | 
			
		||||
"\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 p2 = ivec2(vertexBuffer.elements[i2].pos * subPixelFactor + vec2(0.5, 0.5));\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"		int zIndex = vertexBuffer.elements[i0].zIndex;\n"
 | 
			
		||||
"		vec4 color = vertexBuffer.elements[i0].color;\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"		//NOTE(martin): reorder triangle counter-clockwise and compute bias for each edge\n"
 | 
			
		||||
"		int cw = (p1 - p0).x*(p2 - p0).y - (p1 - p0).y*(p2 - p0).x;\n"
 | 
			
		||||
"		if(cw < 0)\n"
 | 
			
		||||
"		{\n"
 | 
			
		||||
"			uint tmpIndex = i1;\n"
 | 
			
		||||
"			i1 = i2;\n"
 | 
			
		||||
"			i2 = tmpIndex;\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"			ivec2 tmpPoint = p1;\n"
 | 
			
		||||
"			p1 = p2;\n"
 | 
			
		||||
"			p2 = tmpPoint;\n"
 | 
			
		||||
"		}\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"		vec4 cubic0 = vertexBuffer.elements[i0].cubic;\n"
 | 
			
		||||
"		vec4 cubic1 = vertexBuffer.elements[i1].cubic;\n"
 | 
			
		||||
"		vec4 cubic2 = vertexBuffer.elements[i2].cubic;\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"		int bias0 = is_top_left(p1, p2) ? 0 : -1;\n"
 | 
			
		||||
"		int bias1 = is_top_left(p2, p0) ? 0 : -1;\n"
 | 
			
		||||
"		int bias2 = is_top_left(p0, p1) ? 0 : -1;\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"		for(int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)\n"
 | 
			
		||||
"		{\n"
 | 
			
		||||
"			ivec2 samplePoint = samplePoints[sampleIndex];\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"			int w0 = orient2d(p1, p2, samplePoint);\n"
 | 
			
		||||
"			int w1 = orient2d(p2, p0, samplePoint);\n"
 | 
			
		||||
"			int w2 = orient2d(p0, p1, samplePoint);\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"			if((w0+bias0) >= 0 && (w1+bias1) >= 0 && (w2+bias2) >= 0)\n"
 | 
			
		||||
"			{\n"
 | 
			
		||||
"				vec4 cubic = (cubic0*float(w0) + cubic1*float(w1) + cubic2*float(w2))/(float(w0)+float(w1)+float(w2));\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"				float eps = 0.0001;\n"
 | 
			
		||||
"				if(cubic.w*(cubic.x*cubic.x*cubic.x - cubic.y*cubic.z) <= eps)\n"
 | 
			
		||||
"				{\n"
 | 
			
		||||
"					if(zIndex == currentZIndex[sampleIndex])\n"
 | 
			
		||||
"					{\n"
 | 
			
		||||
"						flipCount[sampleIndex]++;\n"
 | 
			
		||||
"					}\n"
 | 
			
		||||
"					else\n"
 | 
			
		||||
"					{\n"
 | 
			
		||||
"						if((flipCount[sampleIndex] & 0x01) != 0)\n"
 | 
			
		||||
"						{\n"
 | 
			
		||||
"							sampleColor[sampleIndex] = currentColor[sampleIndex];\n"
 | 
			
		||||
"						}\n"
 | 
			
		||||
"						currentColor[sampleIndex] = sampleColor[sampleIndex]*(1.-color.a) + color.a*color;\n"
 | 
			
		||||
"						currentZIndex[sampleIndex] = zIndex;\n"
 | 
			
		||||
"						flipCount[sampleIndex] = 1;\n"
 | 
			
		||||
"					}\n"
 | 
			
		||||
"				}\n"
 | 
			
		||||
"			}\n"
 | 
			
		||||
"		}\n"
 | 
			
		||||
"    }\n"
 | 
			
		||||
"    vec4 pixelColor = vec4(0);\n"
 | 
			
		||||
"    for(int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)\n"
 | 
			
		||||
"    {\n"
 | 
			
		||||
"    	if((flipCount[sampleIndex] & 0x01) != 0)\n"
 | 
			
		||||
"    	{\n"
 | 
			
		||||
"			sampleColor[sampleIndex] = currentColor[sampleIndex];\n"
 | 
			
		||||
"    	}\n"
 | 
			
		||||
"    	pixelColor += sampleColor[sampleIndex];\n"
 | 
			
		||||
"	}\n"
 | 
			
		||||
"	fragColor = pixelColor/float(sampleCount);\n"
 | 
			
		||||
"}\n";
 | 
			
		||||
 | 
			
		||||
//NOTE: string imported from src\gles_canvas_shaders\gles_canvas_vertex.glsl
 | 
			
		||||
const char* gles_canvas_vertex = 
 | 
			
		||||
"#version 310 es\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"precision mediump float;\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"void main()\n"
 | 
			
		||||
"{\n"
 | 
			
		||||
"    float x = float(((uint(gl_VertexID) + 2u) / 3u)%2u);\n"
 | 
			
		||||
"    float y = float(((uint(gl_VertexID) + 1u) / 3u)%2u);\n"
 | 
			
		||||
"\n"
 | 
			
		||||
"    gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f);\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__
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
#version 310 es
 | 
			
		||||
 | 
			
		||||
precision mediump float;
 | 
			
		||||
 | 
			
		||||
in vec2 uv;
 | 
			
		||||
out vec4 fragColor;
 | 
			
		||||
 | 
			
		||||
layout(location=0) uniform sampler2D tex;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	fragColor = texture(tex, uv);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,10 +2,13 @@
 | 
			
		|||
 | 
			
		||||
precision mediump float;
 | 
			
		||||
 | 
			
		||||
out vec2 uv;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    float x = float(((uint(gl_VertexID) + 2u) / 3u)%2u);
 | 
			
		||||
    float y = float(((uint(gl_VertexID) + 1u) / 3u)%2u);
 | 
			
		||||
 | 
			
		||||
    gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f);
 | 
			
		||||
    uv = vec2(x, y);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
#version 310 es
 | 
			
		||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 | 
			
		||||
 | 
			
		||||
precision mediump float;
 | 
			
		||||
layout(std430) buffer;
 | 
			
		||||
 | 
			
		||||
layout(binding = 0) coherent restrict writeonly buffer tileCounterBufferSSBO {
 | 
			
		||||
	uint elements[];
 | 
			
		||||
} tileCounterBuffer ;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	uint tileIndex = gl_WorkGroupID.x;
 | 
			
		||||
	tileCounterBuffer.elements[tileIndex] = 0u;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,9 @@
 | 
			
		|||
#version 310 es
 | 
			
		||||
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
 | 
			
		||||
 | 
			
		||||
precision mediump float;
 | 
			
		||||
precision mediump image2D;
 | 
			
		||||
 | 
			
		||||
layout(std430) buffer;
 | 
			
		||||
 | 
			
		||||
struct vertex {
 | 
			
		||||
| 
						 | 
				
			
			@ -12,19 +15,19 @@ struct vertex {
 | 
			
		|||
	int zIndex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
layout(binding = 0) buffer vertexBufferSSBO {
 | 
			
		||||
layout(binding = 0) restrict readonly buffer vertexBufferSSBO {
 | 
			
		||||
	vertex elements[];
 | 
			
		||||
} vertexBuffer ;
 | 
			
		||||
 | 
			
		||||
layout(binding = 1) buffer indexBufferSSBO {
 | 
			
		||||
layout(binding = 1) restrict readonly buffer indexBufferSSBO {
 | 
			
		||||
	uint elements[];
 | 
			
		||||
} indexBuffer ;
 | 
			
		||||
 | 
			
		||||
layout(binding = 2) coherent buffer tileCounterBufferSSBO {
 | 
			
		||||
layout(binding = 2) restrict readonly buffer tileCounterBufferSSBO {
 | 
			
		||||
	uint elements[];
 | 
			
		||||
} tileCounterBuffer ;
 | 
			
		||||
 | 
			
		||||
layout(binding = 3) coherent buffer tileArrayBufferSSBO {
 | 
			
		||||
layout(binding = 3) restrict readonly buffer tileArrayBufferSSBO {
 | 
			
		||||
	uint elements[];
 | 
			
		||||
} tileArrayBuffer ;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,9 +35,14 @@ 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(rgba8, binding = 0) uniform restrict writeonly image2D outTexture;
 | 
			
		||||
 | 
			
		||||
layout(location = 0) out vec4 fragColor;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
 | 
			
		||||
bool is_top_left(ivec2 a, ivec2 b)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -49,14 +57,21 @@ int orient2d(ivec2 a, ivec2 b, ivec2 p)
 | 
			
		|||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	uvec2 tileCoord = uvec2(gl_FragCoord.xy)/tileSize;
 | 
			
		||||
	ivec2 pixelCoord = ivec2(gl_WorkGroupID.xy*uvec2(16, 16) + gl_LocalInvocationID.xy);
 | 
			
		||||
 | 
			
		||||
	imageStore(outTexture, pixelCoord, vec4(1, 0, 1, 1));
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
	uvec2 tileCoord = uvec2(pixelCoord) / tileSize;
 | 
			
		||||
 | 
			
		||||
	uint tileIndex =  tileCoord.y * tileCount.x + tileCoord.x;
 | 
			
		||||
	uint tileCounter = tileCounterBuffer.elements[tileIndex];
 | 
			
		||||
 | 
			
		||||
	const float subPixelFactor = 16.;
 | 
			
		||||
	const int sampleCount = 8;
 | 
			
		||||
	ivec2 centerPoint = ivec2(round((vec2(pixelCoord) + vec2(0.5, 0.5)) * subPixelFactor));
 | 
			
		||||
 | 
			
		||||
	ivec2 centerPoint = ivec2(round(gl_FragCoord.xy * subPixelFactor));
 | 
			
		||||
/*
 | 
			
		||||
	const int sampleCount = 8;
 | 
			
		||||
	ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(1, 3),
 | 
			
		||||
	                                                     centerPoint + ivec2(-1, -3),
 | 
			
		||||
	                                                     centerPoint + ivec2(5, -1),
 | 
			
		||||
| 
						 | 
				
			
			@ -65,28 +80,38 @@ void main()
 | 
			
		|||
	                                                     centerPoint + ivec2(-7, 1),
 | 
			
		||||
	                                                     centerPoint + ivec2(3, -7),
 | 
			
		||||
	                                                     centerPoint + ivec2(7, 7));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
	const int sampleCount = 4;
 | 
			
		||||
	ivec2 samplePoints[sampleCount] = ivec2[sampleCount](centerPoint + ivec2(-2, 6),
 | 
			
		||||
	                                                     centerPoint + ivec2(6, 2),
 | 
			
		||||
	                                                     centerPoint + ivec2(-6, -2),
 | 
			
		||||
	                                                     centerPoint + ivec2(2, -6));
 | 
			
		||||
	//DEBUG
 | 
			
		||||
//*
 | 
			
		||||
	{
 | 
			
		||||
		vec4 fragColor = vec4(0);
 | 
			
		||||
/*
 | 
			
		||||
	if( int(gl_FragCoord.x - 0.5) % 16 == 0
 | 
			
		||||
	  ||int(gl_FragCoord.y - 0.5) % 16 == 0)
 | 
			
		||||
	{
 | 
			
		||||
		fragColor = vec4(0, 0, 0, 1);
 | 
			
		||||
		if( pixelCoord.x % 16 == 0
 | 
			
		||||
	  	||pixelCoord.y % 16 == 0)
 | 
			
		||||
		{
 | 
			
		||||
			fragColor = vec4(0, 0, 0, 1);
 | 
			
		||||
		}
 | 
			
		||||
		else if(tileCounterBuffer.elements[tileIndex] == 0xffffu)
 | 
			
		||||
		{
 | 
			
		||||
			fragColor = vec4(1, 0, 1, 1);
 | 
			
		||||
		}
 | 
			
		||||
		else if(tileCounter != 0u)
 | 
			
		||||
		{
 | 
			
		||||
			fragColor = vec4(0, 1, 0, 1);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			fragColor = vec4(1, 0, 0, 1);
 | 
			
		||||
		}
 | 
			
		||||
*/
 | 
			
		||||
		imageStore(outTexture, pixelCoord, fragColor);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	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;
 | 
			
		||||
//*/
 | 
			
		||||
	//----
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -181,5 +206,8 @@ void main()
 | 
			
		|||
    	}
 | 
			
		||||
    	pixelColor += sampleColor[sampleIndex];
 | 
			
		||||
	}
 | 
			
		||||
	fragColor = pixelColor/float(sampleCount);
 | 
			
		||||
 | 
			
		||||
	imageStore(outTexture, pixelCoord, pixelColor/float(sampleCount));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
#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) restrict readonly buffer vertexBufferSSBO {
 | 
			
		||||
	vertex elements[];
 | 
			
		||||
} vertexBuffer ;
 | 
			
		||||
 | 
			
		||||
layout(binding = 1) restrict readonly buffer indexBufferSSBO {
 | 
			
		||||
	uint elements[];
 | 
			
		||||
} indexBuffer ;
 | 
			
		||||
 | 
			
		||||
layout(binding = 2) coherent readonly restrict buffer tileCounterBufferSSBO {
 | 
			
		||||
	uint elements[];
 | 
			
		||||
} tileCounterBuffer ;
 | 
			
		||||
 | 
			
		||||
layout(binding = 3) coherent restrict 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;
 | 
			
		||||
 | 
			
		||||
int get_zindex(uint tileArrayOffset, uint tileArrayIndex)
 | 
			
		||||
{
 | 
			
		||||
	uint triangleIndex = tileArrayBuffer.elements[tileArrayOffset + tileArrayIndex];
 | 
			
		||||
	uint i0 = indexBuffer.elements[triangleIndex];
 | 
			
		||||
	int zIndex = vertexBuffer.elements[i0].zIndex;
 | 
			
		||||
	return(zIndex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	uint tileIndex = gl_WorkGroupID.x;
 | 
			
		||||
	uint tileArrayOffset = tileArraySize * tileIndex;
 | 
			
		||||
	uint tileArrayCount = tileCounterBuffer.elements[tileIndex];
 | 
			
		||||
 | 
			
		||||
	for(uint tileArrayIndex=1u; tileArrayIndex < tileArrayCount; tileArrayIndex++)
 | 
			
		||||
	{
 | 
			
		||||
		for(uint sortIndex = tileArrayIndex; sortIndex > 0u; sortIndex--)
 | 
			
		||||
		{
 | 
			
		||||
			int zIndex = get_zindex(tileArrayOffset, sortIndex);
 | 
			
		||||
			int prevZIndex = get_zindex(tileArrayOffset, sortIndex-1u);
 | 
			
		||||
 | 
			
		||||
			if(zIndex >= prevZIndex)
 | 
			
		||||
			{
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			uint tmp = tileArrayBuffer.elements[tileArrayOffset + sortIndex];
 | 
			
		||||
			tileArrayBuffer.elements[tileArrayOffset + sortIndex] = tileArrayBuffer.elements[tileArrayOffset + sortIndex - 1u];
 | 
			
		||||
			tileArrayBuffer.elements[tileArrayOffset + sortIndex - 1u] = tmp;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//DEBUG
 | 
			
		||||
	/*
 | 
			
		||||
	int prevZIndex = -1;
 | 
			
		||||
	for(uint tileArrayIndex=1u; tileArrayIndex < tileArrayCount; tileArrayIndex++)
 | 
			
		||||
	{
 | 
			
		||||
		int zIndex = get_zindex(tileArrayOffset, tileArrayIndex);
 | 
			
		||||
 | 
			
		||||
		if(zIndex < prevZIndex)
 | 
			
		||||
		{
 | 
			
		||||
			tileCounterBuffer.elements[tileIndex] = 0xffffu;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		prevZIndex = zIndex;
 | 
			
		||||
	}
 | 
			
		||||
	//*/
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -13,19 +13,19 @@ struct vertex {
 | 
			
		|||
	int zIndex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
layout(binding = 0) buffer vertexBufferSSBO {
 | 
			
		||||
layout(binding = 0) restrict readonly buffer vertexBufferSSBO {
 | 
			
		||||
	vertex elements[];
 | 
			
		||||
} vertexBuffer ;
 | 
			
		||||
 | 
			
		||||
layout(binding = 1) buffer indexBufferSSBO {
 | 
			
		||||
layout(binding = 1) restrict readonly buffer indexBufferSSBO {
 | 
			
		||||
	uint elements[];
 | 
			
		||||
} indexBuffer ;
 | 
			
		||||
 | 
			
		||||
layout(binding = 2) coherent buffer tileCounterBufferSSBO {
 | 
			
		||||
layout(binding = 2) coherent restrict buffer tileCounterBufferSSBO {
 | 
			
		||||
	uint elements[];
 | 
			
		||||
} tileCounterBuffer ;
 | 
			
		||||
 | 
			
		||||
layout(binding = 3) coherent buffer tileArrayBufferSSBO {
 | 
			
		||||
layout(binding = 3) coherent restrict writeonly buffer tileArrayBufferSSBO {
 | 
			
		||||
	uint elements[];
 | 
			
		||||
} tileArrayBuffer ;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,41 +36,35 @@ layout(location = 3) uniform uint tileArraySize;
 | 
			
		|||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
	uint tileIndex = gl_WorkGroupID.y * tileCount.x + gl_WorkGroupID.x;
 | 
			
		||||
	uint tileArrayOffset = tileArraySize * tileIndex;
 | 
			
		||||
	uint triangleIndex = gl_WorkGroupID.x * 3u;
 | 
			
		||||
 | 
			
		||||
	vec4 tileBox = 	vec4(gl_WorkGroupID.x * tileSize,
 | 
			
		||||
	                     gl_WorkGroupID.y * tileSize,
 | 
			
		||||
	                     gl_WorkGroupID.x * tileSize + tileSize,
 | 
			
		||||
	                     gl_WorkGroupID.y * tileSize + tileSize);
 | 
			
		||||
	uint i0 = indexBuffer.elements[triangleIndex];
 | 
			
		||||
	uint i1 = indexBuffer.elements[triangleIndex+1u];
 | 
			
		||||
	uint i2 = indexBuffer.elements[triangleIndex+2u];
 | 
			
		||||
 | 
			
		||||
	uint tileCounter = 0u;
 | 
			
		||||
	vec2 p0 = vertexBuffer.elements[i0].pos;
 | 
			
		||||
	vec2 p1 = vertexBuffer.elements[i1].pos;
 | 
			
		||||
	vec2 p2 = vertexBuffer.elements[i2].pos;
 | 
			
		||||
 | 
			
		||||
	for(uint triangleIndex = 0u; triangleIndex < indexCount; triangleIndex += 3u)
 | 
			
		||||
	vec4 fbox = 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));
 | 
			
		||||
 | 
			
		||||
	uvec4 box = uvec4(floor(fbox))/tileSize;
 | 
			
		||||
 | 
			
		||||
	uint xMin = max(0u, box.x);
 | 
			
		||||
	uint yMin = max(0u, box.y);
 | 
			
		||||
	uint xMax = min(box.z, tileCount.x - 1u);
 | 
			
		||||
	uint yMax = min(box.w, tileCount.y - 1u);
 | 
			
		||||
 | 
			
		||||
	for(uint y = yMin; y <= yMax; y++)
 | 
			
		||||
	{
 | 
			
		||||
		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))
 | 
			
		||||
		for(uint x = xMin ; x <= xMax; x++)
 | 
			
		||||
		{
 | 
			
		||||
			tileArrayBuffer.elements[tileArrayOffset + tileCounter] = triangleIndex;
 | 
			
		||||
			tileCounter++;
 | 
			
		||||
			uint tileIndex = y*tileCount.x + x;
 | 
			
		||||
			uint tileCounter = atomicAdd(tileCounterBuffer.elements[tileIndex], 1u);
 | 
			
		||||
			tileArrayBuffer.elements[tileArraySize*tileIndex + tileCounter] = triangleIndex;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	tileCounterBuffer.elements[tileIndex] = tileCounter;
 | 
			
		||||
 | 
			
		||||
//	tileCounterBuffer.elements[tileIndex] = 1u;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -125,6 +125,7 @@ mg_surface mg_gles_surface_create_for_window(mp_window window)
 | 
			
		|||
 | 
			
		||||
//TODO: reactivate this when finished testing!
 | 
			
		||||
//		eglSwapInterval(surface->eglDisplay, 1);
 | 
			
		||||
		eglSwapInterval(surface->eglDisplay, 0);
 | 
			
		||||
 | 
			
		||||
		res = mg_surface_alloc_handle((mg_surface_data*)surface);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue