16

過去 2 週間、Vulkan を使用していますが、AMD カードでのみ発生する問題に遭遇しました。具体的には AMD 7970M です。プロジェクトを GTX 700 および 900 シリーズのカードで問題なく実行しました。Nvidiaカードを搭載したWindowsとLinux(Steam OS)でも問題なく実行しました。この問題は、AMD カードと私のプロジェクトでのみ発生します。Sascha Willemsのすべてのサンプルとプロジェクトは問題なく動作します。

現在、テクスチャ付きのラプター モデルを描いて、その場で回転させています。それをテクスチャにレンダリングし、そのテクスチャをフルスクリーンの三角形に適用します。基本的なオフスクリーン レンダリング。しかし、7970M では深度が正しくクリアされないようです。代わりに、深度が適切にクリアされていないような、この奇妙なアーティファクトが発生します。

悪い猛禽類

もちろん、RenderDoc でこれを掘り下げてみましたが、その深さは完全に間違っています。ラプターとそれが描かれたフルスクリーンの三角形の両方がめちゃくちゃです:

深さが悪い

バッドトライデプス

私のコードを Sascha Willems の Offscreen の例と比較してみましたが、ほぼすべて同じ方法で行っているようです。深さを作成する方法に何か問題があるのではないかと思いましたが、私が見たすべての例と比較すると問題ないようです。

深度画像とビューを作成している場所のデバッグ ビューを次に示します。

画像情報 画像閲覧情報

メソッド全体は次のとおりです。

        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 は、各フレームが猛禽類のカットアウトのみをレンダリングし、フレームの残りの部分をクリアしないことを示しています。これはドライバーの問題ですか?

編集:いくつかの詳細情報。何も描画せず、フルスクリーンの三角形を描画せずにレンダー パスを開始して終了すると、画面がクリアされることがわかりました。ただし、三角形だけを描画すると、深さが正しくありません (オフスクリーンから何もブリットしたり、何らかのテクスチャを適用したりしなくても)。

編集:より具体的には、色はクリアされますが、深さはクリアされません。何も描画しない場合、深度は黒のままです。すべて 0 です。フルスクリーンの三角形が奥行きの奇妙なスタティックを引き起こす理由はわかりません。

4

2 に答える 2

11

Vulkan の例を AMD ハードウェアで動作させ始めたとき、まさにこれが私に起こりました。

ここに画像の説明を入力

彼らの GPU は正しい画像遷移 (NVIDIA などではほとんど無視されます) に大きく依存しており、スクリーンショットに見られる破損は、事前存在バリアが欠落している結果であると思います。

pre-present バリア (ここを参照) は、カラー アタッチメントのイメージ レイアウトをプレゼンテーション形式に変換し、それをスワップ チェーンに提示します。

これは、カラー アタッチメントへのレンダリングが完了した後に行う必要があります。これは、アタッチメントを提示する前に完成していることを確認するためです。

この例は、私の例の描画ルーチンで見ることができます。

次のフレームをレンダリングする際に、再度レンダリングできるようにするために、カラー アタッチメントのイメージ フォーマットを元に戻す必要があります。

要約すると:

  • カラー アタッチメントにレンダリングする前に、イメージをVK_IMAGE_LAYOUT_PRESENT_SRC_KHRからVK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL(別名「ポスト プレゼント」)に移行します。

  • レンダリングを行う

  • カラー アタッチメント イメージを からVK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMALに移行VK_IMAGE_LAYOUT_PRESENT_SRC_KHRし、それをスワップ チェーンに提示します

于 2016-03-17T14:57:03.833 に答える