[wip, win32, canvas] bin segments to screen tile queues
This commit is contained in:
		
							parent
							
								
									15c54b9385
								
							
						
					
					
						commit
						0870097262
					
				| 
						 | 
					@ -30,7 +30,7 @@ int main()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//NOTE: create surface
 | 
						//NOTE: create surface
 | 
				
			||||||
	mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
 | 
						mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
 | 
				
			||||||
	mg_surface_swap_interval(surface, 0);
 | 
						mg_surface_swap_interval(surface, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(mg_surface_is_nil(surface))
 | 
						if(mg_surface_is_nil(surface))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -124,12 +124,10 @@ typedef struct mg_gl_canvas_backend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	GLuint vao;
 | 
						GLuint vao;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	GLuint pathSetup;
 | 
						GLuint pathSetup;
 | 
				
			||||||
	*/
 | 
					 | 
				
			||||||
	GLuint segmentSetup;
 | 
						GLuint segmentSetup;
 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	GLuint backprop;
 | 
						GLuint backprop;
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
	GLuint merge;
 | 
						GLuint merge;
 | 
				
			||||||
	*/
 | 
						*/
 | 
				
			||||||
	GLuint raster;
 | 
						GLuint raster;
 | 
				
			||||||
| 
						 | 
					@ -242,40 +240,49 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
 | 
				
			||||||
	glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->tileOpCountBuffer);
 | 
						glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->tileOpCountBuffer);
 | 
				
			||||||
	glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int), &zero, GL_DYNAMIC_COPY);
 | 
						glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int), &zero, GL_DYNAMIC_COPY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//NOTE: path setup pass
 | 
						//NOTE: path setup pass
 | 
				
			||||||
	glUseProgram(backend->pathSetup);
 | 
						glUseProgram(backend->pathSetup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, backend->pathBuffer, backend->pathBufferOffset, pathCount*sizeof(mg_gl_path));
 | 
						glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->tileQueueBuffer);
 | 
				
			||||||
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->pathQueueBuffer);
 | 
					 | 
				
			||||||
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->tileQueueBuffer);
 | 
					 | 
				
			||||||
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileQueueCountBuffer);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glUniform1i(0, tileSize);
 | 
					//	glUniform1i(0, tileSize);
 | 
				
			||||||
	glUniform1f(1, scale);
 | 
					//	glUniform1f(1, scale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glDispatchCompute(nTilesX, nTilesY, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glDispatchCompute(pathCount, 1, 1);
 | 
					 | 
				
			||||||
	*/
 | 
					 | 
				
			||||||
	//NOTE: segment setup pass
 | 
						//NOTE: segment setup pass
 | 
				
			||||||
	glUseProgram(backend->segmentSetup);
 | 
						glUseProgram(backend->segmentSetup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, backend->elementBuffer, backend->elementBufferOffset, eltCount*sizeof(mg_gl_path_elt));
 | 
						glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, backend->elementBuffer, backend->elementBufferOffset, eltCount*sizeof(mg_gl_path_elt));
 | 
				
			||||||
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->segmentCountBuffer);
 | 
						glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->segmentCountBuffer);
 | 
				
			||||||
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->segmentBuffer);
 | 
						glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->segmentBuffer);
 | 
				
			||||||
 | 
						glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileOpCountBuffer);
 | 
				
			||||||
 | 
						glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, backend->tileOpBuffer);
 | 
				
			||||||
 | 
						glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, backend->tileQueueBuffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glUniform1f(0, scale);
 | 
						glUniform1f(0, scale);
 | 
				
			||||||
 | 
						glUniform1ui(1, tileSize);
 | 
				
			||||||
 | 
						glUniform2i(2, nTilesX, nTilesY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glDispatchCompute(eltCount, 1, 1);
 | 
						glDispatchCompute(eltCount, 1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//NOTE: backprop pass
 | 
						//NOTE: backprop pass
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
	glUseProgram(backend->backprop);
 | 
						glUseProgram(backend->backprop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->pathQueueBuffer);
 | 
						glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->tileQueueBuffer);
 | 
				
			||||||
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->tileQueueBuffer);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glDispatchCompute(pathCount*16, 1, 1);
 | 
						glUniform2i(0, nTilesX, nTilesY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glDispatchCompute(nTilesY, 1, 1);
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
	//NOTE: merge pass
 | 
						//NOTE: merge pass
 | 
				
			||||||
	glUseProgram(backend->merge);
 | 
						glUseProgram(backend->merge);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -307,6 +314,8 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
 | 
				
			||||||
	glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, backend->pathBuffer, backend->pathBufferOffset, pathCount*sizeof(mg_gl_path));
 | 
						glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, backend->pathBuffer, backend->pathBufferOffset, pathCount*sizeof(mg_gl_path));
 | 
				
			||||||
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->segmentCountBuffer);
 | 
						glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->segmentCountBuffer);
 | 
				
			||||||
	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->segmentBuffer);
 | 
						glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, backend->segmentBuffer);
 | 
				
			||||||
 | 
						glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileQueueBuffer);
 | 
				
			||||||
 | 
						glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, backend->tileOpBuffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//	glUniform1ui(0, tileSize);
 | 
					//	glUniform1ui(0, tileSize);
 | 
				
			||||||
//	glUniform1f(1, scale);
 | 
					//	glUniform1f(1, scale);
 | 
				
			||||||
| 
						 | 
					@ -316,8 +325,6 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		log_error("gl error %i\n", err);
 | 
							log_error("gl error %i\n", err);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	log_info("eltCount = %i\n", eltCount);
 | 
						log_info("eltCount = %i\n", eltCount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ASSERT(eltCount != 0);
 | 
						ASSERT(eltCount != 0);
 | 
				
			||||||
| 
						 | 
					@ -339,7 +346,7 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	*/
 | 
						*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glDispatchCompute(viewportSize.x, viewportSize.y, 1);
 | 
						glDispatchCompute(nTilesX, nTilesY, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//NOTE: blit pass
 | 
						//NOTE: blit pass
 | 
				
			||||||
	glUseProgram(backend->blit);
 | 
						glUseProgram(backend->blit);
 | 
				
			||||||
| 
						 | 
					@ -741,12 +748,10 @@ mg_canvas_backend* gl_canvas_backend_create(mg_wgl_surface* surface)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//NOTE: create programs
 | 
							//NOTE: create programs
 | 
				
			||||||
		int err = 0;
 | 
							int err = 0;
 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		err |= mg_gl_canvas_compile_compute_program(glsl_path_setup, &backend->pathSetup);
 | 
							err |= mg_gl_canvas_compile_compute_program(glsl_path_setup, &backend->pathSetup);
 | 
				
			||||||
		*/
 | 
					 | 
				
			||||||
		err |= mg_gl_canvas_compile_compute_program(glsl_segment_setup, &backend->segmentSetup);
 | 
							err |= mg_gl_canvas_compile_compute_program(glsl_segment_setup, &backend->segmentSetup);
 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		err |= mg_gl_canvas_compile_compute_program(glsl_backprop, &backend->backprop);
 | 
							err |= mg_gl_canvas_compile_compute_program(glsl_backprop, &backend->backprop);
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
		err |= mg_gl_canvas_compile_compute_program(glsl_merge, &backend->merge);
 | 
							err |= mg_gl_canvas_compile_compute_program(glsl_merge, &backend->merge);
 | 
				
			||||||
		*/
 | 
							*/
 | 
				
			||||||
		err |= mg_gl_canvas_compile_compute_program(glsl_raster, &backend->raster);
 | 
							err |= mg_gl_canvas_compile_compute_program(glsl_raster, &backend->raster);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,17 +4,23 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 | 
				
			||||||
precision mediump float;
 | 
					precision mediump float;
 | 
				
			||||||
layout(std430) buffer;
 | 
					layout(std430) buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
layout(binding = 0) restrict readonly buffer pathQueueBufferSSBO
 | 
					layout(binding = 0) restrict buffer tileQueueBufferSSBO
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	mg_gl_path_queue elements[];
 | 
					 | 
				
			||||||
} pathQueueBuffer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
layout(binding = 1) restrict writeonly buffer tileQueueBufferSSBO
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	mg_gl_tile_queue elements[];
 | 
						mg_gl_tile_queue elements[];
 | 
				
			||||||
} tileQueueBuffer;
 | 
					} tileQueueBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					layout(location = 0) uniform ivec2 nTiles;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void main()
 | 
					void main()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int rowIndex = int(gl_WorkGroupID.x);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int sum = 0;
 | 
				
			||||||
 | 
						for(int x = nTiles.x-1; x >= 0; x--)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int tileIndex = rowIndex * nTiles.x + x;
 | 
				
			||||||
 | 
							int offset = tileQueueBuffer.elements[tileIndex].windingOffset;
 | 
				
			||||||
 | 
							tileQueueBuffer.elements[tileIndex].windingOffset = sum;
 | 
				
			||||||
 | 
							sum += offset;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,27 +4,18 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 | 
				
			||||||
precision mediump float;
 | 
					precision mediump float;
 | 
				
			||||||
layout(std430) buffer;
 | 
					layout(std430) buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
layout(binding = 0) restrict readonly buffer pathBufferSSBO
 | 
					layout(binding = 0) restrict writeonly buffer tileQueueBufferSSBO
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	mg_gl_path elements[];
 | 
					 | 
				
			||||||
} pathBuffer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
layout(binding = 1) restrict writeonly buffer pathQueueBufferSSBO
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	mg_gl_path_queue elements[];
 | 
					 | 
				
			||||||
} pathQueueBuffer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
layout(binding = 2) restrict writeonly buffer tileQueueBufferSSBO
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	mg_gl_tile_queue elements[];
 | 
						mg_gl_tile_queue elements[];
 | 
				
			||||||
} tileQueueBuffer;
 | 
					} tileQueueBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
layout(binding = 3) restrict writeonly buffer tileQueueCountBufferSSBO
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int elements[];
 | 
					 | 
				
			||||||
} tileQueueCountBuffer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void main()
 | 
					void main()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						uvec2 nTiles = gl_NumWorkGroups.xy;
 | 
				
			||||||
 | 
						uvec2 tileCoord = gl_WorkGroupID.xy;
 | 
				
			||||||
 | 
						uint tileIndex =  tileCoord.y * nTiles.x + tileCoord.x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tileQueueBuffer.elements[tileIndex].windingOffset = 0;
 | 
				
			||||||
 | 
						tileQueueBuffer.elements[tileIndex].first = -1;
 | 
				
			||||||
 | 
						tileQueueBuffer.elements[tileIndex].last = -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,17 @@ layout(binding = 2) restrict readonly buffer segmentBufferSSBO
 | 
				
			||||||
	mg_gl_segment elements[];
 | 
						mg_gl_segment elements[];
 | 
				
			||||||
} segmentBuffer;
 | 
					} segmentBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					layout(binding = 3) restrict readonly buffer tileQueuesBufferSSBO
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						mg_gl_tile_queue elements[];
 | 
				
			||||||
 | 
					} tileQueuesBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					layout(binding = 4) restrict readonly buffer tileOpBufferSSBO
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						mg_gl_tile_op elements[];
 | 
				
			||||||
 | 
					} tileOpBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//layout(location = 0) uniform uint tileSize; // this has to be commented until it's effectively used!!
 | 
					//layout(location = 0) uniform uint tileSize; // this has to be commented until it's effectively used!!
 | 
				
			||||||
//layout(location = 0) uniform float scale;
 | 
					//layout(location = 0) uniform float scale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,13 +132,39 @@ int side_of_segment(vec2 p, mg_gl_segment seg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void main()
 | 
					void main()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int segCount = segmentCountBuffer.elements[0];
 | 
						uvec2 nTiles = gl_NumWorkGroups.xy;
 | 
				
			||||||
	vec2 sampleCoord = vec2(gl_WorkGroupID.xy*uvec2(16, 16) + gl_LocalInvocationID.xy);
 | 
						uvec2 tileCoord = gl_WorkGroupID.xy;
 | 
				
			||||||
 | 
						uint tileIndex =  tileCoord.y * nTiles.x + tileCoord.x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ivec2 pixelCoord = ivec2(gl_WorkGroupID.xy*uvec2(16, 16) + gl_LocalInvocationID.xy);
 | 
				
			||||||
 | 
						vec2 sampleCoord = vec2(pixelCoord);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						imageStore(outTexture, ivec2(sampleCoord), vec4(1, 1, 1, 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mg_gl_tile_queue tileQueue = tileQueuesBuffer.elements[tileIndex];
 | 
				
			||||||
 | 
						int opIndex = tileQueue.first;
 | 
				
			||||||
 | 
					//	int winding = tileQueue.windingOffset;
 | 
				
			||||||
	int winding = 0;
 | 
						int winding = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for(int segIndex=0; segIndex<segCount; segIndex++)
 | 
						if((pixelCoord.x % 16) == 0 || (pixelCoord.y % 16) == 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							imageStore(outTexture, ivec2(sampleCoord), vec4(0, 0, 0, 1));
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int opCount = 0;
 | 
				
			||||||
 | 
						while(opIndex >= 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							//imageStore(outTexture, ivec2(sampleCoord), vec4(0, 1, 0, 1));
 | 
				
			||||||
 | 
							//return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mg_gl_tile_op op = tileOpBuffer.elements[opIndex];
 | 
				
			||||||
 | 
							opIndex = op.next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(op.kind == MG_GL_OP_SEGMENT)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								int segIndex = op.index;
 | 
				
			||||||
			mg_gl_segment seg = segmentBuffer.elements[segIndex];
 | 
								mg_gl_segment seg = segmentBuffer.elements[segIndex];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if( (sampleCoord.y > seg.box.y)
 | 
								if( (sampleCoord.y > seg.box.y)
 | 
				
			||||||
| 
						 | 
					@ -137,8 +174,7 @@ void main()
 | 
				
			||||||
				winding += seg.windingIncrement;
 | 
									winding += seg.windingIncrement;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
					/*			if(op.crossRight)
 | 
				
			||||||
		if(op->crossRight)
 | 
					 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if( (seg.config == MG_GL_BR || seg.config == MG_GL_TL)
 | 
									if( (seg.config == MG_GL_BR || seg.config == MG_GL_TL)
 | 
				
			||||||
				  &&(sampleCoord.y > seg.box.w))
 | 
									  &&(sampleCoord.y > seg.box.w))
 | 
				
			||||||
| 
						 | 
					@ -151,9 +187,9 @@ void main()
 | 
				
			||||||
					winding -= seg.windingIncrement;
 | 
										winding -= seg.windingIncrement;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		*/
 | 
					*/
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	int pathIndex = 0;
 | 
						int pathIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//	vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
 | 
					//	vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,18 +9,34 @@ layout(binding = 0) restrict readonly buffer elementBufferSSBO
 | 
				
			||||||
	mg_gl_path_elt elements[];
 | 
						mg_gl_path_elt elements[];
 | 
				
			||||||
} elementBuffer;
 | 
					} elementBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
layout(binding = 1) restrict buffer segmentCountBufferSSBO
 | 
					layout(binding = 1) coherent restrict buffer segmentCountBufferSSBO
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int elements[];
 | 
						int elements[];
 | 
				
			||||||
} segmentCountBuffer;
 | 
					} segmentCountBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
layout(binding = 2) restrict writeonly buffer segmentBufferSSBO
 | 
					layout(binding = 2) restrict buffer segmentBufferSSBO
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	mg_gl_segment elements[];
 | 
						mg_gl_segment elements[];
 | 
				
			||||||
} segmentBuffer;
 | 
					} segmentBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
layout(location = 0) uniform float scale;
 | 
					layout(binding = 3) coherent restrict buffer tileOpCountBufferSSBO
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int elements[];
 | 
				
			||||||
 | 
					} tileOpCountBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					layout(binding = 4) restrict buffer tileOpBufferSSBO
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						mg_gl_tile_op elements[];
 | 
				
			||||||
 | 
					} tileOpBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					layout(binding = 5) coherent restrict buffer tileQueuesBufferSSBO
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						mg_gl_tile_queue elements[];
 | 
				
			||||||
 | 
					} tileQueuesBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					layout(location = 0) uniform float scale;
 | 
				
			||||||
 | 
					layout(location = 1) uniform uint tileSize;
 | 
				
			||||||
 | 
					layout(location = 2) uniform ivec2 nTiles;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int push_segment(in vec2 p[4], int kind)
 | 
					int push_segment(in vec2 p[4], int kind)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -82,12 +98,198 @@ int push_segment(in vec2 p[4], int kind)
 | 
				
			||||||
	return(segIndex);
 | 
						return(segIndex);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float ccw(vec2 a, vec2 b, vec2 c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return((b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int side_of_segment(vec2 p, mg_gl_segment seg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int side = 0;
 | 
				
			||||||
 | 
						if(p.y > seg.box.w || p.y <= seg.box.y)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if(p.x > seg.box.x && p.x <= seg.box.z)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if(p.y > seg.box.w)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									side = (seg.config == MG_GL_TL || seg.config == MG_GL_BR)? -1 : 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									side = (seg.config == MG_GL_TL || seg.config == MG_GL_BR)? 1 : -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if(p.x > seg.box.z)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							side = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if(p.x <= seg.box.x)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							side = -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							vec2 a, b, c;
 | 
				
			||||||
 | 
							switch(seg.config)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								case MG_GL_TL:
 | 
				
			||||||
 | 
									a = seg.box.xy;
 | 
				
			||||||
 | 
									b = seg.box.zw;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case MG_GL_BR:
 | 
				
			||||||
 | 
									a = seg.box.zw;
 | 
				
			||||||
 | 
									b = seg.box.xy;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case MG_GL_TR:
 | 
				
			||||||
 | 
									a = seg.box.xw;
 | 
				
			||||||
 | 
									b = seg.box.zy;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case MG_GL_BL:
 | 
				
			||||||
 | 
									a = seg.box.zy;
 | 
				
			||||||
 | 
									b = seg.box.xw;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							c = seg.hullVertex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(ccw(a, b, p) < 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// other side of the diagonal
 | 
				
			||||||
 | 
								side = (seg.config == MG_GL_BR || seg.config == MG_GL_TR) ? -1 : 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if(ccw(b, c, p) < 0 || ccw(c, a, p) < 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// same side of the diagonal, but outside curve hull
 | 
				
			||||||
 | 
								side = (seg.config == MG_GL_BL || seg.config == MG_GL_TL) ? -1 : 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// inside curve hull
 | 
				
			||||||
 | 
								switch(seg.kind)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									case MG_GL_LINE:
 | 
				
			||||||
 | 
										side = 1;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									case MG_GL_QUADRATIC:
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										vec3 ph = {p.x, p.y, 1};
 | 
				
			||||||
 | 
										vec3 klm = seg.implicitMatrix * ph;
 | 
				
			||||||
 | 
										side = ((klm.x*klm.x - klm.y)*klm.z < 0)? -1 : 1;
 | 
				
			||||||
 | 
									} break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									case MG_GL_CUBIC:
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										vec3 ph = {p.x, p.y, 1};
 | 
				
			||||||
 | 
										vec3 klm = seg.implicitMatrix * ph;
 | 
				
			||||||
 | 
										side = (seg.sign*(klm.x*klm.x*klm.x - klm.y*klm.z) < 0)? -1 : 1;
 | 
				
			||||||
 | 
									} break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return(side);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void bin_to_tiles(int segIndex)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						//NOTE: add segment index to the queues of tiles it overlaps with
 | 
				
			||||||
 | 
						const mg_gl_segment seg = segmentBuffer.elements[segIndex];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ivec4 pathArea = ivec4(0, 0, nTiles.x, nTiles.y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ivec4 coveredTiles = ivec4(seg.box)/int(tileSize);
 | 
				
			||||||
 | 
						int xMin = max(0, coveredTiles.x - pathArea.x);
 | 
				
			||||||
 | 
						int yMin = max(0, coveredTiles.y - pathArea.y);
 | 
				
			||||||
 | 
						int xMax = min(coveredTiles.z - pathArea.x, pathArea.z-1);
 | 
				
			||||||
 | 
						int yMax = min(coveredTiles.w - pathArea.y, pathArea.w-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for(int y = yMin; y <= yMax; y++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							for(int x = xMin ; x <= xMax; x++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								vec4 tileBox = vec4(float(x + pathArea.x),
 | 
				
			||||||
 | 
								                    float(y + pathArea.y),
 | 
				
			||||||
 | 
								                    float(x + pathArea.x + 1),
 | 
				
			||||||
 | 
								                    float(y + pathArea.y + 1)) * float(tileSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								vec2 bl = {tileBox.x, tileBox.y};
 | 
				
			||||||
 | 
								vec2 br = {tileBox.z, tileBox.y};
 | 
				
			||||||
 | 
								vec2 tr = {tileBox.z, tileBox.w};
 | 
				
			||||||
 | 
								vec2 tl = {tileBox.x, tileBox.w};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								int sbl = side_of_segment(bl, seg);
 | 
				
			||||||
 | 
								int sbr = side_of_segment(br, seg);
 | 
				
			||||||
 | 
								int str = side_of_segment(tr, seg);
 | 
				
			||||||
 | 
								int stl = side_of_segment(tl, seg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bool crossL = (stl*sbl < 0);
 | 
				
			||||||
 | 
								bool crossR = (str*sbr < 0);
 | 
				
			||||||
 | 
								bool crossT = (stl*str < 0);
 | 
				
			||||||
 | 
								bool crossB = (sbl*sbr < 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								vec2 s0, s1;
 | 
				
			||||||
 | 
								if(seg.config == MG_GL_TL||seg.config == MG_GL_BR)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									s0 = seg.box.xy;
 | 
				
			||||||
 | 
									s1 = seg.box.zw;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									s0 = seg.box.xw;
 | 
				
			||||||
 | 
									s1 = seg.box.zy;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								bool s0Inside =  s0.x >= tileBox.x
 | 
				
			||||||
 | 
								              && s0.x < tileBox.z
 | 
				
			||||||
 | 
								              && s0.y >= tileBox.y
 | 
				
			||||||
 | 
								              && s0.y < tileBox.w;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bool s1Inside =  s1.x >= tileBox.x
 | 
				
			||||||
 | 
								              && s1.x < tileBox.z
 | 
				
			||||||
 | 
								              && s1.y >= tileBox.y
 | 
				
			||||||
 | 
								              && s1.y < tileBox.w;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(crossL || crossR || crossT || crossB || s0Inside || s1Inside)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									int tileOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									tileOpBuffer.elements[tileOpIndex].kind = MG_GL_OP_SEGMENT;
 | 
				
			||||||
 | 
									tileOpBuffer.elements[tileOpIndex].index = segIndex;
 | 
				
			||||||
 | 
									tileOpBuffer.elements[tileOpIndex].crossRight = false;
 | 
				
			||||||
 | 
									tileOpBuffer.elements[tileOpIndex].next = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									int tileIndex = y*pathArea.z + x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									tileOpBuffer.elements[tileOpIndex].next = atomicExchange(tileQueuesBuffer.elements[tileIndex].first, tileOpIndex);
 | 
				
			||||||
 | 
									if(tileOpBuffer.elements[tileOpIndex].next == -1)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										tileQueuesBuffer.elements[tileIndex].last = tileOpIndex;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									//NOTE: if the segment crosses the tile's bottom boundary, update the tile's winding offset
 | 
				
			||||||
 | 
									if(crossB)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										atomicAdd(tileQueuesBuffer.elements[tileIndex].windingOffset, seg.windingIncrement);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									//NOTE: if the segment crosses the right boundary, mark it.
 | 
				
			||||||
 | 
									if(crossR)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										tileOpBuffer.elements[tileOpIndex].crossRight = true;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void line_setup(vec2 p[4])
 | 
					void line_setup(vec2 p[4])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int segIndex = push_segment(p, MG_GL_LINE);
 | 
						int segIndex = push_segment(p, MG_GL_LINE);
 | 
				
			||||||
	segmentBuffer.elements[segIndex].hullVertex = p[0];
 | 
						segmentBuffer.elements[segIndex].hullVertex = p[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//TODO later bin to tiles
 | 
						bin_to_tiles(segIndex);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void main()
 | 
					void main()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue