multisampling in metal

This commit is contained in:
Greg Wells
2025-07-09 13:27:06 -04:00
parent 07d4e13f20
commit 89ea72b341
11 changed files with 59 additions and 20 deletions

View File

@@ -1,5 +1,7 @@
#include "metal_commands.h"
#include "shader_module/metal_shader_module.h"
#include "renderpass/metal_render_pass.h"
#include "utils/math/gryphn_math.h"
void metelBeginRenderPass(gnCommandBuffer buffer, gnRenderPassInfo passInfo) {
int currentColorAttachment = 0;
@@ -127,8 +129,9 @@ void metalBindUniform(gnCommandBufferHandle buffer, gnUniform uniform, uint32_t
];
} else if (uniform->uniform->bindings[i].type == GN_IMAGE_DESCRIPTOR) {
gnImageUniformInfo info = *(gnImageUniformInfo*)uniform->uniform->bindings[i].data;
[encoder setFragmentTexture:info.texture->texture->texture atIndex:
buffer->commandBuffer->boundGraphcisPipeline->graphicsPipeline->fragmentShaderMaps.sets[set].bindings[info.binding]];
uint32_t index = buffer->commandBuffer->boundGraphcisPipeline->graphicsPipeline->fragmentShaderMaps.sets[set].bindings[info.binding];
[encoder setFragmentTexture:info.texture->texture->texture atIndex:index];
[encoder setFragmentSamplerState:info.texture->texture->sampler atIndex:index];
}
}
}

View File

@@ -9,12 +9,6 @@ gnReturnCode createMetalOutputDevice(gnOutputDeviceHandle outputDevice, gnInstan
outputDevice->outputDevice = malloc(sizeof(gnPlatformOutputDevice));
outputDevice->outputDevice->device = deviceInfo.physicalDevice.physicalDevice->device.retain;
outputDevice->outputDevice->transferQueue = outputDevice->outputDevice->device.newCommandQueue;
// outputDevice->outputDevice->queueCount = deviceInfo.queueInfoCount;
// outputDevice->outputDevice->queues = malloc(sizeof(id<MTLCommandQueue>) * deviceInfo.queueInfoCount);
// for (int i = 0; i < deviceInfo.queueInfoCount; i++) {
// outputDevice->outputDevice->queues[i] = outputDevice->outputDevice->device.newCommandQueue;
// }
return GN_SUCCESS;
}

View File

@@ -14,7 +14,6 @@ struct gnPlatformOutputDevice_t {
id<MTLCommandBuffer> executingCommandBuffer;
id<MTLCommandQueue> transferQueue;
// id<MTLRenderPipelineState> framebuffer;
} gnPlatformOutputDevice;
gnPhysicalDevice* getMetalDevices(gnInstanceHandle instance, uint32_t* deviceCount);

View File

@@ -28,6 +28,13 @@ MTLStoreAction mtlGryphnStoreOperation(gnStoreOperation storeOperation) {
}
}
MTLStoreAction mtlGryphnStoreOperationResolve(gnStoreOperation storeOperation) {
switch (storeOperation) {
case GN_STORE_OPERATION_STORE: return MTLStoreActionStoreAndMultisampleResolve;
case GN_STORE_OPERATION_DONT_CARE: return MTLStoreActionDontCare;
}
}
gnReturnCode createMetalFramebuffer(gnFramebuffer framebuffer, gnOutputDevice device, gnFramebufferInfo info) {
framebuffer->framebuffer = malloc(sizeof(struct gnPlatformFramebuffer_t));
if (info.attachmentCount != info.renderPassDescriptor->info.attachmentCount) {
@@ -45,13 +52,20 @@ gnReturnCode createMetalFramebuffer(gnFramebuffer framebuffer, gnOutputDevice de
[framebuffer->framebuffer->subpasses[i] setRenderTargetWidth:info.size.x];
[framebuffer->framebuffer->subpasses[i] setRenderTargetHeight:info.size.y];
gnBool resolve = !(info.renderPassDescriptor->info.subpassInfos[i].resolveAttachments == NULL);
for (int c = 0; c < info.renderPassDescriptor->info.subpassInfos[i].colorAttachmentCount; c++) {
uint32_t attachmentIndex = info.renderPassDescriptor->info.subpassInfos[i].colorAttachments[i].index;
uint32_t attachmentIndex = info.renderPassDescriptor->info.subpassInfos[i].colorAttachments[c].index, resolveAttachemntIndex = 0;
MTLRenderPassColorAttachmentDescriptor* color = framebuffer->framebuffer->subpasses[i].colorAttachments[c];
color.texture = info.attachments[attachmentIndex]->texture->texture;
if (resolve) {
resolveAttachemntIndex = info.renderPassDescriptor->info.subpassInfos[i].resolveAttachments[c].index;
color.resolveTexture = info.attachments[resolveAttachemntIndex]->texture->texture;
color.storeAction = mtlGryphnStoreOperationResolve(info.renderPassDescriptor->info.attachmentInfos[attachmentIndex].storeOperation);
} else {
color.storeAction = mtlGryphnStoreOperation(info.renderPassDescriptor->info.attachmentInfos[attachmentIndex].storeOperation);
}
color.loadAction = mtlGryphnLoadOperation(info.renderPassDescriptor->info.attachmentInfos[attachmentIndex].loadOperation);
color.storeAction = mtlGryphnStoreOperation(info.renderPassDescriptor->info.attachmentInfos[attachmentIndex].storeOperation);
if (color.loadAction == MTLLoadActionClear)
color.clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0);
@@ -66,7 +80,7 @@ gnReturnCode createMetalFramebuffer(gnFramebuffer framebuffer, gnOutputDevice de
depthAttachment.clearDepth = 1.0f;
MTLRenderPassStencilAttachmentDescriptor* stencilAttachment = framebuffer->framebuffer->subpasses[attachmentIndex].stencilAttachment;
stencilAttachment.texture = info.attachments[i]->texture->texture;
stencilAttachment.texture = info.attachments[attachmentIndex]->texture->texture;
}
}

View File

@@ -3,6 +3,7 @@
#include "debugger/gryphn_debugger.h"
#include "shader_module/metal_shader_module.h"
#include "surface/metal_surface.h"
#include "texture/metal_texture.h"
#include "utils/math/gryphn_vec3.h"
@@ -44,6 +45,7 @@ MTLCompareFunction mtlGrypnCompareOperation(gnCompareOperation operation) {
gnReturnCode createMetalGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gnOutputDevice device, gnGraphicsPipelineInfo info) {
graphicsPipeline->graphicsPipeline = malloc(sizeof(struct gnPlatformGraphicsPipeline_t));
MTLRenderPipelineDescriptor* descriptor = [[MTLRenderPipelineDescriptor alloc] init];
descriptor.rasterSampleCount = mtlSampleCount(info.multisample.samples);
if (info.subpassIndex >= info.renderPassDescriptor->info.subpassCount) {
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){

View File

@@ -19,7 +19,6 @@ gnReturnCode metalPresent(gnOutputDeviceHandle device, gnPresentInfo info) {
}];
id<MTLBlitCommandEncoder> blit = [commandBuffer blitCommandEncoder];
[blit copyFromTexture:info.presentationQueues[i]->images[info.imageIndices[i]]->texture->texture
sourceSlice:0
sourceLevel:0

View File

@@ -18,6 +18,11 @@ void destroyMetalWindowSurface(gnWindowSurface windowSurface) {
free(windowSurface->windowSurface);
}
gnImageFormat mtlMetalFormatToGryphn(MTLPixelFormat format) {
if (format == MTLPixelFormatBGRA8Unorm_sRGB) return GN_FORMAT_BGRA8_SRGB;
return GN_FORMAT_NONE;
}
gnSurfaceDetails getMetalSurfaceDetails(
gnWindowSurface windowSurface, gnPhysicalDevice device
) {
@@ -35,6 +40,7 @@ MTLPixelFormat mtlGryphnFormatToMetalFormat(gnImageFormat format) {
switch (format) {
case GN_FORMAT_NONE: return MTLPixelFormatInvalid;
case GN_FORMAT_BGRA8_SRGB: return MTLPixelFormatBGRA8Unorm_sRGB;
case GN_FORMAT_BGRA8: return MTLPixelFormatBGRA8Unorm;
case GN_FORMAT_RGBA8_SRGB: return MTLPixelFormatRGBA8Unorm_sRGB;
case GN_FORMAT_D24S8_UINT: return MTLPixelFormatDepth24Unorm_Stencil8;
case GN_FORMAT_D32S8_UINT: return MTLPixelFormatDepth32Float_Stencil8;
@@ -43,6 +49,7 @@ MTLPixelFormat mtlGryphnFormatToMetalFormat(gnImageFormat format) {
CGColorSpaceRef mtlGryphnColorSpaceToMetalColorSpace(gnColorSpace colorSpace) {
switch (colorSpace) {
case GN_COLOR_SPACE_NONE: { return CGColorSpaceCreateWithName(kCGColorSpaceSRGB); } // very bad if here
case GN_COLOR_SPACE_SRGB_NONLINEAR: { return CGColorSpaceCreateWithName(kCGColorSpaceSRGB); }
}
}

View File

@@ -1,11 +1,16 @@
#pragma once
#include "textures/gryphn_texture.h"
#import <Metal/MTLTexture.h>
#import <Metal/MTLSampler.h>
typedef struct gnPlatformTexture_t {
id<MTLTexture> texture;
id<MTLSamplerState> sampler;
} gnPlatformTexture;
gnReturnCode createMetalTexture(gnTexture texture, gnDevice device, const gnTextureInfo info);
void metalTextureData(gnTextureHandle texture, void* pixelData);
void metalDestroyTexture(gnTexture texture);
NSUInteger mtlSampleCount(gnMultisampleCountFlags flags);

View File

@@ -16,18 +16,30 @@ NSUInteger mtlSampleCount(gnMultisampleCountFlags flags) {
gnReturnCode createMetalTexture(gnTexture texture, gnDevice device, const gnTextureInfo info) {
texture->texture = malloc(sizeof(struct gnPlatformTexture_t));
MTLTextureDescriptor *textureDescriptor = [[MTLTextureDescriptor alloc] init];
textureDescriptor.pixelFormat = mtlGryphnFormatToMetalFormat(info.format);
textureDescriptor.width = info.extent.width;
textureDescriptor.height = info.extent.height;
textureDescriptor.depth = info.extent.depth;
textureDescriptor.sampleCount = mtlSampleCount(info.samples);
if (textureDescriptor.sampleCount >= 2)
textureDescriptor.pixelFormat = mtlGryphnFormatToMetalFormat(info.format);
textureDescriptor.usage = MTLTextureUsageRenderTarget;
if (textureDescriptor.sampleCount >= 2) {
textureDescriptor.textureType = MTLTextureType2DMultisample;
else
}
else {
textureDescriptor.textureType = MTLTextureType2D;
}
MTLSamplerDescriptor *samplerDesc = [[MTLSamplerDescriptor alloc] init];
samplerDesc.minFilter = MTLSamplerMinMagFilterLinear;
samplerDesc.magFilter = MTLSamplerMinMagFilterLinear;
samplerDesc.mipFilter = MTLSamplerMipFilterNotMipmapped;
samplerDesc.sAddressMode = MTLSamplerAddressModeClampToEdge;
samplerDesc.tAddressMode = MTLSamplerAddressModeClampToEdge;
samplerDesc.normalizedCoordinates = YES;
texture->texture->sampler = [device->outputDevice->device newSamplerStateWithDescriptor:samplerDesc];
texture->texture->texture = [device->outputDevice->device newTextureWithDescriptor:textureDescriptor];
[textureDescriptor release];
[samplerDesc release];
return GN_SUCCESS;
}

View File

@@ -75,12 +75,13 @@ gnSurfaceFormat* vkGetSurfaceFormats(
for (int i = 0; i < *formatCount; i++) {
switch (vkFormats[i].format) {
case VK_FORMAT_B8G8R8A8_SRGB: { formats[i].format = GN_FORMAT_BGRA8_SRGB; break; }
default: break;
case VK_FORMAT_B8G8R8A8_UNORM: { formats[i].format = GN_FORMAT_BGRA8; break; }
default: { formats[i].format = GN_FORMAT_NONE; break; }
}
switch (vkFormats[i].colorSpace) {
case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR: { formats[i].colorSpace = GN_COLOR_SPACE_SRGB_NONLINEAR; break; }
default: break;
default: { formats[i].colorSpace = GN_COLOR_SPACE_NONE; break; };
}
}
}
@@ -112,6 +113,7 @@ VkFormat vkGryphnFormatToVulkanFormat(gnImageFormat format) {
switch (format) {
case GN_FORMAT_NONE: return VK_FORMAT_UNDEFINED;
case GN_FORMAT_BGRA8_SRGB: return VK_FORMAT_B8G8R8A8_SRGB;
case GN_FORMAT_BGRA8: return VK_FORMAT_B8G8R8A8_UNORM;
case GN_FORMAT_RGBA8_SRGB: return VK_FORMAT_R8G8B8A8_SRGB;
case GN_FORMAT_D32S8_UINT: return VK_FORMAT_D32_SFLOAT_S8_UINT;
case GN_FORMAT_D24S8_UINT: return VK_FORMAT_D24_UNORM_S8_UINT;
@@ -119,6 +121,7 @@ VkFormat vkGryphnFormatToVulkanFormat(gnImageFormat format) {
}
VkColorSpaceKHR vkGryphnColorSpaceToVulkanColorSpace(gnColorSpace colorSpace) {
switch (colorSpace) {
case GN_COLOR_SPACE_NONE: { return VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; }; // this is a problem if we are trying to convert it
case GN_COLOR_SPACE_SRGB_NONLINEAR: { return VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; }
}
}