2016-11-13 8 views
0
에 대한 vkCmdPipelineBarrier

내 질문은 두 부분으로 구성되어 있습니다 :VULKAN : 데이터 일관성

  1. /볼 수있는 메모리를 사용할 수있는 차이점은 무엇입니까?
  2. 이 튜토리얼 (https://vulkan-tutorial.com)에서 Vulkan을 배우면서 현재 유니폼 데이터 (단순 모델/뷰/프로젝션 행렬)를 장치 로컬 메모리에 업로드하는 다른 방법을 찾고 있습니다. 행렬은 버텍스 쉐이더에서 사용됩니다.

    이 튜토리얼에서는 매트릭스가 업데이트되어 스테이징 버퍼 (vkMapMemory 등)에 복사 된 다음 명령 버퍼를 작성하고 vkCmdCopy을 녹음하고 제출하여 버퍼를 파괴하여 최종 장치 로컬 버퍼로 복사합니다. 나는 드로잉을 위해 명령 버퍼 내에서 마지막 단계를 시도한다.

    튜토리얼 방식으로 유창한 애니메이션을 만들 수 있지만 실험에서이 기능이 빠져 있습니다. 나는 2 개의 bufferBarriers를 설치하여 복사가 완료되었다는 것을 확인했지만 (문제가있는 것 같지만) 도움이되지 않았다. 리소스가 제대로 만들어지고 바인딩됩니다. 정상적으로 작동합니다. vkcpp (https://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; 
    

    임과

    //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의 문제는 syncronisation이 누락되었습니다. 스테이징 버퍼는 이전에 프레임을 렌더링하는 동안 읽히기 전에 부분적으로 업데이트되었습니다. (사용 가능/보이는 메모리의 차이점을 명확히 해 주셔서 감사합니다).

+0

"사용할 수있는 메모리와 보이지 않는 메모리의 차이점은 무엇입니까?" "사용 가능하다는 것의 의미가 명확하지 않습니다. "* 그리고 버퍼를 파괴 *"왜 버퍼를 파괴하겠습니까? 그게 정확히 무슨 뜻이야? –

+0

처음에는 첫 번째 메모리 장벽이 필요하지 않습니다. 메모리 장벽 HOST_WRITE_BIT/HOST_STAGE는 명령 버퍼의 제출에 의해 암시 적으로 수행됩니다. –

+0

@ NicolBolas 첫 번째 질문은 메모리 의존성에 대한 절의 6.4 절을 참조합니다. 나는 어떤 차이도 볼 수 없었다. Destory a buffer는, 나는'vkFreeCommandBuffers'를 호출합니다. 튜토리얼의 코드이므로, 가장 쉬운 방법은 선택하는 것이지 좋은 방법은 아닙니다. – camelCase

답변

0

스테이징 버퍼 메모리가 호스트 일관성이없는 경우 memcpy 이후에 추가로 vkFlushMappedMemoryRanges이 필요합니다 (메모리는 계속 매핑 될 수 있습니다). 그렇지 않으면 데이터가 실제로 gpu에 표시된다는 보장이 없습니다.

첫 번째 장벽 (전송할 호스트)은 실제로 필요하지 않습니다. 제출시 암묵적 장벽이 있습니다.

내가보기에 또 다른 문제는 이전 데이터가 업로드되기 전에 이전 프레임이 끝날 때까지 기다려야한다는 단일 스테이징 버퍼가 있다는 것입니다.

"파괴"는 프레임 당 할당을 의미하는 경우 ... 사용 된 모든 제출 된 명령 버퍼가 완료 될 때까지 먼저 파괴를 기다려야합니다. 두 번째로 그렇게하지 마십시오. GPU 측 할당은 비용이 많이 들지만 대신 한 번 할당하고 링 버퍼를 사용하는 것이 좋습니다.

0

광고 1

가능한 가시는 메모리 의존성의 두 반쪽입니다. 유효한 메모리 의존성이되기 위해서는 꽤 많이 발생해야합니다.

당신은 국가의 순서로 볼 수 있습니다 :

자원은 dst에서 사용 dst → 볼 만든 src →에 의해 제공 src → 의해 writen있다.

캐시의 일관성이 그 목적입니다. 명세는 "캐시"라는 단어가 더 추상적 인 것을 피하려고합니다.

귀하는 제작 및 사용 권한을 담당합니다. 장벽, 이벤트, 일관된 매핑 된 메모리 또는 flushinvalidate 및 일부 다른 작업을 수행 할 수있는 작업은 다음과 같습니다.

AFAIK 동기화 사양 다시 작성이 계획되어 있고 명명 규칙이 변경 될 수 있습니다.