i hate metal cpp

This commit is contained in:
Dynamitos
2025-02-27 20:25:53 +09:00
parent 961cb527af
commit 3fa51f7152
23 changed files with 525 additions and 437 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
target_sources(RayTracer
PRIVATE
MetalRenderer.h
MetalRenderer.cpp
MetalRenderer.mm
MetalScene.h
MetalScene.cpp
MetalScene.mm
Compute.metal
PrivateImpl.mm)
+6 -4
View File
@@ -133,8 +133,8 @@ kernel void computeKernel(
constant PointLight* pointLights [[buffer(6)]],
constant MTLAccelerationStructureInstanceDescriptor* instances [[buffer(7)]],
instance_acceleration_structure accelerationStructure [[buffer(8)]],
device packed_float3* accumulator [[buffer(9)]],
device packed_float3* image [[buffer(10)]]
texture2d<float, access::read_write> accumulator [[texture(0)]],
texture2d<float, access::read_write> image [[texture(1)]]
)
{
Payload payload;
@@ -267,6 +267,8 @@ kernel void computeKernel(
payload.depth++;
}
float resolver = float(sample.samplesPerPixel) / float(sample.pass+1);
accumulator[threadId.x + threadId.y * camera.width] += payload.accumulatedRadiance / float(sample.samplesPerPixel);
image[threadId.x + threadId.y * camera.width] = pow(max(accumulator[threadId.x + threadId.y * camera.width] * resolver, 0), float3(0.45f));
float4 previous = accumulator.read(threadId);
float4 result = previous + float4(payload.accumulatedRadiance / float(sample.samplesPerPixel), 0);
accumulator.write(result, threadId);
image.write(pow(max(result * resolver, 0), float4(0.45f)), threadId);
}
-96
View File
@@ -1,96 +0,0 @@
#include "MetalRenderer.h"
#include "metal/MetalScene.h"
#include "scene/Renderer.h"
#include "util/Camera.h"
#include <Foundation/Foundation.hpp>
#include <Metal/Metal.hpp>
#include <QuartzCore/QuartzCore.hpp>
MetalRenderer::MetalRenderer()
{
device = MTL::CreateSystemDefaultDevice();
library = device->newDefaultLibrary();
queue = device->newCommandQueue();
scene = new MetalScene(device, queue);
function = library->newFunction(NS::String::string("computeKernel", NS::ASCIIStringEncoding));
NS::Error* error;
computePipeline = device->newComputePipelineState(function, &error);
}
MetalRenderer::~MetalRenderer() {}
void MetalRenderer::render(Camera camera, RenderParameter parameter)
{
MTL::Buffer* cameraBuffer = device->newBuffer(sizeof(GPUCamera), 0);
*(GPUCamera*)cameraBuffer->contents() = GPUCamera {
.cameraPosition = camera.position,
.A = camera.A,
.cameraForward = camera.target - camera.position,
.f = camera.f,
.S_O = camera.S_O,
.sensorSize = camera.sensorSize,
.width = parameter.width,
.height = parameter.height,
};
SampleParams sample = {
.samplesPerPixel = parameter.numSamples,
.numDirectionalLights = scene->getNumDirLights(),
.numPointLights = scene->getNumPointLights(),
};
accumulator = device->newBuffer(parameter.width * parameter.height * sizeof(glm::vec3), 0);
resultTexture = device->newBuffer(parameter.width * parameter.height * sizeof(glm::vec3), 0);
for (uint i = 0; i < parameter.numSamples; ++i)
{
MTL::CommandBuffer* cmdBuffer = queue->commandBuffer();
MTL::ComputeCommandEncoder* encoder = cmdBuffer->computeCommandEncoder();
//cmdBuffer->addCompletedHandler([this](MTL::CommandBuffer* cmdBuffer)
// { std::memcpy(image.data(), resultTexture->buffer(), image.size() * sizeof(glm::vec3)); });
sample.pass = i;
MTL::Buffer* sampleBuffer = device->newBuffer(sizeof(SampleParams), 0);
*(SampleParams*)sampleBuffer->contents() = sample;
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->setBuffer(accumulator, 0, 9);
encoder->setBuffer(resultTexture, 0, 10);
encoder->setBuffer(cameraBuffer, 0, 11);
encoder->setBuffer(sampleBuffer, 0, 12);
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);
if(scene->getNumDirLights() > 0)
{
encoder->useResource(scene->directionalLightBuffer, MTL::ResourceUsageRead);}
if(scene->getNumPointLights() > 0)
{encoder->useResource(scene->pointLightBuffer, MTL::ResourceUsageRead);}
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,
(height + threadsPerThreadgroup.height - 1) / threadsPerThreadgroup.height, 1);
encoder->dispatchThreadgroups(threadgroups, threadsPerThreadgroup);
encoder->endEncoding();
cmdBuffer->commit();
cmdBuffer->waitUntilCompleted();
std::memcpy(image.data(), resultTexture->contents(), image.size() * sizeof(glm::vec3));
}
}
+47 -25
View File
@@ -2,8 +2,14 @@
#include "metal/MetalScene.h"
#include "scene/Renderer.h"
#include "util/Camera.h"
#include <Foundation/Foundation.hpp>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#define GLFW_EXPOSE_NATIVE_COCOA
#include <GLFW/glfw3native.h>
#include <Metal/Metal.hpp>
#include <QuartzCore/CAMetalLayer.hpp>
#include <QuartzCore/QuartzCore.hpp>
struct GPUCamera
@@ -17,38 +23,54 @@ struct GPUCamera
float A;
float ka;
glm::vec2 sensorSize;
uint width;
uint height;
uint width;
uint height;
};
struct SampleParams
{
uint pass;
uint samplesPerPixel;
uint numDirectionalLights;
uint numPointLights;
uint pass;
uint samplesPerPixel;
uint numDirectionalLights;
uint numPointLights;
};
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 render(Camera camera, RenderParameter params) override;
private:
MTL::Device* device;
MTL::Library* library;
MTL::CommandQueue* queue;
MTL::Function* function;
MTL::ComputePipelineState* computePipeline;
MTL::Buffer* accumulator;
MTL::Buffer* resultTexture;
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 render(Camera camera, RenderParameter params) override;
MetalScene* scene;
virtual void beginFrame() override;
virtual void update() override;
private:
uint width;
uint height;
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;
};
+172
View File
@@ -0,0 +1,172 @@
#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>
MetalRenderer::MetalRenderer()
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
width = 1920;
height = 1080;
device = MTL::CreateSystemDefaultDevice();
library = device->newDefaultLibrary();
queue = device->newCommandQueue();
scene = new MetalScene(device, queue);
function = library->newFunction(NS::String::string("computeKernel", NS::ASCIIStringEncoding));
NS::Error* error;
computePipeline = device->newComputePipelineState(function, &error);
glfwInit();
float xscale = 1, yscale = 1;
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xscale, &yscale);
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
handle = glfwCreateWindow(width / xscale, height / yscale, "RayTracer", nullptr, nullptr);
int w, h;
glfwGetFramebufferSize(handle, &w, &h);
framebufferWidth = width;
framebufferHeight = height;
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;
NSWindow* cocoaWindow = glfwGetCocoaWindow(handle);
[[cocoaWindow contentView] setLayer:native_layer];
[[cocoaWindow contentView] setWantsLayer:YES];
[[cocoaWindow contentView] setNeedsLayout:YES];
renderPass= MTL::RenderPassDescriptor::alloc()->init();
}
MetalRenderer::~MetalRenderer() {}
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);
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
}
void MetalRenderer::update()
{
ImGui::Render();
ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), (__bridge id)renderCmd, (__bridge id)renderEncoder);
renderCmd->presentDrawable((const MTL::Drawable*)drawable);
renderCmd->commit();
}
void MetalRenderer::render(Camera camera, RenderParameter parameter)
{
GPUCamera gpuCam = {
.cameraPosition = camera.position,
.A = camera.A,
.cameraForward = camera.target - camera.position,
.f = camera.f,
.S_O = camera.S_O,
.sensorSize = camera.sensorSize,
.width = parameter.width,
.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);
for (uint i = 0; i < parameter.numSamples; ++i)
{
MTL::CommandBuffer* cmdBuffer = queue->commandBuffer();
MTL::ComputeCommandEncoder* encoder = cmdBuffer->computeCommandEncoder();
// cmdBuffer->addCompletedHandler([this](MTL::CommandBuffer* cmdBuffer)
// { std::memcpy(image.data(), resultTexture->buffer(), image.size() * sizeof(glm::vec3)); });
SampleParams sample = {
.pass = i,
.samplesPerPixel = parameter.numSamples,
.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);
if (scene->getNumDirLights() > 0)
{
encoder->useResource(scene->directionalLightBuffer, MTL::ResourceUsageRead);
}
if (scene->getNumPointLights() > 0)
{
encoder->useResource(scene->pointLightBuffer, MTL::ResourceUsageRead);
}
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,
(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();
}
}
-109
View File
@@ -1,109 +0,0 @@
#include "MetalScene.h"
MetalScene::MetalScene(MTL::Device* device, MTL::CommandQueue* 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);
if(directionalLights.size() > 0)
{
directionalLightBuffer = device->newBuffer(directionalLights.size() * sizeof(decltype(directionalLights)::value_type), MTL::ResourceStorageModeShared);
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));
}
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));
MTL::AccelerationStructure** primitiveAccelerationStructures = new MTL::AccelerationStructure*[refs.size()];
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));
MTL::PrimitiveAccelerationStructureDescriptor* primitiveDescriptor = MTL::PrimitiveAccelerationStructureDescriptor::descriptor();
primitiveDescriptor->setGeometryDescriptors(NS::Array::array(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;
}
NS::Array* primitiveArray = NS::Array::array((const NS::Object* const*)primitiveAccelerationStructures, refs.size());
std::cout << primitiveArray->debugDescription()->cString(NS::ASCIIStringEncoding) << std::endl;
instanceBuffer = device->newBuffer(sizeof(MTL::AccelerationStructureInstanceDescriptor) * refs.size(), MTL::ResourceOptionCPUCacheModeDefault);
MTL::AccelerationStructureInstanceDescriptor* instanceDescriptors = (MTL::AccelerationStructureInstanceDescriptor*)instanceBuffer->contents();
for(uint i = 0; i < refs.size(); ++i)
{
instanceDescriptors[i].transformationMatrix[0][0] = 1.0f;
instanceDescriptors[i].transformationMatrix[1][0] = 0.0f;
instanceDescriptors[i].transformationMatrix[2][0] = 0.0f;
instanceDescriptors[i].transformationMatrix[3][0] = 0.0f;
instanceDescriptors[i].transformationMatrix[0][1] = 0.0f;
instanceDescriptors[i].transformationMatrix[1][1] = 1.0f;
instanceDescriptors[i].transformationMatrix[2][1] = 0.0f;
instanceDescriptors[i].transformationMatrix[3][1] = 0.0f;
instanceDescriptors[i].transformationMatrix[0][2] = 0.0f;
instanceDescriptors[i].transformationMatrix[1][2] = 0.0f;
instanceDescriptors[i].transformationMatrix[2][2] = 1.0f;
instanceDescriptors[i].transformationMatrix[3][2] = 0.0f;
instanceDescriptors[i].accelerationStructureIndex = i;
instanceDescriptors[i].options = MTL::AccelerationStructureInstanceOptionOpaque;
instanceDescriptors[i].mask = 0xff;
}
MTL::InstanceAccelerationStructureDescriptor* accelDesc = MTL::InstanceAccelerationStructureDescriptor::descriptor();
accelDesc->setInstancedAccelerationStructures(primitiveArray);
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();
}
+107
View File
@@ -0,0 +1,107 @@
#include "MetalScene.h"
MetalScene::MetalScene(MTL::Device* device, MTL::CommandQueue* 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);
if (directionalLights.size() > 0)
{
directionalLightBuffer =
device->newBuffer(directionalLights.size() * sizeof(decltype(directionalLights)::value_type), MTL::ResourceStorageModeShared);
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));
}
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()];
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));
MTL::PrimitiveAccelerationStructureDescriptor* primitiveDescriptor = MTL::PrimitiveAccelerationStructureDescriptor::descriptor();
primitiveDescriptor->setGeometryDescriptors(NS::Array::array(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];
}
instanceBuffer =
device->newBuffer(sizeof(MTL::AccelerationStructureInstanceDescriptor) * refs.size(), MTL::ResourceOptionCPUCacheModeDefault);
MTL::AccelerationStructureInstanceDescriptor* instanceDescriptors =
(MTL::AccelerationStructureInstanceDescriptor*)instanceBuffer->contents();
for (uint i = 0; i < refs.size(); ++i)
{
instanceDescriptors[i].transformationMatrix[0][0] = 1.0f;
instanceDescriptors[i].transformationMatrix[1][0] = 0.0f;
instanceDescriptors[i].transformationMatrix[2][0] = 0.0f;
instanceDescriptors[i].transformationMatrix[3][0] = 0.0f;
instanceDescriptors[i].transformationMatrix[0][1] = 0.0f;
instanceDescriptors[i].transformationMatrix[1][1] = 1.0f;
instanceDescriptors[i].transformationMatrix[2][1] = 0.0f;
instanceDescriptors[i].transformationMatrix[3][1] = 0.0f;
instanceDescriptors[i].transformationMatrix[0][2] = 0.0f;
instanceDescriptors[i].transformationMatrix[1][2] = 0.0f;
instanceDescriptors[i].transformationMatrix[2][2] = 1.0f;
instanceDescriptors[i].transformationMatrix[3][2] = 0.0f;
instanceDescriptors[i].accelerationStructureIndex = i;
instanceDescriptors[i].options = MTL::AccelerationStructureInstanceOptionOpaque;
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();
}
+1 -1
View File
@@ -3,4 +3,4 @@
#define MTL_PRIVATE_IMPLEMENTATION
#include <Foundation/Foundation.hpp>
#include <Metal/Metal.hpp>
#include <QuartzCore/QuartzCore.hpp>
#include <QuartzCore/QuartzCore.hpp>