Ich möchte ein einheitliches Pufferobjekt mit zwei 4x4-Matrizen an den Vertex-Shader übergeben. Ich habe die Struktur in C++ wie folgt deklariert:Vulkan UBO falsch übergeben
struct PerRenderUBO
{
glm::mat4 viewProjection;
glm::mat4 projection; //unused
};
Und in GLSL:
layout(std140, set = 0, binding = 0) uniform UBO {
mat4 viewProjection;
mat4 projection; //unused
} perRenderUBO;
aber sobald ich mehr als ein Mitglied in meinem UBO struct erklären, bekommen einige Objekte gezeichnet falsch durch zu einer falschen SichtProjektionsmatrix. Wenn ich den Datenelement 'projektion' sowohl in der PerRenderUBO-Struktur als auch in der GLSL-Deklaration auskommentiere, wird alles korrekt gerendert (obwohl ich die Projektion nicht einmal im Shader verwendet habe).
Dies führt zu der Annahme, dass mit der Datenausrichtung etwas nicht in Ordnung ist. Ich habe das Layout mit der Annotation std140 deklariert. sizeof (PerRenderUBO) gibt 128 zurück. Ich habe versucht, 'projection' als float zu deklarieren und das Problem bleibt bestehen.
Hier sind die wichtigsten Teile des Deskriptors Satzerstellung:
/** 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}, {});
den Primärzeichenbefehles Puffer vor der Ausführung I der Puffer für die PerRenderUBO wie folgt aktualisieren:
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‘ habe Puffergrößen und Offsets mehrmals überprüft und alles sieht gut aus. Aufgrund der Tatsache, dass der gleiche Deskriptorsatz für jeden Zeichenbefehl gebunden ist und einige Objekte korrekt dargestellt werden, glaube ich, dass die Daten im Puffer selbst korrekt sein müssen. Was fehlt mir?
Können Sie auch den Teil hinzufügen, der die Ubo-Daten tatsächlich hochlädt? –
Ich habe den Code für die Puffererstellung und für das Pufferupdate hinzugefügt. – user3067395
Sie haben nur eine PerRenderUBO-Instanz, sprechen aber über das Rendern mehrerer Objekte. Haben Sie nur eine Zeichnung pro Befehlspuffer (da Sie/memcpy/unmap kurz vor dem Senden des Befehlspuffers abbilden)? Wenn ja, was stellt sicher, dass Sie den UBO-Inhalt für die Zeichnung N + 1 nicht überschreiben, bevor die Zeichnung N abgeschlossen ist? –