[mtl canvas, wip] cubic bézier implicitization

This commit is contained in:
Martin Fouilleul 2023-04-01 19:46:35 +02:00
parent 767841f9c6
commit 9322db8201
3 changed files with 819 additions and 175 deletions

View File

@ -19,7 +19,7 @@
int main() int main()
{ {
LogLevel(LOG_LEVEL_WARNING); LogLevel(LOG_LEVEL_MESSAGE);
mp_init(); mp_init();
mp_clock_init(); //TODO put that in mp_init()? mp_clock_init(); //TODO put that in mp_init()?
@ -89,12 +89,18 @@ int main()
mg_close_path(); mg_close_path();
mg_set_color_rgba(0, 1, 0, 1); mg_set_color_rgba(0, 1, 0, 1);
mg_fill(); mg_fill();
*/
mg_move_to(400, 400); mg_move_to(400, 400);
mg_quadratic_to(600, 601, 800, 400); mg_quadratic_to(600, 601, 800, 400);
mg_close_path(); mg_close_path();
mg_set_color_rgba(0, 0, 1, 1); mg_set_color_rgba(0, 0, 1, 1);
mg_fill(); mg_fill();
*/
mg_move_to(2*400, 2*400);
mg_cubic_to(2*400, 2*200, 2*600, 2*500, 2*600, 2*400);
mg_close_path();
mg_set_color_rgba(0, 0, 1, 1);
mg_fill();
printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n", printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n",
frameTime, frameTime,

View File

@ -40,6 +40,8 @@ typedef struct mg_mtl_canvas_backend
id<MTLBuffer> pathBuffer[MG_MTL_INPUT_BUFFERS_COUNT]; id<MTLBuffer> pathBuffer[MG_MTL_INPUT_BUFFERS_COUNT];
id<MTLBuffer> elementBuffer[MG_MTL_INPUT_BUFFERS_COUNT]; id<MTLBuffer> elementBuffer[MG_MTL_INPUT_BUFFERS_COUNT];
id<MTLBuffer> logBuffer[MG_MTL_INPUT_BUFFERS_COUNT];
id<MTLBuffer> logOffsetBuffer[MG_MTL_INPUT_BUFFERS_COUNT];
id<MTLBuffer> segmentCountBuffer; id<MTLBuffer> segmentCountBuffer;
id<MTLBuffer> segmentBuffer; id<MTLBuffer> segmentBuffer;
@ -61,6 +63,26 @@ static void mg_update_path_extents(vec4* extents, vec2 p)
extents->w = maximum(extents->w, p.y); extents->w = maximum(extents->w, p.y);
} }
void mg_mtl_print_log(int bufferIndex, id<MTLBuffer> logBuffer, id<MTLBuffer> logOffsetBuffer)
{
char* log = [logBuffer contents];
int size = *(int*)[logOffsetBuffer contents];
if(size)
{
LOG_MESSAGE("Log from buffer %i:\n", bufferIndex);
int index = 0;
while(index < size)
{
int len = strlen(log+index);
printf("%s", log+index);
index += (len+1);
}
}
}
void mg_mtl_canvas_render(mg_canvas_backend* interface, void mg_mtl_canvas_render(mg_canvas_backend* interface,
mg_color clearColor, mg_color clearColor,
u32 primitiveCount, u32 primitiveCount,
@ -106,30 +128,11 @@ void mg_mtl_canvas_render(mg_canvas_backend* interface,
//NOTE: transform and push path elt + update primitive bounding box //NOTE: transform and push path elt + update primitive bounding box
vec2 p0 = mg_mat2x3_mul(primitive->attributes.transform, currentPos); vec2 p0 = mg_mat2x3_mul(primitive->attributes.transform, currentPos);
vec2 p3 = mg_mat2x3_mul(primitive->attributes.transform, elt->p[0]); vec2 p1 = mg_mat2x3_mul(primitive->attributes.transform, elt->p[0]);
currentPos = elt->p[0]; currentPos = elt->p[0];
mg_update_path_extents(&pathExtents, p0);
mg_update_path_extents(&pathExtents, p3);
mg_mtl_path_elt* mtlElt = &elementBufferData[mtlEltCount];
mtlEltCount++;
mtlElt->pathIndex = primitiveIndex;
mtlElt->kind = (mg_mtl_seg_kind)elt->type;
mtlElt->p[0] = (vector_float2){p0.x, p0.y};
mtlElt->p[3] = (vector_float2){p3.x, p3.y};
}
else if(elt->type == MG_PATH_QUADRATIC)
{
vec2 p0 = mg_mat2x3_mul(primitive->attributes.transform, currentPos);
vec2 p1 = mg_mat2x3_mul(primitive->attributes.transform, elt->p[0]);
vec2 p3 = mg_mat2x3_mul(primitive->attributes.transform, elt->p[1]);
currentPos = elt->p[1];
mg_update_path_extents(&pathExtents, p0); mg_update_path_extents(&pathExtents, p0);
mg_update_path_extents(&pathExtents, p1); mg_update_path_extents(&pathExtents, p1);
mg_update_path_extents(&pathExtents, p3);
mg_mtl_path_elt* mtlElt = &elementBufferData[mtlEltCount]; mg_mtl_path_elt* mtlElt = &elementBufferData[mtlEltCount];
mtlEltCount++; mtlEltCount++;
@ -138,7 +141,26 @@ void mg_mtl_canvas_render(mg_canvas_backend* interface,
mtlElt->kind = (mg_mtl_seg_kind)elt->type; mtlElt->kind = (mg_mtl_seg_kind)elt->type;
mtlElt->p[0] = (vector_float2){p0.x, p0.y}; mtlElt->p[0] = (vector_float2){p0.x, p0.y};
mtlElt->p[1] = (vector_float2){p1.x, p1.y}; mtlElt->p[1] = (vector_float2){p1.x, p1.y};
mtlElt->p[3] = (vector_float2){p3.x, p3.y}; }
else if(elt->type == MG_PATH_QUADRATIC)
{
vec2 p0 = mg_mat2x3_mul(primitive->attributes.transform, currentPos);
vec2 p1 = mg_mat2x3_mul(primitive->attributes.transform, elt->p[0]);
vec2 p2 = mg_mat2x3_mul(primitive->attributes.transform, elt->p[1]);
currentPos = elt->p[1];
mg_update_path_extents(&pathExtents, p0);
mg_update_path_extents(&pathExtents, p1);
mg_update_path_extents(&pathExtents, p2);
mg_mtl_path_elt* mtlElt = &elementBufferData[mtlEltCount];
mtlEltCount++;
mtlElt->pathIndex = primitiveIndex;
mtlElt->kind = (mg_mtl_seg_kind)elt->type;
mtlElt->p[0] = (vector_float2){p0.x, p0.y};
mtlElt->p[1] = (vector_float2){p1.x, p1.y};
mtlElt->p[2] = (vector_float2){p2.x, p2.y};
} }
else if(elt->type == MG_PATH_CUBIC) else if(elt->type == MG_PATH_CUBIC)
{ {
@ -160,7 +182,7 @@ void mg_mtl_canvas_render(mg_canvas_backend* interface,
mtlElt->kind = (mg_mtl_seg_kind)elt->type; mtlElt->kind = (mg_mtl_seg_kind)elt->type;
mtlElt->p[0] = (vector_float2){p0.x, p0.y}; mtlElt->p[0] = (vector_float2){p0.x, p0.y};
mtlElt->p[1] = (vector_float2){p1.x, p1.y}; mtlElt->p[1] = (vector_float2){p1.x, p1.y};
mtlElt->p[1] = (vector_float2){p2.x, p2.y}; mtlElt->p[2] = (vector_float2){p2.x, p2.y};
mtlElt->p[3] = (vector_float2){p3.x, p3.y}; mtlElt->p[3] = (vector_float2){p3.x, p3.y};
} }
} }
@ -209,6 +231,7 @@ void mg_mtl_canvas_render(mg_canvas_backend* interface,
[blitEncoder fillBuffer: backend->segmentCountBuffer range: NSMakeRange(0, sizeof(int)) value: 0]; [blitEncoder fillBuffer: backend->segmentCountBuffer range: NSMakeRange(0, sizeof(int)) value: 0];
[blitEncoder fillBuffer: backend->tileQueueCountBuffer range: NSMakeRange(0, sizeof(int)) value: 0]; [blitEncoder fillBuffer: backend->tileQueueCountBuffer range: NSMakeRange(0, sizeof(int)) value: 0];
[blitEncoder fillBuffer: backend->tileOpCountBuffer range: NSMakeRange(0, sizeof(int)) value: 0]; [blitEncoder fillBuffer: backend->tileOpCountBuffer range: NSMakeRange(0, sizeof(int)) value: 0];
[blitEncoder fillBuffer: backend->logOffsetBuffer[backend->bufferIndex] range: NSMakeRange(0, sizeof(int)) value: 0];
[blitEncoder endEncoding]; [blitEncoder endEncoding];
//NOTE: path setup pass //NOTE: path setup pass
@ -243,6 +266,8 @@ void mg_mtl_canvas_render(mg_canvas_backend* interface,
[segmentEncoder setBuffer:backend->tileOpBuffer offset:0 atIndex:6]; [segmentEncoder setBuffer:backend->tileOpBuffer offset:0 atIndex:6];
[segmentEncoder setBuffer:backend->tileOpCountBuffer offset:0 atIndex:7]; [segmentEncoder setBuffer:backend->tileOpCountBuffer offset:0 atIndex:7];
[segmentEncoder setBytes:&tileSize length:sizeof(int) atIndex:8]; [segmentEncoder setBytes:&tileSize length:sizeof(int) atIndex:8];
[segmentEncoder setBuffer:backend->logBuffer[backend->bufferIndex] offset:0 atIndex:9];
[segmentEncoder setBuffer:backend->logOffsetBuffer[backend->bufferIndex] offset:0 atIndex:10];
MTLSize segmentGridSize = MTLSizeMake(mtlEltCount, 1, 1); MTLSize segmentGridSize = MTLSizeMake(mtlEltCount, 1, 1);
MTLSize segmentGroupSize = MTLSizeMake([backend->segmentPipeline maxTotalThreadsPerThreadgroup], 1, 1); MTLSize segmentGroupSize = MTLSizeMake([backend->segmentPipeline maxTotalThreadsPerThreadgroup], 1, 1);
@ -329,6 +354,7 @@ void mg_mtl_canvas_render(mg_canvas_backend* interface,
//NOTE: finalize //NOTE: finalize
[surface->commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> commandBuffer) [surface->commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> commandBuffer)
{ {
mg_mtl_print_log(backend->bufferIndex, backend->logBuffer[backend->bufferIndex], backend->logOffsetBuffer[backend->bufferIndex]);
dispatch_semaphore_signal(backend->bufferSemaphore); dispatch_semaphore_signal(backend->bufferSemaphore);
}]; }];
} }
@ -351,6 +377,8 @@ void mg_mtl_canvas_destroy(mg_canvas_backend* interface)
{ {
[backend->pathBuffer[i] release]; [backend->pathBuffer[i] release];
[backend->elementBuffer[i] release]; [backend->elementBuffer[i] release];
[backend->logBuffer[i] release];
[backend->logOffsetBuffer[i] release];
} }
[backend->segmentCountBuffer release]; [backend->segmentCountBuffer release];
[backend->segmentBuffer release]; [backend->segmentBuffer release];
@ -502,6 +530,17 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
int nTilesY = (int)(frame.h * scale + tileSize - 1)/tileSize; int nTilesY = (int)(frame.h * scale + tileSize - 1)/tileSize;
backend->screenTilesBuffer = [metalSurface->device newBufferWithLength: nTilesX*nTilesY*sizeof(int) backend->screenTilesBuffer = [metalSurface->device newBufferWithLength: nTilesX*nTilesY*sizeof(int)
options: bufferOptions]; options: bufferOptions];
bufferOptions = MTLResourceStorageModeShared;
for(int i=0; i<MG_MTL_INPUT_BUFFERS_COUNT; i++)
{
backend->logBuffer[i] = [metalSurface->device newBufferWithLength: 4<<20
options: bufferOptions];
backend->logOffsetBuffer[i] = [metalSurface->device newBufferWithLength: sizeof(int)
options: bufferOptions];
}
} }
} }
return((mg_canvas_backend*)backend); return((mg_canvas_backend*)backend);

File diff suppressed because it is too large Load Diff