2017-11-10 7 views
2

두 개의 4x4 행렬을 포함하는 균일 버퍼 객체를 버텍스 쉐이더에 전달하고 싶습니다. Vulkan UBO가 잘못 전달되었습니다.

struct PerRenderUBO 
{ 
    glm::mat4 viewProjection; 
    glm::mat4 projection; //unused 
}; 

와 GLSL에서

: 최대한 빨리 내 UBO 구조체에서 하나 명 이상의 멤버를 선언하지만

layout(std140, set = 0, binding = 0) uniform UBO { 
    mat4 viewProjection; 
    mat4 projection; //unused 
} perRenderUBO; 

은, 일부 개체가 잘못 인해 그려 얻을 다음과 같이 나는 C++에서 구조체를 선언 한 잘못된 viewProjection 행렬에. PerRenderUBO 구조체와 GLSL 선언 모두에서 'projection'데이터 멤버를 주석 처리하면 모든 것이 올바르게 렌더링됩니다 (셰이더에서 투영을 사용하지 않았더라도).

이렇게하면 데이터 정렬에 문제가있는 것으로 생각됩니다. std140 주석으로 레이아웃을 선언했습니다. sizeof (PerRenderUBO)는 128을 반환합니다. '돌출'을 float로 선언하려고 시도했지만 문제가 지속됩니다.

/** Create Layout **/ 
vk::DescriptorSetLayoutBinding perRenderUBOBinding; 
perRenderUBOBinding.binding = 0; 
perRenderUBOBinding.descriptorCount = 1; 
perRenderUBOBinding.descriptorType = vk::DescriptorType::eUniformBuffer; 
perRenderUBOBinding.stageFlags = vk::ShaderStageFlagBits::eVertex; 
perRenderUBOBinding.pImmutableSamplers = nullptr; 

std::vector<vk::DescriptorSetLayoutBinding> bindings{perRenderUBOBinding}; 

vk::DescriptorSetLayoutCreateInfo createInfo; 
createInfo.bindingCount = bindings.size(); 
createInfo.pBindings = bindings.data(); 
this->perRenderUBOLayout = vkDevice->createDescriptorSetLayout(createInfo); 

/** Create host-visible and host-coherent buffer **/ 
vk::BufferCreateInfo bufferCreateInfo; 
bufferCreateInfo.size = sizeof(PerRenderUBO); 
bufferCreateInfo.usage = vk::BufferUsageFlagBits::eUniformBuffer; 
bufferCreateInfo.sharingMode = vk::SharingMode::eExclusive; 
bufferCreateInfo.queueFamilyIndexCount = queueFamilyIndices.size(); 
bufferCreateInfo.pQueueFamilyIndices = queueFamilyIndices.data(); 
this->buffer = vkDevice->createBuffer(bufferCreateInfo); 

vk::MemoryRequirements memoryRequirements = vkDevice->getBufferMemoryRequirements(this->buffer); 
//allocates device memory as proposed in the specification (10.2 Device Memory) 
this->bufferDeviceMemory = allocate(memoryRequirements, vk::MemoryPropertyFlags{vk::MemoryPropertyFlagBits::eHostVisible} | vk::MemoryPropertyFlags{vk::MemoryPropertyFlagBits::eHostCoherent}); 
vkDevice->bindBufferMemory(this->buffer, this->bufferDeviceMemory, 0); 


this->descriptorPool = ...//create a descriptor pool for 1 uniform buffer 
this->descriptorSet = ...//allocate descriptor set for above layout 

vk::DescriptorBufferInfo bufferInfo; 
bufferInfo.buffer = this->buffer; 
bufferInfo.offset = 0; 
bufferInfo.range = sizeof(PerRenderUBO); 

vk::WriteDescriptorSet writeDescriptorSet; 
writeDescriptorSet.dstSet = *this->descriptorSet; 
writeDescriptorSet.dstBinding = 0; 
writeDescriptorSet.dstArrayElement = 0; 
writeDescriptorSet.descriptorType = vk::DescriptorType::eUniformBuffer; 
writeDescriptorSet.descriptorCount = 1; 
writeDescriptorSet.pBufferInfo = &bufferInfo; 
writeDescriptorSet.pImageInfo = nullptr; 
writeDescriptorSet.pTexelBufferView = nullptr; 

vkDevice->updateDescriptorSets({writeDescriptorSet}, {}); 

차 DRAW 명령 버퍼를 실행하기 전에 다음과 같이, I가 PerRenderUBO 대한 버퍼를 업데이트 :

std::vector<PerRenderUBO> data; //contains 1 instance of PerRenderUBO 
vk::DeviceSize offset = 0; 
vk::DeviceSize size = data.size() * sizeof(PerRenderUBO); 

void* memory = vkDevice->mapMemory(this->bufferDeviceMemory, offset, size); 
std::memcpy(memory, data.data(), size); 
this->deviceMemory->unmap(); 

I '은 다음

이 설명자 세트 생성의 가장 중요한 부분이다 버퍼 크기와 오프셋을 여러 번 확인했는데 모두 괜찮아 보입니다. 또한 동일한 설명자 세트가 모든 그리기 명령에 바인딩되고 일부 객체가 올바르게 렌더링되기 때문에 버퍼 자체의 데이터가 정확해야한다고 생각합니다. 내가 무엇이 누락 되었습니까?

+0

실제로 ubo 데이터를 업로드하는 부분을 추가 할 수 있습니까? –

+0

버퍼 생성 및 버퍼 업데이트 코드를 추가했습니다. – user3067395

+0

하나의 PerRenderUBO 인스턴스 만 있지만 여러 객체 렌더링에 대해 이야기합니다. 커맨드 버퍼 당 하나의 드로잉이 있습니까 (커맨드 버퍼를 제출하기 직전에/memcpy/unmap을 맵핑했기 때문에)? 그렇다면 무승부 N이 완료되기 전에 드로 N + 1에 대한 UBO 내용을 덮어 쓰지 않도록 보장하는 것은 무엇입니까? –

답변

1

일부 개체가 잘못 그려지거나 올바르게 그려지는 경우 동기화 또는 버퍼가 제 시간에 업데이트되지 않는 것이 좋습니다.

먼저 호스트에서 버퍼의 어떤 부분을 업데이트했는지 드라이버에 알릴 필요가 있습니다. 나는 그런 코드를 보지 않고 그것에 대해 아무 것도 언급하지 않는다. 이것은 메모리를 플러시함으로써 이루어집니다 - vkFlushMappedMemoryRanges() 함수를 호출해야합니다.

드라이버가 호스트에 의해 버퍼에 액세스했음을 알리는 장벽을 설정해야 할 수도 있습니다. 그러나 내가 아는 한 그러한 장벽은 명령 버퍼 제출에 암묵적으로 설정되어 있습니다.

+0

고마워요! 나는 vkFlushMappedMemoryRanges()에 대한 호출을 요구해서는 안되는 호스트 - 코 히어 런트 메모리를 할당하고 있음을 명확히해야한다. 그러나 동기화에 문제가있을 수 있습니다. 버퍼에 대한 데이터를 한 번만 설정하여 버퍼 생성 후 쓰기 작업을 수행하지 않았습니다. 불행히도이 문제는 해결되지 않았습니다. 나는 또한 푸시 상수를 통해 PerRenderUBO를 전달하려고했지만 동일한 이상한 동작을합니다. – user3067395