2016-07-09 10 views
4

Nehmen wir an, ich habe mehrere Meshes, die ich mit verschiedenen Materialien rendern möchte. Ich weiß, ich kann push constants für dieses Beispiel verwenden, aber diese Frage ist mehr zu verstehen, wie vkDescriptorset funktionieren soll.Aktualisieren eines VkDescriptorSet in einem renderPass

struct Material { 
    vec4 color; 
    vkDescriptorset descriptorSet; 
    VkDescriptorBufferInfo descriptorBufferInfo; 
}; 

Ich nenne nur vkUpdateDescriptorSets für _descriptorBufferInfo, nachdem der Puffer für die Daten erstellt wurde. Alles funktioniert gut.

Ich testete eine andere Lösung. Anstatt eine vkDescriptorset pro Material zu haben, habe ich nur eine für alle von ihnen. Und innerhalb der rendepass rufe ich vkUpdateDescriptorSets für jedes Material VkDescriptorBufferInfo.

vkDescriptorset globalDescriptorSet; 
struct Material { 
    vec4 color; 
    VkDescriptorBufferInfo descriptorBufferInfo; 
}; 

beginCommandBuffer 
beginRenderPass 
for (auto &mesh : meshes) { 
    ... 
    writeDescriptorSets.dstSet = globalDescriptorSet; 
    writeDescriptorSets.pBufferInfo = &mesh.material.descriptorBufferInfo; 
    .... 
    vkUpdateDescriptorSets(device, 1, &writeDescriptorSets, 0, nullptr); 
    renderMesh(mesh); 
} 
endRenderPass 
endCommandBuffer 

Aber wenn ich das tue, funktioniert es nicht. Der Validierungslayer sagt, dass Sie beginCommandBuffer aufrufen müssen, bevor Sie einen der Befehle vkCmdBindDescriptorSets, vkCmdBindPipeline usw. für das zweite Mesh, das ich rendere, aufrufen.

Also was ist das Problem hier, kann ich nicht ein vkDescriptorset zwischen mehreren VkDescriptorBufferInfo teilen, oder kann ich es nicht in einem RenderPass aktualisieren?

Antwort

2

Aus der Vulkan-Spezifikation:

Der Deskriptor gesetzt Inhalte durch einen Aufruf an vkCmdBindDescriptorSets gebunden kann während der Host-Ausführung des Befehls verbraucht werden, oder während Shader Ausführung des ergebenden anfertigt oder zu jeder Zeit dazwischen. Daher darf der Inhalt nicht geändert werden (überschrieben durch einen Update-Befehl, oder frei) zwischen, wenn der Befehl aufgezeichnet wird und wenn der Befehl die Ausführung in der Warteschlange beendet.

(Hervorhebung hinzugefügt)

Vermutlich Ihren Anruf renderMesh den Deskriptor an den Befehlspuffer gesetzt bindet. Von diesem Moment an dürfen Sie diesen Deskriptorsatz nicht mehr ändern, bis die Befehle in diesem Befehlspuffer abgeschlossen sind (oder der CB wurde zerstört).

Aus diesem Grund gibt es dynamische Uniform/Storage-Buffer. Sie ermöglichen Ihnen, den Basisoffset eines Uniform-/Speicherpuffers ohne zu ändern, der als eine Modifikation des tatsächlichen Deskriptorsatzes betrachtet wird. Sie können also den gleichen Deskriptorsatz an mehreren Stellen mit einem anderen Pufferoffset verwenden.

+0

große Antwort wie immer, danke – hidayat

Verwandte Themen