Forgetting to delete leads to memoryleaks
This commit is contained in:
@@ -23,6 +23,7 @@ protected:
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
};
|
||||
|
||||
DECLARE_REF(UniformBuffer)
|
||||
class UniformBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
@@ -30,7 +31,7 @@ public:
|
||||
virtual ~UniformBuffer();
|
||||
// returns true if an update was performed, false if the old contents == new contents
|
||||
virtual bool updateContents(const DataSource& sourceData);
|
||||
bool isDataEquals(UniformBuffer* other)
|
||||
bool isDataEquals(PUniformBuffer other)
|
||||
{
|
||||
if(other == nullptr)
|
||||
{
|
||||
|
||||
@@ -165,7 +165,7 @@ namespace Gfx
|
||||
{
|
||||
static constexpr bool useAsyncCompute = true;
|
||||
static constexpr bool waitIdleOnSubmit = true;
|
||||
extern bool useMeshShading = false; // enable if supported
|
||||
static constexpr bool useMeshShading = true;
|
||||
static constexpr uint32 numFramesBuffered = 3;
|
||||
|
||||
// meshlet dimensions curated by NVIDIA
|
||||
|
||||
@@ -80,10 +80,11 @@ public:
|
||||
virtual OPipelineLayout createPipelineLayout(PPipelineLayout baseLayout = nullptr) = 0;
|
||||
|
||||
virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) = 0;
|
||||
|
||||
bool supportMeshShading() const { return meshShadingEnabled; }
|
||||
protected:
|
||||
QueueFamilyMapping queueMapping;
|
||||
OShaderCompiler shaderCompiler;
|
||||
bool meshShadingEnabled = false;
|
||||
friend class Window;
|
||||
};
|
||||
DEFINE_REF(Graphics)
|
||||
|
||||
@@ -75,7 +75,7 @@ void BasePass::render()
|
||||
graphics->beginRenderPass(renderPass);
|
||||
Gfx::ShaderPermutation permutation;
|
||||
permutation.hasFragment = true;
|
||||
if(Gfx::useMeshShading)
|
||||
if(graphics->supportMeshShading())
|
||||
{
|
||||
permutation.useMeshShading = true;
|
||||
permutation.hasTaskShader = true;
|
||||
@@ -115,7 +115,7 @@ void BasePass::render()
|
||||
|
||||
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
|
||||
assert(collection != nullptr);
|
||||
if(Gfx::useMeshShading)
|
||||
if(graphics->supportMeshShading())
|
||||
{
|
||||
Gfx::MeshPipelineCreateInfo pipelineInfo;
|
||||
pipelineInfo.taskShader = collection->taskShader;
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
virtual void createRenderPass() override;
|
||||
static void modifyRenderPassMacros(Map<const char*, const char*>& defines);
|
||||
private:
|
||||
Gfx::PRenderTargetAttachment colorAttachment;
|
||||
Gfx::ORenderTargetAttachment colorAttachment;
|
||||
Gfx::PTexture2D depthBuffer;
|
||||
Gfx::PShaderBuffer oLightIndexList;
|
||||
Gfx::PShaderBuffer tLightIndexList;
|
||||
|
||||
@@ -39,7 +39,7 @@ void DepthPrepass::render()
|
||||
depthAttachment->getTexture()->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
Gfx::ShaderPermutation permutation;
|
||||
permutation.hasFragment = false;
|
||||
if(Gfx::useMeshShading)
|
||||
if(graphics->supportMeshShading())
|
||||
{
|
||||
permutation.useMeshShading = true;
|
||||
permutation.hasTaskShader = true;
|
||||
@@ -76,7 +76,7 @@ void DepthPrepass::render()
|
||||
|
||||
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
|
||||
assert(collection != nullptr);
|
||||
if(Gfx::useMeshShading)
|
||||
if(graphics->supportMeshShading())
|
||||
{
|
||||
Gfx::MeshPipelineCreateInfo pipelineInfo;
|
||||
pipelineInfo.taskShader = collection->taskShader;
|
||||
@@ -107,7 +107,7 @@ void DepthPrepass::render()
|
||||
descriptorSets[INDEX_MATERIAL] = instance.materialInstance->getDescriptorSet();
|
||||
descriptorSets[INDEX_SCENE_DATA] = instance.descriptorSet;
|
||||
command->bindDescriptor(descriptorSets);
|
||||
if(Gfx::useMeshShading)
|
||||
if(graphics->supportMeshShading())
|
||||
{
|
||||
command->dispatch(instance.numMeshes, 1, 1);
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ TextPass::FontData& TextPass::getFontData(PFontAsset font)
|
||||
gd.bearing = value.bearing;
|
||||
gd.size = value.size;
|
||||
gd.advance = value.advance;
|
||||
textures.add(value.texture);
|
||||
textures.add(font->getTexture(value.textureIndex));
|
||||
}
|
||||
fd.glyphDataSet = glyphData;
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ public:
|
||||
void loadNormals(MeshId id, const Array<Vector>& data);
|
||||
void loadTangents(MeshId id, const Array<Vector>& data);
|
||||
void loadBiTangents(MeshId id, const Array<Vector>& data);
|
||||
virtual Gfx::PVertexDeclaration getDeclaration() override;
|
||||
virtual void serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer& buffer) override;
|
||||
virtual void deserializeMesh(MeshId id, ArchiveBuffer& buffer) override;
|
||||
virtual void init(Gfx::PGraphics graphics) override;
|
||||
|
||||
@@ -118,7 +118,7 @@ void VertexData::createDescriptors()
|
||||
instanceDataLayout->reset();
|
||||
matInst.descriptorSet = instanceDataLayout->allocateDescriptorSet();
|
||||
matInst.descriptorSet->updateBuffer(0, instanceBuffer);
|
||||
if (Gfx::useMeshShading)
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
Gfx::PShaderBuffer meshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData = {
|
||||
@@ -181,7 +181,7 @@ void Seele::VertexData::init(Gfx::PGraphics graphics)
|
||||
verticesAllocated = NUM_DEFAULT_ELEMENTS;
|
||||
instanceDataLayout = graphics->createDescriptorLayout("VertexDataInstanceLayout");
|
||||
instanceDataLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||
if (Gfx::useMeshShading)
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
// meshData
|
||||
instanceDataLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||
|
||||
@@ -89,10 +89,8 @@ OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
for (auto& it : freeRanges)
|
||||
for (auto& [allocatedOffset, freeAllocation] : freeRanges)
|
||||
{
|
||||
VkDeviceSize allocatedOffset = it.key;
|
||||
OSubAllocation& freeAllocation = it.value;
|
||||
assert(allocatedOffset == freeAllocation->allocatedOffset);
|
||||
VkDeviceSize alignedOffset = allocatedOffset + alignment - 1;
|
||||
alignedOffset /= alignment;
|
||||
@@ -284,18 +282,18 @@ OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2
|
||||
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
||||
}
|
||||
|
||||
void Allocator::free(Allocation *allocation)
|
||||
void Allocator::free(PAllocation allocation)
|
||||
{
|
||||
std::scoped_lock lck(lock);
|
||||
for (auto& heap : heaps)
|
||||
for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
|
||||
{
|
||||
for (uint32 heapIndex = 0; heapIndex < heap.allocations.size(); ++heapIndex)
|
||||
for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
|
||||
{
|
||||
if (heap.allocations[heapIndex] == allocation)
|
||||
if (heaps[heapIndex].allocations[alloc] == allocation)
|
||||
{
|
||||
heap.inUse -= allocation->bytesAllocated;
|
||||
std::cout << "Heap " << heapIndex << " -" <<allocation->bytesAllocated << ":" << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl;
|
||||
heap.allocations.removeAt(heapIndex, false);
|
||||
heaps[heapIndex].inUse -= allocation->bytesAllocated;
|
||||
std::cout << "Heap " << heapIndex << " -" <<allocation->bytesAllocated << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl;
|
||||
heaps[heapIndex].allocations.removeAt(heapIndex, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -432,11 +430,11 @@ OStagingBuffer StagingManager::allocateStagingBuffer(uint64 size, VkBufferUsageF
|
||||
|
||||
void StagingManager::releaseStagingBuffer(OStagingBuffer buffer)
|
||||
{
|
||||
std::scoped_lock l(lock);
|
||||
if(activeBuffers.find(buffer) == activeBuffers.end())
|
||||
if (buffer == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::scoped_lock l(lock);
|
||||
activeBuffers.remove(buffer);
|
||||
std::cout << "Releasing stagingbuffer size " << buffer->getSize() << std::endl;
|
||||
freeBuffers.add(std::move(buffer));
|
||||
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
return allocate(requirements, props, &allocInfo);
|
||||
}
|
||||
|
||||
void free(Allocation *allocation);
|
||||
void free(PAllocation allocation);
|
||||
private:
|
||||
enum
|
||||
{
|
||||
|
||||
@@ -61,20 +61,6 @@ Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::Q
|
||||
|
||||
Buffer::~Buffer()
|
||||
{
|
||||
//PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands();
|
||||
//VkDevice device = graphics->getDevice();
|
||||
//auto deletionLambda = [cmdBuffer, device](VkBuffer) -> void
|
||||
//{
|
||||
// //co_await cmdBuffer->asyncWait();
|
||||
// //vkDestroyBuffer(device, buffer, nullptr);
|
||||
// //co_return;
|
||||
//};
|
||||
//for (uint32 i = 0; i < numBuffers; ++i)
|
||||
//{
|
||||
// deletionLambda(buffers[i].buffer);
|
||||
// buffers[i].allocation = nullptr;
|
||||
//}
|
||||
graphics = nullptr;
|
||||
}
|
||||
|
||||
VkDeviceSize Buffer::getOffset() const
|
||||
|
||||
@@ -7,7 +7,6 @@ namespace Seele
|
||||
{
|
||||
namespace Vulkan
|
||||
{
|
||||
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -114,108 +114,95 @@ void Graphics::executeCommands(const Array<Gfx::PComputeCommand>& commands)
|
||||
|
||||
Gfx::OTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo)
|
||||
{
|
||||
OTexture2D result = new Texture2D(this, createInfo);
|
||||
return result;
|
||||
return new Texture2D(this, createInfo);
|
||||
}
|
||||
|
||||
Gfx::OTexture3D Graphics::createTexture3D(const TextureCreateInfo &createInfo)
|
||||
{
|
||||
OTexture3D result = new Texture3D(this, createInfo);
|
||||
return result;
|
||||
return new Texture3D(this, createInfo);
|
||||
}
|
||||
|
||||
Gfx::OTextureCube Graphics::createTextureCube(const TextureCreateInfo &createInfo)
|
||||
{
|
||||
OTextureCube result = new TextureCube(this, createInfo);
|
||||
return result;
|
||||
return new TextureCube(this, createInfo);
|
||||
}
|
||||
|
||||
Gfx::OUniformBuffer Graphics::createUniformBuffer(const UniformBufferCreateInfo &bulkData)
|
||||
{
|
||||
OUniformBuffer uniformBuffer = new UniformBuffer(this, bulkData);
|
||||
return uniformBuffer;
|
||||
return new UniformBuffer(this, bulkData);
|
||||
}
|
||||
|
||||
Gfx::OShaderBuffer Graphics::createShaderBuffer(const ShaderBufferCreateInfo &bulkData)
|
||||
{
|
||||
OShaderBuffer shaderBuffer = new ShaderBuffer(this, bulkData);
|
||||
return shaderBuffer;
|
||||
return new ShaderBuffer(this, bulkData);
|
||||
}
|
||||
Gfx::OVertexBuffer Graphics::createVertexBuffer(const VertexBufferCreateInfo &bulkData)
|
||||
{
|
||||
OVertexBuffer vertexBuffer = new VertexBuffer(this, bulkData);
|
||||
return vertexBuffer;
|
||||
return new VertexBuffer(this, bulkData);
|
||||
}
|
||||
|
||||
Gfx::OIndexBuffer Graphics::createIndexBuffer(const IndexBufferCreateInfo &bulkData)
|
||||
{
|
||||
OIndexBuffer indexBuffer = new IndexBuffer(this, bulkData);
|
||||
return indexBuffer;
|
||||
return new IndexBuffer(this, bulkData);
|
||||
}
|
||||
Gfx::PRenderCommand Graphics::createRenderCommand(const std::string& name)
|
||||
{
|
||||
PRenderCommand cmdBuffer = getGraphicsCommands()->createRenderCommand(activeRenderPass, activeFramebuffer, name);
|
||||
return cmdBuffer;
|
||||
return getGraphicsCommands()->createRenderCommand(activeRenderPass, activeFramebuffer, name);
|
||||
}
|
||||
|
||||
Gfx::PComputeCommand Graphics::createComputeCommand(const std::string& name)
|
||||
{
|
||||
PComputeCommand cmdBuffer = getComputeCommands()->createComputeCommand(name);
|
||||
return cmdBuffer;
|
||||
return getComputeCommands()->createComputeCommand(name);
|
||||
}
|
||||
|
||||
Gfx::OVertexDeclaration Graphics::createVertexDeclaration(const Array<Gfx::VertexElement>& element)
|
||||
{
|
||||
OVertexDeclaration declaration = new VertexDeclaration(element);
|
||||
return declaration;
|
||||
return new VertexDeclaration(element);
|
||||
}
|
||||
|
||||
Gfx::OVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
OVertexShader shader = new VertexShader(this);
|
||||
shader->create(createInfo);
|
||||
return shader;
|
||||
return std::move(shader);
|
||||
}
|
||||
Gfx::OFragmentShader Graphics::createFragmentShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
OFragmentShader shader = new FragmentShader(this);
|
||||
shader->create(createInfo);
|
||||
return shader;
|
||||
return std::move(shader);
|
||||
}
|
||||
Gfx::OComputeShader Graphics::createComputeShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
OComputeShader shader = new ComputeShader(this);
|
||||
shader->create(createInfo);
|
||||
return shader;
|
||||
return std::move(shader);
|
||||
}
|
||||
Gfx::OTaskShader Graphics::createTaskShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
OTaskShader shader = new TaskShader(this);
|
||||
shader->create(createInfo);
|
||||
return shader;
|
||||
return std::move(shader);
|
||||
}
|
||||
Gfx::OMeshShader Graphics::createMeshShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
OMeshShader shader = new MeshShader(this);
|
||||
shader->create(createInfo);
|
||||
return shader;
|
||||
return std::move(shader);
|
||||
}
|
||||
|
||||
Gfx::OGraphicsPipeline Graphics::createGraphicsPipeline(const Gfx::LegacyPipelineCreateInfo& createInfo)
|
||||
{
|
||||
OGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo);
|
||||
return pipeline;
|
||||
return pipelineCache->createPipeline(createInfo);
|
||||
}
|
||||
Gfx::OGraphicsPipeline Graphics::createGraphicsPipeline(const Gfx::MeshPipelineCreateInfo& createInfo)
|
||||
{
|
||||
OGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo);
|
||||
return pipeline;
|
||||
return pipelineCache->createPipeline(createInfo);
|
||||
}
|
||||
|
||||
Gfx::OComputePipeline Graphics::createComputePipeline(const Gfx::ComputePipelineCreateInfo& createInfo)
|
||||
{
|
||||
OComputePipeline pipeline = pipelineCache->createPipeline(createInfo);
|
||||
return pipeline;
|
||||
return pipelineCache->createPipeline(createInfo);
|
||||
}
|
||||
|
||||
Gfx::OSamplerState Graphics::createSamplerState(const SamplerCreateInfo& createInfo)
|
||||
@@ -240,17 +227,15 @@ Gfx::OSamplerState Graphics::createSamplerState(const SamplerCreateInfo& createI
|
||||
vkInfo.mipmapMode = cast(createInfo.mipmapMode);
|
||||
vkInfo.unnormalizedCoordinates = createInfo.unnormalizedCoordinates;
|
||||
VK_CHECK(vkCreateSampler(handle, &vkInfo, nullptr, &sampler->sampler));
|
||||
return sampler;
|
||||
return std::move(sampler);
|
||||
}
|
||||
Gfx::ODescriptorLayout Graphics::createDescriptorLayout(const std::string& name)
|
||||
{
|
||||
ODescriptorLayout layout = new DescriptorLayout(this, name);
|
||||
return layout;
|
||||
return new DescriptorLayout(this, name);
|
||||
}
|
||||
Gfx::OPipelineLayout Graphics::createPipelineLayout(Gfx::PPipelineLayout baseLayout)
|
||||
{
|
||||
OPipelineLayout layout = new PipelineLayout(this, baseLayout);
|
||||
return layout;
|
||||
return new PipelineLayout(this, baseLayout);
|
||||
}
|
||||
|
||||
void Graphics::copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture)
|
||||
@@ -469,16 +454,19 @@ void Graphics::pickPhysicalDevice()
|
||||
physicalDevice = bestDevice;
|
||||
vkGetPhysicalDeviceProperties(physicalDevice, &props);
|
||||
vkGetPhysicalDeviceFeatures(physicalDevice, &features);
|
||||
uint32 count = 0;
|
||||
vkEnumerateDeviceExtensionProperties(physicalDevice, "VK_EXT_mesh_shader", &count, nullptr);
|
||||
Array<VkExtensionProperties> extensionProps(count);
|
||||
vkEnumerateDeviceExtensionProperties(physicalDevice, "VK_EXT_mesh_shader", &count, extensionProps.data());
|
||||
for(size_t i = 0; i < count; ++i)
|
||||
if (Gfx::useMeshShading)
|
||||
{
|
||||
if(std::strcmp("VK_EXT_mesh_shader", extensionProps[i].extensionName) == 0)
|
||||
uint32 count = 0;
|
||||
vkEnumerateDeviceExtensionProperties(physicalDevice, VK_EXT_MESH_SHADER_EXTENSION_NAME, &count, nullptr);
|
||||
Array<VkExtensionProperties> extensionProps(count);
|
||||
vkEnumerateDeviceExtensionProperties(physicalDevice, VK_EXT_MESH_SHADER_EXTENSION_NAME, &count, extensionProps.data());
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
Gfx::useMeshShading = true;
|
||||
break;
|
||||
if (std::strcmp(VK_EXT_MESH_SHADER_EXTENSION_NAME, extensionProps[i].extensionName) == 0)
|
||||
{
|
||||
meshShadingEnabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -605,7 +593,7 @@ void Graphics::createDevice(GraphicsInitializer initializer)
|
||||
.taskShader = VK_TRUE,
|
||||
.meshShader = VK_TRUE,
|
||||
};
|
||||
if (Gfx::useMeshShading)
|
||||
if (supportMeshShading())
|
||||
{
|
||||
descriptorIndexing.pNext = &enabledMeshShaderFeatures;
|
||||
initializer.deviceExtensions.add("VK_EXT_mesh_shader");
|
||||
|
||||
@@ -38,7 +38,7 @@ PipelineCache::~PipelineCache()
|
||||
{
|
||||
VkDeviceSize cacheSize;
|
||||
vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, nullptr);
|
||||
Array<uint8> cacheData;
|
||||
Array<uint8> cacheData(cacheSize);
|
||||
vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, cacheData.data());
|
||||
std::ofstream stream(cacheFile, std::ios::binary);
|
||||
stream.write((char*)cacheData.data(), cacheSize);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
double useMeshShading = false;
|
||||
double currentFrameDelta = 0;
|
||||
double Gfx::getCurrentFrameDelta()
|
||||
{
|
||||
|
||||
@@ -110,7 +110,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType,
|
||||
if(sourceData.size > 0)
|
||||
{
|
||||
changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
PStagingBuffer staging = graphics->getStagingManager()->allocateStagingBuffer(sourceData.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
||||
OStagingBuffer staging = graphics->getStagingManager()->allocateStagingBuffer(sourceData.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
||||
void* data = staging->getMappedPointer();
|
||||
std::memcpy(data, sourceData.data, sourceData.size);
|
||||
staging->flushMappedMemory();
|
||||
@@ -134,6 +134,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType,
|
||||
|
||||
// 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);
|
||||
graphics->getStagingManager()->releaseStagingBuffer(std::move(staging));
|
||||
}
|
||||
else if(usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
||||
{
|
||||
@@ -213,7 +214,7 @@ void TextureHandle::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Ar
|
||||
{
|
||||
uint64 imageSize = sizeX * sizeY * sizeZ * Gfx::getFormatInfo(format).blockSize;
|
||||
|
||||
PStagingBuffer stagingbuffer = graphics->getStagingManager()->allocateStagingBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true);
|
||||
OStagingBuffer stagingbuffer = graphics->getStagingManager()->allocateStagingBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true);
|
||||
auto prevlayout = layout;
|
||||
changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
|
||||
@@ -236,6 +237,7 @@ void TextureHandle::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Ar
|
||||
buffer.resize(stagingbuffer->getSize());
|
||||
void* data = stagingbuffer->getMappedPointer();
|
||||
std::memcpy(buffer.data(), data, buffer.size());
|
||||
graphics->getStagingManager()->releaseStagingBuffer(std::move(stagingbuffer));
|
||||
}
|
||||
|
||||
void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
|
||||
Reference in New Issue
Block a user