المزامنة بين الطوابير في Vulkan باستخدام السيمافور Semaphore

من ويكي
اذهب إلى: تصفح، ابحث

السيمافور VkSemaphore أحد أدوات المزامنة في Vulkan والذي يشبه السياج من ناحية أنه يأخذ حالين وهي إما جاهز أو غير جاهز، لكنه خلافاً للسياج يستخدم فقط داخل الجهاز للمزامنة بين إرساليات معالجة مرسلة عبر عدة طوابير وكذلك للمزامنة مع نظام العرض عند عرض الصور على الشاشة كما سنرى لاحقاً، لايمكنك انتظار أو ضبط السيمافور، الجهاز فقط يقوم داخلياً بهذا، ولاتقوم أنت سوى بإنشاءه وتمريره للجهاز وهدمه، يمكن أيضاً استخدام السيمافور للمزامنة بين الإرساليات على نفس الطابور لكن هناك الحواجز barriers التي سنتحدث عنها لاحقاً وهي آلية مزامنة أخرى أخف بكثير من السيمافور يمكن استخدامها للمزامنة بين الإرساليات عبر نفس الطابور.

إنشاء السيمافور VkSemaphore

لإنشاء السيمافور نستدعي الدالة vkCreateSemaphore():

VkResult vkCreateSemaphore(
    VkDevice                                    device,
    const VkSemaphoreCreateInfo*                pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkSemaphore*                                pSemaphore);

تأخذ الدالة في المعامل الأول كائن الجهاز، ثم مؤشر للبنية VkSemaphoreCreateInfo، يليها مخصص الذاكرة، وفي المعامل الأخير مؤشر للمتغير الذي سيخزن فيه كائن السيمافور بعد إنشاءه.

البنية VkSemaphoreCreateInfo يفترض أن تحتوي على معلومات السيمافور:

typedef struct VkSemaphoreCreateInfo {
    VkStructureType           sType;
    const void*               pNext;
    VkSemaphoreCreateFlags    flags;
} VkSemaphoreCreateInfo;

ضع VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO في sType، ويجب أن تضع NULL في pNext، العضو flags غير مستخدم حالياً، يجب أن تضعه صفر، هذه البنية موجودة لأنه يمكن أن تضاف لها خيارات في المستقبل.

سنتشئ الدالة سيمافور في حالة عدم الجاهزية.

استخدام السيمافور مع vkQueueSubmit()

السيمافورات التي ستمررها في VkSubmitInfo::pSignalSemaphores يجب أن تكون في حالة عدم الجاهزية، عندما ينتهي الطابور من تنفيذ دفعة الأوامر التي مررتها في VkSubmitInfo::pCommandBuffers فستغير حالة السيمافورات في VkSubmitInfo::pSignalSemaphores إلى حالة الجاهزية، السيمافورات التي ستمررها للدفعة التالية في VkSubmitInfo::pWaitSemaphores يجب أن سبق لك تمريرها في VkSubmitInfo::pSignalSemaphores لدفعة سابقة، حيث سنتنظر vkQueueSubmit() إلى أن تتحول حالتها إلى حالة الجاهزية، وبعدما تتحول لحالة الجاهزية سيقوم الجهاز بإعادة ضبطها وتنفيذ الأوامر التي كانت في الإنتظار وهكذا.

النقطة المهمة هنا هي أنه كوننا لا يمكن أن ننشئ سيمافور في حالة الجاهزية ولا إعادة ضبطه كما هو الحال مع السياج، فهذا يعني أن أول إرسالية ترسلها لايمكن أن تحتوي على سيمافور في VkSubmitInfo::pWaitSemaphores.

هدم السيمافور

بعد التأكد من أن جميع المهام انتهت وأن السيمافور لم يعد في الاستخدام، يمكنك هدم الكائن VkSemaphore باستخدام الدالة vkDestroySemaphore():

void vkDestroySemaphore(
    VkDevice                                    device,
    VkSemaphore                                 semaphore,
    const VkAllocationCallbacks*                pAllocator);