2016-03-14 4 views
15

Я работаю с Vulkan последние пару недель, и у меня возникла проблема, которая произошла только на картах AMD. В частности, AMD 7970M. Я запускал свой проект на картах серии GTX 700 и 900 без проблем. Я даже бегал по ОС Linux (Steam OS) с картами Nvidia без заминки. Проблема возникает только на картах AMD и только с моим проектом; все образцы и проекты от Sascha Willems не работают.Vulkan, неспособный очистить глубину

Сейчас я рисую текстурированную модель Raptor и вращаю ее на месте. Я отрисовываю это до текстуры, а затем применяю эту текстуру к полноэкранному треугольнику; базовый экранный рендеринг. Однако на моем 7970M глубина кажется не совсем корректной. Вместо этого я получаю это странные артефакты, как глубина не очищаются должным образом:

Bad Raptor

Конечно, я пытался углубиться в это с RenderDoc и глубина совершенно неправильно. И Raptor и Полноэкранный треугольник его отрисовывается только беспорядок:

Bad Depth

Bad Tri Depth

Я пытался сравнивать свой код на Offscreen например, от Sascha Уиллемса и кажусь делать делать почти все так же. Я подумал, может быть, что-то было бы неправильно с тем, как я создал свою глубину, но это кажется прекрасным по сравнению со всеми примерами, которые я видел.

Вот некоторые виды отладки, где я творю глубины изображения и вид:

image info image view info

Вот весь метод:

 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; 
      } 

Если кто-то хочет получить больше информации о код не стесняйтесь спрашивать, и я предоставлю его. В этом проекте есть много строк кода, поэтому я не хочу, чтобы каждый мог пробираться через все это. Если вы хотите, чтобы весь код можно было найти по адресу http://github.com/thirddegree/HatchitGraphics/tree/dev

Редактировать: После немного более шумного поиска я обнаружил, что даже цвет не совсем корректно отображается. RenderDoc показывает, что каждый кадр отображает только вырез raptor и не очищает остальную часть кадра. Это проблема с драйвером?

Редактировать: Дополнительная информация. Я обнаружил, что если я рисую НИЧЕГО, просто начните и завершите проход рендеринга даже при рисовании полноэкранного треугольника, экран будет очищен. Однако, если я рисую только треугольник, глубина ошибочна (даже если я ничего не делаю из-за экрана или не применяю какую-либо текстуру).

Редактировать: Более конкретно цвет будет очищен, но глубина не будет. Если я ничего не рисую, глубина останется черной; все 0s. Почему полноэкранный треугольник вызывает странную статическую глубину, я не уверен.

ответ

9

Это именно то, что случилось со мной, когда я начал получать мои Vulkan примеры работают на AMD Оборудование:

enter image description here

Их графические процессоры сильно зависят от правильных графических переходов (которые в основном игнорируются, например, NVIDIA) и я думаю, что коррупция, которую вы видите на ваших снимках экрана, является результатом отсутствия предварительного барьера.

Предшествующий барьер (см. here) преобразует макет изображения вашего цветного вложения в формат презентации для передачи его в цепочку подкачки.

Это необходимо сделать после того, как вы закончили рендеринг в своем цветовом приложении, чтобы убедиться, что приложение завершено до его представления.

Вы можете увидеть пример этого в моих примерах draw routine.

При рендеринге следующего кадра вам необходимо снова преобразовать формат изображения цветного вложения, чтобы он мог снова отобразить его.

Подводя итог:

  • Перед вынесением к вашему цветового перехода крепежного изображение от VK_IMAGE_LAYOUT_PRESENT_SRC_KHR к VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL (так называемый "пост подарок")

  • Делайте рендеринг

  • Transition ваше изображение с изображением цвета от VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL до VK_IMAGE_LAYOUT_PRESENT_SRC_KHR и укажите его на цепочку подкачки

+0

Должно ли это быть сделано как для вложений глубины, так и для цвета? – Honeybunch

+1

Цветное прикрепление должно быть достаточным. Если вы все еще видите коррупцию, даже при существующих барьерах также проверяйте правильность хранения и загрузки файлов для вложений. –

+0

Извините за поздний ответ на этот вопрос. Я очень уверен, что мои операторы загрузки и хранения верны. Я не убежден, что проблемы, связанные с пре-и постами, являются проблемой. Я реализовал их в своем движке очень точно так же, как вы их создали в своих примерах, и это не повлияло на изображение. На самом деле, я думаю, что я просто исправил проблему при написании этого, и я забыл представить команду перехода изображения. – Honeybunch

5

Благодаря Sascha и некоторым дополнительным ошибкам, возникшим с помощью нового 1.0.5 LunarG SDK, мне удалось исправить эту проблему. Фиксации с изменениями крепежными (и пара других мелочей) можно найти здесь: https://github.com/thirddegree/HatchitGraphics/commit/515d0303f45a8e9c00f67a74c824530ea37b687a

Это было сочетание нескольких вещей:

мне нужно, чтобы установить глубину изображения на вложении фреймбуфера из swapchain к VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, а не только VK_IMAGE_ASPECT_DEPTH_BIT

для почти каждого барьера памяти образа, который я забыл specifiy в baseArrayLayer в subresourceRange. Это не вызвало ошибку до версии 1.0.5.

Еще одна ошибка, которая не появлялась до 1.0.5, которая могла бы помочь вам отслеживать подобную ошибку и повлиять на генерацию текстуры, заключалась в том, что до того, как я сопоставил память устройства с текстурой для хранения памяти, мне нужно было перевести ее с VK_IMAGE_LAYOUT_UNDEFINED до VK_IMAGE_LAYOUT_GENERAL, отправьте эту команду, скопируйте ее и переведите ее с GENERAL на VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL (не забудьте также отправить эту команду). Опять же, это только для текстур, которые вы хотите пробовать, но я думаю, что мораль здесь «фактически представляет ваши изображения»