diff --git a/rendering_api/metal/src/core/commands/command_buffer/metal_command_buffer.h b/rendering_api/metal/src/core/commands/command_buffer/metal_command_buffer.h new file mode 100644 index 0000000..96094dd --- /dev/null +++ b/rendering_api/metal/src/core/commands/command_buffer/metal_command_buffer.h @@ -0,0 +1,11 @@ +#pragma once +#include "core/command/command_buffer/gryphn_command_buffer.h" +#include "core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.h" +#import +#import + +typedef struct gnPlatformCommandBuffer_t { + id commandBuffer; + id encoder; + struct gnGraphicsPipeline_t* boundGraphcisPipeline; +} gnPlatformCommandBuffer; diff --git a/rendering_api/metal/src/core/commands/command_buffer/metal_command_buffer.m b/rendering_api/metal/src/core/commands/command_buffer/metal_command_buffer.m new file mode 100644 index 0000000..9aa50d0 --- /dev/null +++ b/rendering_api/metal/src/core/commands/command_buffer/metal_command_buffer.m @@ -0,0 +1,21 @@ +#include "metal_command_buffer.h" +#include "core/commands/command_pool/metal_command_pool.h" +#import + +gnReturnCode gnCommandPoolAllocateCommandBuffersFn(struct gnCommandBuffer_t* commandBuffers, uint32_t count, struct gnCommandPool_t* pool) { + for (int i = 0; i < count; i++) { + commandBuffers[i].commandBuffer = malloc(sizeof(gnPlatformCommandBuffer)); + commandBuffers[i].commandBuffer->commandBuffer = [pool->commandPool->commandQueue commandBuffer]; + } + + return GN_SUCCESS; +} + +gnReturnCode gnBeginCommandBuffer(struct gnCommandBuffer_t* commandBuffer) { + commandBuffer->commandBuffer->boundGraphcisPipeline = NULL; + return GN_SUCCESS; +} + +gnReturnCode gnEndCommandBuffer(struct gnCommandBuffer_t* commandBuffer) { + return GN_SUCCESS; +} diff --git a/rendering_api/metal/src/core/commands/command_pool/metal_command_pool.m b/rendering_api/metal/src/core/commands/command_pool/metal_command_pool.m index f1e4ac6..c95ec74 100644 --- a/rendering_api/metal/src/core/commands/command_pool/metal_command_pool.m +++ b/rendering_api/metal/src/core/commands/command_pool/metal_command_pool.m @@ -4,6 +4,7 @@ gnReturnCode gnCreateCommandPoolFn(struct gnCommandPool_t* commandPool, struct gnOutputDevice_t* device, struct gnCommandPoolInfo_t info) { commandPool->commandPool = malloc(sizeof(struct gnPlatformCommandPool_t)); commandPool->commandPool->commandQueue = [device->outputDevice->device newCommandQueue]; + return GN_SUCCESS; } diff --git a/rendering_api/metal/src/core/commands/commands/metal_commands.m b/rendering_api/metal/src/core/commands/commands/metal_commands.m new file mode 100644 index 0000000..f7b8ddd --- /dev/null +++ b/rendering_api/metal/src/core/commands/commands/metal_commands.m @@ -0,0 +1,85 @@ +#include "core/command/commands/gryphn_command.h" +#include "core/framebuffers/metal_framebuffer.h" +#include "core/commands/command_buffer/metal_command_buffer.h" +#include "core/pipelines/graphics_pipeline/metal_graphics_pipeline.h" +#import + +void gnCommandBeginRenderPassFn(struct gnCommandBuffer_t* buffer, struct gnRenderPassInfo_t passInfo) { + int currentColorAttachment = 0; + for (int i = 0; i < passInfo.clearValueCount; i++) { + gnBool wasDepthStencil = gnFalse; + if (isDepthFormat(passInfo.renderPassDescriptor->info.attachmentInfos[i].format)) { + wasDepthStencil = gnTrue; + } + if (isStencilFormat(passInfo.renderPassDescriptor->info.attachmentInfos[i].format)) { + wasDepthStencil = gnTrue; + } + + if(!wasDepthStencil) { + MTLRenderPassColorAttachmentDescriptor* color = passInfo.framebuffer->framebuffer->framebuffer.colorAttachments[i]; + color.clearColor = MTLClearColorMake( + passInfo.clearValues[i].red, + passInfo.clearValues[i].green, + passInfo.clearValues[i].blue, + passInfo.clearValues[i].alpha + ); + } + } + buffer->commandBuffer->encoder = [buffer->commandBuffer->commandBuffer renderCommandEncoderWithDescriptor:passInfo.framebuffer->framebuffer->framebuffer]; + MTLViewport vp = {(double)passInfo.offset.x, (double)passInfo.offset.y, (double)passInfo.size.x, (double)passInfo.size.y, 0.0f, 1.0f}; + id encoder = (id)buffer->commandBuffer->encoder; + [encoder setViewport:vp]; +} +void gnCommandEndRenderPassFn(struct gnCommandBuffer_t* buffer) { + [buffer->commandBuffer->encoder endEncoding]; +} +void gnCommandBindGraphicsPipelineFn(struct gnCommandBuffer_t* buffer, struct gnGraphicsPipeline_t* graphicsPipeline) { + id encoder = (id)buffer->commandBuffer->encoder; + [encoder setRenderPipelineState:graphicsPipeline->graphicsPipeline->graphicsPipeline]; + + if (graphicsPipeline->info.cullMode.face == GN_CULL_FACE_BACK) + [encoder setCullMode:MTLCullModeBack]; + else if (graphicsPipeline->info.cullMode.face == GN_CULL_FACE_FRONT) + [encoder setCullMode:MTLCullModeFront]; + else if (graphicsPipeline->info.cullMode.face == GN_CULL_FACE_NONE) + [encoder setCullMode:MTLCullModeNone]; + + if (graphicsPipeline->info.cullMode.direction == GN_DIRECTION_CLOCK_WISE) + [encoder setFrontFacingWinding:MTLWindingCounterClockwise]; + if (graphicsPipeline->info.cullMode.direction == GN_DIRECTION_COUNTER_CLOCK_WISE) + [encoder setFrontFacingWinding:MTLWindingClockwise]; + + if (graphicsPipeline->info.fillMode == GN_FILL_MODE_POINT) + [encoder setTriangleFillMode:MTLTriangleFillModeFill]; + if (graphicsPipeline->info.fillMode == GN_FILL_MODE_LINE) + [encoder setTriangleFillMode:MTLTriangleFillModeLines]; + if (graphicsPipeline->info.fillMode == GN_FILL_MODE_FILL) + [encoder setTriangleFillMode:MTLTriangleFillModeFill]; + + buffer->commandBuffer->boundGraphcisPipeline = graphicsPipeline; +} +void gnCommandSetViewportFn(struct gnCommandBuffer_t* buffer, struct gnViewport_t viewport) { + MTLViewport vp = {(double)viewport.position.x, (double)viewport.position.y, (double)viewport.size.x, (double)viewport.size.y, viewport.minDepth, viewport.maxDepth}; + id encoder = (id)buffer->commandBuffer->encoder; + [encoder setViewport:vp]; +} +void gnCommandSetScissorFn(struct gnCommandBuffer_t* buffer, struct gnScissor_t scissor) { + MTLScissorRect scissorRect = { scissor.position.x, scissor.position.y, scissor.size.x, scissor.size.y }; + id encoder = (id)buffer->commandBuffer->encoder; + [encoder setScissorRect:scissorRect]; +} +void gnCommandDrawFn(struct gnCommandBuffer_t* buffer, int vertexCount, int firstVertex, int instanceCount, int firstInstance) { + if (buffer->commandBuffer->boundGraphcisPipeline != NULL) { + id encoder = (id)buffer->commandBuffer->encoder; + if (buffer->commandBuffer->boundGraphcisPipeline->info.primitiveType == GN_PRIMITIVE_POINTS) + [encoder drawPrimitives:MTLPrimitiveTypePoint vertexStart:firstVertex vertexCount:vertexCount instanceCount:instanceCount baseInstance:firstInstance]; + else if (buffer->commandBuffer->boundGraphcisPipeline->info.primitiveType == GN_PRIMITIVE_LINES) + [encoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:firstVertex vertexCount:vertexCount instanceCount:instanceCount baseInstance:firstInstance]; + else if (buffer->commandBuffer->boundGraphcisPipeline->info.primitiveType == GN_PRIMITIVE_LINE_STRIP) + [encoder drawPrimitives:MTLPrimitiveTypeLineStrip vertexStart:firstVertex vertexCount:vertexCount instanceCount:instanceCount baseInstance:firstInstance]; + else if (buffer->commandBuffer->boundGraphcisPipeline->info.primitiveType == GN_PRIMITIVE_TRIANGLES) + [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:firstVertex vertexCount:vertexCount instanceCount:instanceCount baseInstance:firstInstance]; + else if (buffer->commandBuffer->boundGraphcisPipeline->info.primitiveType == GN_PRIMITIVE_TRIANGLE_STRIP) + [encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:firstVertex vertexCount:vertexCount instanceCount:instanceCount baseInstance:firstInstance]; + } +} diff --git a/rendering_api/metal/src/core/framebuffers/metal_framebuffer.h b/rendering_api/metal/src/core/framebuffers/metal_framebuffer.h index 519a6ad..386ff50 100644 --- a/rendering_api/metal/src/core/framebuffers/metal_framebuffer.h +++ b/rendering_api/metal/src/core/framebuffers/metal_framebuffer.h @@ -6,3 +6,6 @@ typedef struct gnPlatformFramebuffer_t { MTLRenderPassDescriptor* framebuffer; } gnPlatformFramebuffer; + +gnBool isDepthFormat(gnImageFormat format); +gnBool isStencilFormat(gnImageFormat format); diff --git a/rendering_api/metal/src/core/framebuffers/metal_framebuffer.m b/rendering_api/metal/src/core/framebuffers/metal_framebuffer.m index ad45fb1..6030ed7 100644 --- a/rendering_api/metal/src/core/framebuffers/metal_framebuffer.m +++ b/rendering_api/metal/src/core/framebuffers/metal_framebuffer.m @@ -38,6 +38,7 @@ gnReturnCode gnCreateFramebufferFn(struct gnFramebuffer_t* framebuffer, struct g [framebuffer->framebuffer->framebuffer setRenderTargetWidth:info.size.x]; [framebuffer->framebuffer->framebuffer setRenderTargetHeight:info.size.y]; + int colorAttachment = 0; for (int i = 0; i < info.renderPassDescriptor->info.attachmentCount; i++) { gnBool wasDepthStencil = gnFalse; if (isDepthFormat(info.renderPassDescriptor->info.attachmentInfos[i].format)) { @@ -54,7 +55,7 @@ gnReturnCode gnCreateFramebufferFn(struct gnFramebuffer_t* framebuffer, struct g } if(!wasDepthStencil) { - MTLRenderPassColorAttachmentDescriptor* color = framebuffer->framebuffer->framebuffer.colorAttachments[i]; + MTLRenderPassColorAttachmentDescriptor* color = framebuffer->framebuffer->framebuffer.colorAttachments[colorAttachment]; color.texture = info.attachments[i].texture->texture; color.loadAction = mtlGryphnLoadOperation(info.renderPassDescriptor->info.attachmentInfos[i].loadOperation); @@ -62,6 +63,8 @@ gnReturnCode gnCreateFramebufferFn(struct gnFramebuffer_t* framebuffer, struct g if (color.loadAction == MTLLoadActionClear) color.clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0); + + colorAttachment++; } } diff --git a/src/core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.c b/src/core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.c index 34377be..f140fc2 100644 --- a/src/core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.c +++ b/src/core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.c @@ -3,6 +3,7 @@ gnReturnCode gnCreateGraphicsPipeline(struct gnGraphicsPipeline_t* graphicsPipeline, struct gnOutputDevice_t* device, struct gnGraphicsPipelineInfo_t info) { graphicsPipeline->device = device; + graphicsPipeline->info = info; return graphicsPipeline->device->deviceFunctions->_gnCreateGraphicsPipeline(graphicsPipeline, device, info); } diff --git a/src/core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.h b/src/core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.h index 5086f8f..0377db2 100644 --- a/src/core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.h +++ b/src/core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.h @@ -94,6 +94,7 @@ struct gnPlatformGraphicsPipeline_t; typedef struct gnGraphicsPipeline_t { struct gnPlatformGraphicsPipeline_t* graphicsPipeline; struct gnOutputDevice_t* device; + struct gnGraphicsPipelineInfo_t info; } gnGraphicsPipeline; gnReturnCode gnCreateGraphicsPipeline(struct gnGraphicsPipeline_t* graphicsPipeline, struct gnOutputDevice_t* device, struct gnGraphicsPipelineInfo_t info);