vkGetInstanceProcAddr并且vkGetDeviceProcAddr在API文档中完全遗漏了.但是,他们需要使用交换链执行命令(从而制作任何有意义的Vulkan应用程序).此外,SDK附带的cube/tri演示使用它们非常不一致.
这两种方法是否可以互换,如果没有,有什么区别?
在Vulkan附带的API-Samples中,似乎在调用vkWaitForFences之后总是vkQueueSubmit直接或通过execute_queue_command_buffer(在util_init.hpp中)调用.调用vkWaitForFences将阻止CPU执行,直到GPU完成之前的所有工作vkQueueSubmit.这实际上不允许同时构造多个帧,这(理论上)显着地限制了性能.
是否需要这些调用,如果是这样,是否有另一种方法在构造新帧之前不要求GPU空闲?
我一直在尝试在Vulkan中使用S3TC(BC/DXT)压缩加载压缩图像,但到目前为止我没有太多运气.
以下是Vulkan规范关于压缩图像的内容:
https://www.khronos.org/registry/dataformat/specs/1.1/dataformat.1.1.html#S3TC:
使用S3TC压缩图像格式存储的压缩纹理图像被表示为4×4纹素块的集合,其中每个块包含64或128位纹素数据.该图像被编码为普通的2D光栅图像,其中每个4×4块被视为单个像素.
https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#resources-images:
对于使用线性平铺创建的图像,rowPitch,arrayPitch和depthPitch描述了线性内存中子资源的布局.对于未压缩格式,rowPitch是相邻行中具有相同x坐标的纹素之间的字节数(y坐标相差一).arrayPitch是纹素之间的字节数,在图像的相邻数组层中具有相同的x和y坐标(数组层值相差一).depthPitch是在3D图像的相邻切片中具有相同x和y坐标的纹素之间的字节数(z坐标相差1).表示为寻址公式,子资源中texel的起始字节具有地址:
//(x,y,z,layer)是texel坐标
address(x,y,z,layer)= layer arrayPitch + z depthPitch + y rowPitch + x texelSize + offset
对于压缩格式,rowPitch是相邻行中压缩块之间的字节数.arrayPitch是相邻阵列层中块之间的字节数.depthPitch是3D图像的相邻切片中的块之间的字节数.
//(x,y,z,layer)是块坐标
address(x,y,z,layer)= layer arrayPitch + z depthPitch + y rowPitch + x blockSize + offset;
对于未创建为数组的图像,未定义arrayPitch.depthPitch仅针对3D图像定义.
对于颜色格式,VkImageSubresource的aspectMask成员必须为VK_IMAGE_ASPECT_COLOR_BIT.对于深度/模板格式,方面必须是VK_IMAGE_ASPECT_DEPTH_BIT或VK_IMAGE_ASPECT_STENCIL_BIT.在分别存储深度和模板方面的实现上,查询每个子资源布局将返回不同的偏移量和大小,表示用于该方面的内存区域.在存储深度和模板方面交错的实现上,返回相同的偏移和大小并表示交叉存储器分配.
我的图像是普通的2D图像(0层,1个mipmap),因此没有arrayPitch或depthPitch.由于硬件直接支持S3TC压缩,因此应该可以在不对其进行解压缩的情况下使用图像数据.在OpenGL中,这可以使用glCompressedTexImage2D来完成,这在过去对我有用.
在OpenGL中,我使用了GL_COMPRESSED_RGBA_S3TC_DXT1_EXT作为图像格式,对于Vulkan,我使用的是VK_FORMAT_BC1_RGBA_UNORM_BLOCK,它应该是等效的.这是我映射图像数据的代码:
auto dds = load_dds("img.dds");
auto *srcData = static_cast<uint8_t*>(dds.data());
auto *destData = static_cast<uint8_t*>(vkImageMapPtr); // Pointer to mapped memory of VkImage
destData += layout.offset(); // layout = VkImageLayout of the image …Run Code Online (Sandbox Code Playgroud) https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkVertexInputBindingDescription.html
- binding是此结构描述的绑定号.
我不确定这是什么意思,例如来自https://github.com/SaschaWillems/Vulkan/blob/master/triangle/triangle.cpp
#define VERTEX_BUFFER_BIND_ID 0
....
vertices.inputAttributes[0].binding = VERTEX_BUFFER_BIND_ID;
vertices.inputAttributes[0].location = 0;
vertices.inputAttributes[0].format = VK_FORMAT_R32G32B32_SFLOAT;
vertices.inputAttributes[0].offset = offsetof(Vertex, position);
// Attribute location 1: Color
vertices.inputAttributes[1].binding = VERTEX_BUFFER_BIND_ID;
vertices.inputAttributes[1].location = 1;
vertices.inputAttributes[1].format = VK_FORMAT_R32G32B32_SFLOAT;
vertices.inputAttributes[1].offset = offsetof(Vertex, color);
Run Code Online (Sandbox Code Playgroud)
并且顶点着色器看起来像这样
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inColor;
layout (binding = 0) uniform UBO
{
mat4 projectionMatrix;
mat4 modelMatrix;
mat4 viewMatrix;
} ubo;
layout …Run Code Online (Sandbox Code Playgroud) 在Mac上支持OpenCL 将在macOS 10.15中结束,因此人们投资PyOpenCL + OpenCL作为进行通用GPU(+ CPU)计算的手段很快就会开始失去一个关键平台.
所以我的问题是:
在尝试为Vulkan构建投影矩阵时,我遇到了矛盾,并且尚未找到投影矩阵应如何将Z从输入向量映射到输出的解释.映射x和y很简单.我的理解是OpenGL Projection矩阵应该将近平截头体平面映射到-1,远远地映射到+1.Vulkan分别为0和+1.映射应该是对数的,允许近场更高的精度.
下面的例子使用near(n)= 1,far(f)= 100.这是使用我为Vulkan规范构造的矩阵的z映射图.它会在渲染中产生错误,但会产生正确的结果,因为我理解它:
lambda z: (f / (f-n) * z - f*n/(f-n)) / z

我在网上找到的最常见的OpenGL投影图,应该从-1到+1:
lambda z: ((-f+n)/(f-n)*z - 2*f*n/(f-n))/-z

这里是我使用的lib生成的一个,用于OpenGL(Rust中的cgmath):

我无法构建一个适当的Vulkan投影矩阵(其中我没有通过谷歌找到),除非我理解z应该映射到什么.我怀疑这是由于着色器后投影矩阵的隐式校正实际上映射到我列出的范围,但如果是这样,我不知道通过项目进入它的范围.
我正在模型的多个网格上渲染不同的纹理,但我没有太多关于这些过程的线索.有人为每个网格建议,创建自己的描述符集并调用vkCmdBindDescriptorSets()和vkCmdDrawIndexed()进行渲染,如下所示:
// Pipeline with descriptor set layout that matches the shared descriptor sets
vkCmdBindPipeline(...pipelines.mesh...);
...
// Mesh A
vkCmdBindDescriptorSets(...&meshA.descriptorSet... );
vkCmdDrawIndexed(...);
// Mesh B
vkCmdBindDescriptorSets(...&meshB.descriptorSet... );
vkCmdDrawIndexed(...);
Run Code Online (Sandbox Code Playgroud)
然而,上述方法与切碎机样品和vulkan的样品有很大不同,这使得我不知道从哪里开始改变.我非常感谢任何帮助,指导我找到正确的方向.
干杯
Vulkan是否支持从管道阶段保存顶点输出?我一直在寻找,我找不到任何例子或参考,也许别人不知道?
Vulkan使用坐标系,其中(-1,-1)位于左上象限,而不是左下象限,就像在学校通常学习的标准笛卡尔坐标系一样.所以(-1,1)位于Vulkan坐标系的左下象限.
(图片来自:http://vulkano.rs/guide/vertex-input)
使用Vulkan坐标系有什么好处?我能看到的一个明显优势是教学法:它迫使人们意识到坐标系是任意的,人们可以很容易地在它们之间进行映射.但是,我怀疑这是设计原因.
那么这个选择的设计原因是什么?
所以最近我一直在使用Vulkan-Hpp(Vulkan Api的官方c ++绑定,Github Link)。
查看源代码,我发现它们围绕本机Vulkan结构(例如vk::InstanceCreateInfo环绕VkInstanceCreateInfo)创建包装器类。(注意:环绕而不是源自)
调用本地Vulkan API时,将指向包装类的指针reinterpret_cast编入本地Vulkan结构中。使用示例vk::InstanceCreateInfo:
//definition of vk::InstanceCreateInfo
struct InstanceCreateInfo
{
/* member function omitted */
private:
StructureType sType = StructureType::eInstanceCreateInfo;
public:
const void* pNext = nullptr;
InstanceCreateFlags flags;
const ApplicationInfo* pApplicationInfo;
uint32_t enabledLayerCount;
const char* const* ppEnabledLayerNames;
uint32_t enabledExtensionCount;
const char* const* ppEnabledExtensionNames;
};
//definition of VkInstanceCreateInfo
typedef struct VkInstanceCreateInfo {
VkStructureType sType;
const void* pNext;
VkInstanceCreateFlags flags;
const VkApplicationInfo* pApplicationInfo;
uint32_t enabledLayerCount; …Run Code Online (Sandbox Code Playgroud)