Vertex attribute not consumed by shader for my Vulkan program

857 Views Asked by At

I'm working with a tutorial to help learn Vulkan in C++, and I'm stuck trying to be able to change what my vertices are and colors. It always shows a triangle with 3 colors interpolated between each vertex (one red, one blue, one green), with neither the positions of the vertices OR the colors changing, even when I manually edit them. The result looks like this. If I try to change the color of one of the vertices, or change the position of it on the screen, nothing changes, and that triangle in the image I linked is displayed.

In my program I have my vertices set as:

const std::vector<Vertex> vertices = {
    {{0.0f, -0.5f}, {0.0f, 1.0f, 0.0f}}, // green at the top
    {{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}}, // blue in the bottom left
    {{0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}},  // red in the bottom right
};

However, in the image that I provided, the RED is at the top, while the blue and green are on the bottom... which confuses the heck out of me.

Additionally, a note in my console comes up saying that the information cannot be passed along into the vertex shader (at location 0 and 1, which is where vertices and colors are passed along, respectively). I've looked for solutions regarding this error, and I still cannot figure out for the life of me what the problem is.

The exact error is: validation error: Validation Performance Warning: [ UNASSIGNED-CoreValidation-Shader-OutputNotConsumed ] Object 0: handle = 0xec4bec0000000000b, type = VK_OBJECT_TYPE_SHADER_MODULE; | MessageID = 0x609a13b | Vertex attribute at location 0 not consumed by vertex shader. Location 0 is supposed to be the input for the position on the screen as a vec2, while location is color as a vec3.

The vertex shader code (GLSL) is as follows:

#version 450

layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor;

layout(location = 0) out vec3 fragColor;

void main() {
    gl_Position = vec4(inPosition, 0.0, 1.0);
    fragColor = inColor;
}

Meanwhile, the C++ code where I create the vertex buffer is:

void createVertexBuffer() {
    VkBufferCreateInfo bufferInfo{};
    bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
    bufferInfo.size = sizeof(vertices[0]) * vertices.size();
    bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
    bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

    if (vkCreateBuffer(device, &bufferInfo, nullptr, &vertexBuffer) != VK_SUCCESS) {
        throw std::runtime_error("failed to create vertex buffer!");
    }
}

Finally, the C++ code where I bind the vertices to the appropriate buffer is:

void RTXApp::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {

    VkCommandBufferBeginInfo beginInfo{};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    beginInfo.flags = 0;
    beginInfo.pInheritanceInfo = nullptr;

    // error catching
    if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {
        throw std::runtime_error("failed to begin recording command buffer!");
    }

    VkRenderPassBeginInfo renderPassInfo{};
    renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
    renderPassInfo.renderPass = renderPass;
    renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex];
    renderPassInfo.renderArea.offset = { 0, 0 };
    renderPassInfo.renderArea.extent = swapChainExtent;

    VkClearValue clearColor = { {{0.0f, 0.0f, 0.0f, 1.0f}} }; // set "default" color to black
    renderPassInfo.clearValueCount = 1;
    renderPassInfo.pClearValues = &clearColor;

    // begin render pass
    vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);

    // bind graphics pipeline object to command buffer
    vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);

    // bind the vertex buffer to draw from
    VkBuffer vertexBuffers[] = { vertexBuffer };
    VkDeviceSize offsets[] = { 0 };
    vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);

    // draw from the vertex buffer
    vkCmdDraw(commandBuffer, static_cast<uint32_t>(vertices.size()), 1, 0, 0);

    // end render pass
    vkCmdEndRenderPass(commandBuffer);

    // error catching 
    if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
        throw std::runtime_error("failed to record command buffer!");
    }
}

I've tried both my version of the code and the code found at the tutorial that I'm using (found here), both seem to have the same effect. I'm not sure what I'm doing wrong, since I've followed the entire thing to the letter, trying very carefully to make sure all of the results are as I want them before moving on. I'm honestly not sure what to do anymore, since I've looked for solutions for this specific problem and I've found nothing.

Apologies if this isn't exactly the clearest, the code is super long, I'm not sure why this error is happening, and I'm a bit new to stack overflow in general. Any help would be appreciated, I'm losing my sanity trying to figure out what's wrong.

The code at the bottom of this page is basically the long version of what I have, and is what I'm trying to recreate with the code that I'm using. I'm on Windows 11, using MSVS 2022 and the Windows 10 Vulkan SDK, if that matters at all - my project settings are supposedly all good, and match the Windows version of this setup.

Edit: here is the part of the code with the VkPipelineVertexInputCreateInfo, as requested. Still cannot figure out what's going on.

    auto vertShaderCode = readFile("shaders/vert.spv");
    auto fragShaderCode = readFile("shaders/frag.spv");

    VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
    VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);


    // create the vertex shader stage of the pipleline
    VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
    vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
    vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
    vertShaderStageInfo.module = vertShaderModule;
    vertShaderStageInfo.pName = "main";

    // create the fragment shader stages of the pipeline
    VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
    fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
    fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
    fragShaderStageInfo.module = fragShaderModule;
    fragShaderStageInfo.pName = "main";

    // store steps of shader stages in an array (vertex first, then fragment)
    VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };


    VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
    vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
    
    auto bindingDescription = Vertex::getBindingDescription();
    auto attributeDescriptions = Vertex::getAttributeDescriptions();

    vertexInputInfo.vertexBindingDescriptionCount = 1;
    vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
    vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
    vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
1

There are 1 best solutions below

1
user3280571 On

I had an identical issue. The issue was that my updated shader files weren't compiled.