Ich habe in den letzten paar Wochen mit Vulkan gearbeitet und bin auf ein Problem gestoßen, das nur auf AMD-Karten passiert ist. Speziell die AMD 7970M. Ich habe mein Projekt auf GTX 700 und 900 Serie Karten ohne Problem ausgeführt. Ich habe sogar unter Windows ein Linux (Steam OS) mit Nvidia-Karten ohne Probleme laufen lassen. Das Problem tritt nur auf AMD-Karten und nur bei meinem Projekt auf; Alle Proben und Projekte von Sascha Willems laufen kein Problem.Vulkan versäumt, Tiefe zu löschen
Im Moment zeichne ich ein texturiertes Raptor Modell und spinne es an Ort und Stelle. Ich rendere das auf eine Textur und wende diese Textur dann auf ein Fullscreen-Dreieck an; grundlegendes Offscreen-Rendering. Die Tiefe scheint auf meiner 7970M jedoch nicht korrekt zu sein. Stattdessen bekomme ich diese seltsame Artefakte wie die Tiefe ist nicht richtig gelöscht wird:
Natürlich habe ich versucht, mit RenderDoc in diesem Graben und die Tiefe ist völlig falsch. Sowohl der Raptor und der das Vollbild Dreieck gezeichnet auf nur ein einziges Durcheinander:
Ich habe versucht, meinen Code zu dem Offscreen Beispiel von Sascha Willems zu vergleichen und erscheinen mich fast do tun alles gleich. Ich dachte, dass mit der Art und Weise, wie ich meine Tiefe erstellt habe, vielleicht etwas nicht stimmen würde, aber im Vergleich zu all den Beispielen, die ich gesehen habe, scheint es in Ordnung zu sein.
Hier sind einige Debug-Ansichten von wo ich die Tiefe Bild erschaffe und Aussicht:
Hier ist die ganze Methode:
bool VKRenderTarget::setupFramebuffer(VKRenderer* renderer)
{
VkDevice device = renderer->GetVKDevice();
VkCommandBuffer setupCommand;
m_colorFormat = renderer->GetPreferredImageFormat();
m_depthFormat = renderer->GetPreferredDepthFormat();
renderer->CreateSetupCommandBuffer();
setupCommand = renderer->GetSetupCommandBuffer();
VkResult err;
//Color attachment
VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.pNext = nullptr;
imageInfo.format = m_colorFormat;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.extent.width = m_width;
imageInfo.extent.height = m_height;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
imageInfo.flags = 0;
VkMemoryAllocateInfo memAllocInfo = {};
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
VkMemoryRequirements memReqs;
err = vkCreateImage(device, &imageInfo, nullptr, &m_color.image);
assert(!err);
if (err != VK_SUCCESS)
{
#ifdef _DEBUG
Core::DebugPrintF("VKRenderTarget::VPrepare(): Error creating color image!\n");
#endif
return false;
}
vkGetImageMemoryRequirements(device, m_color.image, &memReqs);
memAllocInfo.allocationSize = memReqs.size;
renderer->MemoryTypeFromProperties(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAllocInfo.memoryTypeIndex);
err = vkAllocateMemory(device, &memAllocInfo, nullptr, &m_color.memory);
assert(!err);
if (err != VK_SUCCESS)
{
#ifdef _DEBUG
Core::DebugPrintF("VKRenderTarget::VPrepare(): Error allocating color image memory!\n");
#endif
return false;
}
err = vkBindImageMemory(device, m_color.image, m_color.memory, 0);
if (err != VK_SUCCESS)
{
#ifdef _DEBUG
Core::DebugPrintF("VKRenderTarget::VPrepare(): Error binding color image memory!\n");
#endif
return false;
}
renderer->SetImageLayout(setupCommand, m_color.image, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkImageViewCreateInfo viewInfo = {};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.pNext = nullptr;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = m_colorFormat;
viewInfo.flags = 0;
viewInfo.subresourceRange = {};
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
viewInfo.image = m_color.image;
err = vkCreateImageView(device, &viewInfo, nullptr, &m_color.view);
if (err != VK_SUCCESS)
{
#ifdef _DEBUG
Core::DebugPrintF("VKRenderTarget::VPrepare(): Error creating color image view!\n");
#endif
return false;
}
//We can reuse the same info structs to build the depth image
imageInfo.format = m_depthFormat;
imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
err = vkCreateImage(device, &imageInfo, nullptr, &(m_depth.image));
assert(!err);
if (err != VK_SUCCESS)
{
#ifdef _DEBUG
Core::DebugPrintF("VKRenderTarget::VPrepare(): Error creating depth image!\n");
#endif
return false;
}
viewInfo.format = m_depthFormat;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
vkGetImageMemoryRequirements(device, m_depth.image, &memReqs);
memAllocInfo.allocationSize = memReqs.size;
renderer->MemoryTypeFromProperties(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAllocInfo.memoryTypeIndex);
err = vkAllocateMemory(device, &memAllocInfo, nullptr, &m_depth.memory);
assert(!err);
if (err != VK_SUCCESS)
{
#ifdef _DEBUG
Core::DebugPrintF("VKRenderTarget::VPrepare(): Error allocating depth image memory!\n");
#endif
return false;
}
err = vkBindImageMemory(device, m_depth.image, m_depth.memory, 0);
if (err != VK_SUCCESS)
{
#ifdef _DEBUG
Core::DebugPrintF("VKRenderTarget::VPrepare(): Error binding depth image memory!\n");
#endif
return false;
}
renderer->SetImageLayout(setupCommand, m_depth.image,
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
viewInfo.image = m_depth.image;
err = vkCreateImageView(device, &viewInfo, nullptr, &m_depth.view);
if (err != VK_SUCCESS)
{
#ifdef _DEBUG
Core::DebugPrintF("VKRenderTarget::VPrepare(): Error creating depth image view!\n");
#endif
return false;
}
renderer->FlushSetupCommandBuffer();
//Finally create internal framebuffer
VkImageView attachments[2];
attachments[0] = m_color.view;
attachments[1] = m_depth.view;
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.pNext = nullptr;
framebufferInfo.flags = 0;
framebufferInfo.renderPass = *((VKRenderPass*)m_renderPass)->GetVkRenderPass();
framebufferInfo.attachmentCount = 2;
framebufferInfo.pAttachments = attachments;
framebufferInfo.width = m_width;
framebufferInfo.height = m_height;
framebufferInfo.layers = 1;
err = vkCreateFramebuffer(device, &framebufferInfo, nullptr, &m_framebuffer);
if (err != VK_SUCCESS)
{
#ifdef _DEBUG
Core::DebugPrintF("VKRenderTarget::VPrepare(): Error creating framebuffer!\n");
#endif
return false;
}
return true;
}
Wenn jemand mehr Informationen über das will Code fühlen sich frei zu fragen, und ich werde es zur Verfügung stellen. Es gibt eine Menge Codezeilen für dieses Projekt, also möchte ich nicht, dass alle sich das alles ansehen müssen. Wenn Sie möchten, obwohl alle den Code finden Sie unter http://github.com/thirddegree/HatchitGraphics/tree/dev
Edit: Nach ein bisschen mehr herum stochern habe ich festgestellt, dass selbst die Farbe nicht wirklich klar ist. RenderDoc zeigt, dass jeder Frame nur den Ausschnitt des Raptors rendert und den Rest des Frames nicht löscht. Ist das ein Treiberproblem?
Bearbeiten: Einige weitere Informationen. Ich habe festgestellt, dass, wenn ich NOTHING zeichne, nur einen Render-Pass beginne und beende, ohne mein Vollbild-Dreieck zu zeichnen, der Bildschirm wird gelöscht. Wenn ich jedoch nur das Dreieck zeichne, ist die Tiefe falsch (auch wenn ich nichts vom Bildschirm blitze oder irgendeine Art von Textur anlege).
Edit: Genauer gesagt wird die Farbe löschen, aber die Tiefe nicht. Wenn ich nichts zeichne, bleibt die Tiefe schwarz; alle 0s. Warum das Fullscreen-Dreieck die seltsame Statik der Tiefe verursacht, bin ich nicht sicher.
Sollte dies sowohl für die Tiefe und Farbe Anhänge getan werden? – Honeybunch
Die Farbbefestigung sollte ausreichend sein. Wenn Sie immer noch Korruption sehen, prüfen Sie auch bei den aktuellen Barrieren, ob Ihre Store- und Load-Ops für die Anhänge korrekt sind. –
Entschuldigung für die späte Antwort zu diesem Thema. Ich bin mir sehr sicher, dass meine Lade- und Speicheroperationen korrekt sind. Ich bin nicht davon überzeugt, dass die Prä- und Post-Barrieren das Problem sind. Ich habe sie in meiner Engine sehr ähnlich implementiert, wie Sie sie in Ihren Beispielen eingerichtet haben. Es hatte keinerlei Auswirkungen auf das Bild. In der Tat, ich denke, ich habe gerade das Problem behoben, während ich dies geschrieben habe und ich habe vergessen, einen Bildübergangsbefehl einzureichen. – Honeybunch