2016-05-27 19 views
16

Có một số cách để xử lý đồng bộ hóa trong Vulkan. Đây là cách tôi hiểu:Đồng bộ hóa giữa các bộ đệm lệnh trong Vulkan

  • Hàng rào là GPU để đồng bộ hóa CPU.
  • Semaphores là đồng bộ GPU với GPU, chúng được sử dụng để đồng bộ hóa hàng đợi nội dung gửi (trên cùng hàng hoặc hàng đợi khác nhau).
  • Sự kiện tổng quát hơn, đặt lại và kiểm tra trên cả CPU và GPU.
  • Các rào cản được sử dụng để đồng bộ hóa bên trong bộ đệm lệnh.

Trong trường hợp của tôi, tôi có hai bộ đệm lệnh. Và tôi muốn bộ đệm lệnh thứ hai thực hiện sau lần đầu tiên.

submitInfo.pCommandBuffers = &firstCommandBuffer; 
vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); 

// wait for first command buffer to finish 
submitInfo.pCommandBuffers = &secondCommandBuffer; 
vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); 

Loại đồng bộ hóa nào là tốt nhất cho việc này? Nếu tôi sử dụng vkQueueWaitIdle(queue)), là điều tương tự như sử dụng hàng rào hoặc tôi có nên sử dụng sự kiện hoặc ẩn dụ cho việc này không?

Nếu tôi gửi nhiều commandbuffer vào hàng đợi cùng một lúc:

std::vector<VkCommandBuffer> submitCmdBuffers = { 
     firstCommandBuffer, 
     secondCommandBuffer 
    }; 
    submitInfo.commandBufferCount = submitCmdBuffers.size(); 
    submitInfo.pCommandBuffers = submitCmdBuffers.data(); 

vẫn Có cách nào để đồng bộ hóa giữa đầu tiên và thứ hai?

+2

"* Và tôi muốn bộ đệm lệnh thứ hai thực thi sau lần đầu tiên. *" Bạn muốn "bao nhiêu" điều đó xảy ra? Đó là, bộ đệm lệnh thứ hai làm điều đó là bắt buộc đến mức cái đầu tiên đã thực hiện * đã hoàn thành * trước khi lệnh thứ hai bắt đầu? –

+1

Bộ đệm lệnh đầu tiên là đối tượng rendering với kiểm tra độ sâu được bật. Bộ đệm lệnh thứ hai là hiển thị đường viền của các mắt lưới với kiểm tra độ sâu bị tắt. Bởi vì nó phải được trên đầu trang của các đối tượng khác. – hidayat

+0

Nếu bạn thực hiện một lần gửi. sau đó sử dụng vkCmdSetEvent trong bộ đệm lệnh đầu tiên của bạn và vkCmdWaitEvents trong lần thứ hai của bạn và giữ cho các mặt nạ sân khấu src và dst càng hẹp càng tốt. –

Trả lời

11

Bộ đệm lệnh đầu tiên là đối tượng kết xuất với thử nghiệm độ sâu được bật. Bộ đệm lệnh thứ hai là hiển thị đường viền của các mắt lưới với kiểm tra độ sâu bị tắt. Bởi vì nó phải được trên đầu trang của các đối tượng khác.

Đối với trường hợp này, những gì bạn cần thay vì phụ thuộc vào bộ đệm lệnh đó là gì.

Nếu đó là bộ đệm lệnh phụ được thực hiện trong cùng một phiên bản trả về, thì bạn không cần bất kỳ sự đồng bộ hóa nào. Không, trừ khi bạn đang đọc bằng tay từ kết cấu sâu trong bộ đệm lệnh phụ. Tại sao?

Vì mục 2.2.1 API Ordering bảo vệ bạn. Kiểm tra chiều sâu và viết sâu trong một thể hiện hiển thị sẽ luôn luôn tiến hành theo thứ tự API. Vì vậy, các lệnh sau này, cho dù trong cùng một CB hay một lệnh khác, sẽ được sắp xếp theo chiều sâu kiểm tra/ghi.

Tuy nhiên, nếu bạn cần đọc bộ đệm độ sâu đó hoặc bộ đệm lệnh của bạn nằm trong các trường hợp trả về khác nhau, thì bạn cần đồng bộ hóa rõ ràng thông qua sự kiện.

Trong trường hợp này, mặt nạ sân khấu cho lệnh vkCmdSetEvent phải là giai đoạn ghi giá trị độ sâu.Đây có thể là EARLY_FRAGMENT_TESTS_BIT hoặc LATE_FRAGMENT_TESTS_BIT. Để an toàn, hãy sử dụng cả hai. Tuy nhiên, vì bạn có thể cập nhật cùng một bộ đệm màu, bạn cũng cần có giai đoạn COLOR_ATTACHMENT_OUTPUT_BIT. Chèn lệnh này vào cuối của bộ đệm lệnh đầu tiên (hoặc sau khi tất cả các văn bản chiều sâu được thực hiện).

Đối với vkCmdWaitEvent, bạn muốn đợi các giai đoạn của đường dẫn cần đến. Trong trường hợp của bạn, đây là một lần nữa các bài kiểm tra mảnh và tập tin đính kèm màu sắc. Nhưng nếu một giai đoạn đổ bóng sẽ đọc chiều sâu, bạn cũng cần giai đoạn đó trong lệnh chờ.

Vì bộ nhớ có liên quan, vkCmdWaitEvent của bạn cũng sẽ cần sử dụng phụ thuộc bộ nhớ trên bộ đệm độ sâu và màu.

Thực sự, tất cả sự phức tạp này là lý do tại sao bạn nên thử đặt các bộ đệm lệnh này trong cùng một trường hợp trả về nếu có thể. Lý do duy nhất bạn sẽ không thể làm như vậy là nếu bạn cần đọc từ bộ đệm độ sâu trong trình đổ bóng.

+0

kiến ​​thức của bạn là ấn tượng :), "Nếu đó là bộ đệm lệnh phụ", tại sao nó quan trọng nếu chúng là bộ đệm lệnh chính hoặc phụ nếu chúng ở trong cùng một kết xuất trả về? – hidayat

+1

@hidayat: Bởi vì bạn không thể có hai bộ đệm lệnh chính trong cùng một thể hiện trả về. 'vkCmdEndCommandBuffer' * không thể * được gọi trong khi một thể hiện renderpass đang hoạt động. Chỉ với bộ đệm lệnh phụ là có thể cho cả hai lệnh phát hành trong cùng một thể hiện renderpass. Họ làm điều này bằng cách kế thừa thể hiện renderpass của bộ đệm lệnh chính mà chúng thực thi bên trong. –

4

Đối với kịch bản của bạn, bạn nên sử dụng sự kiện. Đây nên là các đối tượng đồng bộ hóa trọng lượng nhẹ nhất để đồng bộ thực thi hai bộ đệm lệnh theo một thứ tự nhất định, ngay cả khi bạn gửi chúng cùng một lúc. Nhưng lưu ý rằng các sự kiện không hoạt động trên các hàng đợi khác nhau. Nếu bạn chỉ sử dụng một, sử dụng các sự kiện và cố gắng giữ cho mặt nạ sân khấu đường ống src và dst càng hẹp càng tốt.

Semaphores là một cách khác để đồng bộ hóa việc thực hiện bộ đệm lệnh, nhưng chúng chỉ hoạt động trong quá trình gửi hàng đợi, vì vậy chúng nặng hơn các sự kiện.

+0

Không thể có rào cản? Tôi tiếp tục đọc ở đây rằng các rào cản làm việc trên các ranh giới bộ đệm lệnh: http://stackoverflow.com/a/36602598/1364776 Không thể áp dụng ở đây? Hay nó chỉ là sự kiện nhẹ hơn rào chắn là gì? – mjwach

Các vấn đề liên quan