lot of metal changes, but no idea how this stuff works

This commit is contained in:
Dynamitos
2025-02-14 00:39:53 +01:00
parent 52cbdd8470
commit ee03b5fa5f
31 changed files with 335 additions and 157 deletions
+1 -2
View File
@@ -96,8 +96,7 @@ class UniformBuffer : public Gfx::UniformBuffer {
virtual ~UniformBuffer();
virtual void updateContents(uint64 offset, uint64 size, void* data) override;
virtual void rotateBuffer(uint64 size) override;
void* getContents() const { return contents.data(); }
size_t getSize() const { return contents.size(); }
Array<uint8> getContents() const { return contents; }
protected:
// Inherited via QueueOwnedResource
+78 -19
View File
@@ -3,12 +3,14 @@
#include "Containers/Array.h"
#include "Descriptor.h"
#include "Enums.h"
#include "Graphics/Graphics.h"
#include "Graphics/Command.h"
#include "Graphics/Enums.h"
#include "Graphics/Graphics.h"
#include "Graphics/Resources.h"
#include "Metal/MTLArgumentEncoder.hpp"
#include "Metal/MTLCaptureManager.hpp"
#include "Metal/MTLLibrary.hpp"
#include "Metal/MTLRenderCommandEncoder.hpp"
#include "Pipeline.h"
#include "Resources.h"
#include "Window.h"
@@ -40,8 +42,7 @@ void Command::present(MTL::Drawable* drawable) { cmdBuffer->presentDrawable(draw
void Command::end(PEvent signal) {
assert(!parallelEncoder);
if(blitEncoder)
{
if (blitEncoder) {
blitEncoder->endEncoding();
}
if (signal != nullptr) {
@@ -51,9 +52,7 @@ void Command::end(PEvent signal) {
cmdBuffer->commit();
}
void Command::waitDeviceIdle() {
cmdBuffer->waitUntilCompleted();
}
void Command::waitDeviceIdle() { cmdBuffer->waitUntilCompleted(); }
void Command::signalEvent(PEvent event) { cmdBuffer->encodeSignalEvent(event->getHandle(), 1); }
@@ -80,7 +79,7 @@ void RenderCommand::setViewport(Gfx::PViewport viewport) {
void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline pipeline) {
boundPipeline = pipeline.cast<GraphicsPipeline>();
encoder->setRenderPipelineState(boundPipeline->getHandle());
if(boundPipeline->getPipelineLayout()->hasPushConstants()) {
if (boundPipeline->getPipelineLayout()->hasPushConstants()) {
constantsBuffer = boundPipeline->graphics->getDevice()->newBuffer(boundPipeline->getPipelineLayout()->getPushConstantsSize(), 0);
}
}
@@ -91,10 +90,46 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) {
auto metalSet = descriptorSet.cast<DescriptorSet>();
metalSet->bind();
uint32 descriptorIndex = boundPipeline->getPipelineLayout()->findParameter(metalSet->getLayout()->getName());
encoder->setVertexBuffer(metalSet->getArgumentBuffer(), 0, descriptorIndex);
encoder->setFragmentBuffer(metalSet->getArgumentBuffer(), 0, descriptorIndex);
encoder->setObjectBuffer(metalSet->getArgumentBuffer(), 0, descriptorIndex);
encoder->setMeshBuffer(metalSet->getArgumentBuffer(), 0, descriptorIndex);
auto createEncoder = [&metalSet, descriptorIndex](MTL::Function* function, const Array<uint32>& usedSets) {
if(metalSet->encoder == nullptr) {
if (metalSet->isPlainDescriptor()) {
metalSet->encoder = metalSet->createEncoder();
} else if (function != nullptr && usedSets.contains(descriptorIndex)) {
metalSet->encoder = function->newArgumentEncoder(descriptorIndex);
}
}
};
createEncoder(boundPipeline->taskFunction, boundPipeline->taskSets);
createEncoder(boundPipeline->meshFunction, boundPipeline->meshSets);
createEncoder(boundPipeline->vertexFunction, boundPipeline->vertexSets);
createEncoder(boundPipeline->fragmentFunction, boundPipeline->fragmentSets);
if(metalSet->argumentBuffer == nullptr) {
metalSet->argumentBuffer = metalSet->graphics->getDevice()->newBuffer(metalSet->encoder->encodedLength(), MTL::ResourceOptionCPUCacheModeDefault);
metalSet->encoder->setArgumentBuffer(metalSet->argumentBuffer, 0);
}
for (const auto& write : metalSet->uniformWrites) {
write.apply(metalSet->encoder);
}
for (const auto& write : metalSet->bufferWrites) {
write.apply(metalSet->encoder);
}
for (const auto& write : metalSet->samplerWrites) {
write.apply(metalSet->encoder);
}
for (const auto& write : metalSet->textureWrites) {
write.apply(metalSet->encoder);
}
for (const auto& write : metalSet->accelerationWrites) {
write.apply(metalSet->encoder);
}
encoder->setObjectBuffer(metalSet->argumentBuffer, 0, descriptorIndex);
encoder->setMeshBuffer(metalSet->argumentBuffer, 0, descriptorIndex);
encoder->setVertexBuffer(metalSet->argumentBuffer, 0, descriptorIndex);
encoder->setFragmentBuffer(metalSet->argumentBuffer, 0, descriptorIndex);
}
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets) {
@@ -163,7 +198,7 @@ void ComputeCommand::end() {
void ComputeCommand::bindPipeline(Gfx::PComputePipeline pipeline) {
boundPipeline = pipeline.cast<ComputePipeline>();
encoder->setComputePipelineState(boundPipeline->getHandle());
if(boundPipeline->getPipelineLayout()->hasPushConstants()) {
if (boundPipeline->getPipelineLayout()->hasPushConstants()) {
constantsBuffer = boundPipeline->graphics->getDevice()->newBuffer(boundPipeline->getPipelineLayout()->getPushConstantsSize(), 0);
}
}
@@ -172,7 +207,34 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set) {
auto metalSet = set.cast<DescriptorSet>();
metalSet->bind();
uint32 descriptorIndex = boundPipeline->getPipelineLayout()->findParameter(metalSet->getLayout()->getName());
encoder->setBuffer(metalSet->getArgumentBuffer(), 0, descriptorIndex);
if(metalSet->encoder == nullptr) {
if (metalSet->isPlainDescriptor()) {
metalSet->encoder = metalSet->createEncoder();
} else {
metalSet->encoder = boundPipeline->computeFunction->newArgumentEncoder(descriptorIndex);
}
metalSet->argumentBuffer = metalSet->graphics->getDevice()->newBuffer(metalSet->encoder->encodedLength(), MTL::ResourceOptionCPUCacheModeDefault);
metalSet->encoder->setArgumentBuffer(metalSet->argumentBuffer, 0);
}
for (const auto& write : metalSet->uniformWrites) {
write.apply(metalSet->encoder);
}
for (const auto& write : metalSet->bufferWrites) {
write.apply(metalSet->encoder);
}
for (const auto& write : metalSet->samplerWrites) {
write.apply(metalSet->encoder);
}
for (const auto& write : metalSet->textureWrites) {
write.apply(metalSet->encoder);
}
for (const auto& write : metalSet->accelerationWrites) {
write.apply(metalSet->encoder);
}
encoder->setBuffer(metalSet->argumentBuffer, 0, descriptorIndex);
}
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) {
@@ -192,7 +254,7 @@ void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) {
encoder->dispatchThreadgroups(MTL::Size(threadX, threadY, threadZ), MTL::Size(32, 32, 1));
}
void ComputeCommand::dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset){
void ComputeCommand::dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset) {
encoder->dispatchThreadgroups(buffer.cast<ShaderBuffer>()->getHandle(), offset, MTL::Size(32, 32, 1));
}
@@ -240,14 +302,11 @@ void CommandQueue::submitCommands(PEvent signalSemaphore) {
activeCommand->waitDeviceIdle();
PEvent prevCmdEvent = activeCommand->getCompletedEvent();
pendingCommands.add(std::move(activeCommand));
if(!readyCommands.empty())
{
if (!readyCommands.empty()) {
activeCommand = std::move(readyCommands.front());
readyCommands.removeAt(0);
activeCommand->waitForEvent(prevCmdEvent);
}
else
{
} else {
MTL::CommandBufferDescriptor* descriptor = MTL::CommandBufferDescriptor::alloc()->init();
descriptor->setErrorOptions(MTL::CommandBufferErrorOptionEncoderExecutionStatus);
activeCommand = new Command(graphics, queue->commandBuffer(descriptor));
+48 -3
View File
@@ -4,7 +4,9 @@
#include "Foundation/NSObject.hpp"
#include "Graphics/Descriptor.h"
#include "Graphics/Initializer.h"
#include "Graphics/Metal/Command.h"
#include "Graphics/Metal/Resources.h"
#include "Metal/MTLAccelerationStructure.hpp"
#include "Metal/MTLArgumentEncoder.hpp"
#include "Metal/MTLLibrary.hpp"
#include "Metal/MTLResource.hpp"
@@ -21,6 +23,7 @@ class DescriptorLayout : public Gfx::DescriptorLayout {
MTL::ArgumentEncoder* createEncoder();
uint32 getFlattenedIndex(uint32 binding, uint32 arrayIndex) const { return flattenMap.at(flattenIndex(binding, arrayIndex)); }
constexpr uint32 getTotalBindingCount() const { return flattenedBindingCount; }
constexpr bool isPlainDescriptor() const { return plainDescriptor; }
private:
constexpr uint64 flattenIndex(uint32 binding, uint32 arrayIndex) const { return uint64(arrayIndex) << 32 | binding; }
@@ -28,6 +31,9 @@ class DescriptorLayout : public Gfx::DescriptorLayout {
NS::Array* arguments;
Map<uint64, uint32> flattenMap;
uint32 flattenedBindingCount = 0;
// descriptor sets containing only uniform data are not actually argument buffers, so they need to be
// handled separately
bool plainDescriptor = true;
};
DEFINE_REF(DescriptorLayout)
@@ -62,15 +68,54 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource {
virtual void updateAccelerationStructure(uint32 binding, uint32 index, Gfx::PTopLevelAS as) override;
constexpr const Array<MTL::Resource*>& getBoundResources() const { return boundResources; }
MTL::Buffer* getArgumentBuffer() const { return argumentBuffer; }
constexpr bool isPlainDescriptor() const { return owner->getLayout()->isPlainDescriptor(); }
constexpr MTL::ArgumentEncoder* createEncoder() const { return owner->getLayout()->createEncoder(); }
private:
PGraphics graphics;
PDescriptorPool owner;
Array<MTL::Resource*> boundResources;
MTL::ArgumentEncoder* encoder;
MTL::Buffer* argumentBuffer = nullptr;
MTL::ArgumentEncoder* encoder = nullptr;
struct UniformWriteInfo
{
uint32 index;
Array<uint8> content;
void apply(MTL::ArgumentEncoder* encoder) const { std::memcpy(encoder->constantData(index), content.data(), content.size()); }
};
Array<UniformWriteInfo> uniformWrites;
struct BufferWriteInfo
{
uint32 index;
MTL::Buffer* buffer;
void apply(MTL::ArgumentEncoder* encoder) const { encoder->setBuffer(buffer, 0, 2); }
};
Array<BufferWriteInfo> bufferWrites;
struct TextureWriteInfo
{
uint32 index;
MTL::Texture* texture;
void apply(MTL::ArgumentEncoder* encoder) const { encoder->setTexture(texture, index); }
};
Array<TextureWriteInfo> textureWrites;
struct SamplerWriteInfo
{
uint32 index;
MTL::SamplerState* sampler;
void apply(MTL::ArgumentEncoder* encoder) const { encoder->setSamplerState(sampler, index); }
};
Array<SamplerWriteInfo> samplerWrites;
struct AccelerationStructureWriteInfo
{
uint32 index;
MTL::AccelerationStructure* accelerationStructure;
void apply(MTL::ArgumentEncoder* encoder) const { encoder->setAccelerationStructure(accelerationStructure, index); }
};
Array<AccelerationStructureWriteInfo> accelerationWrites;
friend class RenderCommand;
friend class ComputeCommand;
};
DEFINE_REF(DescriptorSet)
+42 -69
View File
@@ -34,65 +34,16 @@ void DescriptorLayout::create() {
MTL::ArgumentDescriptor** objects = new MTL::ArgumentDescriptor*[descriptorBindings.size()];
flattenedBindingCount = 0;
for (uint32 i = 0; i < descriptorBindings.size(); ++i) {
objects[i] = MTL::ArgumentDescriptor::alloc()->init();
objects[i]->setIndex(flattenedBindingCount);
objects[i]->setAccess(cast(descriptorBindings[i].access));
objects[i]->setArrayLength(descriptorBindings[i].descriptorCount);
MTL::DataType dataType;
switch (descriptorBindings[i].descriptorType) {
case Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case Gfx::SE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
case Gfx::SE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
dataType = MTL::DataTypeTexture;
break;
case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
dataType = MTL::DataTypePointer;
break;
case Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case Gfx::SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
dataType = MTL::DataTypeChar;
if(descriptorBindings[i].descriptorType != Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER) {
plainDescriptor = false;
} else {
objects[i] = MTL::ArgumentDescriptor::alloc()->init();
objects[i]->setIndex(flattenedBindingCount);
objects[i]->setAccess(cast(descriptorBindings[i].access));
objects[i]->setArrayLength(descriptorBindings[i].descriptorCount);
objects[i]->setDataType(MTL::DataTypeChar);
objects[i]->setArrayLength(descriptorBindings[i].uniformLength);
break;
case Gfx::SE_DESCRIPTOR_TYPE_SAMPLER:
dataType = MTL::DataTypeSampler;
break;
case Gfx::SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
dataType = MTL::DataTypeInstanceAccelerationStructure;
break;
default:
throw new std::logic_error("unknown descriptor type");
}
objects[i]->setDataType(dataType);
MTL::TextureType textureType;
switch (descriptorBindings[i].textureType) {
case Gfx::SE_IMAGE_VIEW_TYPE_1D:
textureType = MTL::TextureType1D;
break;
case Gfx::SE_IMAGE_VIEW_TYPE_2D:
textureType = MTL::TextureType2D;
break;
case Gfx::SE_IMAGE_VIEW_TYPE_3D:
textureType = MTL::TextureType3D;
break;
case Gfx::SE_IMAGE_VIEW_TYPE_CUBE:
textureType = MTL::TextureTypeCube;
break;
case Gfx::SE_IMAGE_VIEW_TYPE_1D_ARRAY:
textureType = MTL::TextureType1DArray;
break;
case Gfx::SE_IMAGE_VIEW_TYPE_2D_ARRAY:
textureType = MTL::TextureType2DArray;
break;
case Gfx::SE_IMAGE_VIEW_TYPE_CUBE_ARRAY:
textureType = MTL::TextureTypeCubeArray;
break;
}
objects[i]->setTextureType(textureType);
for(uint32 j = 0; j < descriptorBindings[i].descriptorCount; ++j) {
flattenMap[flattenIndex(i, j)] = flattenedBindingCount++;
}
@@ -124,10 +75,6 @@ void DescriptorPool::reset() {}
DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner)
: Gfx::DescriptorSet(owner->getLayout()), CommandBoundResource(graphics), graphics(graphics), owner(owner) {
encoder = owner->getLayout()->createEncoder();
argumentBuffer = graphics->getDevice()->newBuffer(encoder->encodedLength(), 0);
std::cout << owner->getLayout()->getName() << ": " << encoder->encodedLength() << std::endl;
encoder->setArgumentBuffer(argumentBuffer, 0);
boundResources.resize(owner->getLayout()->getTotalBindingCount());
}
@@ -138,56 +85,82 @@ void DescriptorSet::writeChanges() {}
void DescriptorSet::updateBuffer(uint32 binding, uint32 index, Gfx::PUniformBuffer uniformBuffer) {
uint32 flattenedIndex = owner->getLayout()->getFlattenedIndex(binding, index);
PUniformBuffer buffer = uniformBuffer.cast<UniformBuffer>();
std::memcpy(encoder->constantData(flattenedIndex), buffer->getContents(), buffer->getSize());
boundResources[flattenedIndex] = nullptr;
uniformWrites.add(UniformWriteInfo{
.index = flattenedIndex,
.content = buffer->getContents(),
});
}
void DescriptorSet::updateBuffer(uint32 binding, uint32 index, Gfx::PShaderBuffer uniformBuffer) {
uint32 flattenedIndex = owner->getLayout()->getFlattenedIndex(binding, index);
PShaderBuffer buffer = uniformBuffer.cast<ShaderBuffer>();
encoder->setBuffer(buffer->getHandle(), 0, flattenedIndex);
boundResources[flattenedIndex] = buffer->getHandle();
bufferWrites.add(BufferWriteInfo{
.index = flattenedIndex,
.buffer = buffer->getHandle(),
});
}
void DescriptorSet::updateBuffer(uint32 binding, uint32 index, Gfx::PVertexBuffer uniformBuffer) {
uint32 flattenedIndex = owner->getLayout()->getFlattenedIndex(binding, index);
PVertexBuffer buffer = uniformBuffer.cast<VertexBuffer>();
encoder->setBuffer(buffer->getHandle(), 0, flattenedIndex);
boundResources[flattenedIndex] = buffer->getHandle();
bufferWrites.add(BufferWriteInfo{
.index = flattenedIndex,
.buffer = buffer->getHandle(),
});
}
void DescriptorSet::updateBuffer(uint32 binding, uint32 index, Gfx::PIndexBuffer uniformBuffer) {
uint32 flattenedIndex = owner->getLayout()->getFlattenedIndex(binding, index);
PIndexBuffer buffer = uniformBuffer.cast<IndexBuffer>();
encoder->setBuffer(buffer->getHandle(), 0, flattenedIndex);
boundResources[flattenedIndex] = buffer->getHandle();
bufferWrites.add(BufferWriteInfo{
.index = flattenedIndex,
.buffer = buffer->getHandle(),
});
}
void DescriptorSet::updateSampler(uint32 binding, uint32 index, Gfx::PSampler samplerState) {
uint32 flattenedIndex = owner->getLayout()->getFlattenedIndex(binding, index);
PSampler sampler = samplerState.cast<Sampler>();
encoder->setSamplerState(sampler->getHandle(), flattenedIndex);
boundResources[flattenedIndex] = nullptr;
samplerWrites.add(SamplerWriteInfo{
.index = flattenedIndex,
.sampler = sampler->getHandle(),
});
boundResources[flattenedIndex] = nullptr; // Samplers are not resources??????
}
void DescriptorSet::updateTexture(uint32 binding, uint32 index, Gfx::PTexture2D texture) {
uint32 flattenedIndex = owner->getLayout()->getFlattenedIndex(binding, index);
PTextureBase tex = texture.cast<TextureBase>();
encoder->setTexture(tex->getImage(), flattenedIndex);
boundResources[flattenedIndex] = tex->getImage();
textureWrites.add(TextureWriteInfo{
.index = flattenedIndex,
.texture = tex->getImage(),
});
}
void DescriptorSet::updateTexture(uint32 binding, uint32 index, Gfx::PTexture3D texture) {
uint32 flattenedIndex = owner->getLayout()->getFlattenedIndex(binding, index);
PTextureBase tex = texture.cast<TextureBase>();
encoder->setTexture(tex->getImage(), flattenedIndex);
boundResources[flattenedIndex] = tex->getImage();
textureWrites.add(TextureWriteInfo{
.index = flattenedIndex,
.texture = tex->getImage(),
});
}
void DescriptorSet::updateTexture(uint32 binding, uint32 index, Gfx::PTextureCube texture) {
uint32 flattenedIndex = owner->getLayout()->getFlattenedIndex(binding, index);
PTextureBase tex = texture.cast<TextureBase>();
encoder->setTexture(tex->getImage(), flattenedIndex);
boundResources[flattenedIndex] = tex->getImage();
textureWrites.add(TextureWriteInfo{
.index = flattenedIndex,
.texture = tex->getImage(),
});
}
void DescriptorSet::updateAccelerationStructure(uint32 binding, uint32 index, Gfx::PTopLevelAS as) { assert(false && "TODO"); }
+1
View File
@@ -22,6 +22,7 @@ class Graphics : public Gfx::Graphics {
virtual void endRenderPass() override;
virtual void waitDeviceIdle() override;
virtual void executeCommands(Gfx::ORenderCommand commands) override;
virtual void executeCommands(Array<Gfx::ORenderCommand> commands) override;
virtual void executeCommands(Gfx::OComputeCommand commands) override;
virtual void executeCommands(Array<Gfx::OComputeCommand> commands) override;
+6
View File
@@ -50,6 +50,12 @@ void Graphics::waitDeviceIdle() {
queue->submitCommands();
}
void Graphics::executeCommands(Gfx::ORenderCommand commands) {
Array<Gfx::ORenderCommand> command;
command.add(std::move(commands));
queue->executeCommands(std::move(command));
}
void Graphics::executeCommands(Array<Gfx::ORenderCommand> commands) { queue->executeCommands(std::move(commands)); }
void Graphics::executeCommands(Gfx::OComputeCommand commands) {
+9
View File
@@ -22,6 +22,14 @@ class GraphicsPipeline : public Gfx::GraphicsPipeline {
PGraphics graphics;
MTL::RenderPipelineState* state;
MTL::PrimitiveType primitiveType;
MTL::Function* taskFunction = nullptr;
Array<uint32> taskSets;
MTL::Function* meshFunction = nullptr;
Array<uint32> meshSets;
MTL::Function* vertexFunction = nullptr;
Array<uint32> vertexSets;
MTL::Function* fragmentFunction = nullptr;
Array<uint32> fragmentSets;
private:
};
@@ -33,6 +41,7 @@ class ComputePipeline : public Gfx::ComputePipeline {
constexpr MTL::ComputePipelineState* getHandle() const { return state; }
PGraphics graphics;
MTL::Function* computeFunction;
private:
MTL::ComputePipelineState* state;
+39 -6
View File
@@ -1,6 +1,7 @@
#include "PipelineCache.h"
#include "Descriptor.h"
#include "Enums.h"
#include "Metal/MTLLibrary.hpp"
#include "RenderPass.h"
#include "Foundation/NSError.hpp"
#include "Foundation/NSString.hpp"
@@ -62,10 +63,17 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo cr
}
}
pipelineDescriptor->setVertexDescriptor(vertexDescriptor);
pipelineDescriptor->setVertexFunction(createInfo.vertexShader.cast<VertexShader>()->getFunction());
auto vertShader = createInfo.vertexShader.cast<VertexShader>();
Array<uint32> vertexSets = vertShader->usedDescriptors;
MTL::Function* vertexFunction = vertShader->getFunction();
Array<uint32> fragmentSets;
MTL::Function* fragmentFunction = nullptr;
pipelineDescriptor->setVertexFunction(vertexFunction);
if (createInfo.fragmentShader != nullptr) {
pipelineDescriptor->setFragmentFunction(createInfo.fragmentShader.cast<FragmentShader>()->getFunction());
auto fragShader = createInfo.fragmentShader.cast<FragmentShader>();
fragmentSets = fragShader->usedDescriptors;
fragmentFunction = fragShader->getFunction();
pipelineDescriptor->setFragmentFunction(fragmentFunction);
}
pipelineDescriptor->setInputPrimitiveTopology(cast(createInfo.topology));
for(uint c = 0; c < renderPass->getLayout().colorAttachments.size(); ++c) {
@@ -137,6 +145,10 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo cr
}
pipelineDescriptor->release();
graphicsPipelines[hash]->vertexSets = vertexSets;
graphicsPipelines[hash]->vertexFunction = vertexFunction;
graphicsPipelines[hash]->fragmentSets = fragmentSets;
graphicsPipelines[hash]->fragmentFunction = fragmentFunction;
return graphicsPipelines[hash];
}
@@ -144,12 +156,25 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo crea
PRenderPass renderPass = createInfo.renderPass.cast<RenderPass>();
MTL::MeshRenderPipelineDescriptor* pipelineDescriptor = MTL::MeshRenderPipelineDescriptor::alloc()->init();
pipelineDescriptor->setMeshFunction(createInfo.meshShader.cast<MeshShader>()->getFunction());
auto meshShader = createInfo.meshShader.cast<MeshShader>();
Array<uint32> meshSets = meshShader->usedDescriptors;
MTL::Function* meshFunction = meshShader->getFunction();
Array<uint32> taskSets;
MTL::Function* taskFunction = nullptr;
Array<uint32> fragmentSets;
MTL::Function* fragmentFunction = nullptr;
pipelineDescriptor->setMeshFunction(meshFunction);
if (createInfo.taskShader != nullptr) {
pipelineDescriptor->setObjectFunction(createInfo.taskShader.cast<TaskShader>()->getFunction());
auto taskShader = createInfo.taskShader.cast<TaskShader>();
taskSets = taskShader->usedDescriptors;
taskFunction = taskShader->getFunction();
pipelineDescriptor->setObjectFunction(taskFunction);
}
if (createInfo.fragmentShader != nullptr) {
pipelineDescriptor->setFragmentFunction(createInfo.fragmentShader.cast<FragmentShader>()->getFunction());
auto fragShader = createInfo.fragmentShader.cast<FragmentShader>();
fragmentSets = fragShader->usedDescriptors;
fragmentFunction = fragShader->getFunction();
pipelineDescriptor->setFragmentFunction(fragmentFunction);
}
for(uint c = 0; c < renderPass->getLayout().colorAttachments.size(); ++c) {
const auto& color = renderPass->getLayout().colorAttachments[c];
@@ -187,6 +212,13 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo crea
}
pipelineDescriptor->release();
graphicsPipelines[hash]->taskSets = taskSets;
graphicsPipelines[hash]->taskFunction = taskFunction;
graphicsPipelines[hash]->meshSets = meshSets;
graphicsPipelines[hash]->meshFunction = meshFunction;
graphicsPipelines[hash]->fragmentSets = fragmentSets;
graphicsPipelines[hash]->fragmentFunction = fragmentFunction;
return graphicsPipelines[hash];
}
@@ -201,5 +233,6 @@ PComputePipeline PipelineCache::createPipeline(Gfx::ComputePipelineCreateInfo cr
computePipelines[hash] = new ComputePipeline(graphics, graphics->getDevice()->newComputePipelineState(shader->getFunction(), &error),
std::move(createInfo.pipelineLayout));
assert(!error);
computePipelines[hash]->computeFunction = shader->getFunction();
return computePipelines[hash];
}
+8 -1
View File
@@ -25,7 +25,14 @@ class Shader {
PGraphics graphics;
MTL::Library* library;
MTL::Function* function;
// since metal is stupid and doesnt let us create argument encoders for
// descriptors of stages that dont use them, we have to track
// which stage uses what descriptors, which makes sense since functions are independent
// but since metal ALSO doesnt provide any way to find out we have to
// literally manually string search the generated code to find out
Array<uint32> usedDescriptors;
uint32 hash;
friend class PipelineCache;
};
DEFINE_REF(Shader)
@@ -60,4 +67,4 @@ DEFINE_REF(AnyHitShader)
DEFINE_REF(MissShader)
DEFINE_REF(CallableShader)
} // namespace Metal
} // namespace Seele
} // namespace Seele
+11 -3
View File
@@ -10,6 +10,7 @@
#include <fstream>
#include <iostream>
#include <slang.h>
#include <regex>
using namespace Seele;
using namespace Seele::Metal;
@@ -26,9 +27,16 @@ Shader::~Shader() {
void Shader::create(const ShaderCreateInfo& createInfo) {
auto [kernelBlob, entryPoint] = generateShader(createInfo);
hash = CRC::Calculate(kernelBlob->getBufferPointer(), kernelBlob->getBufferSize(), CRC::CRC_32());
std::ofstream test("test.metal");
test.write((const char*)kernelBlob->getBufferPointer(), kernelBlob->getBufferSize());
test.close();
std::regex pattern("\\[\\[buffer\\(\\d+\\)\\]\\]");
std::string codeStr = std::string((const char*)kernelBlob->getBufferPointer());
auto matches_begin = std::sregex_iterator(codeStr.begin(), codeStr.end(), pattern);
auto matches_end = std::sregex_iterator();
for (auto it = matches_begin; it != matches_end; ++it) {
usedDescriptors.add(std::atoi((*it).str().c_str()+9)); // [[buffer( is 9 characters
}
NS::Error* error;
MTL::CompileOptions* options = MTL::CompileOptions::alloc()->init();
library = graphics->getDevice()->newLibrary(NS::String::string((char*)kernelBlob->getBufferPointer(), NS::ASCIIStringEncoding), options,