2016-11-13 30 views
0

我的問題有兩個部分:福爾康:vkCmdPipelineBarrier數據一致性

  1. 是什麼可用的內存/可見的區別?
  2. 我從本教程中學習Vulkan(https://vulkan-tutorial.com),並且目前偷偷摸摸尋找將統一數據(簡單模型/視圖/投影矩陣)上傳到設備本地內存的不同方法。矩陣用在頂點着色器中。

    在教程矩陣得到更新和被複制到一個臨時緩衝器(vkMapMemory等)和通過創建一個命令緩衝區,記錄vkCmdCopy,submiting它並破壞緩衝器之後複製到最終設備本地緩衝器。我嘗試在繪圖的強制命令緩衝區內完成最後一步。

    雖然教程方式導致流暢的動畫,但我的實驗忽略了此功能。我試圖安裝2個bufferBarriers,以確保副本完成(這似乎是問題),但這沒有幫助。資源被正確創建和綁定 - 工作正常。

    //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. 
    } 
    

    使用vkcpphttps://github.com/KhronosGroup/Vulkan-Hpp

    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; 
    

    林。

    這是非流體動畫缺少數據一致性的原因 - 我是否試圖實現這個目標?

在此先感謝!

編輯:第2部分的問題是缺少syncronisation;在渲染幀之前,暫存緩衝區在被讀取之前(部分)被更新。 (感謝您澄清內存可用/可見之間的差異)。

+0

「*可用內存/可見內容之間的區別是什麼?*」目前尚不清楚「可用內存」的含義。 「*並銷燬緩衝區*」爲什麼要銷燬緩衝區?你究竟是什麼意思? –

+0

順便說一句,你不需要第一個內存屏障。內存屏障HOST_WRITE_BIT/HOST_STAGE通過提交命令緩衝區隱式完成。 –

+0

@NicolBolas第一個問題涉及規範的第6.4節,關於內存依賴關係的段落。我看不出有什麼區別。 Destory是一個緩衝區,我稱之爲'vkFreeCommandBuffers'。由於這是來自教程的代碼,所以選擇了最簡單的方法,而不是一個好的方法。 – camelCase

回答

0

如果暫存緩衝區內存不是主機一致的,那麼在memcpy(內存可以保持映射)之後還需要vkFlushMappedMemoryRanges。如果你不這麼做,那麼就不能保證這些數據實際上是可見的。

第一道屏障(主機轉移)實際上並不需要;提交時存在隱含的障礙。

我看到的另一個問題是,您有一個臨時緩存,這意味着您需要等待上一幀完成,然後才能上傳新數據。

如果提及「銷燬」意味着您按每幀分配......首先,您必須等待銷燬,直到所有提交的命令緩衝區使用完成爲止,其次不要這樣做。 GPU端分配是昂貴的,而不是更喜歡分配一次並使用環形緩衝區。

0

廣告1.

推介可見是一個存儲器依賴兩半。幾乎兩者都必須發生,因爲它是有效的內存依賴。

,您可以查看它作爲國家的一個序列:

資源由src→提供通過src→可見於dst→通過dst使用writen。

它的目的是緩存的一致性。該規範試圖避免單詞「緩存」更抽象。

您負責製作和可見。操作,可以做一些對於壁壘,事件,連貫的映射內存或flushinvalidate和其他一些...

AFAIK有一個同步規格的rewrite計劃和命名可能會改變。