2016-11-13 9 views
0
ためvkCmdPipelineBarrier

私の質問は2つの部分があります。バルカン:データの一貫性

  1. /見えメモリが利用可能であることの違いは何ですか?
  2. このチュートリアル(https://vulkan-tutorial.com)からVulkanを学んで、デバイスのローカルメモリに一様なデータ(単純なモデル/ビュー/投影行列)をアップロードする別のアプローチを紹介しています。行列は頂点シェーダで使用されます。

    このチュートリアルでは、マトリクスが更新され、ステージングバッファ(vkMapMemoryなど)にコピーされ、コマンドバッファを作成してvkCmdCopyを記録し、バッファを破棄して最後のデバイスローカルバッファにコピーします。私は描画のために義務的なコマンドバッファ内で最後のステップを試みます。

    チュートリアルの方法は流暢なアニメーションにつながりますが、私の実験ではこの機能が欠けています。私は2つのbufferBarriersをインストールして、コピーが完了したことを確認しようとしましたが(これは問題のようです)、それは助けになりませんでした。リソースは適切に作成され、バインドされています。正常に動作しています。

    namespace Tools { 
        struct UniformBufferObject { 
        glm::mat4 model; 
        glm::mat4 view; 
        glm::mat4 proj; 
        }; 
    }; 
    vk::Buffer uniformStagingBuffer; 
    vk::DeviceMemory uniformStagingMemory; 
    //dataBuffer also contains the vertex and index data, is device local 
    vk::Buffer dataBuffer; 
    vk::DeviceMemory dataBufferMemory; 
    vk::vector<vk::DeviceSize> dataBufferOffsets; 
    
    std::vector<vk::CommandBuffer> cmdBuffers; 
    

    vkcppを使用してIM(https://github.com/KhronosGroup/Vulkan-Hpp)と

    //update uniform buffer and copy it to the staging buffer 
    //(called every frame) 
    Tools::UniformBufferObject ubo; 
    //set the matrices 
    void* data; 
    data = device.mapMemory(uniformStagingMemory, 0, sizeof(ubo), (vk::MemoryMapFlagBits) 0); 
        memcpy(data, &ubo, sizeof(ubo)); 
    device.unmapMemory(uniformStagingMemory); 
    
    
    //once: create a command buffer for each framebuffer of the swapchain 
    //queueFamily struct members set properly 
    //1st barrier: make transfer from host memory to staging buffer available/visible 
    vk::BufferMemoryBarrier bufMemBarrierStaging; 
    bufMemBarrierStaging.srcAccessMask = vk::AccessFlagBits::eHostWrite; 
    bufMemBarrierStaging.dstAccessMask = vk::AccessFlagBits::eTransferRead; 
    bufMemBarrierStaging.buffer = uniformStagingBuffer; 
    bufMemBarrierStaging.offset = 0; 
    bufMemBarrierStaging.size = sizeof(Tools::UniformBufferObject); 
    
    //2nd barrier: make transfer from staging buffer to device local buffer available/visible 
    vk::BufferMemoryBarrier bufMemBarrier; 
    bufMemBarrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; 
    bufMemBarrier.dstAccessMask = vk::AccessFlagBits::eUniformRead | vk::AccessFlagBits::eShaderRead; 
    bufMemBarrier.buffer = dataBuffer; 
    bufMemBarrier.offset = dataBufferOffsets[2]; 
    bufMemBarrier.size = sizeof(Tools::UniformBufferObject); 
    
    for(size_t i = 0; i < cmdBuffers.size(); i++) { 
        //begin command buffer 
    
        cmdBuffers[i].pipelineBarrier(
         vk::PipelineStageFlagBits::eHost, //srcPipelineStage 
         vk::PipelineStageFlagBits::eTransfer, //dstPipelineStage 
         (vk::DependencyFlagBits) 0, 
         nullptr, //memBarrier 
         bufMemBarrierStaging, 
         nullptr //imgBarrier 
        ); 
        vk::BufferCopy copyRegion; //filled appropriate 
        cmdBuffers[i].copyBuffer(uniformStagingBuffer, dataBuffer, copyRegion); 
    
        cmdBuffers[i].pipelineBarrier(
         vk::PipelineStageFlagBits::eTransfer, //srcPipelineStage 
         vk::PipelineStageFlagBits::eVertexShader, //dstPipelineStage 
         (vk::DependencyFlagBits) 0, 
         nullptr, //memBarrier 
         bufMemBarrier, 
         nullptr //imgBarrier 
        ); 
        //renderpass stuff and drawing etc. 
    } 
    

    この非流動アニメーションがデータ一貫性を欠いている理由は、これを達成しようと間違っていましたか?

ありがとうございます!

編集:パート2の問題は同期が失われていました。ステージングバッファは、前にフレームをレンダリングする間に読み取られる前に部分的に更新されていました。 (使用可能/表示可能なメモリの違いを明確にしてくれてありがとう)。

+0

"利用可能なメモリと表示されているメモリの違いは何ですか?" "利用可能であることを意味するものではありません。 "*とバッファを破壊する*"なぜあなたはバッファを破壊するだろうか?それはどういう意味ですか? –

+0

ところで、最初のメモリバリアは必要ありません。メモリバリアHOST_WRITE_BIT/HOST_STAGEは、コマンドバッファの提出によって暗黙的に行われます。 –

+0

@NicolBolas第1の質問は、仕様のセクション6.4、メモリ依存性に関する段落を参照しています。私は何の違いも見られませんでした。 Destory a bufferは、私は 'vkFreeCommandBuffers'を呼び出します。これはチュートリアルのコードなので、最も簡単な方法が選択されます。良い方法ではありません。 – camelCase

答えて

0

ステージバッファメモリがホストコヒーレントでない場合は、memcpyの後にさらにvkFlushMappedMemoryRangesが必要です(メモリはマップされたままです)。そうしなければ、データが実際にgpuに見えるという保証はありません。

最初の障壁(転送するホスト)は実際には必要ありません。提出する際に暗黙的な障壁があります。

私が見るもう一つの問題は、あなたが新しいデータをアップロードする前に完了する前のフレームを待つ必要があることを意味し、単一のステージング・バッファを持っているということです。

あなたは、フレームごとに割り当てることを意味し、「破壊」に言及する場合...まず、あなたが使用しているすべての提出コマンドバッファが終了するまで、第二それをしない、破壊に待たなければなりません。 GPU側の割り当ては高価ですが、代わりに一度割り当てるとリングバッファを使用することをお勧めします。

0

広告1.

利用可能見えるメモリー依存の二つの半分です。有効なメモリ依存であるためには、かなり多くのことが起こります。

あなたは状態のシーケンスとしてそれを見ることができます:

リソースは→dstで使用dst→に見えるようになるsrcによって使用可能になるsrc→によって書かれています。

キャッシュの目的は、キャッシュの一貫性です。この仕様では、「キャッシュ」という単語がより抽象的であることを回避しようとしています。

あなたは利用可能であり、目に見えるものを担当しています。バリア、イベント、コヒーレントマップメモリ​​、またはflushおよびinvalidateなどいくつかの操作が可能な操作は、次のとおりです。

AFAIK同期仕様の書き換えが計画されていて、命名法が変更されることがあります。

関連する問題