[canvas, mtl backend] Compute each layer with pre-multiplied alpha, starting from transparent color. Composite them to surface with premultiplied alpha too.

This commit is contained in:
Martin Fouilleul 2023-02-27 14:24:59 +01:00
parent 9ed630fc55
commit d195fb1f61
3 changed files with 5 additions and 20 deletions

View File

@ -467,11 +467,6 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
//----------------------------------------------------------- //-----------------------------------------------------------
backend->tileCounters = [metalSurface->device newBufferWithLength: RENDERER_MAX_TILES*sizeof(uint) backend->tileCounters = [metalSurface->device newBufferWithLength: RENDERER_MAX_TILES*sizeof(uint)
options: MTLResourceStorageModePrivate]; options: MTLResourceStorageModePrivate];
id<MTLCommandBuffer> commandBuffer = [metalSurface->commandQueue commandBuffer];
id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];
[blitEncoder fillBuffer: backend->tileCounters range: NSMakeRange(0, RENDERER_MAX_TILES*sizeof(uint)) value: 0];
[blitEncoder endEncoding];
//----------------------------------------------------------- //-----------------------------------------------------------
//NOTE(martin): load the library //NOTE(martin): load the library
//----------------------------------------------------------- //-----------------------------------------------------------
@ -539,12 +534,11 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
pipelineStateDescriptor.colorAttachments[0].pixelFormat = metalSurface->mtlLayer.pixelFormat; pipelineStateDescriptor.colorAttachments[0].pixelFormat = metalSurface->mtlLayer.pixelFormat;
pipelineStateDescriptor.colorAttachments[0].blendingEnabled = YES; pipelineStateDescriptor.colorAttachments[0].blendingEnabled = YES;
pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;
pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorZero; pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne; pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
// create render pipeline // create render pipeline
backend->renderPipeline = [metalSurface->device newRenderPipelineStateWithDescriptor: pipelineStateDescriptor error:&err]; backend->renderPipeline = [metalSurface->device newRenderPipelineStateWithDescriptor: pipelineStateDescriptor error:&err];

View File

@ -266,6 +266,7 @@ kernel void RenderKernel(texture2d<float, access::write> outTexture [[texture(0)
int shapeIndex = v0->shapeIndex; int shapeIndex = v0->shapeIndex;
float4 color = shapeBuffer[shapeIndex].color; float4 color = shapeBuffer[shapeIndex].color;
color.rgb *= color.a;
const device float* uvTransform2x3 = shapeBuffer[shapeIndex].uvTransform; const device float* uvTransform2x3 = shapeBuffer[shapeIndex].uvTransform;
matrix_float3x3 uvTransform = {{uvTransform2x3[0], uvTransform2x3[3], 0}, matrix_float3x3 uvTransform = {{uvTransform2x3[0], uvTransform2x3[3], 0},
@ -298,6 +299,7 @@ kernel void RenderKernel(texture2d<float, access::write> outTexture [[texture(0)
{ {
constexpr sampler smp(mip_filter::nearest, mag_filter::linear, min_filter::linear); constexpr sampler smp(mip_filter::nearest, mag_filter::linear, min_filter::linear);
texColor = texAtlas.sample(smp, uv); texColor = texAtlas.sample(smp, uv);
texColor.rgb *= texColor.a;
} }
//TODO(martin): this is a quick and dirty fix for solid polygons where we use //TODO(martin): this is a quick and dirty fix for solid polygons where we use
// cubic = (1, 1, 1, 1) on all vertices, which can cause small errors to // cubic = (1, 1, 1, 1) on all vertices, which can cause small errors to

View File

@ -99,17 +99,6 @@ void mg_mtl_surface_prepare(mg_surface_data* interface)
{ {
mg_mtl_surface* surface = (mg_mtl_surface*)interface; mg_mtl_surface* surface = (mg_mtl_surface*)interface;
mg_mtl_surface_acquire_drawable_and_command_buffer(surface); mg_mtl_surface_acquire_drawable_and_command_buffer(surface);
@autoreleasepool
{
MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
renderPassDescriptor.colorAttachments[0].texture = surface->drawable.texture;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0,0.0,0.0,0.0);
id<MTLRenderCommandEncoder> renderEncoder = [surface->commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
[renderEncoder endEncoding];
}
} }
void mg_mtl_surface_present(mg_surface_data* interface) void mg_mtl_surface_present(mg_surface_data* interface)