如何使用Vulkan API上的分期缓冲区解决网状损坏
How to solve mesh corruption with staging buffer on Vulkan Api
我在代码中发现了一个错误,该错误使用分期缓冲区在某些情况下导致网格数据损坏。我有:
-
临时网格数据
-
具有一定尺寸的分期缓冲区,通过命令缓冲区和memcpy同时使用,但一次不同时使用。
-
缓冲液分配器,它给出了合适的顶点索引缓冲区的一部分,其中网格数据通过VKCMDCOPYBUFFER从分期转移。缓冲区包含许多针对不同网格的段。
当我通过命令缓冲区和memcpy同时使用登台缓冲区时,网格数据会不正确地写入(被覆盖/损坏(,甚至可能导致vk_error_device_lost。
。https://i.stack.imgur.com/xlupf.jpg"正确网格"
https://i.stack.imgur.com/aw949.jpg"破碎网格"
[[nodiscard]] static Result writeMeshBuffer(TransferData &data, GpuMesh &buffer)
{
Result result; using namespace vkw;
auto &mesh = buffer.source;
size_t vSize = mesh.vertices_count * mesh.vertex_size;
size_t iSize = mesh.indices_count * mesh.index_size;
size_t mesh_size = vSize + iSize;
auto &staging_offset = data.stagingData.buffer_offset_unused;
// write data to staging buffer
{
// guaranteed that mesh_size will less or equal than staging buffer size
//FIXME false condition generate broken meshes somehow
bool is_wait_before = mesh_size > TransferStagingData::BUFFER_SIZE - staging_offset;
//will work correctly:
//bool is_wait_before = true;
if (is_wait_before) // if we need more memory on staging buffer than not used already
{
result = data.wait_transfer();
if (result != VK_SUCCESS)
return result;
staging_offset = 0;
}
uint8_t *pMemory = static_cast<uint8_t*>(data.stagingData.pMemory) + staging_offset;
memcpy(pMemory, mesh.vertices.pX, vSize);
memcpy(pMemory + vSize, mesh.indices.pXX, iSize);
if (not is_wait_before)
{
result = data.wait_transfer();
if (result != VK_SUCCESS)
return result;
}
}
// write data from staging buffer to mesh buffer
{
auto cmd_cpy_buff = [](CommandBuffer cmd, BufferCopy copy, Offsets offsets, DeviceSizeT size)
{
cmd.cmd_copy_buffer(copy, offsets, size);
};
// SRC DST
BufferCopy copy = { data.stagingData.buffer, buffer.info.buffer };
Offsets offsets = { staging_offset, buffer.info.region.offset };
result = data.transfer.prepare(cmd_cpy_buff, data.transfer.cmd_buffer, copy, offsets, mesh_size);
if (result != VK_SUCCESS)
return result;
data.reset_fence();
result = data.transfer.submit({&data.transfer.cmd_buffer,1},{}, {}, {}, data.transferFence);
if (result != VK_SUCCESS)
return result;
}
// save usused offset to data.stagingData.buffer_offset_unused;
staging_offset = staging_offset == 0 ? mesh_size : 0;
return result;
}
如果我不能使用这样的登台缓冲区,那么为什么。
如果我有错误,idk,
问题是
staging_offset = staging_offset == 0 ? mesh_size : 0;
需要更改
staging_offset = staging_offset == 0 ? TransferStagingData::BUFFER_SIZE - mesh_size : 0;
更改后所有工作都正确。
相关文章:
- 运行同一解决方案的另一个项目的项目
- C++字符*缓冲区的大小
- Project Euler问题4的错误解决方案
- Ardunio UNO解决了多个重叠的定时器循环
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- ostream过载时的缓冲区冲洗
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- Xaudio2在更改缓冲区或循环时弹出声音
- 两个文件使用彼此的功能-如何解决
- 计算每个节点的树高,帮助我解释这个代码解决方案
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 如何解决"invalid conversion from 'char' to 'const char*'"
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 我正在尝试使用回溯来解决 N queen 问题,但在编译时它会给出运行时错误(动态堆栈缓冲区溢出)
- 如何使用Vulkan API上的分期缓冲区解决网状损坏
- 如何解决此缓冲区溢出问题?
- ISR中使用的循环缓冲区(声明为volatile)会出错.为什么?如何解决此问题
- 作为跨语言序列化解决方案的节俭或协议缓冲区