i hate metal cpp
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
target_sources(RayTracer
|
||||
PRIVATE
|
||||
MetalRenderer.h
|
||||
MetalRenderer.cpp
|
||||
MetalRenderer.mm
|
||||
MetalScene.h
|
||||
MetalScene.cpp
|
||||
MetalScene.mm
|
||||
Compute.metal
|
||||
PrivateImpl.mm)
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -3,4 +3,4 @@
|
||||
#define MTL_PRIVATE_IMPLEMENTATION
|
||||
#include <Foundation/Foundation.hpp>
|
||||
#include <Metal/Metal.hpp>
|
||||
#include <QuartzCore/QuartzCore.hpp>
|
||||
#include <QuartzCore/QuartzCore.hpp>
|
||||
|
||||
Reference in New Issue
Block a user