2017-11-07 8 views
0

Vulkan에서 인스턴스화 된 메쉬 렌더링을 구현하려고합니다.Vulkan vkCmdDrawIndexed는 처음에만 VertexBuffer의 값을 사용했습니다.

내 문제는 Vulkan이 바인드 된 VertexBuffer의 첫 번째 Vertex 만 사용하고 모든 Indices의 Value를 복제한다는 것입니다. 출력 RenderDoc :

RenderDoc output Duplicated Vertex Input

다음은 올바른 값이어야한다는 {{<inPosition>는}, {<inColor>}, {<inTexCoord>는}} :

const vkf::Vertex vertices[] = { 
    { { -0.2f, -0.5f, 0.0f },{ 1.0f, 0.0f, 0.0f },{ 1.0f, 0.0f } }, 
    { { 0.5f, -0.5f, 0.0f },{ 0.0f, 1.0f, 0.0f },{ 0.0f, 0.0f } }, 
    { { 0.5f, 0.5f, 0.0f },{ 0.0f, 0.0f, 1.0f },{ 0.0f, 1.0f } }, 
    { { -0.5f, 0.5f, 0.0f },{ 1.0f, 1.0f, 1.0f },{ 1.0f, 1.0f } } 
}; 

가 나는 VertexBuffer에 여러 번 확인하고 그것을 한 올바른 값을 포함합니다.

다음은 내 CommandBuffer의 작성에서 냈다입니다 :

 vkCmdBindPipeline(m_commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.agents); 

     VkBuffer vertexBuffers[] = { models.agent.verticesBuffer }; 
     VkBuffer instanceBuffers[] = { m_instanceBuffer.buffer }; 

     VkDeviceSize offsets[] = { 0 }; 
     vkCmdBindVertexBuffers(m_commandBuffers[i], 0, 1, vertexBuffers, offsets); 
     vkCmdBindVertexBuffers(m_commandBuffers[i], 1, 1, instanceBuffers, offsets); 

     vkCmdBindIndexBuffer(m_commandBuffers[i], models.agent.indexBuffer, 0, VK_INDEX_TYPE_UINT16); 

     vkCmdBindDescriptorSets(m_commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayouts.pipelineLayoutAgent, 0, 1, &descriptorSets.agent, 0, nullptr); 
     vkCmdDrawIndexed(m_commandBuffers[i], static_cast<uint32_t> (models.agent.indexCount), 5, 0, 0, 0); 

나의 첫번째 가정 내 바인딩 설명을 잘못이었다. 하지만 오류가 표시되지 않습니다.

bindingDescription = {}; 
bindingDescription.binding = 0; 
bindingDescription.stride = sizeof(Vertex); 
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 

왜 버퍼의 첫 번째 값만 사용됩니까?

EDIT :

InstanceData :

struct InstanceData 
{ 
    glm::vec3 pos; 
    glm::vec3 rot; 
    float scale; 


    static VkVertexInputBindingDescription getBindingDescription() 
    { 
     VkVertexInputBindingDescription bindingDescription = {}; 
     bindingDescription.binding = INSTANCING_BIND_ID; 
     bindingDescription.stride = sizeof(InstanceData); 
     bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; 

     return bindingDescription; 
    } 

}; 

전체 VkPipelineVertexInputStateCreateInfo :

std::vector<VkVertexInputBindingDescription> bindingDesciption = {}; 
std::vector<VkVertexInputAttributeDescription> attributeDescriptions = {}; 

bindingDesciption = { 
    models.agent.bindingDescription,  
    InstanceData::getBindingDescription() 
}; 
attributeDescriptions = 
{ 
    vertexInputAttributeDescription(VERTEX_BIND_ID, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(vkf::Vertex, pos)), 
    vertexInputAttributeDescription(VERTEX_BIND_ID, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(vkf::Vertex, color)), 
    vertexInputAttributeDescription(INSTANCING_BIND_ID, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(InstanceData, pos)), 
    vertexInputAttributeDescription(VERTEX_BIND_ID, 3, VK_FORMAT_R32G32_SFLOAT, offsetof(vkf::Vertex, texCoord)) 
}; 

VkPipelineVertexInputStateCreateInfo vertexInputInfo = {}; 

vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 
vertexInputInfo.vertexBindingDescriptionCount = static_cast<uint32_t>(bindingDesciption.size()); 
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size()); 
vertexInputInfo.pVertexBindingDescriptions = bindingDesciption.data(); 
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); 

EDIT 2

#define VERTEX_BIND_ID 0 
#define INSTANCING_BIND_ID 1 
,

편집 3 : 나는 VulkanMemoryAllocator를 사용하고 있습니다.

copyBuffer(stagingVertexBuffer, verticesBuffer, vertexBufferSize); 

void Base::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) 
{ 
    VkCommandBuffer commandBuffer = beginSingleTimeCommands(); 

    VkBufferCopy copyRegion = {}; 
    copyRegion.dstOffset = 0; 
    copyRegion.srcOffset = 0; 
    copyRegion.size = size; 
    vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion); 

    endSingleTimeCommands(commandBuffer); 
} 

I : 이것은 내가 준비에서 내 버퍼를 transfair 어떻게

createBuffer(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY); 

VkBuffer createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VmaMemoryUsage vmaUsage) 
{ 
    VkBuffer buffer; 

    VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; 
    bufferInfo.size = size; 
    bufferInfo.usage = usage; 
    bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 

    VmaAllocationCreateInfo allocCreateInfo = {}; 
    allocCreateInfo.usage = vmaUsage; 
    allocCreateInfo.flags = 0; 

    VmaAllocationInfo allocInfo; 
    if (vmaCreateBuffer(m_allocator, &bufferInfo, &allocCreateInfo, &buffer, &m_allocation, &allocInfo) != VK_SUCCESS) 
    { 
     throw std::runtime_error("failed to create Buffer!"); 
    }  
    return buffer; 
} 

:

memcpy(mappedStaging, vertices, vertexBufferSize); 

버퍼를 만들기 : 는

size_t vertexBufferSize = sizeof(vkf::Vertex) *_countof(vertices); 

createStagingBuffer(vertexBufferSize); 

VkBuffer createStagingBuffer(VkDeviceSize size) 
{ 
    VkBuffer buffer; 
    VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; 
    bufferInfo.size = size; 
    bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; 
    bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 

    VmaAllocationCreateInfo allocCreateInfo = {}; 
    allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; 
    allocCreateInfo.flags = VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT; 

    VmaAllocationInfo allocInfo = {}; 
    if (vmaCreateBuffer(m_allocator, &bufferInfo, &allocCreateInfo, &buffer, &m_allocation, &allocInfo) != VK_SUCCESS) 
    { 
     throw std::runtime_error("failed to create Buffer!"); 
    } 
    return buffer; 
} 

복사 정점 버퍼를 준비 만들기 데이터가 스테이징 버퍼에 있고 vertexBuffer에서도 createBuffer Prozess를 수정 한 후 여러 번 검사했습니다. 그들은 올바르게 거기에 저장됩니다.

+0

전체'VkPipelineVertexInputStateCreateInfo'을 보여주십시오. 또한 버퍼 데이터를 설정/전송하는 방법. 또한 버텍스 쉐이더 인터페이스 블록이 좋을 것입니다. – krOoze

+0

추신 : 최신 유효성 검사 레이어를 사용하도록 설정 했습니까? – krOoze

+0

내 게시물에 전체 VkPipelineVertexInputStateCreateInfo를 추가했습니다. VK_LAYER_LUNARG_standard_validation 확장 기능이 활성화되었습니다. –

답변

0

실수를 발견했습니다. 실수가 여기에 있었다 :

bindingDesciption = { 
    models.agent.bindingDescription,  
    InstanceData::getBindingDescription() 
}; 

(가) 바인딩이 무렵, models.agent.bindingDescription는 아직 초기화되지 않았습니다. 따라서 VkVertexInputBindingDescription에 결함이 있습니다. models.agent.bindingDescription은 VkVertexInputBindingDescription에 대한 표준 값으로 채워졌습니다 :

binding = 0 
stroke = 0 
inputRate = VK_VERTEX_INPUT_RATE_VERTEX 
+0

허. 나는 심지어 '스트라이드 (stride)'가 합법적이라고 기대하지 않았다 ... – krOoze

+0

나는 그 중 하나도 생각하지 못했다. 이제 작동합니다. 도와 주셔서 감사합니다. –