Descriptor sets and refactoring
This commit is contained in:
@@ -7,65 +7,80 @@
|
||||
namespace Seele {
|
||||
namespace Metal {
|
||||
DECLARE_REF(Graphics)
|
||||
class Buffer
|
||||
{
|
||||
class Buffer {
|
||||
public:
|
||||
Buffer(PGraphics graphics, uint64 size, void* data, bool dynamic);
|
||||
Buffer(PGraphics graphics, uint64 size, void *data, bool dynamic);
|
||||
virtual ~Buffer();
|
||||
MTL::Buffer* getHandle() const
|
||||
{
|
||||
return buffers[currentBuffer];
|
||||
}
|
||||
uint64 getSize() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
void advanceBuffer()
|
||||
{
|
||||
currentBuffer = (currentBuffer + 1) % numBuffers;
|
||||
}
|
||||
void* map(bool writeOnly = true);
|
||||
void* mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly);
|
||||
MTL::Buffer *getHandle() const { return buffers[currentBuffer]; }
|
||||
uint64 getSize() const { return size; }
|
||||
void advanceBuffer() { currentBuffer = (currentBuffer + 1) % numBuffers; }
|
||||
void *map(bool writeOnly = true);
|
||||
void *mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly);
|
||||
void unmap();
|
||||
private:
|
||||
|
||||
protected:
|
||||
PGraphics graphics;
|
||||
uint32 currentBuffer;
|
||||
uint64 size;
|
||||
MTL::Buffer* buffers[Gfx::numFramesBuffered];
|
||||
MTL::Buffer *buffers[Gfx::numFramesBuffered];
|
||||
uint32 numBuffers;
|
||||
};
|
||||
DEFINE_REF(Buffer)
|
||||
class VertexBuffer : public Gfx::VertexBuffer, public Buffer
|
||||
{
|
||||
class VertexBuffer : public Gfx::VertexBuffer, public Buffer {
|
||||
public:
|
||||
VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo& createInfo);
|
||||
VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &createInfo);
|
||||
virtual ~VertexBuffer();
|
||||
private:
|
||||
virtual void updateRegion(DataSource update) override;
|
||||
virtual void download(Array<uint8> &buffer) override;
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override;
|
||||
virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
|
||||
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
|
||||
};
|
||||
DEFINE_REF(VertexBuffer)
|
||||
class IndexBuffer : public Gfx::IndexBuffer, public Buffer
|
||||
{
|
||||
class IndexBuffer : public Gfx::IndexBuffer, public Buffer {
|
||||
public:
|
||||
IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& createInfo);
|
||||
IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &createInfo);
|
||||
virtual ~IndexBuffer();
|
||||
private:
|
||||
|
||||
virtual void download(Array<uint8> &buffer) override;
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override;
|
||||
virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
|
||||
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
|
||||
};
|
||||
DEFINE_REF(IndexBuffer)
|
||||
class UniformBuffer : public Gfx::UniformBuffer, public Buffer
|
||||
{
|
||||
DEFINE_REF(IndexBuffer)
|
||||
class UniformBuffer : public Gfx::UniformBuffer, public Buffer {
|
||||
public:
|
||||
UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo& createInfo);
|
||||
UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &createInfo);
|
||||
virtual ~UniformBuffer();
|
||||
private:
|
||||
|
||||
virtual bool updateContents(const DataSource &sourceData) override;
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override;
|
||||
virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
|
||||
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
|
||||
};
|
||||
DEFINE_REF(UniformBuffer)
|
||||
class ShaderBuffer : public Gfx::ShaderBuffer, public Buffer
|
||||
{
|
||||
class ShaderBuffer : public Gfx::ShaderBuffer, public Buffer {
|
||||
public:
|
||||
ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& createInfo);
|
||||
ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &createInfo);
|
||||
virtual ~ShaderBuffer();
|
||||
private:
|
||||
|
||||
virtual bool updateContents(const DataSource &sourceData) override;
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override;
|
||||
virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
|
||||
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
|
||||
};
|
||||
DEFINE_REF(ShaderBuffer)
|
||||
}
|
||||
}
|
||||
} // namespace Metal
|
||||
} // namespace Seele
|
||||
@@ -8,8 +8,7 @@
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
|
||||
Buffer::Buffer(PGraphics graphics, uint64 size, void *data, bool dynamic)
|
||||
: graphics(graphics), size(size) {
|
||||
Buffer::Buffer(PGraphics graphics, uint64 size, void* data, bool dynamic) : graphics(graphics), size(size) {
|
||||
if (dynamic) {
|
||||
numBuffers = Gfx::numFramesBuffered;
|
||||
} else {
|
||||
@@ -17,11 +16,9 @@ Buffer::Buffer(PGraphics graphics, uint64 size, void *data, bool dynamic)
|
||||
}
|
||||
for (size_t i = 0; i < numBuffers; ++i) {
|
||||
if (data != nullptr) {
|
||||
buffers[i] = graphics->getDevice()->newBuffer(
|
||||
data, size, MTL::ResourceOptionCPUCacheModeDefault);
|
||||
buffers[i] = graphics->getDevice()->newBuffer(data, size, MTL::ResourceOptionCPUCacheModeDefault);
|
||||
} else {
|
||||
buffers[i] = graphics->getDevice()->newBuffer(
|
||||
size, MTL::ResourceOptionCPUCacheModeDefault);
|
||||
buffers[i] = graphics->getDevice()->newBuffer(size, MTL::ResourceOptionCPUCacheModeDefault);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,45 +29,83 @@ Buffer::~Buffer() {
|
||||
}
|
||||
}
|
||||
|
||||
void *Buffer::map(bool) { return getHandle()->contents(); }
|
||||
void* Buffer::map(bool) { return getHandle()->contents(); }
|
||||
|
||||
void *Buffer::mapRegion(uint64 regionOffset, uint64, bool) {
|
||||
return (char *)getHandle()->contents() + regionOffset;
|
||||
}
|
||||
void* Buffer::mapRegion(uint64 regionOffset, uint64, bool) { return (char*)getHandle()->contents() + regionOffset; }
|
||||
|
||||
void unmap() {}
|
||||
|
||||
VertexBuffer::VertexBuffer(PGraphics graphics,
|
||||
const VertexBufferCreateInfo &createInfo)
|
||||
: Gfx::VertexBuffer(graphics->getFamilyMapping(), createInfo.numVertices,
|
||||
createInfo.vertexSize, createInfo.sourceData.owner),
|
||||
Seele::Metal::Buffer(graphics, createInfo.sourceData.size,
|
||||
createInfo.sourceData.data, false) {}
|
||||
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo& createInfo)
|
||||
: Gfx::VertexBuffer(graphics->getFamilyMapping(), createInfo.numVertices, createInfo.vertexSize,
|
||||
createInfo.sourceData.owner),
|
||||
Seele::Metal::Buffer(graphics, createInfo.sourceData.size, createInfo.sourceData.data, false) {}
|
||||
|
||||
VertexBuffer::~VertexBuffer() {}
|
||||
|
||||
IndexBuffer::IndexBuffer(PGraphics graphics,
|
||||
const IndexBufferCreateInfo &createInfo)
|
||||
: Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo.sourceData.size,
|
||||
createInfo.indexType, createInfo.sourceData.owner),
|
||||
Seele::Metal::Buffer(graphics, createInfo.sourceData.size,
|
||||
createInfo.sourceData.data, false) {}
|
||||
void VertexBuffer::updateRegion(DataSource update) {
|
||||
void* data = getHandle()->contents();
|
||||
std::memcpy((char*)data + update.offset, update.data, update.size);
|
||||
}
|
||||
|
||||
void VertexBuffer::download(Array<uint8>& buffer) {
|
||||
void* data = getHandle()->contents();
|
||||
buffer.resize(size);
|
||||
std::memcpy(buffer.data(), data, size);
|
||||
}
|
||||
|
||||
void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { currentOwner = newOwner; }
|
||||
|
||||
void VertexBuffer::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
|
||||
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) {}
|
||||
|
||||
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& createInfo)
|
||||
: Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo.sourceData.size, createInfo.indexType,
|
||||
createInfo.sourceData.owner),
|
||||
Seele::Metal::Buffer(graphics, createInfo.sourceData.size, createInfo.sourceData.data, false) {}
|
||||
|
||||
IndexBuffer::~IndexBuffer() {}
|
||||
|
||||
UniformBuffer::UniformBuffer(PGraphics graphics,
|
||||
const UniformBufferCreateInfo &createInfo)
|
||||
void IndexBuffer::download(Array<uint8>& buffer) {
|
||||
void* data = getHandle()->contents();
|
||||
buffer.resize(size);
|
||||
std::memcpy(buffer.data(), data, size);
|
||||
}
|
||||
void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { currentOwner = newOwner; }
|
||||
|
||||
void IndexBuffer::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
|
||||
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) {}
|
||||
|
||||
UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo& createInfo)
|
||||
: Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.sourceData),
|
||||
Seele::Metal::Buffer(graphics, createInfo.sourceData.size,
|
||||
createInfo.sourceData.data, createInfo.dynamic) {}
|
||||
Seele::Metal::Buffer(graphics, createInfo.sourceData.size, createInfo.sourceData.data, createInfo.dynamic) {}
|
||||
|
||||
UniformBuffer::~UniformBuffer() {}
|
||||
|
||||
ShaderBuffer::ShaderBuffer(PGraphics graphics,
|
||||
const ShaderBufferCreateInfo &createInfo)
|
||||
: Gfx::ShaderBuffer(graphics->getFamilyMapping(), createInfo.numElements,
|
||||
createInfo.sourceData),
|
||||
Seele::Metal::Buffer(graphics, createInfo.sourceData.size,
|
||||
createInfo.sourceData.data, createInfo.dynamic) {}
|
||||
bool UniformBuffer::updateContents(const DataSource& sourceData) {
|
||||
void* data = getHandle()->contents();
|
||||
std::memcpy((char*)data + sourceData.offset, sourceData.data, sourceData.size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { currentOwner = newOwner; }
|
||||
|
||||
void UniformBuffer::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
|
||||
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) {}
|
||||
|
||||
ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& createInfo)
|
||||
: Gfx::ShaderBuffer(graphics->getFamilyMapping(), createInfo.numElements, createInfo.sourceData),
|
||||
Seele::Metal::Buffer(graphics, createInfo.sourceData.size, createInfo.sourceData.data, createInfo.dynamic) {}
|
||||
|
||||
ShaderBuffer::~ShaderBuffer() {}
|
||||
|
||||
bool ShaderBuffer::updateContents(const DataSource& sourceData) {
|
||||
void* data = getHandle()->contents();
|
||||
std::memcpy((char*)data + sourceData.offset, sourceData.data, sourceData.size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { currentOwner = newOwner; }
|
||||
|
||||
|
||||
void ShaderBuffer::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
|
||||
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) {}
|
||||
@@ -12,6 +12,8 @@ target_sources(Engine
|
||||
Graphics.mm
|
||||
Pipeline.h
|
||||
Pipeline.mm
|
||||
PipelineCache.h
|
||||
PipelineCache.mm
|
||||
PrivateImpl.mm
|
||||
RenderPass.h
|
||||
RenderPass.mm
|
||||
|
||||
@@ -8,64 +8,75 @@
|
||||
namespace Seele {
|
||||
namespace Metal {
|
||||
DECLARE_REF(Graphics)
|
||||
DECLARE_REF(DescriptorPool)
|
||||
class DescriptorLayout : public Gfx::DescriptorLayout {
|
||||
public:
|
||||
DescriptorLayout(PGraphics graphics, const std::string &name);
|
||||
DescriptorLayout(PGraphics graphics, const std::string& name);
|
||||
virtual ~DescriptorLayout();
|
||||
virtual void create() override;
|
||||
NS::Array* getArguments() const
|
||||
{
|
||||
return arguments;
|
||||
}
|
||||
|
||||
NS::Array* getArguments() const { return arguments; }
|
||||
|
||||
private:
|
||||
PGraphics graphics;
|
||||
NS::Array* arguments;
|
||||
};
|
||||
class PipelineLayout : public Gfx::PipelineLayout {
|
||||
DEFINE_REF(DescriptorLayout)
|
||||
|
||||
DECLARE_REF(DescriptorSet)
|
||||
class DescriptorPool : public Gfx::DescriptorPool {
|
||||
public:
|
||||
PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout)
|
||||
: Gfx::PipelineLayout(baseLayout), graphics(graphics) {}
|
||||
DescriptorPool(PGraphics graphics, PDescriptorLayout layout);
|
||||
virtual ~DescriptorPool();
|
||||
virtual Gfx::PDescriptorSet allocateDescriptorSet() override;
|
||||
virtual void reset() override;
|
||||
constexpr NS::Array* getArguments() const { return layout->getArguments(); }
|
||||
constexpr PDescriptorLayout getLayout() const { return layout; }
|
||||
|
||||
private:
|
||||
PGraphics graphics;
|
||||
PDescriptorLayout layout;
|
||||
Array<ODescriptorSet> allocatedSets;
|
||||
};
|
||||
DEFINE_REF(PipelineLayout)
|
||||
DEFINE_REF(DescriptorPool)
|
||||
|
||||
class DescriptorSet : public Gfx::DescriptorSet {
|
||||
public:
|
||||
DescriptorSet(PGraphics graphics, PDescriptorPool owner);
|
||||
virtual ~DescriptorSet();
|
||||
virtual void writeChanges();
|
||||
virtual void updateBuffer(uint32_t binding,
|
||||
Gfx::PUniformBuffer uniformBuffer);
|
||||
virtual void updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer);
|
||||
virtual void updateBuffer(uint32_t binding, Gfx::PShaderBuffer uniformBuffer);
|
||||
virtual void updateSampler(uint32_t binding, Gfx::PSampler samplerState);
|
||||
virtual void updateTexture(uint32_t binding, Gfx::PTexture texture,
|
||||
Gfx::PSampler sampler = nullptr);
|
||||
virtual void updateTextureArray(uint32_t binding,
|
||||
Array<Gfx::PTexture> texture);
|
||||
virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler sampler = nullptr);
|
||||
virtual void updateTextureArray(uint32_t binding, Array<Gfx::PTexture> texture);
|
||||
virtual bool operator<(Gfx::PDescriptorSet other);
|
||||
|
||||
constexpr bool isCurrentlyBound() const { return bindCount > 0; }
|
||||
constexpr bool isCurrentlyInUse() const { return currentlyInUse; }
|
||||
constexpr void bind() { bindCount++; }
|
||||
constexpr void unbind() { bindCount--; }
|
||||
constexpr void allocate() { currentlyInUse = true; }
|
||||
constexpr void free() { currentlyInUse = false; }
|
||||
|
||||
private:
|
||||
PGraphics graphics;
|
||||
PDescriptorPool owner;
|
||||
MTL::Buffer* buffer;
|
||||
MTL::ArgumentEncoder* encoder;
|
||||
uint32 bindCount;
|
||||
bool currentlyInUse;
|
||||
};
|
||||
DEFINE_REF(DescriptorSet)
|
||||
|
||||
class DescriptorPool : public Gfx::DescriptorPool {
|
||||
class PipelineLayout : public Gfx::PipelineLayout {
|
||||
public:
|
||||
DescriptorPool(PGraphics graphics, DescriptorLayout& layout);
|
||||
virtual ~DescriptorPool();
|
||||
NS::Array* getArguments() const
|
||||
{
|
||||
return layout.getArguments();
|
||||
}
|
||||
PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout);
|
||||
virtual ~PipelineLayout();
|
||||
virtual void create() override;
|
||||
|
||||
private:
|
||||
PGraphics graphics;
|
||||
DescriptorLayout& layout;
|
||||
};
|
||||
DEFINE_REF(PipelineLayout)
|
||||
} // namespace Metal
|
||||
} // namespace Seele
|
||||
@@ -1,28 +1,128 @@
|
||||
#include "Descriptor.h"
|
||||
#include "Graphics.h"
|
||||
#include "Buffer.h"
|
||||
#include "Enums.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Texture.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
|
||||
DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner)
|
||||
: graphics(graphics)
|
||||
, owner(owner)
|
||||
{
|
||||
encoder = graphics->getDevice()->newArgumentEncoder(owner->getArguments());
|
||||
}
|
||||
DescriptorSet::~DescriptorSet()
|
||||
{
|
||||
}
|
||||
void DescriptorSet::writeChanges()
|
||||
{
|
||||
DescriptorLayout::DescriptorLayout(PGraphics graphics, const std::string& name)
|
||||
: Gfx::DescriptorLayout(name), graphics(graphics) {}
|
||||
|
||||
DescriptorLayout::~DescriptorLayout() {}
|
||||
|
||||
void DescriptorLayout::create() {
|
||||
Array<NS::Object*> descriptors;
|
||||
for (size_t i = 0; i < descriptorBindings.size(); ++i) {
|
||||
const auto& binding = descriptorBindings[i];
|
||||
auto desc = MTL::ArgumentDescriptor::alloc()->init();
|
||||
desc->setAccess(cast(binding.access));
|
||||
desc->setArrayLength(binding.descriptorCount);
|
||||
MTL::DataType dataType;
|
||||
switch (binding.descriptorType) {
|
||||
case Gfx::SE_DESCRIPTOR_TYPE_SAMPLER:
|
||||
case Gfx::SE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||
case Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||
case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||
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_UNIFORM_BUFFER:
|
||||
case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||
case Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||
case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||
case Gfx::SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
|
||||
dataType = MTL::DataTypeStruct;
|
||||
break;
|
||||
case Gfx::SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
|
||||
dataType = MTL::DataTypePrimitiveAccelerationStructure;
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("Nooo");
|
||||
}
|
||||
desc->setDataType(dataType);
|
||||
descriptors.add(desc);
|
||||
}
|
||||
arguments = NS::Array::array(descriptors.data(), descriptors.size());
|
||||
}
|
||||
|
||||
void DescriptorSet::updateBuffer(uint32_t binding,
|
||||
Gfx::PUniformBuffer uniformBuffer){}
|
||||
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer uniformBuffer){}
|
||||
void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState){}
|
||||
void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture,
|
||||
Gfx::PSampler sampler){}
|
||||
void DescriptorSet::updateTextureArray(uint32_t binding,
|
||||
Array<Gfx::PTexture> texture){}
|
||||
bool DescriptorSet::operator<(Gfx::PDescriptorSet other){return this < other.getHandle();}
|
||||
DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout) : graphics(graphics), layout(layout) {}
|
||||
|
||||
DescriptorPool::~DescriptorPool() {}
|
||||
|
||||
Gfx::PDescriptorSet DescriptorPool::allocateDescriptorSet() {
|
||||
for (uint32 setIndex = 0; setIndex < allocatedSets.size(); ++setIndex) {
|
||||
if (allocatedSets[setIndex]->isCurrentlyBound() || allocatedSets[setIndex]->isCurrentlyInUse()) {
|
||||
// Currently in use, skip
|
||||
continue;
|
||||
}
|
||||
allocatedSets[setIndex]->allocate();
|
||||
|
||||
// Found set, stop searching
|
||||
return PDescriptorSet(allocatedSets[setIndex]);
|
||||
}
|
||||
allocatedSets.add(new DescriptorSet(graphics, this));
|
||||
return PDescriptorSet(allocatedSets.back());
|
||||
}
|
||||
|
||||
void DescriptorPool::reset() {
|
||||
for (auto& set : allocatedSets) {
|
||||
set->free();
|
||||
}
|
||||
}
|
||||
|
||||
DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner)
|
||||
: Gfx::DescriptorSet(owner->getLayout()), graphics(graphics), owner(owner), bindCount(0), currentlyInUse(false) {
|
||||
encoder = graphics->getDevice()->newArgumentEncoder(owner->getArguments());
|
||||
buffer = graphics->getDevice()->newBuffer(encoder->encodedLength(), MTL::ResourceOptionCPUCacheModeDefault);
|
||||
encoder->setArgumentBuffer(buffer, 0);
|
||||
}
|
||||
|
||||
DescriptorSet::~DescriptorSet() {}
|
||||
|
||||
void DescriptorSet::writeChanges() {}
|
||||
|
||||
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) {
|
||||
PUniformBuffer metalBuffer = uniformBuffer.cast<UniformBuffer>();
|
||||
encoder->setBuffer(metalBuffer->getHandle(), 0, binding);
|
||||
}
|
||||
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer uniformBuffer) {
|
||||
PShaderBuffer metalBuffer = uniformBuffer.cast<ShaderBuffer>();
|
||||
encoder->setBuffer(metalBuffer->getHandle(), 0, binding);
|
||||
}
|
||||
void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState) {
|
||||
PSampler sampler = samplerState.cast<Sampler>();
|
||||
encoder->setSamplerState(sampler->getHandle(), binding);
|
||||
}
|
||||
void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler samplerState) {
|
||||
PTextureBase base = texture.cast<TextureBase>();
|
||||
PSampler sampler = samplerState.cast<Sampler>();
|
||||
encoder->setTexture(base->getTexture(), binding);
|
||||
encoder->setSamplerState(sampler->getHandle(), binding);
|
||||
}
|
||||
|
||||
void DescriptorSet::updateTextureArray(uint32_t binding, Array<Gfx::PTexture> array) {
|
||||
for (auto& t : array) {
|
||||
PTextureBase metalTexture = t.cast<TextureBase>();
|
||||
encoder->setTexture(metalTexture->getTexture(), binding++);
|
||||
}
|
||||
}
|
||||
|
||||
bool DescriptorSet::operator<(Gfx::PDescriptorSet other) { return this < other.getHandle(); }
|
||||
|
||||
PipelineLayout::PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout)
|
||||
: Gfx::PipelineLayout(baseLayout), graphics(graphics) {}
|
||||
|
||||
PipelineLayout::~PipelineLayout(){}
|
||||
|
||||
void PipelineLayout::create()
|
||||
{
|
||||
for(auto& set : descriptorSetLayouts)
|
||||
{
|
||||
uint32 setHash = set->getHash();
|
||||
layoutHash = CRC::Calculate(&setHash, sizeof(uint32), CRC::CRC_32(), layoutHash);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Metal/MTLDepthStencil.hpp"
|
||||
#include "Metal/MTLSampler.hpp"
|
||||
#include "Resources.h"
|
||||
|
||||
namespace Seele
|
||||
@@ -12,5 +14,17 @@ MTL::LoadAction cast(Gfx::SeAttachmentLoadOp loadOp);
|
||||
Gfx::SeAttachmentLoadOp cast(MTL::LoadAction loadOp);
|
||||
MTL::StoreAction cast(Gfx::SeAttachmentStoreOp storeOp);
|
||||
Gfx::SeAttachmentStoreOp cast(MTL::StoreAction storeOp);
|
||||
MTL::BindingAccess cast(Gfx::SeDescriptorAccessTypeFlags access);
|
||||
Gfx::SeDescriptorAccessTypeFlags cast(MTL::BindingAccess access);
|
||||
MTL::SamplerBorderColor cast(Gfx::SeBorderColor color);
|
||||
Gfx::SeBorderColor cast(MTL::SamplerBorderColor color);
|
||||
MTL::CompareFunction cast(Gfx::SeCompareOp compare);
|
||||
Gfx::SeCompareOp cast(MTL::CompareFunction compare);
|
||||
MTL::SamplerMinMagFilter cast(Gfx::SeFilter filter);
|
||||
Gfx::SeFilter cast(MTL::SamplerMinMagFilter filter);
|
||||
MTL::SamplerMipFilter cast(Gfx::SeSamplerMipmapMode filter);
|
||||
Gfx::SeSamplerMipmapMode cast(MTL::SamplerMipFilter filter);
|
||||
MTL::SamplerAddressMode cast(Gfx::SeSamplerAddressMode mode);
|
||||
Gfx::SeSamplerAddressMode cast(MTL::SamplerAddressMode mode);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "Enums.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Metal/MTLArgument.hpp"
|
||||
#include "Metal/MTLDepthStencil.hpp"
|
||||
#include "Metal/MTLSampler.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace Seele;
|
||||
@@ -587,3 +590,181 @@ Gfx::SeAttachmentStoreOp Seele::Metal::cast(MTL::StoreAction storeOp) {
|
||||
throw std::logic_error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
MTL::BindingAccess Seele::Metal::cast(Gfx::SeDescriptorAccessTypeFlags access) {
|
||||
switch (access) {
|
||||
case Gfx::SE_DESCRIPTOR_ACCESS_READ_ONLY_BIT:
|
||||
return MTL::ArgumentAccessReadOnly;
|
||||
case Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT:
|
||||
return MTL::ArgumentAccessReadWrite;
|
||||
case Gfx::SE_DESCRIPTOR_ACCESS_WRITE_ONLY_BIT:
|
||||
return MTL::ArgumentAccessWriteOnly;
|
||||
default:
|
||||
throw std::logic_error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::SeDescriptorAccessTypeFlags Seele::Metal::cast(MTL::BindingAccess access) {
|
||||
switch (access) {
|
||||
case MTL::ArgumentAccessReadOnly:
|
||||
return Gfx::SE_DESCRIPTOR_ACCESS_READ_ONLY_BIT;
|
||||
case MTL::ArgumentAccessReadWrite:
|
||||
return Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT;
|
||||
case MTL::ArgumentAccessWriteOnly:
|
||||
return Gfx::SE_DESCRIPTOR_ACCESS_WRITE_ONLY_BIT;
|
||||
default:
|
||||
throw std::logic_error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
MTL::SamplerBorderColor Seele::Metal::cast(Gfx::SeBorderColor color) {
|
||||
switch (color) {
|
||||
case Gfx::SE_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
|
||||
return MTL::SamplerBorderColorTransparentBlack;
|
||||
case Gfx::SE_BORDER_COLOR_INT_TRANSPARENT_BLACK:
|
||||
return MTL::SamplerBorderColorTransparentBlack;
|
||||
case Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
|
||||
return MTL::SamplerBorderColorOpaqueBlack;
|
||||
case Gfx::SE_BORDER_COLOR_INT_OPAQUE_BLACK:
|
||||
return MTL::SamplerBorderColorOpaqueBlack;
|
||||
case Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
|
||||
return MTL::SamplerBorderColorOpaqueWhite;
|
||||
case Gfx::SE_BORDER_COLOR_INT_OPAQUE_WHITE:
|
||||
return MTL::SamplerBorderColorOpaqueWhite;
|
||||
default:
|
||||
throw std::logic_error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::SeBorderColor Seele::Metal::cast(MTL::SamplerBorderColor color) {
|
||||
switch (color) {
|
||||
case MTL::SamplerBorderColorTransparentBlack:
|
||||
return Gfx::SE_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
case MTL::SamplerBorderColorOpaqueBlack:
|
||||
return Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
|
||||
case MTL::SamplerBorderColorOpaqueWhite:
|
||||
return Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||
default:
|
||||
throw std::logic_error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
MTL::CompareFunction Seele::Metal::cast(Gfx::SeCompareOp compare) {
|
||||
switch (compare) {
|
||||
case Gfx::SE_COMPARE_OP_NEVER:
|
||||
return MTL::CompareFunctionNever;
|
||||
case Gfx::SE_COMPARE_OP_LESS:
|
||||
return MTL::CompareFunctionLess;
|
||||
case Gfx::SE_COMPARE_OP_EQUAL:
|
||||
return MTL::CompareFunctionEqual;
|
||||
case Gfx::SE_COMPARE_OP_LESS_OR_EQUAL:
|
||||
return MTL::CompareFunctionLessEqual;
|
||||
case Gfx::SE_COMPARE_OP_GREATER:
|
||||
return MTL::CompareFunctionGreater;
|
||||
case Gfx::SE_COMPARE_OP_NOT_EQUAL:
|
||||
return MTL::CompareFunctionNotEqual;
|
||||
case Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL:
|
||||
return MTL::CompareFunctionGreaterEqual;
|
||||
case Gfx::SE_COMPARE_OP_ALWAYS:
|
||||
return MTL::CompareFunctionAlways;
|
||||
default:
|
||||
throw std::logic_error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::SeCompareOp Seele::Metal::cast(MTL::CompareFunction compare) {
|
||||
switch (compare) {
|
||||
case MTL::CompareFunctionNever:
|
||||
return Gfx::SE_COMPARE_OP_NEVER;
|
||||
case MTL::CompareFunctionLess:
|
||||
return Gfx::SE_COMPARE_OP_LESS;
|
||||
case MTL::CompareFunctionEqual:
|
||||
return Gfx::SE_COMPARE_OP_EQUAL;
|
||||
case MTL::CompareFunctionLessEqual:
|
||||
return Gfx::SE_COMPARE_OP_LESS_OR_EQUAL;
|
||||
case MTL::CompareFunctionGreater:
|
||||
return Gfx::SE_COMPARE_OP_GREATER;
|
||||
case MTL::CompareFunctionNotEqual:
|
||||
return Gfx::SE_COMPARE_OP_NOT_EQUAL;
|
||||
case MTL::CompareFunctionGreaterEqual:
|
||||
return Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL;
|
||||
case MTL::CompareFunctionAlways:
|
||||
return Gfx::SE_COMPARE_OP_ALWAYS;
|
||||
}
|
||||
}
|
||||
|
||||
MTL::SamplerMinMagFilter Seele::Metal::cast(Gfx::SeFilter filter) {
|
||||
switch (filter) {
|
||||
case Gfx::SE_FILTER_NEAREST:
|
||||
return MTL::SamplerMinMagFilterNearest;
|
||||
case Gfx::SE_FILTER_LINEAR:
|
||||
return MTL::SamplerMinMagFilterLinear;
|
||||
case Gfx::SE_FILTER_CUBIC_IMG:
|
||||
return MTL::SamplerMinMagFilterLinear;
|
||||
default:
|
||||
throw std::logic_error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::SeFilter Seele::Metal::cast(MTL::SamplerMinMagFilter filter) {
|
||||
switch (filter) {
|
||||
case MTL::SamplerMinMagFilterNearest:
|
||||
return Gfx::SE_FILTER_NEAREST;
|
||||
case MTL::SamplerMinMagFilterLinear:
|
||||
return Gfx::SE_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
MTL::SamplerMipFilter Seele::Metal::cast(Gfx::SeSamplerMipmapMode filter) {
|
||||
switch (filter) {
|
||||
case Seele::Gfx::SE_SAMPLER_MIPMAP_MODE_NEAREST:
|
||||
return MTL::SamplerMipFilterNearest;
|
||||
case Seele::Gfx::SE_SAMPLER_MIPMAP_MODE_LINEAR:
|
||||
return MTL::SamplerMipFilterLinear;
|
||||
default:
|
||||
throw std::logic_error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::SeSamplerMipmapMode Seele::Metal::cast(MTL::SamplerMipFilter filter) {
|
||||
switch (filter) {
|
||||
case MTL::SamplerMipFilterNotMipmapped:
|
||||
return Gfx::SE_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
case MTL::SamplerMipFilterNearest:
|
||||
return Gfx::SE_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case MTL::SamplerMipFilterLinear:
|
||||
return Gfx::SE_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
MTL::SamplerAddressMode Seele::Metal::cast(Gfx::SeSamplerAddressMode mode) {
|
||||
switch (mode) {
|
||||
case Gfx::SE_SAMPLER_ADDRESS_MODE_REPEAT:
|
||||
return MTL::SamplerAddressModeRepeat;
|
||||
case Gfx::SE_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:
|
||||
return MTL::SamplerAddressModeMirrorRepeat;
|
||||
case Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
|
||||
return MTL::SamplerAddressModeMirrorClampToEdge;
|
||||
case Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER:
|
||||
return MTL::SamplerAddressModeClampToBorderColor;
|
||||
case Gfx::SE_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE:
|
||||
return MTL::SamplerAddressModeMirrorClampToEdge;
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::SeSamplerAddressMode Seele::Metal::cast(MTL::SamplerAddressMode mode) {
|
||||
switch (mode) {
|
||||
case MTL::SamplerAddressModeClampToEdge:
|
||||
return Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
case MTL::SamplerAddressModeMirrorClampToEdge:
|
||||
return Gfx::SE_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
|
||||
case MTL::SamplerAddressModeRepeat:
|
||||
return Gfx::SE_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
case MTL::SamplerAddressModeMirrorRepeat:
|
||||
return Gfx::SE_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
||||
case MTL::SamplerAddressModeClampToZero:
|
||||
return Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
case MTL::SamplerAddressModeClampToBorderColor:
|
||||
return Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "Graphics.h"
|
||||
#include "Graphics/Metal/Shader.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Shader.h"
|
||||
#include "RenderPass.h"
|
||||
#include "Command.h"
|
||||
#include "Window.h"
|
||||
#include "Buffer.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
@@ -82,22 +84,22 @@ Gfx::OTextureCube Graphics::createTextureCube(const TextureCreateInfo &createInf
|
||||
|
||||
Gfx::OUniformBuffer Graphics::createUniformBuffer(const UniformBufferCreateInfo &bulkData)
|
||||
{
|
||||
|
||||
return new UniformBuffer(this, bulkData);
|
||||
}
|
||||
|
||||
Gfx::OShaderBuffer Graphics::createShaderBuffer(const ShaderBufferCreateInfo &bulkData)
|
||||
{
|
||||
|
||||
return new ShaderBuffer(this, bulkData);
|
||||
}
|
||||
|
||||
Gfx::OVertexBuffer Graphics::createVertexBuffer(const VertexBufferCreateInfo &bulkData)
|
||||
{
|
||||
|
||||
return new VertexBuffer(this, bulkData);
|
||||
}
|
||||
|
||||
Gfx::OIndexBuffer Graphics::createIndexBuffer(const IndexBufferCreateInfo &bulkData)
|
||||
{
|
||||
|
||||
return new IndexBuffer(this, bulkData);
|
||||
}
|
||||
|
||||
Gfx::ORenderCommand Graphics::createRenderCommand(const std::string& name)
|
||||
@@ -112,11 +114,15 @@ Gfx::OComputeCommand Graphics::createComputeCommand(const std::string& name)
|
||||
|
||||
Gfx::OVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
|
||||
OVertexShader result = new VertexShader(this);
|
||||
result->create(createInfo);
|
||||
return result;
|
||||
}
|
||||
Gfx::OFragmentShader Graphics::createFragmentShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
|
||||
OFragmentShader result = new FragmentShader(this);
|
||||
result->create(createInfo);
|
||||
return result;
|
||||
}
|
||||
Gfx::OComputeShader Graphics::createComputeShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
@@ -133,12 +139,16 @@ Gfx::OMeshShader Graphics::createMeshShader(const ShaderCreateInfo& createInfo)
|
||||
}
|
||||
Gfx::OTaskShader Graphics::createTaskShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
|
||||
OTaskShader result = new TaskShader(this);
|
||||
result->create(createInfo);
|
||||
return result;
|
||||
}
|
||||
|
||||
Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo createInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(Gfx::MeshPipelineCreateInfo createInfo)
|
||||
{
|
||||
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
#pragma once
|
||||
#include "Graphics/Pipeline.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Pipeline.h"
|
||||
|
||||
namespace Seele {
|
||||
namespace Metal {
|
||||
class PipelineCache
|
||||
{
|
||||
|
||||
public:
|
||||
PipelineCache(PGraphics graphics, const std::string& cacheFilePath);
|
||||
~PipelineCache();
|
||||
PGraphicsPipeline createPipeline(Gfx::LegacyPipelineCreateInfo createInfo);
|
||||
PGraphicsPipeline createPipeline(Gfx::MeshPipelineCreateInfo createInfo);
|
||||
PComputePipeline createPipeline(Gfx::ComputePipelineCreateInfo createInfo);
|
||||
private:
|
||||
PGraphics graphics;
|
||||
Map<uint32, OGraphicsPipeline> graphicsPipelines;
|
||||
Map<uint32, OComputePipeline> computePipeline;
|
||||
std::string cacheFile;
|
||||
};
|
||||
DEFINE_REF(PipelineCache)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#include "PipelineCache.h"
|
||||
#include "Descriptor.h"
|
||||
#include "Graphics.h"
|
||||
#include "Shader.h"
|
||||
#include "Graphics/Descriptor.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Metal/MTLRenderPipeline.hpp"
|
||||
#include "Metal/MTLVertexDescriptor.hpp"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
|
||||
PipelineCache::PipelineCache(PGraphics graphics, const std::string& name) : graphics(graphics), cacheFile(name) {}
|
||||
|
||||
PipelineCache::~PipelineCache() {}
|
||||
|
||||
PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo createInfo) {
|
||||
PPipelineLayout layout = Gfx::PPipelineLayout(createInfo.pipelineLayout).cast<PipelineLayout>();
|
||||
uint32 hash = layout->getHash();
|
||||
MTL::RenderPipelineDescriptor* pipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
|
||||
|
||||
MTL::VertexDescriptor* vertexDescriptor = MTL::VertexDescriptor::alloc()->init();
|
||||
|
||||
MTL::VertexAttributeDescriptorArray* attributes = vertexDescriptor->attributes();
|
||||
|
||||
const auto& vertexInfo = createInfo.vertexInput->getInfo();
|
||||
|
||||
for (size_t attr = 0; attr < vertexInfo.attributes.size(); ++attr) {
|
||||
MTL::VertexAttributeDescriptor* attribute = MTL::VertexAttributeDescriptor::alloc()->init();
|
||||
attribute->setBufferIndex(vertexInfo.attributes[attr].binding);
|
||||
switch (vertexInfo.attributes[attr].format) {
|
||||
case Gfx::SE_FORMAT_R32G32B32_SFLOAT:
|
||||
attribute->setFormat(MTL::VertexFormatFloat3);
|
||||
break;
|
||||
default:
|
||||
throw std::logic_error("TODO");
|
||||
}
|
||||
attribute->setOffset(vertexInfo.attributes[attr].offset);
|
||||
attributes->setObject(attribute, attr);
|
||||
}
|
||||
|
||||
MTL::VertexBufferLayoutDescriptorArray* bufferLayout = vertexDescriptor->layouts();
|
||||
|
||||
for (size_t binding = 0; binding < vertexInfo.bindings.size(); ++binding) {
|
||||
MTL::VertexBufferLayoutDescriptor* buffer = MTL::VertexBufferLayoutDescriptor::alloc()->init();
|
||||
buffer->setStride(vertexInfo.bindings[binding].stride);
|
||||
buffer->setStepRate(1);
|
||||
switch (vertexInfo.bindings[binding].inputRate) {
|
||||
case Gfx::SE_VERTEX_INPUT_RATE_VERTEX:
|
||||
buffer->setStepFunction(MTL::VertexStepFunctionPerVertex);
|
||||
break;
|
||||
case Gfx::SE_VERTEX_INPUT_RATE_INSTANCE:
|
||||
buffer->setStepFunction(MTL::VertexStepFunctionPerInstance);
|
||||
break;
|
||||
}
|
||||
bufferLayout->setObject(buffer, binding);
|
||||
}
|
||||
|
||||
pipelineDescriptor->setVertexDescriptor(vertexDescriptor);
|
||||
|
||||
pipelineDescriptor->setVertexFunction(createInfo.vertexShader.cast<VertexShader>()->getFunction());
|
||||
|
||||
|
||||
vertexDescriptor->release();
|
||||
pipelineDescriptor->release();
|
||||
}
|
||||
|
||||
PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo createInfo) {}
|
||||
|
||||
PComputePipeline PipelineCache::createPipeline(Gfx::ComputePipelineCreateInfo createInfo) {}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "Graphics/Resources.h"
|
||||
#include "Metal/MTLSampler.hpp"
|
||||
#include <Foundation/Foundation.hpp>
|
||||
#include <Metal/Metal.hpp>
|
||||
#include <QuartzCore/CAMetalLayer.h>
|
||||
@@ -29,5 +30,18 @@ private:
|
||||
MTL::Event *handle;
|
||||
};
|
||||
DEFINE_REF(Event)
|
||||
class Sampler : public Gfx::Sampler
|
||||
{
|
||||
public:
|
||||
Sampler(PGraphics graphics, const SamplerCreateInfo& createInfo);
|
||||
virtual ~Sampler();
|
||||
MTL::SamplerState* getHandle() const
|
||||
{
|
||||
return sampler;
|
||||
}
|
||||
private:
|
||||
MTL::SamplerState* sampler;
|
||||
};
|
||||
DEFINE_REF(Sampler)
|
||||
} // namespace Metal
|
||||
} // namespace Seele
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "Resources.h"
|
||||
#include "Graphics.h"
|
||||
#include "Metal/MTLSampler.hpp"
|
||||
#include "Enums.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
@@ -10,4 +12,30 @@ Fence::~Fence() { handle->release(); }
|
||||
|
||||
Event::Event(PGraphics graphics) : handle(graphics->getDevice()->newEvent()) {}
|
||||
|
||||
Event::~Event() { handle->release(); }
|
||||
Event::~Event() { handle->release(); }
|
||||
|
||||
Sampler::Sampler(PGraphics graphics, const SamplerCreateInfo& createInfo)
|
||||
{
|
||||
MTL::SamplerDescriptor* desc = MTL::SamplerDescriptor::alloc()->init();
|
||||
desc->setBorderColor(cast(createInfo.borderColor));
|
||||
desc->setCompareFunction(cast(createInfo.compareOp));
|
||||
desc->setLodAverage(createInfo.mipLodBias);
|
||||
desc->setLodMaxClamp(createInfo.maxLod);
|
||||
desc->setLodMinClamp(createInfo.minLod);
|
||||
desc->setMinFilter(cast(createInfo.minFilter));
|
||||
desc->setMagFilter(cast(createInfo.magFilter));
|
||||
desc->setMipFilter(cast(createInfo.mipmapMode));
|
||||
desc->setMaxAnisotropy(createInfo.maxAnisotropy);
|
||||
desc->setNormalizedCoordinates(!createInfo.unnormalizedCoordinates);
|
||||
desc->setRAddressMode(cast(createInfo.addressModeU));
|
||||
desc->setSAddressMode(cast(createInfo.addressModeV));
|
||||
desc->setTAddressMode(cast(createInfo.addressModeW));
|
||||
desc->setSupportArgumentBuffers(true);
|
||||
sampler = graphics->getDevice()->newSamplerState(desc);
|
||||
desc->release();
|
||||
}
|
||||
|
||||
Sampler::~Sampler()
|
||||
{
|
||||
sampler->release();
|
||||
}
|
||||
@@ -1,10 +1,15 @@
|
||||
#include "Shader.h"
|
||||
#include "Foundation/NSError.hpp"
|
||||
#include "Foundation/NSString.hpp"
|
||||
#include "Graphics.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Graphics/slang-compile.h"
|
||||
#include "Metal/MTLDevice.hpp"
|
||||
#include "Metal/MTLLibrary.hpp"
|
||||
#include <iostream>
|
||||
#include </usr/local/include/metal_irconverter/metal_irconverter.h>
|
||||
#include <slang.h>
|
||||
#include <spirv_cross.hpp>
|
||||
#include <spirv_cross/spirv_msl.hpp>
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
@@ -20,64 +25,27 @@ Shader::~Shader() {
|
||||
|
||||
void Shader::create(const ShaderCreateInfo &createInfo) {
|
||||
Slang::ComPtr<slang::IBlob> kernelBlob =
|
||||
generateShader(createInfo, SLANG_DXIL);
|
||||
thread_local IRCompiler *pCompiler = nullptr;
|
||||
if (pCompiler == nullptr) {
|
||||
pCompiler = IRCompilerCreate();
|
||||
generateShader(createInfo, SLANG_SPIRV);
|
||||
spirv_cross::CompilerMSL comp((const uint32 *)kernelBlob->getBufferPointer(),
|
||||
kernelBlob->getBufferSize() / 4);
|
||||
auto options = comp.get_msl_options();
|
||||
options.argument_buffers = true;
|
||||
options.argument_buffers_tier =
|
||||
spirv_cross::CompilerMSL::Options::ArgumentBuffersTier::Tier2;
|
||||
options.set_msl_version(3);
|
||||
comp.set_msl_options(options);
|
||||
std::string metalCode = comp.compile();
|
||||
NS::Error *error = nullptr;
|
||||
MTL::CompileOptions *mtlOptions = MTL::CompileOptions::alloc()->init();
|
||||
|
||||
library = graphics->getDevice()->newLibrary(
|
||||
NS::String::string(metalCode.c_str(), NS::ASCIIStringEncoding),
|
||||
mtlOptions, &error);
|
||||
if (error) {
|
||||
std::cout << error->debugDescription() << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
IRCompilerSetEntryPointName(pCompiler, "main");
|
||||
|
||||
IRObject *pDXIL = IRObjectCreateFromDXIL(
|
||||
(const uint8 *)kernelBlob->getBufferPointer(),
|
||||
kernelBlob->getBufferSize(), IRBytecodeOwnershipNone);
|
||||
|
||||
// Compile DXIL to Metal IR:
|
||||
IRError *pError = nullptr;
|
||||
IRObject *pOutIR =
|
||||
IRCompilerAllocCompileAndLink(pCompiler, NULL, pDXIL, &pError);
|
||||
|
||||
if (!pOutIR) {
|
||||
// Inspect pError to determine cause.
|
||||
IRErrorDestroy(pError);
|
||||
}
|
||||
IRShaderStage irStage;
|
||||
switch (stage) {
|
||||
case Gfx::SE_SHADER_STAGE_VERTEX_BIT: irStage = IRShaderStageVertex;
|
||||
case Gfx::SE_SHADER_STAGE_FRAGMENT_BIT: irStage = IRShaderStageFragment;
|
||||
case Gfx::SE_SHADER_STAGE_COMPUTE_BIT: irStage = IRShaderStageCompute;
|
||||
case Gfx::SE_SHADER_STAGE_TASK_BIT_NV: irStage = IRShaderStageAmplification;
|
||||
case Gfx::SE_SHADER_STAGE_MESH_BIT_NV: irStage = IRShaderStageMesh;
|
||||
}
|
||||
// Retrieve Metallib:
|
||||
IRMetalLibBinary *pMetallib = IRMetalLibBinaryCreate();
|
||||
IRObjectGetMetalLibBinary(pOutIR, irStage, pMetallib);
|
||||
size_t metallibSize = IRMetalLibGetBytecodeSize(pMetallib);
|
||||
uint8_t *metallib = new uint8_t[metallibSize];
|
||||
IRMetalLibGetBytecode(pMetallib, metallib);
|
||||
|
||||
IRShaderReflection* reflection = IRShaderReflectionCreate();
|
||||
IRObjectGetReflection(pOutIR, irStage, reflection);
|
||||
Array<IRResourceLocation> locations(
|
||||
IRShaderReflectionGetResourceCount(reflection));
|
||||
IRShaderReflectionGetResourceLocations(reflection, locations.data());
|
||||
for(auto l : locations)
|
||||
{
|
||||
std::cout << "Resource " << l.resourceName << " Type " << l.resourceType << " size " << l.sizeBytes << " slot " << l.slot << " space " << l.space << " offset " << l.topLevelOffset << std::endl;
|
||||
}
|
||||
IRShaderReflectionDestroy(reflection);
|
||||
|
||||
// Store the metallib to custom format or disk, or use to create a MTLLibrary.
|
||||
NS::Error *__autoreleasing error = nil;
|
||||
dispatch_data_t data = dispatch_data_create(metallib, metallibSize,
|
||||
dispatch_get_main_queue(), NULL);
|
||||
|
||||
library = graphics->getDevice()->newLibrary(data, &error);
|
||||
function =
|
||||
library->newFunction(NS::String::string("main", NS::ASCIIStringEncoding));
|
||||
|
||||
delete[] metallib;
|
||||
IRMetalLibBinaryDestroy(pMetallib);
|
||||
IRObjectDestroy(pDXIL);
|
||||
IRObjectDestroy(pOutIR);
|
||||
IRCompilerDestroy(pCompiler);
|
||||
mtlOptions->release();
|
||||
}
|
||||
Reference in New Issue
Block a user