Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用500MB RAM的10MB图像_C++_Memory Leaks_Vulkan - Fatal编程技术网

C++ 使用500MB RAM的10MB图像

C++ 使用500MB RAM的10MB图像,c++,memory-leaks,vulkan,C++,Memory Leaks,Vulkan,我的Vulkan应用程序内存有问题。加载一个10mb的PNG图像需要使用大约500mb的ram TextureObject* createTextureImage(const char* File) { auto Tex = Textures.emplace_back(new TextureObject(_Driver)); //decode unsigned error = lodepng::decode(Tex->Pixels, Tex->Width,

我的Vulkan应用程序内存有问题。加载一个10mb的PNG图像需要使用大约500mb的ram

TextureObject* createTextureImage(const char* File) {

    auto Tex = Textures.emplace_back(new TextureObject(_Driver));

    //decode
    unsigned error = lodepng::decode(Tex->Pixels, Tex->Width, Tex->Height, File);

    //if there's an error, display it
    if (error) printf("PNG Decoder error: (%i) %s", error, lodepng_error_text(error));

    Tex->Empty = false;

    VkDeviceSize imageSize = Tex->Width * Tex->Height * 4;

    //
    //  Image Staging Buffer
    VkBufferCreateInfo stagingBufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
    stagingBufferInfo.size = imageSize;
    stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;

    VmaAllocationCreateInfo allocInfo = {};
    allocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
    allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;

    VkBuffer stagingImageBuffer = VK_NULL_HANDLE;
    VmaAllocation stagingImageBufferAlloc = VK_NULL_HANDLE;
    vmaCreateBuffer(_Driver->allocator, &stagingBufferInfo, &allocInfo, &stagingImageBuffer, &stagingImageBufferAlloc, nullptr);

    memcpy(stagingImageBufferAlloc->GetMappedData(), Tex->Pixels.data(), static_cast<size_t>(imageSize));
    Tex->Pixels.clear();

    VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
    imageInfo.imageType = VK_IMAGE_TYPE_2D;
    imageInfo.extent.width = static_cast<uint32_t>(Tex->Width);
    imageInfo.extent.height = static_cast<uint32_t>(Tex->Height);
    imageInfo.extent.depth = 1;
    imageInfo.mipLevels = 1;
    imageInfo.arrayLayers = 1;
    imageInfo.format = VK_FORMAT_B8G8R8A8_SRGB;
    imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
    imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
    imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
    imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;

    allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;

    VmaAllocationInfo imageBufferAllocInfo = {};
    vmaCreateImage(_Driver->allocator, &imageInfo, &allocInfo, &Tex->Image, &Tex->Allocation, nullptr);
    //
    //  CPU->GPU Copy
    VkCommandBuffer commandBuffer = _Driver->_SceneGraph->beginSingleTimeCommands();
    VkImageMemoryBarrier imgMemBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
    imgMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    imgMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    imgMemBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    imgMemBarrier.subresourceRange.baseMipLevel = 0;
    imgMemBarrier.subresourceRange.levelCount = 1;
    imgMemBarrier.subresourceRange.baseArrayLayer = 0;
    imgMemBarrier.subresourceRange.layerCount = 1;
    imgMemBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    imgMemBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
    imgMemBarrier.image = Tex->Image;
    imgMemBarrier.srcAccessMask = 0;
    imgMemBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;

    vkCmdPipelineBarrier(
        commandBuffer,
        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
        VK_PIPELINE_STAGE_TRANSFER_BIT,
        0,
        0, nullptr,
        0, nullptr,
        1, &imgMemBarrier);

    VkBufferImageCopy region = {};
    region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    region.imageSubresource.layerCount = 1;
    region.imageExtent.width = static_cast<uint32_t>(Tex->Width);
    region.imageExtent.height = static_cast<uint32_t>(Tex->Height);
    region.imageExtent.depth = 1;

    vkCmdCopyBufferToImage(commandBuffer, stagingImageBuffer, Tex->Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);

    imgMemBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
    imgMemBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
    imgMemBarrier.image = Tex->Image;
    imgMemBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
    imgMemBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;

    vkCmdPipelineBarrier(
        commandBuffer,
        VK_PIPELINE_STAGE_TRANSFER_BIT,
        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
        0,
        0, nullptr,
        0, nullptr,
        1, &imgMemBarrier);

    _Driver->_SceneGraph->endSingleTimeCommands(commandBuffer);

    vmaDestroyBuffer(_Driver->allocator, stagingImageBuffer, stagingImageBufferAlloc);

    VkImageViewCreateInfo textureImageViewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
    textureImageViewInfo.image = Tex->Image;
    textureImageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
    textureImageViewInfo.format = VK_FORMAT_B8G8R8A8_SRGB;
    textureImageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    textureImageViewInfo.subresourceRange.baseMipLevel = 0;
    textureImageViewInfo.subresourceRange.levelCount = 1;
    textureImageViewInfo.subresourceRange.baseArrayLayer = 0;
    textureImageViewInfo.subresourceRange.layerCount = 1;
    vkCreateImageView(_Driver->device, &textureImageViewInfo, nullptr, &Tex->ImageView);

    VkSamplerCreateInfo samplerInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
    samplerInfo.magFilter = VK_FILTER_LINEAR;
    samplerInfo.minFilter = VK_FILTER_LINEAR;
    samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
    samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
    samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
    samplerInfo.anisotropyEnable = VK_TRUE;
    samplerInfo.maxAnisotropy = 16;
    samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
    samplerInfo.unnormalizedCoordinates = VK_FALSE;
    samplerInfo.compareEnable = VK_FALSE;
    samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
    samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
    samplerInfo.mipLodBias = 0.0f;
    samplerInfo.minLod = 0.0f;
    samplerInfo.maxLod = 0.0f;
    if (vkCreateSampler(_Driver->device, &samplerInfo, nullptr, &Tex->Sampler) != VK_SUCCESS) {
#ifdef _DEBUG
        throw std::runtime_error("failed to create texture sampler!");
#endif
    }

    return Tex;
}
即使是1kb png也需要大约5mb的负载,这似乎是非常高的

我还尝试使用加载png文件,它给出了相同的结果


编辑2:10mb png是4096x4096,1kb png是16x16


EDIT2:在一些内存分析之后,在检查其中一个内存峰值后,分配了58000个void实例(占563000000字节),其中超过500000000个位于我称为
.clear()
的向量中。我不知道如何真正解除分配,或者这是否是一个大问题

加载10mb png文件时如何使用超过500mb的加载空间

嗯,是10MB的压缩数据。这里所有的缓冲区都是解压后的,所以每个64MB


一个可能的漏洞是
vector.clear()
不能保证重新分配,因此当您在此处调用
clear()
来释放对象时,您可能仍然占用64MB的备份存储空间,直到向量被销毁后才会释放

你有没有试着去看看现在有多少RAM消耗了其他的程序?我是说图像查看器之类的?你的图像的实际尺寸是多少?这将最终定义原始位图的大小。编辑:我刚刚创建了一个10.000 x 10.000的纯白PNG,结果是32kb,所以PNG确实可以进行相当大的压缩。我看到了
新的TextureObject(_Driver)
,但我没有看到相应的
删除
。10mb的PNG是4096x4096,1kb的PNG是16x16。看起来我需要找出如何减少大图像上的内存使用。所以它应该只需要大约64MB。你确定这500 MB实际上是提交的,而不是简单地分配为虚拟内存吗?在进行一些内存分析后,在检查一个内存峰值后,分配了58000个void实例(占563000000字节),其中超过500000000个实例位于我称为
.clear()
的向量中。我不知道如何真正解除分配,或者它是否有那么大的问题?@KKlouzal:。另一种方法是在向量中存储指针(智能或其他),然后内存分配就不会与向量的生命周期相关联。
unsigned int Width = 0;
unsigned int Height = 0;
std::vector<unsigned char> Pixels = {};