- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用Vulkan在C++中开发体素引擎。大部分样板代码很大程度上基于vulkan-tutorial.com。我有一个看起来像这样的drawFrame函数...
void drawFrame(float dt) {
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
uint32_t imageIndex;
VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
updateUniformBuffer(imageIndex, dt);
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
recreateSwapChain();
return;
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
throw std::runtime_error("failed to acquire swap chain image!");
}
// Check if a previous frame is using this image (i.e.there is its fence to wait on)
if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
}
// Mark the image as now being in use by this frame
imagesInFlight[imageIndex] = inFlightFences[currentFrame];
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffers[imageIndex];
VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
vkResetFences(device, 1, &inFlightFences[currentFrame]);
result = vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]);
if (result != VK_SUCCESS) {
throw std::runtime_error("failed to submit draw command buffer!");
}
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
VkSwapchainKHR swapChains[] = { swapChain };
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
presentInfo.pResults = nullptr; // Optional
result = vkQueuePresentKHR(presentQueue, &presentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) {
framebufferResized = false;
recreateSwapChain();
} else if (result != VK_SUCCESS) {
throw std::runtime_error("failed to present swap chain image!");
}
// Increment the frame. By using the modulo(%) operator, we ensure that the frame index loops around after every MAX_FRAMES_IN_FLIGHT enqueued frames.
currentFrame = (currentFrame + 1) % config->maxFramesInFlight;
}
我通过这样的顶点...
void createVertexAndIndexBuffer() {
for (size_t x = 0; x < 100; x++) {
for (size_t y = 0; y < 4; y++) {
for (size_t z = 0; z < 100; z++) {
// for each block in the world vector
auto blockId = world.getBlock(x, y, z);
if (blockId == BlockId::Air) {
continue;
}
Vec3 blockPosition = { x, y, z };
// get its data
auto verts = blockdb.blockDataFor(blockId).getVertices();
auto inds = blockdb.blockDataFor(blockId).getIndices();
// account for the block position and store the new verts for later
for (int i = 0; i < verts.size(); i++) {
Vertex v(verts[i]);
v.pos += blockPosition;
vertices.push_back(v);
}
// store the indices for later accounting for the offset into the verts vector
for (int i = 0; i < inds.size(); i++) {
int ind(inds[i] + vertices.size());
indices.push_back(ind);
}
}
}
}
// time to start creating the actual buffer
VkDeviceSize vertexBufferSize = sizeof(vertices[0]) * vertices.size();
VkBuffer vertexStagingBuffer;
VkDeviceMemory vertexStagingBufferMemory;
createBuffer(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexStagingBuffer, vertexStagingBufferMemory);
void* vertexData;
vkMapMemory(device, vertexStagingBufferMemory, 0, vertexBufferSize, 0, &vertexData);
memcpy(vertexData, vertices.data(), (size_t)vertexBufferSize);
vkUnmapMemory(device, vertexStagingBufferMemory);
createBuffer(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);
// use copyBuffer() to move the vertex data to the device local buffer
copyBuffer(vertexStagingBuffer, vertexBuffer, vertexBufferSize);
// After copying the data from the staging buffer to the device buffer, we should clean up the staging buffer since it is no longer needed.
vkDestroyBuffer(device, vertexStagingBuffer, nullptr);
vkFreeMemory(device, vertexStagingBufferMemory, nullptr);
// and do the same for the index buffer
VkDeviceSize indexBufferSize = sizeof(indices[0]) * indices.size();
VkBuffer indexStagingBuffer;
VkDeviceMemory indexStagingBufferMemory;
createBuffer(indexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, indexStagingBuffer, indexStagingBufferMemory);
void* indexData;
vkMapMemory(device, indexStagingBufferMemory, 0, indexBufferSize, 0, &indexData);
memcpy(indexData, indices.data(), (size_t)indexBufferSize);
vkUnmapMemory(device, indexStagingBufferMemory);
createBuffer(indexBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);
copyBuffer(indexStagingBuffer, indexBuffer, indexBufferSize);
vkDestroyBuffer(device, indexStagingBuffer, nullptr);
vkFreeMemory(device, indexStagingBufferMemory, nullptr);
}
一切都可以正常工作,但是我需要能够按块而不是按块进行渲染,以实现块几何优化。这是我的chunk.h和chunk.cpp ...
#pragma once
#include "Layer.h"
class Chunk {
public:
Chunk() = default;
Chunk(World* _world, Vec2XZ pos);
~Chunk() {}
BlockId getBlock(int x, int y, int z);
bool setBlock(BlockId id, int x, int y, int z);
bool isBlockOutOfBounds(int x, int y, int z);
void generateVerticesAndIndices();
void load();
std::array<Layer, CHUNK_HEIGHT> layers;
const Vec2XZ position;
const World* world;
bool isLoaded = false;
std::vector<Vertex> vertices;
std::vector<uint32_t> indices;
private:
};
#pragma once
#include "Chunk.h"
Chunk::Chunk(World* _world, Vec2XZ pos) :
position(pos),
world(_world) {
}
BlockId Chunk::getBlock(int x, int y, int z) {
if (isBlockOutOfBounds(x, y, z)) {
return BlockId::Air;
}
return layers[y].getBlock(x, z);
}
bool Chunk::setBlock(BlockId id, int x, int y, int z) {
if (!isBlockOutOfBounds(x, y, z)) {
if (layers[y].setBlock(id, x, z)) {
return true;
}
}
return false;
}
bool Chunk::isBlockOutOfBounds(int x, int y, int z) {
if (x >= CHUNK_WIDTH)
return true;
if (z >= CHUNK_WIDTH)
return true;
if (x < 0)
return true;
if (y < 0)
return true;
if (z < 0)
return true;
if (y >= CHUNK_HEIGHT) {
return true;
}
return false;
}
void Chunk::generateVerticesAndIndices() {
vertices.clear();
indices.clear();
for (int y = 0; y < CHUNK_HEIGHT; y++) {
for (int x = 0; x < CHUNK_WIDTH; x++) {
for (int z = 0; z < CHUNK_WIDTH; z++) {
// for each block in this chunk
auto blockId = getBlock(x, y, z);
if (blockId == BlockId::Air) {
continue; // dont render air
}
// infer the block position using its coordinates
Vec3 blockPosition = { x, y, z };
// get its data
auto verts = world->blockdb->blockDataFor(blockId).getVertices();
auto inds = world->blockdb->blockDataFor(blockId).getIndices();
// account for the block position and store the new verts
for (int i = 0; i < verts.size(); i++) {
Vertex v(verts[i]);
v.pos += blockPosition;
vertices.push_back(v);
}
// store the indices for later accounting for the offset into the verts vector
for (int i = 0; i < inds.size(); i++) {
int ind(inds[i] + vertices.size());
indices.push_back(ind);
}
}
}
}
}
void Chunk::load() {
if (isLoaded) {
return;
}
// todo: actual terrain generation
for (int y = 0; y < 4; y++) {
for (int x = 0; x < CHUNK_WIDTH; x++) {
for (int z = 0; z < CHUNK_WIDTH; z++) {
setBlock(BlockId::Grass, x, y, z);
}
}
}
isLoaded = true;
}
因此,我基本上已经将createVertexAndIndexBuffer()的顶部迁移到了块类。然后在createVertexAndIndexBuffer()中,这样遍历渲染距离内播放器周围的块...
void createVertexAndIndexBuffer() {
// set bounds of how far out to render based on what chunk the player is in
Vec2XZ playerChunkCoords = { floor(player.position.x) / CHUNK_WIDTH, floor(player.position.z) / CHUNK_WIDTH };
Vec2XZ lowChunkXZ = { playerChunkCoords.x - renderDistance, playerChunkCoords.z - renderDistance };
Vec2XZ highChunkXZ = { playerChunkCoords.x + renderDistance, playerChunkCoords.z + renderDistance };
// for each chunk around the player within render distance
for (int x = lowChunkXZ.x; x < highChunkXZ.x; x++) {
for (int z = lowChunkXZ.z; z < highChunkXZ.z; z++) {
// get the chunk
Chunk* chunk = &world.getChunk(x, z);
// load it if it isnt already
if (!chunk->isLoaded) {
chunk->load();
}
// generate its geometry if it doesnt already exist
if (chunk->vertices.size() == 0 || chunk->indices.size() == 0) {
chunk->generateVerticesAndIndices();
}
auto verts = chunk->vertices;
auto inds = chunk->indices;
// account for the chunk position and store the new verts for later
for (int i = 0; i < verts.size(); i++) {
Vertex v(verts[i]);
v.pos.x += x * CHUNK_WIDTH;
v.pos.z += z * CHUNK_WIDTH;
vertices.push_back(v);
}
// store the indices for later accounting for the offset into the verts vector
for (int i = 0; i < inds.size(); i++) {
int ind(inds[i] + vertices.size());
indices.push_back(ind);
}
}
}
// time to start creating the actual buffer
VkDeviceSize vertexBufferSize = sizeof(vertices[0]) * vertices.size();
VkBuffer vertexStagingBuffer;
VkDeviceMemory vertexStagingBufferMemory;
createBuffer(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexStagingBuffer, vertexStagingBufferMemory);
void* vertexData;
vkMapMemory(device, vertexStagingBufferMemory, 0, vertexBufferSize, 0, &vertexData);
memcpy(vertexData, vertices.data(), (size_t)vertexBufferSize);
vkUnmapMemory(device, vertexStagingBufferMemory);
createBuffer(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);
// use copyBuffer() to move the vertex data to the device local buffer
copyBuffer(vertexStagingBuffer, vertexBuffer, vertexBufferSize);
// After copying the data from the staging buffer to the device buffer, we should clean up the staging buffer since it is no longer needed.
vkDestroyBuffer(device, vertexStagingBuffer, nullptr);
vkFreeMemory(device, vertexStagingBufferMemory, nullptr);
// and do the same for the index buffer
VkDeviceSize indexBufferSize = sizeof(indices[0]) * indices.size();
VkBuffer indexStagingBuffer;
VkDeviceMemory indexStagingBufferMemory;
createBuffer(indexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, indexStagingBuffer, indexStagingBufferMemory);
void* indexData;
vkMapMemory(device, indexStagingBufferMemory, 0, indexBufferSize, 0, &indexData);
memcpy(indexData, indices.data(), (size_t)indexBufferSize);
vkUnmapMemory(device, indexStagingBufferMemory);
createBuffer(indexBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);
copyBuffer(indexStagingBuffer, indexBuffer, indexBufferSize);
vkDestroyBuffer(device, indexStagingBuffer, nullptr);
vkFreeMemory(device, indexStagingBufferMemory, nullptr);
}
使用此代码,引擎可以正常启动,但屏幕保持白色,然后在drawFrame()中对vkQueueSubmit()进行几次调用后,vkQueueSubmit()返回VK_ERROR_DEVICE_LOST而不是VK_SUCCESS,然后应用程序抛出相应的运行时错误,打印相应的调试信息“无法提交绘制命令缓冲区!”,等待我按一个键,然后最后以EXIT_FAILURE终止。
最佳答案
我分配的索引不正确,它被图形驱动程序捕获。存在比顶点 vector 大的索引。
关于c++ - 是什么原因导致调用vkQueueSubmit时出现VK_ERROR_DEVICE_LOST?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63092926/
我对cassandra并使用1.2.10非常陌生。我有一个时间戳数据类型的主键列。现在,我正在尝试检索日期范围的数据。由于我们知道不能在cassandra中使用,因此我使用的是大于()来获取日期范围。
我正在尝试进行有条件的转场。但我得到: Terminating app due to uncaught exception 'NSInvalidArgumentException', reas
我有一个游戏项目,在调试和发布模式下在设备上运行得非常好。我有两个版本。旧版本和新版本具有更多(后来我添加了)功能,并且两者的 bundle ID、版本相同。当我构建旧版本时,之前没有安装“myGam
这个问题已经有答案了: 奥 git _a (2 个回答) 已关闭 5 年前。 我正在获取 ClassCastException 。这两个类来自不同的 jar,但是JettyContinuationPr
以下代码行抛出异常: HttpResponse response = client.execute(request); // actual HTTP request 我能够捕获它并打印: Log
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
public class TwoThreads { private static Object resource = new Object(); private static void
当我输入 6 (int) 作为值时,运行此命令会出现段错误 (gcc filename.c -lm)。请帮助我解决这个问题。预期的功能尚未实现,但我需要知道为什么我已经陷入段错误。 谢谢! #incl
所以,过去一周半我一直在研究这个 .OBJ/.MTL 网格解析器。在这段时间里,我一直在追踪/修复很多错误、清理代码、记录代码等等。 问题是,每修复一个错误,仍然会出现这个问题,而且一张图片胜过一千个
我正在运行一个代码,它基本上围绕 3 个维度旋转一个大数据数组(5000 万行)。但是,我遇到了一个奇怪的问题,我已将其缩小到如何评估旋转矩阵。基本上,对于除绕 x 轴以外的任何旋转,python 代
就在你说这是重复之前,我已经看到了其他问题,但我仍然想发布这个。 所以我正在阅读 Thinking in Java -Bruce Eckel 这篇文章是关于小写命名约定的: In Java 1.0 a
我想在我的应用程序中使用 REST API。它为我从这个应用程序发出的所有请求抛出 SocketTimeoutException。 Logcat 输出:(您也可以在此处看到带有漂亮格式的输出:http
我知道 raise ... from None 并已阅读 How can I more easily suppress previous exceptions when I raise my own
在未能找到各种Unix工具(例如xargs和whatnot)的最新独立二进制文件(this version很好,但需要外部DLL)后,我承担了自己进行编译的挑战。 ...这是痛苦的。 最终,尽管如此,
我有一个用PHP编写的流套接字服务器。 为了查看一次可以处理多少个连接,我用C语言编写了一个模拟器来创建1000个不同的客户端以连接到服务器。 stream_socket_accept几次返回fals
我的Android Studio昨天运行良好,但是今天当我启动Android Studio并想在移动设备上运行应用程序时,发生了以下错误, 我在互联网和stackoverflow上进行了搜索,但没有解
默认情况下,grails似乎为Java域对象的toString()返回:。那当然不是我想要的,所以我尝试@Override toString()返回我想要的。当我尝试grails generate-a
尝试通过LDAP通过LDAP对用户进行身份验证时,出现以下错误。 Reason: Cannot pass null or empty values to constructor. 谁能告诉我做错了什么
我正在尝试使用应用程序附带的 Houdini Python 模块,该模块是 Houdini 安装文件夹的一部分,位于标准 Python 路径之外。按照安装说明操作后,运行 Houdini Termin
简单地说,我正在为基本数据库编写单链表的原始实现。当用户请求打印索引下列出的元素高于数据库中当前记录数量时,我不断出现段错误,但仅当差值为 1 时。对于更高的数字,它只会触发我在那里编写的错误系统。
我是一名优秀的程序员,十分优秀!