we are leaking lots of memory
This commit is contained in:
@@ -242,7 +242,7 @@ template <typename T, typename Allocator = std::pmr::polymorphic_allocator<T>> s
|
||||
|
||||
template <class Pred>
|
||||
requires std::predicate<Pred, value_type>
|
||||
constexpr iterator find(Pred pred) noexcept {
|
||||
constexpr iterator find(Pred&& pred) noexcept {
|
||||
for (size_type i = 0; i < arraySize; ++i) {
|
||||
if (pred(_data[i])) {
|
||||
return iterator(&_data[i]);
|
||||
@@ -292,8 +292,11 @@ template <typename T, typename Allocator = std::pmr::polymorphic_allocator<T>> s
|
||||
}
|
||||
template <class Pred>
|
||||
requires std::predicate<Pred, value_type>
|
||||
constexpr void remove_if(Pred pred, bool keepOrder = true) {
|
||||
remove(find(pred), keepOrder);
|
||||
constexpr void remove_if(Pred&& pred, bool keepOrder = true) {
|
||||
Iterator it;
|
||||
while((it = find(pred)) != end()) {
|
||||
erase(it, keepOrder);
|
||||
}
|
||||
}
|
||||
constexpr void remove(const value_type& element, bool keepOrder = true) { erase(find(element), keepOrder); }
|
||||
constexpr void remove(value_type&& element, bool keepOrder = true) { erase(find(element), keepOrder); }
|
||||
@@ -326,11 +329,11 @@ template <typename T, typename Allocator = std::pmr::polymorphic_allocator<T>> s
|
||||
arraySize = 0;
|
||||
allocated = 0;
|
||||
}
|
||||
constexpr size_type indexOf(iterator iterator) { return iterator - begin(); }
|
||||
constexpr size_type indexOf(const_iterator iterator) const { return iterator.p - begin().p; }
|
||||
constexpr size_type indexOf(T& t) { return indexOf(find(t)); }
|
||||
constexpr size_type indexOf(const T& t) const { return indexOf(find(t)); }
|
||||
constexpr size_type size() const noexcept { return arraySize; }
|
||||
[[nodiscard]] constexpr size_type indexOf(iterator iterator) { return iterator - begin(); }
|
||||
[[nodiscard]] constexpr size_type indexOf(const_iterator iterator) const { return iterator.p - begin().p; }
|
||||
[[nodiscard]] constexpr size_type indexOf(T& t) { return indexOf(find(t)); }
|
||||
[[nodiscard]] constexpr size_type indexOf(const T& t) const { return indexOf(find(t)); }
|
||||
[[nodiscard]] constexpr size_type size() const noexcept { return arraySize; }
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return arraySize == 0; }
|
||||
constexpr void reserve(size_type new_cap) {
|
||||
if (new_cap > allocated) {
|
||||
|
||||
@@ -42,8 +42,7 @@ void BufferAllocation::unmap() {}
|
||||
Buffer::Buffer(PGraphics graphics, uint64 size, Gfx::SeBufferUsageFlags usage, Gfx::QueueType queueType, bool dynamic, std::string name,
|
||||
bool createCleared, uint32 clearValue)
|
||||
: graphics(graphics), currentBuffer(0), dynamic(dynamic), createCleared(createCleared), name(name), clearValue(clearValue) {
|
||||
if(size > 0)
|
||||
{
|
||||
if(size > 0) {
|
||||
buffers.add(nullptr);
|
||||
createBuffer(size, 0);
|
||||
}
|
||||
@@ -53,6 +52,7 @@ Buffer::~Buffer() {
|
||||
for (size_t i = 0; i < buffers.size(); ++i) {
|
||||
// TODO
|
||||
}
|
||||
buffers.clear();
|
||||
}
|
||||
|
||||
void Buffer::updateContents(uint64 regionOffset, uint64 regionSize, void* ptr) {
|
||||
|
||||
@@ -63,7 +63,7 @@ class RenderCommand : public Gfx::RenderCommand {
|
||||
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override;
|
||||
virtual void pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) override;
|
||||
virtual void draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) override;
|
||||
virtual void drawIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride);
|
||||
virtual void drawIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) override;
|
||||
virtual void drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance) override;
|
||||
virtual void drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) override;
|
||||
virtual void drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) override;
|
||||
@@ -73,7 +73,6 @@ class RenderCommand : public Gfx::RenderCommand {
|
||||
PGraphicsPipeline boundPipeline;
|
||||
PIndexBuffer boundIndexBuffer;
|
||||
MTL::RenderCommandEncoder* encoder;
|
||||
MTL::Buffer* constantsBuffer;
|
||||
std::string name;
|
||||
};
|
||||
DEFINE_REF(RenderCommand)
|
||||
@@ -93,7 +92,6 @@ class ComputeCommand : public Gfx::ComputeCommand {
|
||||
PComputePipeline boundPipeline;
|
||||
MTL::CommandBuffer* commandBuffer;
|
||||
MTL::ComputeCommandEncoder* encoder;
|
||||
MTL::Buffer* constantsBuffer;
|
||||
std::string name;
|
||||
};
|
||||
DEFINE_REF(ComputeCommand)
|
||||
|
||||
@@ -24,19 +24,29 @@ using namespace Seele::Metal;
|
||||
Command::Command(PGraphics graphics, MTL::CommandBuffer* cmdBuffer)
|
||||
: graphics(graphics), completed(new Event(graphics)), cmdBuffer(cmdBuffer) {}
|
||||
|
||||
Command::~Command() {}
|
||||
Command::~Command() {
|
||||
assert(parallelEncoder == nullptr);
|
||||
if(blitEncoder != nullptr) {
|
||||
blitEncoder->endEncoding();
|
||||
blitEncoder->release();
|
||||
}
|
||||
cmdBuffer->release();
|
||||
}
|
||||
|
||||
void Command::beginRenderPass(PRenderPass renderPass) {
|
||||
if (blitEncoder) {
|
||||
blitEncoder->endEncoding();
|
||||
blitEncoder->release();
|
||||
blitEncoder = nullptr;
|
||||
}
|
||||
renderPass->updateRenderPass();
|
||||
parallelEncoder = cmdBuffer->parallelRenderCommandEncoder(renderPass->getDescriptor());
|
||||
parallelEncoder->setLabel(NS::String::string(renderPass->getName().c_str(), NS::ASCIIStringEncoding));
|
||||
}
|
||||
|
||||
void Command::endRenderPass() {
|
||||
parallelEncoder->endEncoding();
|
||||
parallelEncoder->release();
|
||||
parallelEncoder = nullptr;
|
||||
}
|
||||
|
||||
@@ -46,6 +56,8 @@ void Command::end(PEvent signal) {
|
||||
assert(!parallelEncoder);
|
||||
if (blitEncoder) {
|
||||
blitEncoder->endEncoding();
|
||||
blitEncoder->release();
|
||||
blitEncoder = nullptr;
|
||||
}
|
||||
if (signal != nullptr) {
|
||||
cmdBuffer->encodeSignalEvent(signal->getHandle(), 1);
|
||||
@@ -62,7 +74,7 @@ void Command::waitForEvent(PEvent event) { cmdBuffer->encodeWait(event->getHandl
|
||||
|
||||
RenderCommand::RenderCommand(MTL::RenderCommandEncoder* encoder, const std::string& name) : encoder(encoder), name(name) {}
|
||||
|
||||
RenderCommand::~RenderCommand() {}
|
||||
RenderCommand::~RenderCommand() { encoder->release(); }
|
||||
|
||||
void RenderCommand::end() { encoder->endEncoding(); }
|
||||
|
||||
@@ -81,9 +93,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()) {
|
||||
constantsBuffer = boundPipeline->graphics->getDevice()->newBuffer(boundPipeline->getPipelineLayout()->getPushConstantsSize(), 0);
|
||||
}
|
||||
encoder->setDepthStencilState(boundPipeline->depth);
|
||||
}
|
||||
|
||||
void RenderCommand::bindPipeline(Gfx::PRayTracingPipeline pipeline) {}
|
||||
@@ -150,19 +160,18 @@ void RenderCommand::bindVertexBuffer(const Array<Gfx::PVertexBuffer>& buffers) {
|
||||
void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer gfxIndexBuffer) { boundIndexBuffer = gfxIndexBuffer.cast<IndexBuffer>(); }
|
||||
|
||||
void RenderCommand::pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) {
|
||||
std::memcpy(constantsBuffer->contents(), data, size);
|
||||
uint pushIndex = boundPipeline->getPipelineLayout()->findParameter("pOffsets");
|
||||
if (stage & Gfx::SE_SHADER_STAGE_VERTEX_BIT) {
|
||||
encoder->setVertexBuffer(constantsBuffer, 0, pushIndex); // TODO: hardcoded
|
||||
encoder->setVertexBytes(data, size, pushIndex); // TODO: hardcoded
|
||||
}
|
||||
if (stage & Gfx::SE_SHADER_STAGE_FRAGMENT_BIT) {
|
||||
encoder->setFragmentBuffer(constantsBuffer, 0, pushIndex); // TODO: hardcoded
|
||||
encoder->setFragmentBytes(data, size, pushIndex); // TODO: hardcoded
|
||||
}
|
||||
if (stage & Gfx::SE_SHADER_STAGE_TASK_BIT_EXT) {
|
||||
encoder->setObjectBuffer(constantsBuffer, 0, pushIndex); // TODO: hardcoded
|
||||
encoder->setObjectBytes(data, size, pushIndex); // TODO: hardcoded
|
||||
}
|
||||
if (stage & Gfx::SE_SHADER_STAGE_MESH_BIT_EXT) {
|
||||
encoder->setMeshBuffer(constantsBuffer, 0, pushIndex); // TODO: hardcoded
|
||||
encoder->setMeshBytes(data, size, pushIndex); // TODO: hardcoded
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +200,7 @@ void RenderCommand::traceRays(uint32 width, uint32 height, uint32 depth) {}
|
||||
ComputeCommand::ComputeCommand(MTL::CommandBuffer* cmdBuffer, const std::string& name)
|
||||
: commandBuffer(cmdBuffer), encoder(cmdBuffer->computeCommandEncoder()), name(name) {}
|
||||
|
||||
ComputeCommand::~ComputeCommand() {}
|
||||
ComputeCommand::~ComputeCommand() { encoder->release(); commandBuffer->release(); }
|
||||
|
||||
void ComputeCommand::end() {
|
||||
encoder->endEncoding();
|
||||
@@ -201,9 +210,6 @@ void ComputeCommand::end() {
|
||||
void ComputeCommand::bindPipeline(Gfx::PComputePipeline pipeline) {
|
||||
boundPipeline = pipeline.cast<ComputePipeline>();
|
||||
encoder->setComputePipelineState(boundPipeline->getHandle());
|
||||
if (boundPipeline->getPipelineLayout()->hasPushConstants()) {
|
||||
constantsBuffer = boundPipeline->graphics->getDevice()->newBuffer(boundPipeline->getPipelineLayout()->getPushConstantsSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set) {
|
||||
@@ -248,9 +254,8 @@ void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) {
|
||||
}
|
||||
|
||||
void ComputeCommand::pushConstants(Gfx::SeShaderStageFlags, uint32 offset, uint32 size, const void* data) {
|
||||
std::memcpy(constantsBuffer->contents(), data, size);
|
||||
uint pushIndex = boundPipeline->getPipelineLayout()->findParameter("pMipParam");
|
||||
encoder->setBuffer(constantsBuffer, 0, pushIndex); // TODO: hardcoded
|
||||
encoder->setBytes(data, size, pushIndex); // TODO: hardcoded
|
||||
}
|
||||
|
||||
void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) {
|
||||
|
||||
@@ -26,7 +26,7 @@ using namespace Seele::Metal;
|
||||
|
||||
DescriptorLayout::DescriptorLayout(PGraphics graphics, const std::string& name) : Gfx::DescriptorLayout(name), graphics(graphics) {}
|
||||
|
||||
DescriptorLayout::~DescriptorLayout() {}
|
||||
DescriptorLayout::~DescriptorLayout() { arguments->release(); }
|
||||
|
||||
void DescriptorLayout::create() {
|
||||
pool = new DescriptorPool(graphics, this);
|
||||
@@ -36,14 +36,14 @@ void DescriptorLayout::create() {
|
||||
for (uint32 i = 0; i < descriptorBindings.size(); ++i) {
|
||||
if (descriptorBindings[i].descriptorType != Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER) {
|
||||
plainDescriptor = false;
|
||||
} else {
|
||||
objects[i] = MTL::ArgumentDescriptor::alloc()->init();
|
||||
objects[i]->setIndex(mappingCounter);
|
||||
objects[i]->setAccess(MTL::BindingAccessReadOnly);
|
||||
objects[i]->setArrayLength(descriptorBindings[i].descriptorCount);
|
||||
objects[i]->setDataType(MTL::DataTypeChar);
|
||||
objects[i]->setArrayLength(descriptorBindings[i].uniformLength);
|
||||
}
|
||||
objects[i] = MTL::ArgumentDescriptor::alloc()->init();
|
||||
objects[i]->setIndex(mappingCounter);
|
||||
objects[i]->setAccess(MTL::BindingAccessReadOnly);
|
||||
objects[i]->setArrayLength(descriptorBindings[i].descriptorCount);
|
||||
objects[i]->setDataType(MTL::DataTypeChar);
|
||||
objects[i]->setArrayLength(descriptorBindings[i].uniformLength);
|
||||
|
||||
variableMapping[descriptorBindings[i].name] = DescriptorMapping{
|
||||
.index = mappingCounter,
|
||||
.constantSize = descriptorBindings[i].uniformLength,
|
||||
@@ -53,6 +53,7 @@ void DescriptorLayout::create() {
|
||||
}
|
||||
numResources = mappingCounter;
|
||||
arguments = NS::Array::array((NS::Object**)objects, descriptorBindings.size());
|
||||
delete[] objects;
|
||||
}
|
||||
|
||||
MTL::ArgumentEncoder* DescriptorLayout::createEncoder() { return graphics->getDevice()->newArgumentEncoder(arguments); }
|
||||
@@ -79,9 +80,18 @@ void DescriptorPool::reset() {}
|
||||
|
||||
DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner)
|
||||
: Gfx::DescriptorSet(owner->getLayout()), CommandBoundResource(graphics), graphics(graphics), owner(owner) {
|
||||
std::cout << "New Descriptor set" << std::endl;
|
||||
}
|
||||
|
||||
DescriptorSet::~DescriptorSet() {}
|
||||
DescriptorSet::~DescriptorSet() {
|
||||
if(encoder != nullptr) {
|
||||
encoder->release();
|
||||
}
|
||||
if(argumentBuffer != nullptr) {
|
||||
argumentBuffer->release();
|
||||
}
|
||||
std::cout << "destroying descriptor set" << std::endl;
|
||||
}
|
||||
|
||||
void DescriptorSet::reset() {
|
||||
uniformWrites.clear();
|
||||
|
||||
@@ -21,6 +21,7 @@ class GraphicsPipeline : public Gfx::GraphicsPipeline {
|
||||
constexpr MTL::PrimitiveType getPrimitive() const { return primitiveType; }
|
||||
PGraphics graphics;
|
||||
MTL::RenderPipelineState* state;
|
||||
MTL::DepthStencilState* depth;
|
||||
MTL::PrimitiveType primitiveType;
|
||||
MTL::Function* taskFunction = nullptr;
|
||||
Array<uint32> taskSets;
|
||||
|
||||
@@ -86,7 +86,11 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo cr
|
||||
desc->setBlendingEnabled(false);
|
||||
pipelineDescriptor->colorAttachments()->setObject(desc, c);
|
||||
}
|
||||
|
||||
MTL::DepthStencilDescriptor* depthDescriptor = MTL::DepthStencilDescriptor::alloc()->init();
|
||||
if (createInfo.renderPass->getLayout().depthAttachment.getTexture() != nullptr) {
|
||||
depthDescriptor->setDepthWriteEnabled(createInfo.depthStencilState.depthWriteEnable);
|
||||
depthDescriptor->setDepthCompareFunction(cast(createInfo.depthStencilState.depthCompareOp));
|
||||
pipelineDescriptor->setDepthAttachmentPixelFormat(
|
||||
cast(createInfo.renderPass->getLayout().depthAttachment.getTexture().cast<Texture2D>()->getFormat()));
|
||||
}
|
||||
@@ -94,7 +98,10 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo cr
|
||||
pipelineDescriptor->setAlphaToOneEnabled(createInfo.multisampleState.alphaToOneEnable);
|
||||
pipelineDescriptor->setRasterSampleCount(createInfo.multisampleState.samples);
|
||||
pipelineDescriptor->setRasterizationEnabled(!createInfo.rasterizationState.rasterizerDiscardEnable);
|
||||
|
||||
|
||||
MTL::DepthStencilState* depthState = graphics->getDevice()->newDepthStencilState(depthDescriptor);
|
||||
depthDescriptor->release();
|
||||
|
||||
uint32 hash = pipelineDescriptor->hash();
|
||||
|
||||
if (graphicsPipelines.contains(hash)) {
|
||||
@@ -145,10 +152,12 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo cr
|
||||
}
|
||||
|
||||
pipelineDescriptor->release();
|
||||
|
||||
graphicsPipelines[hash]->vertexSets = vertexSets;
|
||||
graphicsPipelines[hash]->vertexFunction = vertexFunction;
|
||||
graphicsPipelines[hash]->fragmentSets = fragmentSets;
|
||||
graphicsPipelines[hash]->fragmentFunction = fragmentFunction;
|
||||
graphicsPipelines[hash]->depth = depthState;
|
||||
return graphicsPipelines[hash];
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,14 @@ class RenderPass : public Gfx::RenderPass {
|
||||
virtual ~RenderPass();
|
||||
void updateRenderPass();
|
||||
MTL::RenderPassDescriptor* getDescriptor() const { return renderPass; }
|
||||
const std::string& getName() const { return name; }
|
||||
|
||||
private:
|
||||
PGraphics graphics;
|
||||
Gfx::PViewport viewport;
|
||||
MTL::RenderPassDescriptor* renderPass;
|
||||
std::string name;
|
||||
};
|
||||
DEFINE_REF(RenderPass)
|
||||
} // namespace Metal
|
||||
} // namespace Seele
|
||||
} // namespace Seele
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
using namespace Seele;
|
||||
using namespace Seele::Metal;
|
||||
|
||||
RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout layout, Array<Gfx::SubPassDependency> dependencies,
|
||||
RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Array<Gfx::SubPassDependency> dependencies,
|
||||
Gfx::PViewport viewport, const std::string& name)
|
||||
: Gfx::RenderPass(layout, dependencies), graphics(graphics), viewport(viewport) {
|
||||
: Gfx::RenderPass(std::move(_layout), dependencies), graphics(graphics), viewport(viewport), name(name) {
|
||||
renderPass = MTL::RenderPassDescriptor::renderPassDescriptor();
|
||||
renderPass->setRenderTargetArrayLength(1);
|
||||
renderPass->setRenderTargetWidth(viewport->getWidth());
|
||||
@@ -27,7 +27,12 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout layout, Array
|
||||
if (!layout.resolveAttachments.empty()) {
|
||||
const auto& resolve = layout.resolveAttachments[i];
|
||||
desc->setResolveLevel(0);
|
||||
desc->setStoreAction(MTL::StoreActionStoreAndMultisampleResolve);
|
||||
// store multisampled attachment as well
|
||||
if(color.getStoreOp() == Gfx::SE_ATTACHMENT_STORE_OP_STORE) {
|
||||
desc->setStoreAction(MTL::StoreActionStoreAndMultisampleResolve);
|
||||
} else {
|
||||
desc->setStoreAction(MTL::StoreActionMultisampleResolve);
|
||||
}
|
||||
desc->setResolveTexture(resolve.getTexture().cast<TextureBase>()->getImage());
|
||||
}
|
||||
}
|
||||
@@ -38,8 +43,13 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout layout, Array
|
||||
depth->setStoreAction(cast(layout.depthAttachment.getStoreOp()));
|
||||
|
||||
if (layout.depthResolveAttachment.getTexture() != nullptr) {
|
||||
// store multisampled attachment as well
|
||||
if(layout.depthAttachment.getStoreOp() == Gfx::SE_ATTACHMENT_STORE_OP_STORE) {
|
||||
depth->setStoreAction(MTL::StoreActionStoreAndMultisampleResolve);
|
||||
} else {
|
||||
depth->setStoreAction(MTL::StoreActionMultisampleResolve);
|
||||
}
|
||||
depth->setResolveTexture(layout.depthResolveAttachment.getTexture().cast<TextureBase>()->getImage());
|
||||
depth->setStoreAction(MTL::StoreActionStoreAndMultisampleResolve);
|
||||
}
|
||||
}
|
||||
// TODO: stencil
|
||||
@@ -56,4 +66,4 @@ void RenderPass::updateRenderPass() {
|
||||
auto depth = renderPass->depthAttachment();
|
||||
depth->setTexture(layout.depthAttachment.getTexture().cast<TextureBase>()->getImage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ class TextureHandle {
|
||||
uint32 height;
|
||||
uint32 depth;
|
||||
uint32 arrayCount;
|
||||
uint32 layerCount;
|
||||
uint32 mipLevels;
|
||||
uint32 samples;
|
||||
Gfx::SeFormat format;
|
||||
@@ -140,4 +139,4 @@ class TextureCube : public Gfx::TextureCube, public TextureBase {
|
||||
};
|
||||
DEFINE_REF(TextureCube)
|
||||
} // namespace Metal
|
||||
} // namespace Seele
|
||||
} // namespace Seele
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include "Graphics/Metal/Graphics.h"
|
||||
#include "Command.h"
|
||||
#include "Metal/MTLTexture.hpp"
|
||||
#include "Metal/MTLTypes.hpp"
|
||||
|
||||
@@ -11,7 +12,7 @@ using namespace Seele::Metal;
|
||||
|
||||
TextureHandle::TextureHandle(PGraphics graphics, MTL::TextureType type, const TextureCreateInfo& createInfo, MTL::Texture* existingImage)
|
||||
: texture(existingImage), type(type), width(createInfo.width), height(createInfo.height), depth(createInfo.depth),
|
||||
arrayCount(createInfo.elements), layerCount(createInfo.layers), mipLevels(1), samples(createInfo.samples), format(createInfo.format),
|
||||
arrayCount(createInfo.elements), mipLevels(1), samples(createInfo.samples), format(createInfo.format),
|
||||
usage(createInfo.usage), layout(Gfx::SE_IMAGE_LAYOUT_UNDEFINED), ownsImage(existingImage == nullptr) {
|
||||
if (createInfo.useMip) {
|
||||
mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1;
|
||||
@@ -37,17 +38,36 @@ TextureHandle::TextureHandle(PGraphics graphics, MTL::TextureType type, const Te
|
||||
descriptor->setTextureType(type);
|
||||
descriptor->setSampleCount(samples);
|
||||
descriptor->setUsage(mtlUsage);
|
||||
descriptor->setStorageMode(MTL::StorageModePrivate);
|
||||
if(usage & Gfx::SE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
|
||||
descriptor->setStorageMode(MTL::StorageModeMemoryless);
|
||||
}
|
||||
|
||||
texture = graphics->getDevice()->newTexture(descriptor);
|
||||
texture->setLabel(NS::String::string(createInfo.name.c_str(), NS::ASCIIStringEncoding));
|
||||
|
||||
descriptor->release();
|
||||
}
|
||||
// if(createInfo.sourceData.data != nullptr)
|
||||
// {
|
||||
// MTL::Region region(0, 0, 0, width, height, depth);
|
||||
// texture->replaceRegion(region, 0, createInfo.sourceData.data,
|
||||
// createInfo.sourceData.size / (depth * height));
|
||||
// }
|
||||
if(createInfo.sourceData.data != nullptr)
|
||||
{
|
||||
MTL::Buffer* stagingBuffer = graphics->getDevice()->newBuffer(createInfo.sourceData.size, MTL::ResourceStorageModeShared);
|
||||
std::memcpy(stagingBuffer->contents(), createInfo.sourceData.data, createInfo.sourceData.size);
|
||||
MTL::BlitCommandEncoder* blitEnc = graphics->getQueue()->getCommands()->getBlitEncoder();
|
||||
uint32 sliceSize = createInfo.sourceData.size / arrayCount;
|
||||
uint32 numSlices = arrayCount;
|
||||
if(type == MTL::TextureTypeCube || type == MTL::TextureTypeCubeArray) {
|
||||
sliceSize /= 6;
|
||||
numSlices *= 6;
|
||||
}
|
||||
uint32 offset = 0;
|
||||
for(uint32 slice = 0; slice < numSlices; ++slice){
|
||||
blitEnc->copyFromBuffer(stagingBuffer, offset, sliceSize / createInfo.height, arrayCount == 1 ? 0 : sliceSize, MTL::Size(createInfo.width, createInfo.height, createInfo.depth), texture, slice, 0, MTL::Origin());
|
||||
offset += sliceSize;
|
||||
}
|
||||
if(mipLevels > 1) {
|
||||
blitEnc->generateMipmaps(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextureHandle::~TextureHandle() {
|
||||
|
||||
@@ -87,11 +87,11 @@ Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo) : graphic
|
||||
metalWindow = glfwGetCocoaWindow(handle);
|
||||
metalLayer = [CAMetalLayer layer];
|
||||
metalLayer.device = (__bridge id<MTLDevice>)graphics->getDevice();
|
||||
metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB;
|
||||
metalLayer.drawableSize = CGSizeMake(createInfo.width, createInfo.height);
|
||||
metalWindow.contentView.layer = metalLayer;
|
||||
metalWindow.contentView.wantsLayer = YES;
|
||||
framebufferFormat = Gfx::SE_FORMAT_B8G8R8A8_UNORM;
|
||||
framebufferFormat = Gfx::SE_FORMAT_B8G8R8A8_SRGB;
|
||||
|
||||
drawable = (__bridge CA::MetalDrawable*)[metalLayer nextDrawable];
|
||||
createBackBuffer();
|
||||
@@ -104,8 +104,6 @@ void Window::show() { glfwShowWindow(windowHandle); }
|
||||
void Window::pollInput() { glfwPollEvents(); }
|
||||
|
||||
void Window::beginFrame() {
|
||||
drawable = (__bridge CA::MetalDrawable*)[metalLayer nextDrawable];
|
||||
createBackBuffer();
|
||||
static double start = glfwGetTime();
|
||||
double end = glfwGetTime();
|
||||
currentFrameDelta = end - start;
|
||||
@@ -114,9 +112,12 @@ void Window::beginFrame() {
|
||||
}
|
||||
|
||||
void Window::endFrame() {
|
||||
graphics->waitDeviceIdle();
|
||||
graphics->getQueue()->getCommands()->present(drawable);
|
||||
graphics->getQueue()->submitCommands();
|
||||
currentFrameIndex++;
|
||||
drawable = (__bridge CA::MetalDrawable*)[metalLayer nextDrawable];
|
||||
createBackBuffer();
|
||||
}
|
||||
|
||||
void Window::onWindowCloseEvent() {}
|
||||
@@ -156,17 +157,17 @@ void Window::resize(int width, int height) {
|
||||
}
|
||||
paused = true;
|
||||
metalLayer.drawableSize = CGSizeMake(width, height);
|
||||
drawable->release();
|
||||
[drawable release];
|
||||
framebufferWidth = width;
|
||||
framebufferHeight = height;
|
||||
// Deallocate the textures if they have been created
|
||||
drawable = (__bridge CA::MetalDrawable*)[[metalLayer nextDrawable] autorelease];
|
||||
drawable = (__bridge CA::MetalDrawable*)[metalLayer nextDrawable];
|
||||
createBackBuffer();
|
||||
resizeCallback(width, height);
|
||||
}
|
||||
|
||||
void Window::createBackBuffer() {
|
||||
MTL::Texture* buf = drawable->texture();
|
||||
MTL::Texture* buf = (__bridge MTL::Texture*)[drawable texture];
|
||||
backBuffer = new Texture2D(graphics,
|
||||
TextureCreateInfo{
|
||||
.width = static_cast<uint32>(buf->width()),
|
||||
@@ -186,8 +187,8 @@ Viewport::Viewport(PWindow owner, const ViewportCreateInfo& createInfo) : Gfx::V
|
||||
viewport.height = sizeY;
|
||||
viewport.originX = offsetX;
|
||||
viewport.originY = offsetY;
|
||||
viewport.znear = 0.0f;
|
||||
viewport.zfar = 1.0f;
|
||||
viewport.znear = 1.0f;
|
||||
viewport.zfar = 0.0f;
|
||||
}
|
||||
|
||||
Viewport::~Viewport() {}
|
||||
|
||||
@@ -259,7 +259,6 @@ void BasePass::render() {
|
||||
graphics->executeCommands(std::move(skyboxCommand));
|
||||
}
|
||||
graphics->endRenderPass();
|
||||
graphics->waitDeviceIdle();
|
||||
/*
|
||||
// Transparent rendering
|
||||
{
|
||||
@@ -416,13 +415,18 @@ void BasePass::publishOutputs() {
|
||||
msDepthAttachment =
|
||||
Gfx::RenderTargetAttachment(msBasePassDepth, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_DONT_CARE);
|
||||
msDepthAttachment.clear.depthStencil.depth = 0.0f;
|
||||
|
||||
colorAttachment = Gfx::RenderTargetAttachment(viewport, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
|
||||
Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_DONT_CARE);
|
||||
|
||||
msColorAttachment =
|
||||
Gfx::RenderTargetAttachment(msBasePassColor, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_DONT_CARE);
|
||||
msColorAttachment.clear.color.float32[0] = 0;
|
||||
msColorAttachment.clear.color.float32[1] = 1;
|
||||
msColorAttachment.clear.color.float32[2] = 0;
|
||||
msColorAttachment.clear.color.float32[3] = 1;
|
||||
|
||||
resources->registerRenderPassOutput("BASEPASS_COLOR", colorAttachment);
|
||||
resources->registerRenderPassOutput("BASEPASS_DEPTH", depthAttachment);
|
||||
|
||||
@@ -95,62 +95,62 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, const
|
||||
.pObjectName = name.c_str(),
|
||||
};
|
||||
vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo);
|
||||
ownsImage = true;
|
||||
}
|
||||
const DataSource& sourceData = createInfo.sourceData;
|
||||
if (sourceData.size > 0) {
|
||||
changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_NONE, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
void* data;
|
||||
VkBufferCreateInfo stagingInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.size = sourceData.size,
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
};
|
||||
VmaAllocationCreateInfo alloc = {
|
||||
.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||
};
|
||||
OBufferAllocation stagingAlloc =
|
||||
new BufferAllocation(graphics, fmt::format("{}Staging", createInfo.name), stagingInfo, alloc, Gfx::QueueType::TRANSFER);
|
||||
vmaMapMemory(graphics->getAllocator(), stagingAlloc->allocation, &data);
|
||||
std::memcpy(data, sourceData.data, sourceData.size);
|
||||
vmaUnmapMemory(graphics->getAllocator(), stagingAlloc->allocation);
|
||||
|
||||
PCommandPool commandPool = graphics->getQueueCommands(owner);
|
||||
VkBufferImageCopy region = {
|
||||
.bufferOffset = 0,
|
||||
.bufferRowLength = 0,
|
||||
.bufferImageHeight = 0,
|
||||
.imageSubresource =
|
||||
{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = arrayCount * layerCount,
|
||||
},
|
||||
.imageOffset =
|
||||
{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.z = 0,
|
||||
},
|
||||
.imageExtent = {.width = width, .height = height, .depth = depth},
|
||||
};
|
||||
|
||||
vkCmdCopyBufferToImage(commandPool->getCommands()->getHandle(), stagingAlloc->buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ®ion);
|
||||
|
||||
commandPool->getCommands()->bindResource(PBufferAllocation(stagingAlloc));
|
||||
generateMipmaps();
|
||||
// When loading a texture from a file, we will almost always use it as a texture map for fragment shaders
|
||||
changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
graphics->getDestructionManager()->queueResourceForDestruction(std::move(stagingAlloc));
|
||||
ownsImage = true;const DataSource& sourceData = createInfo.sourceData;
|
||||
if (sourceData.size > 0) {
|
||||
changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_NONE, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
void* data;
|
||||
VkBufferCreateInfo stagingInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.size = sourceData.size,
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
};
|
||||
VmaAllocationCreateInfo alloc = {
|
||||
.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||
};
|
||||
OBufferAllocation stagingAlloc =
|
||||
new BufferAllocation(graphics, fmt::format("{}Staging", createInfo.name), stagingInfo, alloc, Gfx::QueueType::TRANSFER);
|
||||
vmaMapMemory(graphics->getAllocator(), stagingAlloc->allocation, &data);
|
||||
std::memcpy(data, sourceData.data, sourceData.size);
|
||||
vmaUnmapMemory(graphics->getAllocator(), stagingAlloc->allocation);
|
||||
|
||||
PCommandPool commandPool = graphics->getQueueCommands(owner);
|
||||
VkBufferImageCopy region = {
|
||||
.bufferOffset = 0,
|
||||
.bufferRowLength = 0,
|
||||
.bufferImageHeight = 0,
|
||||
.imageSubresource =
|
||||
{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = arrayCount * layerCount,
|
||||
},
|
||||
.imageOffset =
|
||||
{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.z = 0,
|
||||
},
|
||||
.imageExtent = {.width = width, .height = height, .depth = depth},
|
||||
};
|
||||
|
||||
vkCmdCopyBufferToImage(commandPool->getCommands()->getHandle(), stagingAlloc->buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ®ion);
|
||||
|
||||
commandPool->getCommands()->bindResource(PBufferAllocation(stagingAlloc));
|
||||
generateMipmaps();
|
||||
// When loading a texture from a file, we will almost always use it as a texture map for fragment shaders
|
||||
changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
graphics->getDestructionManager()->queueResourceForDestruction(std::move(stagingAlloc));
|
||||
}
|
||||
}
|
||||
|
||||
VkImageViewCreateInfo viewInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
|
||||
Reference in New Issue
Block a user