no more metal cpp, we doing obj c now

This commit is contained in:
Dynamitos
2025-02-27 22:01:28 +09:00
parent 3fa51f7152
commit 7f83894d39
8 changed files with 235 additions and 195 deletions
+1 -3
View File
@@ -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"
+2 -2
View File
@@ -1,11 +1,11 @@
#include "metal/MetalRenderer.h"
#include "scene/Renderer.h"
#include "util/ModelLoader.h"
#include "metal/MetalRenderer.h"
#include <imgui.h>
int main()
{
std::unique_ptr<Renderer> renderer = std::make_unique<MetalRenderer>();
std::unique_ptr<Renderer> renderer = std::make_unique<MetalRenderer>();
renderer->addDirectionalLight(DirectionalLight{
.direction = glm::normalize(glm::vec3(-0.4f, -0.3f, -0.2f)),
+1 -2
View File
@@ -4,5 +4,4 @@ target_sources(RayTracer
MetalRenderer.mm
MetalScene.h
MetalScene.mm
Compute.metal
PrivateImpl.mm)
Compute.metal)
+6 -25
View File
@@ -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 <GLFW/glfw3native.h>
#include <Metal/Metal.hpp>
#include <QuartzCore/CAMetalLayer.hpp>
#include <QuartzCore/QuartzCore.hpp>
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<PModel> 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<PModel> 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;
};
+89 -80
View File
@@ -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 <Foundation/Foundation.hpp>
#include <GLFW/glfw3.h>
#include <Metal/Metal.hpp>
#include <QuartzCore/QuartzCore.hpp>
#include <QuartzCore/CAMetalLayer.h>
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_metal.h>
NSWindow* window;
CAMetalLayer* metalLayer;
id<CAMetalDrawable> drawable;
id<MTLDevice> device;
id<MTLLibrary> library;
id<MTLCommandQueue> queue;
id<MTLFunction> function;
id<MTLComputePipelineState> computePipeline;
id<MTLTexture> accumulator;
id<MTLTexture> resultTexture;
MTLRenderPassDescriptor* renderPass;
id<MTLRenderCommandEncoder> renderEncoder;
id<MTLCommandBuffer> 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<PModel> 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<MTLCommandBuffer> cmdBuffer = [queue commandBuffer];
id<MTLComputeCommandEncoder> 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];
}
}
+17 -16
View File
@@ -1,28 +1,29 @@
#pragma once
#include "scene/Scene.h"
#include <Foundation/Foundation.hpp>
#include <Metal/Metal.hpp>
#include <QuartzCore/QuartzCore.hpp>
#include <Metal/Metal.h>
#include <QuartzCore/QuartzCore.h>
class MetalScene : public Scene
{
public:
MetalScene(MTL::Device* device, MTL::CommandQueue* queue);
MetalScene(id<MTLDevice> device, id<MTLCommandQueue> queue);
virtual ~MetalScene();
virtual void createRayTracingHierarchy() override;
id<MTLAccelerationStructure> newAccelerationStructureWithDescriptor(MTLAccelerationStructureDescriptor* descriptor);
MTL::Device* device;
MTL::CommandQueue* queue;
id<MTLDevice> device;
id<MTLCommandQueue> 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<MTLBuffer> indicesBuffer;
id<MTLBuffer> positionBuffer;
id<MTLBuffer> texCoordsBuffer;
id<MTLBuffer> normalBuffer;
id<MTLBuffer> modelRefsBuffer;
id<MTLBuffer> directionalLightBuffer;
id<MTLBuffer> pointLightBuffer;
id<MTLBuffer> instanceBuffer;
MTL::AccelerationStructure* accelerationStructure;
};
id<MTLAccelerationStructure> accelerationStructure;
};
+119 -61
View File
@@ -1,60 +1,58 @@
#include "MetalScene.h"
MetalScene::MetalScene(MTL::Device* device, MTL::CommandQueue* queue) : device(device), queue(queue) {}
MetalScene::MetalScene(id<MTLDevice> device, id<MTLCommandQueue> 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<MTLAccelerationStructure> 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<MTLAccelerationStructure> 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 <MTLAccelerationStructure> 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 <MTLBuffer> scratchBuffer = [device newBufferWithLength:accelSizes.buildScratchBufferSize options:MTLResourceStorageModePrivate];
// Create a commandbuffer that performs the acceleration structure build.
id <MTLCommandBuffer> commandBuffer = [queue commandBuffer];
// Create an acceleration structure command encoder.
id <MTLAccelerationStructureCommandEncoder> commandEncoder = [commandBuffer accelerationStructureCommandEncoder];
// Allocate a buffer for Metal to write the compacted accelerated structure's size into.
id <MTLBuffer> 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 <MTLAccelerationStructure> 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;
}
-6
View File
@@ -1,6 +0,0 @@
#define NS_PRIVATE_IMPLEMENTATION
#define CA_PRIVATE_IMPLEMENTATION
#define MTL_PRIVATE_IMPLEMENTATION
#include <Foundation/Foundation.hpp>
#include <Metal/Metal.hpp>
#include <QuartzCore/QuartzCore.hpp>