2017-02-20 12 views
-1

Я пытаюсь реализовать азартные квадрики в геомерном шейдере для визуализации эффектов частиц. Геометрический шейдерный ввод представляет собой точки (vec3), а его выход представляет собой треугольную полосу с координатами положения и UV (vec3, vec2). Я пробовал два варианта привязок ввода вершин, но не работает.Vulkan: VkVertexInputBindingDescription всегда ошибочно с геометрическим шейдером

Если я создал вершину связывания, как это:

VkVertexInputBindingDescription binding_desc[2] = {}; 
binding_desc[0].binding = 0; 
binding_desc[0].stride = sizeof(glm::vec3); 
binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 

binding_desc[1].binding = 1; 
binding_desc[1].stride = sizeof(glm::vec2); 
binding_desc[1].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 

VkVertexInputAttributeDescription attribute_desc[2] = {}; 
attribute_desc[0].location = 0; 
attribute_desc[0].binding = binding_desc[0].binding; 
attribute_desc[0].format = VK_FORMAT_R32G32B32_SFLOAT; 
attribute_desc[0].offset = offsetof(vert_shader_vertex, pos); 

attribute_desc[1].location = 1; 
attribute_desc[1].binding = binding_desc[1].binding; 
attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; 
attribute_desc[1].offset = offsetof(vert_shader_vertex, uv); 

Я получаю следующее сообщение об ошибке при вызове vkCmdDraw:

ERROR [по умолчанию] DS: (OBJECT 0) (КОД 24) Объект состояния трубопровода (0x3c) ожидает, что привязка вершины командного буфера Index 1 должна быть установлена ​​через vkCmdBindVertexBuffers. Это происходит потому, что VkVertexInputBindingDescription структура с индексом 1 pVertexBindingDescriptions имеет связывающее значение 1.

Однако, если установить его как это:

VkVertexInputBindingDescription binding_desc[1] = {}; 
binding_desc[0].binding = 0; 
binding_desc[0].stride = sizeof(glm::vec3); 
binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 

VkVertexInputAttributeDescription attribute_desc[1] = {}; 
attribute_desc[0].location = 0; 
attribute_desc[0].binding = binding_desc[0].binding; 
attribute_desc[0].format = VK_FORMAT_R32G32B32_SFLOAT; 
attribute_desc[0].offset = offsetof(vert_shader_vertex, pos); 

Я получаю эту ошибку при вызове vkCreateGraphicsPipelines:

ОШИБКА [по умолчанию] СК: (ОБЪЕКТ 0) (КОД 3) вершинный шейдер потребляет вход в местоположении 1, но не предусмотрен

  • Описывает ли VkVertexInputBindingDescription вход в геометрический шейдер или вершинный шейдер?
  • Нужно ли мне «фиктивные» UV-координаты в моем буфере вершин в качестве места?
  • Возможно ли, что мой геометрический шейдер не активирован и как я могу подтвердить?
  • Какой из этих двух подходов правильный, как я могу обратиться к соответствующей ошибке?
  • Будучи в стороне, я новичок в Vulkan, поэтому комментарии к шейдерам приветствуются.

Геометрия шейдер

#version 450 

#extension GL_ARB_separate_shader_objects : enable 
#extension GL_ARB_shading_language_420pack : enable 

layout (points) in; 
layout (triangle_strip, max_vertices = 4) out; 

layout (location = 0) in vec3 inPos[]; 

layout (location = 0) out vec3 outPos; 
layout (location = 1) out vec2 outUV; 

layout (push_constant) uniform constants_t { 
    vec3 up; 
    vec3 right; 
    mat4x4 world; 
    mat4x4 projection; 
} constants; 

void main(void) 
{ 
    const vec3 pos = gl_in[0].gl_Position.xyz; 
    const vec3 up = constants.up; 
    const vec3 right = constants.right; 

    outPos = pos + up - right; 
    outUV = vec2(0, 0); 
    EmitVertex(); 

    outPos = pos + up + right; 
    outUV = vec2(1, 0); 
    EmitVertex(); 

    outPos = pos - up - right; 
    outUV = vec2(0, 1); 
    EmitVertex(); 

    outPos = pos - up + right; 
    outUV = vec2(1, 1); 
    EmitVertex(); 

    EndPrimitive(); 
} 

вершинный шейдер

#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 vec2 inUV; 

layout (location = 0) out vec4 outPos; 
layout (location = 1) out vec2 outUV; 

layout (push_constant) uniform constants_t { 
    vec3 up; 
    vec3 right; 
    mat4x4 world; 
    mat4x4 projection; 
} constants; 

void main(void) { 
    outUV = inUV; 
    outPos = vec4(inPos.xyz, 1.0) * constants.world * constants.projection; 
} 

vkCmdBindVertexBuffers
VkBuffer vertex_buffers[1] = {vertexBuffer}; 
VkDeviceSize vertex_offset[1] = {0}; 
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertex_buffers, vertex_offset); 
+0

"* При вызове vkCmdDraw появляется следующее сообщение: *« Чтобы узнать, что происходит, нам нужно увидеть фактические команды, которые вы отправляете * до *, которые вы визуализируете. –

+0

Я думаю, что vkCmdBindVertexBuffers будут очень важны для первого варианта. –

+0

@NicolBolas. Вы действительно? В моем сообщении содержатся вопросы, связанные с пулями, которые довольно общие. Кроме того, у меня нет разрешения сбрасывать весь код где-то для вас. – Brent

ответ

2
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertex_buffers, vertex_offset); 

Это говорит о том, что вы привязываете один буфер к индексу 0. Однако вы сказали конвейер, когда создали его, чтобы связать два буфера.

Не лгать Вулкану; всегда знает (когда вы используете уровни проверки;)).

Скорее всего, вы должны иметь оба атрибута вершин, используя тот же буферный объект. Я вывел это из того факта, что вы использовали offsetof для вычисления относительных смещений для них. Если это ваше намерение, тогда у вас должно быть два атрибута вершин, которые используют привязку буфера .

Описывает ли VkVertexInputBindingDescription вход в геометрический шейдер или вершинный шейдер?

Он не может описать вход к GS, так как на первом этапе трубопровода шейдер является вершинным шейдером. И создание графического конвейера без VS невозможно.

 Смежные вопросы

  • Нет связанных вопросов^_^