সিঙ্ক্রোনাইজেশন ফ্রেমওয়ার্ক

সিঙ্ক্রোনাইজেশন ফ্রেমওয়ার্কটি অ্যান্ড্রয়েড গ্রাফিক্স সিস্টেমের বিভিন্ন অ্যাসিঙ্ক্রোনাস অপারেশনের মধ্যকার নির্ভরশীলতা স্পষ্টভাবে বর্ণনা করে। এই ফ্রেমওয়ার্কটি একটি এপিআই (API) প্রদান করে, যা কম্পোনেন্টগুলোকে বাফার কখন মুক্ত করা হয় তা নির্দেশ করতে সক্ষম করে। এছাড়াও, এই ফ্রেমওয়ার্কটি কার্নেল থেকে ইউজারস্পেসে ড্রাইভারগুলোর মধ্যে এবং ইউজারস্পেস প্রসেসগুলোর নিজেদের মধ্যে সিঙ্ক্রোনাইজেশন প্রিমিটিভ আদান-প্রদানের সুযোগ দেয়।

উদাহরণস্বরূপ, একটি অ্যাপ্লিকেশন জিপিইউ-তে সম্পাদন করার জন্য কাজ সারিবদ্ধ করতে পারে। জিপিইউ সেই ছবিটি আঁকা শুরু করে। যদিও ছবিটি এখনও মেমরিতে আঁকা হয়নি, বাফার পয়েন্টারটি একটি ফেন্স সহ উইন্ডো কম্পোজিটরের কাছে পাঠানো হয়, যা নির্দেশ করে জিপিইউ-এর কাজটি কখন শেষ হবে। উইন্ডো কম্পোজিটর সময়ের আগেই প্রসেসিং শুরু করে এবং কাজটি ডিসপ্লে কন্ট্রোলারের কাছে পাঠিয়ে দেয়। একইভাবে, সিপিইউ-এর কাজও সময়ের আগেই সম্পন্ন করা হয়। জিপিইউ-এর কাজ শেষ হয়ে গেলে, ডিসপ্লে কন্ট্রোলার অবিলম্বে ছবিটি প্রদর্শন করে।

সিঙ্ক্রোনাইজেশন ফ্রেমওয়ার্কটি বাস্তবায়নকারীদের তাদের নিজস্ব হার্ডওয়্যার উপাদানগুলিতে সিঙ্ক্রোনাইজেশন রিসোর্স ব্যবহার করার সুযোগ দেয়। পরিশেষে, ফ্রেমওয়ার্কটি ডিবাগিংয়ে সহায়তার জন্য গ্রাফিক্স পাইপলাইনের ভেতরের অবস্থা দেখার সুবিধা প্রদান করে।

সুস্পষ্ট সিঙ্ক্রোনাইজেশন

সুস্পষ্ট সিঙ্ক্রোনাইজেশন গ্রাফিক্স বাফারের উৎপাদক এবং ব্যবহারকারীদেরকে একটি বাফারের ব্যবহার শেষ হলে সংকেত দেওয়ার সুযোগ করে দেয়। সুস্পষ্ট সিঙ্ক্রোনাইজেশন কার্নেল-স্পেসে বাস্তবায়িত হয়।

সুস্পষ্ট সিঙ্ক্রোনাইজেশনের সুবিধাগুলোর মধ্যে রয়েছে:

  • ডিভাইসগুলোর মধ্যে আচরণের ভিন্নতা কম
  • উন্নত ডিবাগিং সমর্থন
  • উন্নত পরীক্ষার মেট্রিক্স

সিঙ্ক ফ্রেমওয়ার্কের তিনটি অবজেক্ট টাইপ রয়েছে:

  • sync_timeline
  • sync_pt
  • sync_fence

সিঙ্ক_টাইমলাইন

sync_timeline হলো একটি একমুখী ক্রমবর্ধমান টাইমলাইন যা ভেন্ডরদের প্রতিটি ড্রাইভার ইনস্ট্যান্সের জন্য প্রয়োগ করা উচিত, যেমন একটি GL কনটেক্সট, ডিসপ্লে কন্ট্রোলার বা 2D ব্লিটার। sync_timeline একটি নির্দিষ্ট হার্ডওয়্যারের জন্য কার্নেলে জমা দেওয়া জবগুলো গণনা করে। sync_timeline অপারেশনগুলোর ক্রম নিশ্চিত করে এবং হার্ডওয়্যার-নির্দিষ্ট বাস্তবায়ন সক্ষম করে।

sync_timeline প্রয়োগ করার সময় এই নির্দেশিকাগুলো অনুসরণ করুন:

  • ডিবাগিং সহজ করার জন্য সমস্ত ড্রাইভার, টাইমলাইন এবং ফেন্সের জন্য দরকারি নাম দিন।
  • ডিবাগিং আউটপুট আরও সহজে পাঠযোগ্য করার জন্য টাইমলাইনে timeline_value_str এবং pt_value_str অপারেটরগুলো প্রয়োগ করুন।
  • প্রয়োজনে জিএল লাইব্রেরির মতো ইউজারস্পেস লাইব্রেরিগুলোকে ব্যক্তিগত টাইমলাইন ডেটাতে অ্যাক্সেস দেওয়ার জন্য `fill driver_data প্রয়োগ করুন। data_driver ভেন্ডরদের অপরিবর্তনীয় sync_fence এবং sync_pts সম্পর্কিত তথ্য সরবরাহ করতে দেয়, যাতে সেগুলোর উপর ভিত্তি করে কমান্ড লাইন তৈরি করা যায়।
  • ইউজারস্পেসকে স্পষ্টভাবে কোনো ফেন্স তৈরি বা সিগন্যাল করার অনুমতি দেবেন না। স্পষ্টভাবে সিগন্যাল/ফেন্স তৈরি করলে একটি ডিনায়াল-অফ-সার্ভিস অ্যাটাক হয়, যা পাইপলাইনের কার্যকারিতা বন্ধ করে দেয়।
  • sync_timeline , sync_pt , বা sync_fence এলিমেন্টগুলো সরাসরি অ্যাক্সেস করবেন না। এপিআই-তেই সমস্ত প্রয়োজনীয় ফাংশন দেওয়া আছে।

সিঙ্ক_পিটি

sync_pt হলো sync_timeline উপর একটি একক মান বা পয়েন্ট। একটি পয়েন্টের তিনটি অবস্থা থাকে: active, signaled, এবং error। পয়েন্টগুলো active অবস্থা থেকে শুরু হয়ে signaled বা error অবস্থায় পরিবর্তিত হয়। উদাহরণস্বরূপ, যখন কোনো ইমেজ কনজিউমারের আর বাফারের প্রয়োজন হয় না, তখন একটি sync_pt সিগন্যাল করা হয়, যাতে ইমেজ প্রডিউসার বুঝতে পারে যে বাফারটিতে আবার লেখা যাবে।

সিঙ্ক_ফেন্স

sync_fence হলো sync_pt ভ্যালুগুলোর একটি সংগ্রহ, যেগুলোর প্রায়শই ভিন্ন ভিন্ন sync_timeline প্যারেন্ট থাকে (যেমন ডিসপ্লে কন্ট্রোলার এবং জিপিইউ-এর জন্য)। sync_fence , sync_pt , এবং sync_timeline হলো প্রধান প্রিমিটিভ যা ড্রাইভার এবং ইউজারস্পেস তাদের নির্ভরতা জানানোর জন্য ব্যবহার করে। যখন একটি ফেন্স সিগন্যালড হয়, তখন সেই ফেন্সের আগে জারি করা সমস্ত কমান্ড সম্পন্ন হয়ে যায়, কারণ কার্নেল ড্রাইভার বা হার্ডওয়্যার ব্লক কমান্ডগুলো ক্রমানুসারে সম্পাদন করে।

সিঙ্ক ফ্রেমওয়ার্ক একাধিক কনজিউমার বা প্রডিউসারকে একটি বাফার ব্যবহার শেষ হলে সংকেত দেওয়ার সুযোগ দেয়, যা একটিমাত্র ফাংশন প্যারামিটারের মাধ্যমে নির্ভরতার তথ্য আদান-প্রদান করে। ফেন্সগুলো একটি ফাইল ডেসক্রিপ্টর দ্বারা সমর্থিত থাকে এবং কার্নেল স্পেস থেকে ইউজারস্পেসে পাঠানো হয়। উদাহরণস্বরূপ, একটি ফেন্স দুটি sync_pt ভ্যালু ধারণ করতে পারে, যা নির্দেশ করে কখন দুটি পৃথক ইমেজ কনজিউমার একটি বাফার পড়া শেষ করেছে। যখন ফেন্সটিতে সংকেত পাঠানো হয়, তখন ইমেজ প্রডিউসাররা বুঝতে পারে যে উভয় কনজিউমারেরই কনজিউমিং শেষ হয়েছে।

ফেন্সগুলো, sync_pt ভ্যালুগুলোর মতোই, শুরুতে সক্রিয় থাকে এবং তাদের পয়েন্টগুলোর অবস্থার ওপর ভিত্তি করে নিজেদের অবস্থা পরিবর্তন করে। যদি সমস্ত sync_pt ভ্যালু সিগন্যালড হয়ে যায়, তাহলে sync_fence সিগন্যালড হয়ে যায়। যদি একটি sync_pt এরর স্টেটে চলে যায়, তাহলে পুরো sync_fence এরর স্টেটে চলে যায়।

একটি sync_fence তৈরি হয়ে গেলে এর সদস্যপদ অপরিবর্তনীয় থাকে। একটি ফেন্সে একাধিক পয়েন্ট পেতে হলে, একটি merge প্রক্রিয়া সম্পন্ন করা হয়, যেখানে দুটি ভিন্ন ফেন্সের পয়েন্ট একটি তৃতীয় ফেন্সে যোগ করা হয়। যদি সেই পয়েন্টগুলোর মধ্যে একটি মূল ফেন্সটিতে signaled অবস্থায় থাকে এবং অন্যটি না থাকে, তবে তৃতীয় ফেন্সটিও signaled অবস্থায় থাকবে না।

সুস্পষ্ট সিঙ্ক্রোনাইজেশন বাস্তবায়ন করতে, নিম্নলিখিতগুলি প্রদান করুন:

  • একটি কার্নেল-স্পেস সাবসিস্টেম যা একটি নির্দিষ্ট হার্ডওয়্যার ড্রাইভারের জন্য সিঙ্ক ফ্রেমওয়ার্ক বাস্তবায়ন করে। যেসব ড্রাইভারকে ফেন্স-অ্যাওয়্যার হতে হয়, সেগুলো সাধারণত হার্ডওয়্যার কম্পোজার (HWC)-কে অ্যাক্সেস করে বা এর সাথে যোগাযোগ করে। মূল ফাইলগুলোর মধ্যে রয়েছে:
    • মূল বাস্তবায়ন:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • kernel/common/Documentation/sync.txt এ ডকুমেন্টেশন
    • platform/system/core/libsync এ কার্নেল স্পেসের সাথে যোগাযোগের জন্য লাইব্রেরি।
  • বিক্রেতাকে অবশ্যই হার্ডওয়্যার অ্যাবস্ট্রাকশন লেয়ারে (HAL) থাকা validateDisplay() এবং presentDisplay() ফাংশনগুলিতে প্যারামিটার হিসেবে উপযুক্ত সিনক্রোনাইজেশন ফেন্স সরবরাহ করতে হবে।
  • দুটি ফেন্স-সম্পর্কিত জিএল এক্সটেনশন ( EGL_ANDROID_native_fence_sync এবং EGL_ANDROID_wait_sync ) এবং গ্রাফিক্স ড্রাইভারে ফেন্স সাপোর্ট।

কেস স্টাডি: একটি ডিসপ্লে ড্রাইভার বাস্তবায়ন

সিঙ্ক্রোনাইজেশন ফাংশন সমর্থনকারী এপিআই ব্যবহার করতে, এমন একটি ডিসপ্লে ড্রাইভার তৈরি করুন যাতে একটি ডিসপ্লে বাফার ফাংশন থাকে। সিঙ্ক্রোনাইজেশন ফ্রেমওয়ার্কটি আসার আগে, এই ফাংশনটি dma-buf অবজেক্ট গ্রহণ করত, সেই বাফারগুলো ডিসপ্লেতে রাখত এবং বাফারটি দৃশ্যমান থাকা পর্যন্ত ব্লক হয়ে থাকত। উদাহরণস্বরূপ:

/*
 * assumes buffer is ready to be displayed.  returns when buffer is no longer on
 * screen.
 */
void display_buffer(struct dma_buf *buffer);

সিনক্রোনাইজেশন ফ্রেমওয়ার্কের সাথে, display_buffer ফাংশনটি আরও জটিল। কোনো বাফার প্রদর্শনে রাখার সময়, বাফারটি একটি ফেন্সের সাথে যুক্ত থাকে যা নির্দেশ করে বাফারটি কখন প্রস্তুত হবে। ফেন্সটি ক্লিয়ার হওয়ার পর আপনি কাজটি কিউতে যুক্ত করে শুরু করতে পারেন।

ফেন্স ক্লিয়ার হওয়ার পরে কাজ কিউতে রাখা এবং শুরু করা কোনো কিছু ব্লক করে না। আপনি অবিলম্বে আপনার নিজের ফেন্স রিটার্ন করেন, যা নির্দেশ করে কখন বাফারটি ডিসপ্লে থেকে অফ হবে। আপনি যখন বাফার কিউতে রাখেন, কার্নেল সিনক্রোনাইজেশন ফ্রেমওয়ার্কের সাথে নির্ভরতা তালিকাভুক্ত করে:

/*
 * displays buffer when fence is signaled.  returns immediately with a fence
 * that signals when buffer is no longer displayed.
 */
struct sync_fence* display_buffer(struct dma_buf *buffer, struct sync_fence
*fence);

সিঙ্ক ইন্টিগ্রেশন

এই অংশে ব্যাখ্যা করা হয়েছে কীভাবে কার্নেল-স্পেস সিঙ্ক ফ্রেমওয়ার্ককে অ্যান্ড্রয়েড ফ্রেমওয়ার্কের ইউজারস্পেস অংশ এবং একে অপরের সাথে যোগাযোগকারী ড্রাইভারগুলোর সাথে একীভূত করতে হয়। কার্নেল-স্পেস অবজেক্টগুলো ইউজারস্পেসে ফাইল ডেসক্রিপ্টর হিসেবে উপস্থাপিত হয়।

একীকরণ প্রথা

অ্যান্ড্রয়েড HAL ইন্টারফেসের নিয়মাবলী অনুসরণ করুন:

  • যদি API এমন একটি ফাইল ডেসক্রিপ্টর প্রদান করে যা একটি sync_pt কে নির্দেশ করে, তাহলে ভেন্ডরের ড্রাইভার অথবা API ব্যবহারকারী HAL-কে অবশ্যই ফাইল ডেসক্রিপ্টরটি বন্ধ করতে হবে।
  • যদি ভেন্ডর ড্রাইভার বা HAL কোনো API ফাংশনে sync_pt সম্বলিত একটি ফাইল ডেসক্রিপ্টর প্রেরণ করে, তবে ভেন্ডর ড্রাইভার বা HAL অবশ্যই সেই ফাইল ডেসক্রিপ্টরটি বন্ধ করবে না।
  • ফেন্স ফাইল ডেসক্রিপ্টরটির ব্যবহার অব্যাহত রাখতে, ভেন্ডর ড্রাইভার বা HAL-কে অবশ্যই ডেসক্রিপ্টরটির প্রতিলিপি তৈরি করতে হবে।

একটি ফেন্স অবজেক্ট প্রতিবার BufferQueue-এর মধ্য দিয়ে যাওয়ার সময় নতুন করে নামকরণ করা হয়। কার্নেল ফেন্স সাপোর্টের কারণে ফেন্সের নাম স্ট্রিং হতে পারে, তাই সিঙ্ক ফ্রেমওয়ার্ক ফেন্সটির নামকরণের জন্য কিউতে থাকা উইন্ডোর নাম এবং বাফার ইনডেক্স ব্যবহার করে, যেমন SurfaceView:0 । এটি ডিবাগিংয়ের সময় ডেডলকের উৎস শনাক্ত করতে সহায়ক, কারণ এই নামগুলো /d/sync এর আউটপুট এবং বাগ রিপোর্টে দেখা যায়।

ANativeWindow ইন্টিগ্রেশন

ANativeWindow হলো ফেন্স-অ্যাওয়ার। dequeueBuffer , queueBuffer , এবং cancelBuffer ফেন্স প্যারামিটার রয়েছে।

OpenGL ES ইন্টিগ্রেশন

OpenGL ES সিঙ্ক ইন্টিগ্রেশন দুটি EGL এক্সটেনশনের উপর নির্ভর করে:

  • EGL_ANDROID_native_fence_sync EGLSyncKHR অবজেক্টের মধ্যে নেটিভ অ্যান্ড্রয়েড ফেন্স ফাইল ডেসক্রিপ্টরগুলোকে র‍্যাপ করতে বা তৈরি করার একটি উপায় প্রদান করে।
  • EGL_ANDROID_wait_sync সিপিইউ-এর পরিবর্তে জিপিইউ-তে স্টল করার সুযোগ দেয়, যার ফলে জিপিইউ EGLSyncKHR জন্য অপেক্ষা করে। EGL_ANDROID_wait_sync এক্সটেনশনটি EGL_KHR_wait_sync এক্সটেনশনের মতোই।

এই এক্সটেনশনগুলি স্বাধীনভাবে ব্যবহার করার জন্য, সংশ্লিষ্ট কার্নেল সাপোর্ট সহ EGL_ANDROID_native_fence_sync এক্সটেনশনটি ইমপ্লিমেন্ট করুন। এরপর, আপনার ড্রাইভারে EGL_ANDROID_wait_sync এক্সটেনশনটি এনাবল করুন। EGL_ANDROID_native_fence_sync এক্সটেনশনটি একটি স্বতন্ত্র নেটিভ ফেন্স EGLSyncKHR অবজেক্ট টাইপ নিয়ে গঠিত। ফলে, বিদ্যমান EGLSyncKHR অবজেক্ট টাইপগুলিতে প্রযোজ্য এক্সটেনশনগুলি EGL_ANDROID_native_fence অবজেক্টগুলিতে অগত্যা প্রযোজ্য হয় না, যা অনাকাঙ্ক্ষিত ইন্টারঅ্যাকশন এড়িয়ে চলে।

EGL_ANDROID_native_fence_sync এক্সটেনশনটি একটি সংশ্লিষ্ট নেটিভ ফেন্স ফাইল ডেসক্রিপ্টর অ্যাট্রিবিউট ব্যবহার করে, যা শুধুমাত্র তৈরির সময় সেট করা যায় এবং কোনো বিদ্যমান সিঙ্ক অবজেক্ট থেকে সরাসরি পরবর্তীতে কোয়েরি করা যায় না। এই অ্যাট্রিবিউটটি দুটি মোডের যেকোনো একটিতে সেট করা যেতে পারে:

  • একটি বৈধ ফেন্স ফাইল ডেসক্রিপ্টর একটি EGLSyncKHR অবজেক্টের মধ্যে বিদ্যমান একটি নেটিভ অ্যান্ড্রয়েড ফেন্স ফাইল ডেসক্রিপ্টরকে র‍্যাপ করে।
  • -1 একটি EGLSyncKHR অবজেক্ট থেকে একটি নেটিভ অ্যান্ড্রয়েড ফেন্স ফাইল ডেসক্রিপ্টর তৈরি করে।

নেটিভ অ্যান্ড্রয়েড ফেন্স ফাইল ডেসক্রিপ্টর থেকে EGLSyncKHR অবজেক্টটি এক্সট্র্যাক্ট করতে DupNativeFenceFD() ফাংশন কলটি ব্যবহার করুন। এর ফলাফল সেট অ্যাট্রিবিউট কোয়েরি করার মতোই, কিন্তু এটি এই কনভেনশনটি মেনে চলে যে প্রাপকই ফেন্সটি বন্ধ করে (এজন্যই এটি একটি ডুপ্লিকেট অপারেশন)। সবশেষে, EGLSyncKHR অবজেক্টটি ডেস্ট্রয় করলে ইন্টারনাল ফেন্স অ্যাট্রিবিউটটি বন্ধ হয়ে যায়।

হার্ডওয়্যার কম্পোজার ইন্টিগ্রেশন

HWC তিন ধরনের সিঙ্ক ফেন্স পরিচালনা করে:

  • অ্যাকোয়ার ফেন্সগুলো ইনপুট বাফারের সাথে setLayerBuffer এবং setClientTarget কলগুলোতে পাঠানো হয়। এগুলো বাফারে একটি আসন্ন রাইট নির্দেশ করে এবং কম্পোজিশন সম্পাদনের জন্য SurfaceFlinger বা HWC সংশ্লিষ্ট বাফার থেকে রিড করার চেষ্টা করার আগে অবশ্যই সিগন্যাল দিতে হবে।
  • presentDisplay কল করার পর getReleaseFences কল ব্যবহার করে রিলিজ ফেন্সগুলো পুনরুদ্ধার করা হয়। এগুলো একই লেয়ারের পূর্ববর্তী বাফার থেকে একটি অপেক্ষমান রিডকে নির্দেশ করে। একটি রিলিজ ফেন্স সংকেত দেয় যখন HWC আর পূর্ববর্তী বাফারটি ব্যবহার করছে না, কারণ ডিসপ্লেতে বর্তমান বাফারটি পূর্ববর্তী বাফারকে প্রতিস্থাপন করেছে। বর্তমান কম্পোজিশনের সময় যে পূর্ববর্তী বাফারগুলো প্রতিস্থাপিত হবে, সেগুলোর সাথে রিলিজ ফেন্সগুলোও অ্যাপে ফেরত পাঠানো হয়। ফেরত পাঠানো বাফারে নতুন কন্টেন্ট লেখার আগে, অ্যাপকে অবশ্যই একটি রিলিজ ফেন্সের সংকেত দেওয়া পর্যন্ত অপেক্ষা করতে হবে।
  • presentDisplay কল করার অংশ হিসেবে, প্রতি ফ্রেমে একটি করে প্রেজেন্ট ফেন্স রিটার্ন করা হয়। প্রেজেন্ট ফেন্স নির্দেশ করে যে এই ফ্রেমের কম্পোজিশন কখন সম্পন্ন হয়েছে, অথবা বিকল্পভাবে, পূর্ববর্তী ফ্রেমের কম্পোজিশন ফলাফলের আর প্রয়োজন নেই। ফিজিক্যাল ডিসপ্লের ক্ষেত্রে, বর্তমান ফ্রেমটি স্ক্রিনে প্রদর্শিত হলে presentDisplay প্রেজেন্ট ফেন্স রিটার্ন করে। প্রেজেন্ট ফেন্স রিটার্ন করার পর, প্রযোজ্য হলে SurfaceFlinger টার্গেট বাফারে পুনরায় লেখা নিরাপদ। ভার্চুয়াল ডিসপ্লের ক্ষেত্রে, আউটপুট বাফার থেকে পড়া নিরাপদ হলে প্রেজেন্ট ফেন্স রিটার্ন করা হয়।