From 7f83894d398f1e6d1b7e009a79ab96e603ef471e Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Thu, 27 Feb 2025 22:01:28 +0900 Subject: [PATCH] no more metal cpp, we doing obj c now --- CMakeLists.txt | 4 +- src/main.cpp | 4 +- src/metal/CMakeLists.txt | 3 +- src/metal/MetalRenderer.h | 31 ++----- src/metal/MetalRenderer.mm | 169 +++++++++++++++++----------------- src/metal/MetalScene.h | 33 +++---- src/metal/MetalScene.mm | 180 ++++++++++++++++++++++++------------- src/metal/PrivateImpl.mm | 6 -- 8 files changed, 235 insertions(+), 195 deletions(-) delete mode 100644 src/metal/PrivateImpl.mm diff --git a/CMakeLists.txt b/CMakeLists.txt index 1336c17..7836904 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,9 +36,7 @@ target_include_directories(RayTracer PUBLIC ${VCPKG_INSTALLED_DIR}/x64-windows/i target_link_libraries(RayTracer PUBLIC ${VCPKG_INSTALLED_DIR}/x64-windows/lib/slang.lib) elseif(APPLE) target_include_directories(RayTracer PUBLIC ${VCPKG_INSTALLED_DIR}/arm64-osx/include) -target_include_directories(RayTracer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/external/metal-cpp) -SET(CMAKE_OSX_DEPLOYMENT_TARGET 15.3.1) - +SET(CMAKE_OSX_DEPLOYMENT_TARGET 15.0) target_link_libraries(RayTracer PUBLIC "-framework Metal" "-framework MetalKit" diff --git a/src/main.cpp b/src/main.cpp index b5f0b24..d25162b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,11 @@ -#include "metal/MetalRenderer.h" #include "scene/Renderer.h" #include "util/ModelLoader.h" +#include "metal/MetalRenderer.h" #include int main() { - std::unique_ptr renderer = std::make_unique(); + std::unique_ptr renderer = std::make_unique(); renderer->addDirectionalLight(DirectionalLight{ .direction = glm::normalize(glm::vec3(-0.4f, -0.3f, -0.2f)), diff --git a/src/metal/CMakeLists.txt b/src/metal/CMakeLists.txt index 776e3b9..e89c2a0 100644 --- a/src/metal/CMakeLists.txt +++ b/src/metal/CMakeLists.txt @@ -4,5 +4,4 @@ target_sources(RayTracer MetalRenderer.mm MetalScene.h MetalScene.mm - Compute.metal - PrivateImpl.mm) \ No newline at end of file + Compute.metal) \ No newline at end of file diff --git a/src/metal/MetalRenderer.h b/src/metal/MetalRenderer.h index 17e310e..2d1746e 100644 --- a/src/metal/MetalRenderer.h +++ b/src/metal/MetalRenderer.h @@ -1,5 +1,4 @@ #pragma once -#include "metal/MetalScene.h" #include "scene/Renderer.h" #include "util/Camera.h" @@ -8,10 +7,6 @@ #define GLFW_EXPOSE_NATIVE_COCOA #include -#include -#include -#include - struct GPUCamera { glm::vec3 cameraPosition; @@ -40,11 +35,11 @@ class MetalRenderer : public Renderer public: MetalRenderer(); virtual ~MetalRenderer(); - virtual void addPointLight(PointLight point) override { scene->addPointLight(point); } - virtual void addDirectionalLight(DirectionalLight dir) override { scene->addDirectionalLight(dir); } - virtual void addModel(PModel model, glm::mat4 transform) override { scene->addModel(std::move(model), transform); } - virtual void addModels(std::vector models, glm::mat4 transform) override { scene->addModels(std::move(models), transform); } - virtual void generate() override { scene->generate(); } + virtual void addPointLight(PointLight point) override; + virtual void addDirectionalLight(DirectionalLight dir) override; + virtual void addModel(PModel model, glm::mat4 transform) override; + virtual void addModels(std::vector models, glm::mat4 transform) override; + virtual void generate() override; virtual void render(Camera camera, RenderParameter params) override; virtual void beginFrame() override; @@ -56,21 +51,7 @@ private: uint framebufferWidth; uint framebufferHeight; GLFWwindow* handle; - CA::MetalLayer* metalLayer; - CA::MetalDrawable* drawable; - MTL::Device* device; - MTL::Library* library; - MTL::CommandQueue* queue; - MTL::Function* function; - MTL::ComputePipelineState* computePipeline; - MTL::Texture* accumulator; - MTL::Texture* resultTexture; - - MTL::RenderPassDescriptor* renderPass; - MTL::RenderCommandEncoder* renderEncoder; - MTL::CommandBuffer* renderCmd; - - MetalScene* scene; + class MetalScene* scene; }; diff --git a/src/metal/MetalRenderer.mm b/src/metal/MetalRenderer.mm index 6ba82b0..9ce1adc 100644 --- a/src/metal/MetalRenderer.mm +++ b/src/metal/MetalRenderer.mm @@ -1,21 +1,28 @@ #include "MetalRenderer.h" -#include "Foundation/NSSharedPtr.hpp" -#include "Metal/MTLBlitCommandEncoder.hpp" -#include "Metal/MTLDrawable.hpp" -#include "Metal/MTLRenderPass.hpp" -#include "QuartzCore/CAMetalLayer.hpp" #include "metal/MetalScene.h" #include "scene/Renderer.h" #include "util/Camera.h" -#include #include -#include -#include -#include #include #include #include + NSWindow* window; +CAMetalLayer* metalLayer; +id drawable; + +id device; +id library; +id queue; +id function; +id computePipeline; +id accumulator; +id resultTexture; + +MTLRenderPassDescriptor* renderPass; +id renderEncoder; +id renderCmd; + MetalRenderer::MetalRenderer() { IMGUI_CHECKVERSION(); @@ -26,18 +33,18 @@ MetalRenderer::MetalRenderer() width = 1920; height = 1080; - device = MTL::CreateSystemDefaultDevice(); + device = MTLCreateSystemDefaultDevice(); - library = device->newDefaultLibrary(); + library = [device newDefaultLibrary]; - queue = device->newCommandQueue(); + queue = [device newCommandQueue]; scene = new MetalScene(device, queue); - function = library->newFunction(NS::String::string("computeKernel", NS::ASCIIStringEncoding)); + function = [library newFunctionWithName:@"computeKernel"]; - NS::Error* error; - computePipeline = device->newComputePipelineState(function, &error); + NSError* error; + computePipeline = [device newComputePipelineStateWithFunction:function error:&error]; glfwInit(); float xscale = 1, yscale = 1; @@ -53,34 +60,37 @@ MetalRenderer::MetalRenderer() ImGui_ImplGlfw_InitForOpenGL(handle, false); ImGui_ImplMetal_Init((__bridge id)device); - metalLayer = CA::MetalLayer::layer(); - metalLayer->setDevice(device); - metalLayer->setPixelFormat(MTL::PixelFormatBGRA8Unorm); - metalLayer->setDrawableSize(CGSizeMake(w, h)); - metalLayer->setFramebufferOnly(true); - CAMetalLayer* native_layer = (__bridge CAMetalLayer*)metalLayer; + metalLayer = [CAMetalLayer layer]; + metalLayer.device = device; + metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; + metalLayer.drawableSize = CGSizeMake(w, h); + metalLayer.framebufferOnly = true; NSWindow* cocoaWindow = glfwGetCocoaWindow(handle); - [[cocoaWindow contentView] setLayer:native_layer]; + [[cocoaWindow contentView] setLayer:metalLayer]; [[cocoaWindow contentView] setWantsLayer:YES]; [[cocoaWindow contentView] setNeedsLayout:YES]; - renderPass= MTL::RenderPassDescriptor::alloc()->init(); + renderPass = [[MTLRenderPassDescriptor alloc] init]; } MetalRenderer::~MetalRenderer() {} +void MetalRenderer::addPointLight(PointLight point) { scene->addPointLight(point); } +void MetalRenderer::addDirectionalLight(DirectionalLight dir) { scene->addDirectionalLight(dir); } +void MetalRenderer::addModel(PModel model, glm::mat4 transform) { scene->addModel(std::move(model), transform); } +void MetalRenderer::addModels(std::vector models, glm::mat4 transform) { scene->addModels(std::move(models), transform); } +void MetalRenderer::generate() { scene->generate(); } + void MetalRenderer::beginFrame() { - drawable = metalLayer->nextDrawable(); - renderCmd = queue->commandBuffer(); - MTL::RenderPassColorAttachmentDescriptor* colorAttachment = MTL::RenderPassColorAttachmentDescriptor::alloc()->init(); - colorAttachment->setClearColor(MTL::ClearColor(0, 0, 0, 0)); - colorAttachment->setTexture(drawable->texture()); - colorAttachment->setLoadAction(MTL::LoadActionClear); - colorAttachment->setStoreAction(MTL::StoreActionStore); - renderPass->colorAttachments()->setObject(colorAttachment, 0); - renderEncoder = renderCmd->renderCommandEncoder(renderPass); - ImGui_ImplMetal_NewFrame((__bridge id)renderPass); + drawable = [metalLayer nextDrawable]; + renderCmd = [queue commandBuffer]; + renderPass.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 0); + renderPass.colorAttachments[0].texture = drawable.texture; + renderPass.colorAttachments[0].loadAction = MTLLoadActionClear; + renderPass.colorAttachments[0].storeAction = MTLStoreActionStore; + renderEncoder = [renderCmd renderCommandEncoderWithDescriptor:renderPass]; + ImGui_ImplMetal_NewFrame(renderPass); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); } @@ -88,9 +98,10 @@ void MetalRenderer::beginFrame() void MetalRenderer::update() { ImGui::Render(); - ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), (__bridge id)renderCmd, (__bridge id)renderEncoder); - renderCmd->presentDrawable((const MTL::Drawable*)drawable); - renderCmd->commit(); + ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), renderCmd, renderEncoder); + [renderEncoder endEncoding]; + [renderCmd presentDrawable:drawable]; + [renderCmd commit]; } void MetalRenderer::render(Camera camera, RenderParameter parameter) @@ -106,17 +117,17 @@ void MetalRenderer::render(Camera camera, RenderParameter parameter) .height = parameter.height, }; - MTL::TextureDescriptor* texDescriptor = MTL::TextureDescriptor::alloc()->init(); - texDescriptor->setWidth(parameter.width); - texDescriptor->setHeight(parameter.height); - texDescriptor->setPixelFormat(MTL::PixelFormatRGBA32Float); - texDescriptor->setUsage(MTL::TextureUsageShaderWrite | MTL::TextureUsageShaderRead); - accumulator = device->newTexture(texDescriptor); - resultTexture = device->newTexture(texDescriptor); + MTLTextureDescriptor* texDescriptor = [[MTLTextureDescriptor alloc] init]; + [texDescriptor setWidth:parameter.width]; + [texDescriptor setHeight:parameter.height]; + [texDescriptor setPixelFormat:MTLPixelFormatRGBA32Float]; + [texDescriptor setUsage:MTLTextureUsageShaderWrite | MTLTextureUsageShaderRead]; + accumulator = [device newTextureWithDescriptor:texDescriptor]; + resultTexture = [device newTextureWithDescriptor:texDescriptor]; for (uint i = 0; i < parameter.numSamples; ++i) { - MTL::CommandBuffer* cmdBuffer = queue->commandBuffer(); - MTL::ComputeCommandEncoder* encoder = cmdBuffer->computeCommandEncoder(); + id cmdBuffer = [queue commandBuffer]; + id encoder = [cmdBuffer computeCommandEncoder]; // cmdBuffer->addCompletedHandler([this](MTL::CommandBuffer* cmdBuffer) // { std::memcpy(image.data(), resultTexture->buffer(), image.size() * sizeof(glm::vec3)); }); @@ -126,47 +137,45 @@ void MetalRenderer::render(Camera camera, RenderParameter parameter) .numDirectionalLights = scene->getNumDirLights(), .numPointLights = scene->getNumPointLights(), }; - encoder->setComputePipelineState(computePipeline); - encoder->setBuffer(scene->indicesBuffer, 0, 0); - encoder->setBuffer(scene->positionBuffer, 0, 1); - encoder->setBuffer(scene->texCoordsBuffer, 0, 2); - encoder->setBuffer(scene->normalBuffer, 0, 3); - encoder->setBuffer(scene->modelRefsBuffer, 0, 4); - encoder->setBuffer(scene->directionalLightBuffer, 0, 5); - encoder->setBuffer(scene->pointLightBuffer, 0, 6); - encoder->setBuffer(scene->instanceBuffer, 0, 7); - encoder->setAccelerationStructure(scene->accelerationStructure, 8); - encoder->setTexture(accumulator, 0); - encoder->setTexture(resultTexture, 1); - encoder->setBytes(&gpuCam, sizeof(GPUCamera), 9); - encoder->setBytes(&sample, sizeof(SampleParams), 10); - encoder->useResource(scene->instanceBuffer, MTL::ResourceUsageRead); - encoder->useResource(scene->positionBuffer, MTL::ResourceUsageRead); - encoder->useResource(scene->texCoordsBuffer, MTL::ResourceUsageRead); - encoder->useResource(scene->normalBuffer, MTL::ResourceUsageRead); - encoder->useResource(scene->modelRefsBuffer, MTL::ResourceUsageRead); + [encoder setComputePipelineState:computePipeline]; + [encoder setBuffer:scene->indicesBuffer offset:0 atIndex:0]; + [encoder setBuffer:scene->positionBuffer offset:0 atIndex:1]; + [encoder setBuffer:scene->texCoordsBuffer offset:0 atIndex:2]; + [encoder setBuffer:scene->normalBuffer offset:0 atIndex:3]; + [encoder setBuffer:scene->modelRefsBuffer offset:0 atIndex:4]; + [encoder setBuffer:scene->directionalLightBuffer offset:0 atIndex:5]; + [encoder setBuffer:scene->pointLightBuffer offset:0 atIndex:6]; + [encoder setBuffer:scene->instanceBuffer offset:0 atIndex:7]; + [encoder setAccelerationStructure:scene->accelerationStructure atBufferIndex:8]; + [encoder setTexture:accumulator atIndex:0]; + [encoder setTexture:resultTexture atIndex:1]; + [encoder setBytes:&gpuCam length:sizeof(GPUCamera) atIndex:9]; + [encoder setBytes:&sample length:sizeof(SampleParams) atIndex:10]; + [encoder useResource:scene->instanceBuffer usage:MTLResourceUsageRead]; + [encoder useResource:scene->positionBuffer usage:MTLResourceUsageRead]; + [encoder useResource:scene->texCoordsBuffer usage:MTLResourceUsageRead]; + [encoder useResource:scene->normalBuffer usage:MTLResourceUsageRead]; + [encoder useResource:scene->modelRefsBuffer usage:MTLResourceUsageRead]; if (scene->getNumDirLights() > 0) { - encoder->useResource(scene->directionalLightBuffer, MTL::ResourceUsageRead); + [encoder useResource:scene->directionalLightBuffer usage:MTLResourceUsageRead]; } if (scene->getNumPointLights() > 0) { - encoder->useResource(scene->pointLightBuffer, MTL::ResourceUsageRead); + [encoder useResource:scene->pointLightBuffer usage:MTLResourceUsageRead]; } - encoder->useResource(scene->instanceBuffer, MTL::ResourceUsageRead); - encoder->useResource(scene->accelerationStructure, MTL::ResourceUsageRead); - encoder->useResource(accumulator, MTL::ResourceUsageWrite); - encoder->useResource(resultTexture, MTL::ResourceUsageWrite); - NS::UInteger width = (NS::UInteger)parameter.width; - NS::UInteger height = (NS::UInteger)parameter.height; - MTL::Size threadsPerThreadgroup = MTL::Size(8, 8, 1); - MTL::Size threadgroups = MTL::Size((width + threadsPerThreadgroup.width - 1) / threadsPerThreadgroup.width, + [encoder useResource:scene->instanceBuffer usage:MTLResourceUsageRead]; + [encoder useResource:scene->accelerationStructure usage:MTLResourceUsageRead]; + [encoder useResource:accumulator usage:MTLResourceUsageWrite]; + [encoder useResource:resultTexture usage:MTLResourceUsageWrite]; + NSUInteger width = (NSUInteger)parameter.width; + NSUInteger height = (NSUInteger)parameter.height; + MTLSize threadsPerThreadgroup = MTLSizeMake(8, 8, 1); + MTLSize threadgroups = MTLSizeMake((width + threadsPerThreadgroup.width - 1) / threadsPerThreadgroup.width, (height + threadsPerThreadgroup.height - 1) / threadsPerThreadgroup.height, 1); - encoder->dispatchThreadgroups(threadgroups, threadsPerThreadgroup); - encoder->endEncoding(); - MTL::BlitCommandEncoder* blitCommandEncoder = cmdBuffer->blitCommandEncoder(); - blitCommandEncoder->copyFromTexture(resultTexture, 0, 0, MTL::Origin(), MTL::Size(parameter.width, parameter.height, 1), drawable->texture(), 0, 0, MTL::Origin()); - cmdBuffer->commit(); - cmdBuffer->waitUntilCompleted(); + [encoder dispatchThreadgroups:threadgroups threadsPerThreadgroup:threadsPerThreadgroup]; + [encoder endEncoding]; + [cmdBuffer commit]; + [cmdBuffer waitUntilCompleted]; } } diff --git a/src/metal/MetalScene.h b/src/metal/MetalScene.h index d16974d..069897f 100644 --- a/src/metal/MetalScene.h +++ b/src/metal/MetalScene.h @@ -1,28 +1,29 @@ #pragma once #include "scene/Scene.h" -#include -#include -#include +#include +#include class MetalScene : public Scene { public: - MetalScene(MTL::Device* device, MTL::CommandQueue* queue); + MetalScene(id device, id queue); virtual ~MetalScene(); virtual void createRayTracingHierarchy() override; + + id newAccelerationStructureWithDescriptor(MTLAccelerationStructureDescriptor* descriptor); - MTL::Device* device; - MTL::CommandQueue* queue; + id device; + id queue; - MTL::Buffer* indicesBuffer; - MTL::Buffer* positionBuffer; - MTL::Buffer* texCoordsBuffer; - MTL::Buffer* normalBuffer; - MTL::Buffer* modelRefsBuffer; - MTL::Buffer* directionalLightBuffer; - MTL::Buffer* pointLightBuffer; - MTL::Buffer* instanceBuffer; + id indicesBuffer; + id positionBuffer; + id texCoordsBuffer; + id normalBuffer; + id modelRefsBuffer; + id directionalLightBuffer; + id pointLightBuffer; + id instanceBuffer; - MTL::AccelerationStructure* accelerationStructure; -}; \ No newline at end of file + id accelerationStructure; +}; diff --git a/src/metal/MetalScene.mm b/src/metal/MetalScene.mm index d2726ba..bf42527 100644 --- a/src/metal/MetalScene.mm +++ b/src/metal/MetalScene.mm @@ -1,60 +1,58 @@ #include "MetalScene.h" -MetalScene::MetalScene(MTL::Device* device, MTL::CommandQueue* queue) : device(device), queue(queue) {} +MetalScene::MetalScene(id device, id queue) : device(device), queue(queue) {} MetalScene::~MetalScene() {} void MetalScene::createRayTracingHierarchy() { - indicesBuffer = device->newBuffer(indicesPool.size() * sizeof(decltype(indicesPool)::value_type), MTL::ResourceStorageModeShared); - positionBuffer = device->newBuffer(positionPool.size() * sizeof(decltype(positionPool)::value_type), MTL::ResourceStorageModeShared); - texCoordsBuffer = device->newBuffer(texCoordsPool.size() * sizeof(decltype(texCoordsPool)::value_type), MTL::ResourceStorageModeShared); - normalBuffer = device->newBuffer(normalsPool.size() * sizeof(decltype(normalsPool)::value_type), MTL::ResourceStorageModeShared); - modelRefsBuffer = device->newBuffer(refs.size() * sizeof(decltype(refs)::value_type), MTL::ResourceStorageModeShared); + indicesBuffer = [device newBufferWithLength:indicesPool.size() * sizeof(decltype(indicesPool)::value_type) options:MTLResourceStorageModeShared]; + positionBuffer = [device newBufferWithLength:positionPool.size() * sizeof(decltype(positionPool)::value_type) options:MTLResourceStorageModeShared]; + texCoordsBuffer = [device newBufferWithLength:texCoordsPool.size() * sizeof(decltype(texCoordsPool)::value_type) options:MTLResourceStorageModeShared]; + normalBuffer = [device newBufferWithLength:normalsPool.size() * sizeof(decltype(normalsPool)::value_type) options:MTLResourceStorageModeShared]; + modelRefsBuffer = [device newBufferWithLength:refs.size() * sizeof(decltype(refs)::value_type) options:MTLResourceStorageModeShared]; if (directionalLights.size() > 0) { directionalLightBuffer = - device->newBuffer(directionalLights.size() * sizeof(decltype(directionalLights)::value_type), MTL::ResourceStorageModeShared); - std::memcpy(directionalLightBuffer->contents(), directionalLights.data(), + [device newBufferWithLength:directionalLights.size() * sizeof(decltype(directionalLights)::value_type) options:MTLResourceStorageModeShared]; + std::memcpy(directionalLightBuffer.contents, directionalLights.data(), directionalLights.size() * sizeof(decltype(directionalLights)::value_type)); } if (pointLights.size() > 0) { - pointLightBuffer = device->newBuffer(pointLights.size() * sizeof(decltype(pointLights)::value_type), MTL::ResourceStorageModeShared); - std::memcpy(pointLightBuffer->contents(), pointLights.data(), pointLights.size() * sizeof(decltype(pointLights)::value_type)); + pointLightBuffer = [device newBufferWithLength:pointLights.size() * sizeof(decltype(pointLights)::value_type) options:MTLResourceStorageModeShared]; + std::memcpy(pointLightBuffer.contents, pointLights.data(), pointLights.size() * sizeof(decltype(pointLights)::value_type)); } - std::memcpy(indicesBuffer->contents(), indicesPool.data(), indicesPool.size() * sizeof(decltype(indicesPool)::value_type)); - std::memcpy(positionBuffer->contents(), positionPool.data(), positionPool.size() * sizeof(decltype(positionPool)::value_type)); - std::memcpy(texCoordsBuffer->contents(), texCoordsPool.data(), texCoordsPool.size() * sizeof(decltype(texCoordsPool)::value_type)); - std::memcpy(normalBuffer->contents(), normalsPool.data(), normalsPool.size() * sizeof(decltype(normalsPool)::value_type)); - std::memcpy(modelRefsBuffer->contents(), refs.data(), refs.size() * sizeof(decltype(refs)::value_type)); + std::memcpy(indicesBuffer.contents, indicesPool.data(), indicesPool.size() * sizeof(decltype(indicesPool)::value_type)); + std::memcpy(positionBuffer.contents, positionPool.data(), positionPool.size() * sizeof(decltype(positionPool)::value_type)); + std::memcpy(texCoordsBuffer.contents, texCoordsPool.data(), texCoordsPool.size() * sizeof(decltype(texCoordsPool)::value_type)); + std::memcpy(normalBuffer.contents, normalsPool.data(), normalsPool.size() * sizeof(decltype(normalsPool)::value_type)); + std::memcpy(modelRefsBuffer.contents, refs.data(), refs.size() * sizeof(decltype(refs)::value_type)); - CFTypeRef* descriptors = new CFTypeRef[refs.size()]; - MTL::AccelerationStructure** primitiveAccelerationStructures = new MTL::AccelerationStructure*[refs.size()]; + NSMutableArray* primitiveStructures = [[NSMutableArray alloc] init]; for (uint i = 0; i < refs.size(); ++i) { - MTL::AccelerationStructureTriangleGeometryDescriptor* descriptor = MTL::AccelerationStructureTriangleGeometryDescriptor::descriptor(); - descriptor->setTriangleCount(refs[i].numIndices / 3); - descriptor->setIndexBuffer(indicesBuffer); - descriptor->setIndexBufferOffset(refs[i].indicesOffset * sizeof(glm::uvec3)); - descriptor->setIndexType(MTL::IndexTypeUInt32); - descriptor->setVertexBuffer(positionBuffer); - descriptor->setVertexBufferOffset(refs[i].positionOffset * sizeof(glm::vec3)); + MTLAccelerationStructureTriangleGeometryDescriptor* descriptor = [MTLAccelerationStructureTriangleGeometryDescriptor descriptor]; + descriptor.triangleCount = refs[i].numIndices; + descriptor.indexBuffer = indicesBuffer; + descriptor.indexBufferOffset = refs[i].indicesOffset * sizeof(glm::uvec3); + descriptor.indexType = MTLIndexTypeUInt32; + descriptor.vertexBuffer = positionBuffer; + descriptor.vertexBufferOffset = refs[i].positionOffset * sizeof(glm::vec3); - MTL::PrimitiveAccelerationStructureDescriptor* primitiveDescriptor = MTL::PrimitiveAccelerationStructureDescriptor::descriptor(); - primitiveDescriptor->setGeometryDescriptors(NS::Array::array(descriptor)); + MTLPrimitiveAccelerationStructureDescriptor* primitiveDescriptor = [MTLPrimitiveAccelerationStructureDescriptor descriptor]; + primitiveDescriptor.geometryDescriptors = @[ descriptor ]; - primitiveAccelerationStructures[i] = device->newAccelerationStructure(primitiveDescriptor); - primitiveAccelerationStructures[i]->setLabel(NS::String::string("Primitive Structure", NS::ASCIIStringEncoding)); - std::cout << primitiveAccelerationStructures[i]->debugDescription()->cString(NS::ASCIIStringEncoding) << std::endl; - descriptors[i] = (CFTypeRef)primitiveAccelerationStructures[i]; + id accelerationStructure = newAccelerationStructureWithDescriptor(primitiveDescriptor); + [accelerationStructure setLabel:@"Primitive Structure"]; + [primitiveStructures addObject:accelerationStructure]; } instanceBuffer = - device->newBuffer(sizeof(MTL::AccelerationStructureInstanceDescriptor) * refs.size(), MTL::ResourceOptionCPUCacheModeDefault); + [device newBufferWithLength:sizeof(MTLAccelerationStructureInstanceDescriptor) * refs.size() options:MTLResourceStorageModeShared]; - MTL::AccelerationStructureInstanceDescriptor* instanceDescriptors = - (MTL::AccelerationStructureInstanceDescriptor*)instanceBuffer->contents(); + MTLAccelerationStructureInstanceDescriptor* instanceDescriptors = + (MTLAccelerationStructureInstanceDescriptor*)instanceBuffer.contents; for (uint i = 0; i < refs.size(); ++i) { instanceDescriptors[i].transformationMatrix[0][0] = 1.0f; @@ -74,34 +72,94 @@ void MetalScene::createRayTracingHierarchy() instanceDescriptors[i].accelerationStructureIndex = i; - instanceDescriptors[i].options = MTL::AccelerationStructureInstanceOptionOpaque; + instanceDescriptors[i].options = MTLAccelerationStructureInstanceOptionOpaque; instanceDescriptors[i].mask = 0xff; } - NS::Array* pGeoDescriptors = ( NS::Array* )( CFArrayCreate( kCFAllocatorDefault, descriptors, refs.size(), &kCFTypeArrayCallBacks ) ); - MTL::InstanceAccelerationStructureDescriptor* accelDesc = MTL::InstanceAccelerationStructureDescriptor::descriptor(); - accelDesc->setInstancedAccelerationStructures(pGeoDescriptors); - accelDesc->setInstanceDescriptorBuffer(instanceBuffer); - accelDesc->setInstanceCount(refs.size()); - - MTL::AccelerationStructureSizes accelSizes = device->accelerationStructureSizes(accelDesc); - MTL::AccelerationStructure* tempStructure = device->newAccelerationStructure(accelSizes.accelerationStructureSize); - tempStructure->setLabel(NS::String::string("Temporary AS", NS::ASCIIStringEncoding)); - MTL::Buffer* scratchBuffer = device->newBuffer(accelSizes.buildScratchBufferSize, MTL::StorageModeManaged); - MTL::CommandBuffer* cmdBuffer = queue->commandBuffer(); - MTL::AccelerationStructureCommandEncoder* encoder = cmdBuffer->accelerationStructureCommandEncoder(); - MTL::Buffer* compactedBuffer = device->newBuffer(sizeof(uint), MTL::ResourceOptionCPUCacheModeDefault); - encoder->buildAccelerationStructure(tempStructure, accelDesc, scratchBuffer, 0); - encoder->writeCompactedAccelerationStructureSize(tempStructure, compactedBuffer, 0); - encoder->endEncoding(); - cmdBuffer->commit(); - cmdBuffer->waitUntilCompleted(); - uint compactedSize = *(uint*)compactedBuffer->contents(); - accelerationStructure = device->newAccelerationStructure(compactedSize); - accelerationStructure->setLabel(NS::String::string("Instance AS", NS::ASCIIStringEncoding)); - cmdBuffer = queue->commandBuffer(); - encoder = cmdBuffer->accelerationStructureCommandEncoder(); - encoder->copyAndCompactAccelerationStructure(tempStructure, accelerationStructure); - encoder->endEncoding(); - cmdBuffer->commit(); - cmdBuffer->waitUntilCompleted(); + MTLInstanceAccelerationStructureDescriptor* accelDesc = [MTLInstanceAccelerationStructureDescriptor descriptor]; + [accelDesc setInstancedAccelerationStructures:primitiveStructures]; + [accelDesc setInstanceDescriptorBuffer:instanceBuffer]; + [accelDesc setInstanceCount:refs.size()]; + accelerationStructure = newAccelerationStructureWithDescriptor(accelDesc); +} + +id MetalScene::newAccelerationStructureWithDescriptor(MTLAccelerationStructureDescriptor* descriptor) +{ + // Query for the sizes needed to store and build the acceleration structure. + MTLAccelerationStructureSizes accelSizes = [device accelerationStructureSizesWithDescriptor:descriptor]; + + // Allocate an acceleration structure large enough for this descriptor. This method + // doesn't actually build the acceleration structure, but rather allocates memory. + id accelerationStructure = [device newAccelerationStructureWithSize:accelSizes.accelerationStructureSize]; + + // Allocate scratch space Metal uses to build the acceleration structure. + // Use MTLResourceStorageModePrivate for the best performance because the sample + // doesn't need access to buffer's contents. + id scratchBuffer = [device newBufferWithLength:accelSizes.buildScratchBufferSize options:MTLResourceStorageModePrivate]; + + // Create a commandbuffer that performs the acceleration structure build. + id commandBuffer = [queue commandBuffer]; + + // Create an acceleration structure command encoder. + id commandEncoder = [commandBuffer accelerationStructureCommandEncoder]; + + // Allocate a buffer for Metal to write the compacted accelerated structure's size into. + id compactedSizeBuffer = [device newBufferWithLength:sizeof(uint32_t) options:MTLResourceStorageModeShared]; + + // Schedule the actual acceleration structure build. + [commandEncoder buildAccelerationStructure:accelerationStructure + descriptor:descriptor + scratchBuffer:scratchBuffer + scratchBufferOffset:0]; + + // Compute and write the compacted acceleration structure size into the buffer. You + // must already have a built acceleration structure because Metal determines the compacted + // size based on the final size of the acceleration structure. Compacting an acceleration + // structure can potentially reclaim significant amounts of memory because Metal must + // create the initial structure using a conservative approach. + + [commandEncoder writeCompactedAccelerationStructureSize:accelerationStructure + toBuffer:compactedSizeBuffer + offset:0]; + + // End encoding, and commit the command buffer so the GPU can start building the + // acceleration structure. + [commandEncoder endEncoding]; + + [commandBuffer commit]; + + // The sample waits for Metal to finish executing the command buffer so that it can + // read back the compacted size. + + // Note: Don't wait for Metal to finish executing the command buffer if you aren't compacting + // the acceleration structure, as doing so requires CPU/GPU synchronization. You don't have + // to compact acceleration structures, but do so when creating large static acceleration + // structures, such as static scene geometry. Avoid compacting acceleration structures that + // you rebuild every frame, as the synchronization cost may be significant. + + [commandBuffer waitUntilCompleted]; + + uint32_t compactedSize = *(uint32_t *)compactedSizeBuffer.contents; + + // Allocate a smaller acceleration structure based on the returned size. + id compactedAccelerationStructure = [device newAccelerationStructureWithSize:compactedSize]; + + // Create another command buffer and encoder. + commandBuffer = [queue commandBuffer]; + + commandEncoder = [commandBuffer accelerationStructureCommandEncoder]; + + // Encode the command to copy and compact the acceleration structure into the + // smaller acceleration structure. + [commandEncoder copyAndCompactAccelerationStructure:accelerationStructure + toAccelerationStructure:compactedAccelerationStructure]; + + // End encoding and commit the command buffer. You don't need to wait for Metal to finish + // executing this command buffer as long as you synchronize any ray-intersection work + // to run after this command buffer completes. The sample relies on Metal's default + // dependency tracking on resources to automatically synchronize access to the new + // compacted acceleration structure. + [commandEncoder endEncoding]; + [commandBuffer commit]; + + return compactedAccelerationStructure; } diff --git a/src/metal/PrivateImpl.mm b/src/metal/PrivateImpl.mm deleted file mode 100644 index 7fa7137..0000000 --- a/src/metal/PrivateImpl.mm +++ /dev/null @@ -1,6 +0,0 @@ -#define NS_PRIVATE_IMPLEMENTATION -#define CA_PRIVATE_IMPLEMENTATION -#define MTL_PRIVATE_IMPLEMENTATION -#include -#include -#include