no more metal cpp, we doing obj c now
This commit is contained in:
@@ -4,5 +4,4 @@ target_sources(RayTracer
|
||||
MetalRenderer.mm
|
||||
MetalScene.h
|
||||
MetalScene.mm
|
||||
Compute.metal
|
||||
PrivateImpl.mm)
|
||||
Compute.metal)
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user