আমি কীভাবে জিএলএসএল শেডারগুলি ডিবাগ করতে পারি?


45

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

তাহলে আমি কীভাবে আসলে একটি শেডার ডিবাগ করব? শেডার দিয়ে পা রাখার কোনও উপায় আছে কি? আমি কি একটি নির্দিষ্ট শীর্ষবিন্দু / আদিম / খণ্ডে শেডারটির সম্পাদনা দেখতে পারি?

(এই প্রশ্নটি শ্যাডার কোডটি কীভাবে ডিবাগ করা যায় সে সম্পর্কে রাষ্ট্রের পরিবর্তনের মতো ডিবাগিংয়ের মতো নয়, "সাধারণ" কোডটি কীভাবে সমান হয়) specifically


আপনি কি জিডিইবাগারে সন্ধান করেছেন? সাইটটি উদ্ধৃত করে: "জিডিইবাগার একটি উন্নত ওপেনজিএল এবং ওপেনসিএল ডিবাগার, প্রোফাইলার এবং মেমরি অ্যানালাইজার DE " মঞ্জুর, কোনও ভিএস স্টাইল ডিবাগিং / কোডের মাধ্যমে পদক্ষেপ নয়, তবে এটি আপনাকে আপনার শেডার কী করে (বা করণীয়) তার মধ্যে কিছুটা অন্তর্দৃষ্টি দিতে পারে। ক্রিটেক রেন্ডারডক নামক ডাইরেক্ট শেডার "ডিবাগিং" এর জন্য একটি অনুরূপ সরঞ্জাম প্রকাশ করেছিলেন (বিনামূল্যে, তবে কঠোরভাবে এইচএলএসএল শেডারগুলির জন্য, সম্ভবত আপনার পক্ষে প্রাসঙ্গিক নয়)।
বার্ট

@ বার্ট এইচ হ্যাঁ, আমার ধারণা জিডিডিবার্গার কি ওপেনজিএলকে ওয়েবজিএল-ইন্সপেক্টরের সমতুল্য? আমি পরে ব্যবহার করেছি। এটি অত্যন্ত কার্যকর, তবে এটি অবশ্যই ছাপার মৃত্যুর চেয়ে ওপেনএল কল এবং রাষ্ট্র পরিবর্তনগুলি আরও বেশি ডিবাগ করছে।
মার্টিন ইন্ডার

1
আমি কখনও কোনও ওয়েবজিএল প্রোগ্রামিং করি নি এবং তাই আমি ওয়েবজিএল-পরিদর্শকের সাথে পরিচিত নই। জিডিইবাগারের সাহায্যে আপনি কমপক্ষে টেক্সচার মেমরি, ভারটেক্স ডেটা ইত্যাদি সহ আপনার শেডার পাইপলাইনের পুরো রাজ্যটি পরিদর্শন করতে পারেন তবুও, কোড আফিকের মাধ্যমে কোনও আসল পদক্ষেপ নেই।
বার্ট

gdeBugger চূড়ান্তভাবে পুরানো এবং কিছুক্ষণ থেকে সমর্থিত নয়। আপনি যদি ফ্রেম এবং জিপিইউ রাষ্ট্রীয় বিশ্লেষণ থেকে সন্ধান করছেন তবে আপনি এই অন্যান্য প্রশ্নটির সাথে
দৃ related়ভাবে

: এখানে একটি ডিবাগিং পদ্ধতি আমি একটি সম্পর্কিত প্রশ্নের প্রস্তাব দেওয়া হচ্ছে stackoverflow.com/a/29816231/758666
wip

উত্তর:


26

আমি যতদূর জানি এমন কোনও সরঞ্জাম নেই যা আপনাকে শেডারে কোডের সাহায্যে পদক্ষেপ নিতে দেয় (এছাড়াও, সেক্ষেত্রে আপনাকে কেবল একটি পিক্সেল / ভার্টেক্স নির্বাচন করতে সক্ষম হতে হবে যা আপনি "ডিবাগ" করতে চান, মৃত্যুদন্ড কার্যকর হওয়ার সম্ভাবনা রয়েছে তার উপর নির্ভর করে পরিবর্তিত হয়)।

আমি ব্যক্তিগতভাবে যা করি তা হ্যাকিযুক্ত "রঙিন ডিবাগিং"। তাই আমি গার্ডগুলির সাথে #if DEBUG / #endifএকত্রে গতিশীল শাখাগুলি ছিটিয়েছি যা মূলত বলে

#if DEBUG
if( condition ) 
    outDebugColour = aColorSignal;
#endif

.. rest of code .. 

// Last line of the pixel shader
#if DEBUG
OutColor = outDebugColour;
#endif

সুতরাং আপনি এইভাবে ডিবাগ তথ্য "পর্যবেক্ষণ" করতে পারেন। আমি সাধারণত আরও বিভিন্ন জটিল ইভেন্ট বা নন-বাইনারি স্টাফ পরীক্ষা করার জন্য বিভিন্ন "কালার কোড" এর মধ্যে লেটার্প বা মিশ্রণের মতো বিভিন্ন কৌশল করি।

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

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

তবে, এটি বলার অপেক্ষা রাখে না যে আমি যদি একটি পিক্সেল শেডার বা কম্পিউট শেডারকে "ডিবাগিং" না করে থাকি তবে আমি এই "ডিবাগ কালার" তথ্যটি পাইপলাইনে বিভাজন ছাড়াই পাস করি ( flat কীওয়ার্ড সহ জিএলএসএল )

আবার, এটি খুব হ্যাকি এবং সঠিক ডিবাগিং থেকে অনেক দূরে তবে সঠিক বিকল্পটি না জেনে আমি আটকে রয়েছি।


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

9

রয়েছে GLSL-ডিবাগার । এটি একটি ডিবাগার যা "জিএলএসএল ডেভিল" নামে পরিচিত।

ডিবাগার নিজেই কেবল জিএলএসএল কোডের জন্যই নয়, ওপেনজিএল নিজেই দুর্দান্ত ব্যবহার করে। আপনার কাছে কল কলগুলির মধ্যে ঝাঁপিয়ে পড়ার এবং শেদার সুইচগুলিতে ব্রেক করার ক্ষমতা রয়েছে have এটি আপনাকে ওপেনজিএল দ্বারা প্রেরিত ত্রুটি বার্তাগুলি নিজেই অ্যাপ্লিকেশনটিতে দেখায়।


2
মনে রাখবেন যে 2018-08-07 পর্যন্ত এটি GLSL 1.2 এর চেয়ে বেশি কিছু সমর্থন করে না এবং এটি সক্রিয়ভাবে রক্ষণাবেক্ষণ করা হচ্ছে না।
রুসলান

এই মন্তব্যটি বৈধভাবে আমাকে দুঃখিত করেছে :(
rdelfin

প্রকল্পটি মুক্ত উত্স এবং এটি আধুনিকীকরণে সত্যই পছন্দ করবে। এটির কাজটি করে এমন কোনও সরঞ্জাম নেই।
জেননোফআর্টিকাস

7

সেখানে এএমডির মত জিপিইউ বিক্রেতাদের দ্বারা বিভিন্ন অফার যা CodeXL বা এনভিডিয়া এর nSight / লিনাক্স GFX ডিবাগার যা শেডার মাধ্যমে পদবিন্যাস মঞ্জুরি দিন কিন্তু নিজ নিজ বিক্রেতার হার্ডওয়্যার বাঁধা হয়।

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

আমি সম্প্রতি যে বিকল্পটি ব্যবহার করতে এসেছি তা হ'ল আমার শ্যাডার কোডটি মডুলারিকরণ#includes এবং অন্তর্ভুক্ত কোডটি জিএলএসএল এবং সি ++ ও গ্লিমের একটি সাধারণ উপসেটে সীমাবদ্ধ করে দেওয়া

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

যখন এটি একটি যুক্তিযুক্ত ত্রুটি হয় আমি সিপিইউতে জিপিইউ থেকে একই তথ্য দিয়ে সিপিইউতে অন্তর্ভুক্ত কোডটি কল করে পরিস্থিতি পুনর্নির্মাণের চেষ্টা করি। তারপরে আমি সিপিইউতে এটি দিয়ে যেতে পারি।

কোডের পরিমিতিকরণের উপর ভিত্তি করে আপনি এর জন্য ইউনিটেক্সট লেখার চেষ্টা করতে পারেন এবং জিপিইউ রান এবং সিপিইউ রানের মধ্যে ফলাফলগুলির তুলনা করতে পারেন। তবে আপনাকে সচেতন হতে হবে যে কোণার কেসগুলি রয়েছে যেখানে সি ++ জিএলএসএল থেকে আলাদা আচরণ করতে পারে, এইভাবে এই তুলনাগুলিতে আপনাকে মিথ্যা ইতিবাচক দিক দেয়।

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

এবং আপনাকে এখানে একটি সংক্ষিপ্ত বিবরণ দেওয়া আমার ডিবাগিং প্রক্রিয়াটির একটি ফ্লোচার্ট: পাঠ্যে বর্ণিত পদ্ধতির ফ্লো চার্ট

এটি বন্ধ করে দেওয়ার জন্য এখানে এলোমেলো উপকার এবং বিপরীতে একটি তালিকা রয়েছে:

স্বপক্ষে

  • সাধারণ ডিবাগার দিয়ে যেতে
  • অতিরিক্ত (প্রায়শই ভাল) সংকলক ডায়াগনস্টিক্স

বিরূদ্ধে


এটি দুর্দান্ত ধারণা এবং সম্ভবত আপনি একক-পদক্ষেপের শেডার কোডটি পেতে পারেন। আমি ভাবছি যদি কোনও সফ্টওয়্যার রেন্ডারারের (মেসা?) মাধ্যমে চালানো কি একই রকম সুবিধা পাবে?

@ ক্র্যারেট: আমি সে সম্পর্কেও ভেবেছিলাম কিন্তু এখনও চেষ্টা করার সময় পাইনি। আমি মেসায় কোনও বিশেষজ্ঞ নই তবে আমার ধারণা শ্যাডার ডিবাগ করা শক্ত হতে পারে কারণ শেডার ডিবাগের তথ্যটি কোনওভাবে ডিবাগরে পৌঁছে যেতে পারে। তারপর আবার, হয়তো Mesa এ ভাবেন ইতিমধ্যে জন্য একটি ইন্টারফেস Mesa নিজেই ডিবাগ :) আছে
কেউ

5

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

while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
    Log.e(TAG, label + ": glError " + error);
    throw new RuntimeException(label + ": glError " + error);

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

সম্পাদনা: ওয়েবজিলের জন্য, আমি এই প্রকল্পটি দেখছি, তবে আমি কেবল এটি পেয়েছি ... এটির জন্য কোনও প্রমাণ দেওয়া যায় না।


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

2

এটি স্ট্যাকওভারফ্লোতে একই প্রশ্নের আমার উত্তরের একটি অনুলিপি


এই উত্তরের নীচে জিএলএসএল কোডের একটি উদাহরণ যা floatআইইইই 754 এনকোডিং, রঙ হিসাবে পুরো মান আউটপুট করতে দেয় binary32। আমি এটি নীচের মতো ব্যবহার করি (এই স্নিপেটটি yyমডেলভিউ ম্যাট্রিক্সের উপাদান দেয় ):

vec4 xAsColor=toColor(gl_ModelViewMatrix[1][1]);
if(bool(1)) // put 0 here to get lowest byte instead of three highest
    gl_FrontColor=vec4(xAsColor.rgb,1);
else
    gl_FrontColor=vec4(xAsColor.a,0,0,1);

পরে আপনি স্ক্রীনে এই পেতে, আপনি ঠিক কোন রঙ জুতো নিতে পারে, HTML হিসাবে রঙ ফরম্যাট (সংযোজন 00করার rgbমান যদি উচ্চতর স্পষ্টতা প্রয়োজন হবে না, এবং একটি দ্বিতীয় পাস করছেন নিম্ন বাইট পেতে যদি আপনি না), এবং আপনি floatআইইইই 754 হিসাবে হেক্সাডেসিমাল উপস্থাপনা পান binary32

এর বাস্তব বাস্তবায়ন এখানে toColor():

const int emax=127;
// Input: x>=0
// Output: base 2 exponent of x if (x!=0 && !isnan(x) && !isinf(x))
//         -emax if x==0
//         emax+1 otherwise
int floorLog2(float x)
{
    if(x==0.) return -emax;
    // NOTE: there exist values of x, for which floor(log2(x)) will give wrong
    // (off by one) result as compared to the one calculated with infinite precision.
    // Thus we do it in a brute-force way.
    for(int e=emax;e>=1-emax;--e)
        if(x>=exp2(float(e))) return e;
    // If we are here, x must be infinity or NaN
    return emax+1;
}

// Input: any x
// Output: IEEE 754 biased exponent with bias=emax
int biasedExp(float x) { return emax+floorLog2(abs(x)); }

// Input: any x such that (!isnan(x) && !isinf(x))
// Output: significand AKA mantissa of x if !isnan(x) && !isinf(x)
//         undefined otherwise
float significand(float x)
{
    // converting int to float so that exp2(genType) gets correctly-typed value
    float expo=float(floorLog2(abs(x)));
    return abs(x)/exp2(expo);
}

// Input: x\in[0,1)
//        N>=0
// Output: Nth byte as counted from the highest byte in the fraction
int part(float x,int N)
{
    // All comments about exactness here assume that underflow and overflow don't occur
    const float byteShift=256.;
    // Multiplication is exact since it's just an increase of exponent by 8
    for(int n=0;n<N;++n)
        x*=byteShift;

    // Cut higher bits away.
    // $q \in [0,1) \cap \mathbb Q'.$
    float q=fract(x);

    // Shift and cut lower bits away. Cutting lower bits prevents potentially unexpected
    // results of rounding by the GPU later in the pipeline when transforming to TrueColor
    // the resulting subpixel value.
    // $c \in [0,255] \cap \mathbb Z.$
    // Multiplication is exact since it's just and increase of exponent by 8
    float c=floor(byteShift*q);
    return int(c);
}

// Input: any x acceptable to significand()
// Output: significand of x split to (8,8,8)-bit data vector
ivec3 significandAsIVec3(float x)
{
    ivec3 result;
    float sig=significand(x)/2.; // shift all bits to fractional part
    result.x=part(sig,0);
    result.y=part(sig,1);
    result.z=part(sig,2);
    return result;
}

// Input: any x such that !isnan(x)
// Output: IEEE 754 defined binary32 number, packed as ivec4(byte3,byte2,byte1,byte0)
ivec4 packIEEE754binary32(float x)
{
    int e = biasedExp(x);
    // sign to bit 7
    int s = x<0. ? 128 : 0;

    ivec4 binary32;
    binary32.yzw=significandAsIVec3(x);
    // clear the implicit integer bit of significand
    if(binary32.y>=128) binary32.y-=128;
    // put lowest bit of exponent into its position, replacing just cleared integer bit
    binary32.y+=128*int(mod(float(e),2.));
    // prepare high bits of exponent for fitting into their positions
    e/=2;
    // pack highest byte
    binary32.x=e+s;

    return binary32;
}

vec4 toColor(float x)
{
    ivec4 binary32=packIEEE754binary32(x);
    // Transform color components to [0,1] range.
    // Division is inexact, but works reliably for all integers from 0 to 255 if
    // the transformation to TrueColor by GPU uses rounding to nearest or upwards.
    // The result will be multiplied by 255 back when transformed
    // to TrueColor subpixel value by OpenGL.
    return vec4(binary32)/255.;
}

1

আমার পক্ষে যে সমাধানটি কাজ করেছিল তা হ'ল শেডার কোডটি সি ++ তে সংকলন - যেমনটি কেউই উল্লেখ করেছেন। একটি জটিল কোডে কাজ করার সময় এটির বেশ কয়েকটি সেটআপ প্রয়োজন হলেও এটি অত্যন্ত দক্ষ হয়ে উঠেছে।

আমি বেশিরভাগ এইচএলএসএল কম্পিউট শেডারের সাথে কাজ করছি যার জন্য আমি এখানে একটি প্রুফ-অফ কনসেপ্ট লাইব্রেরি তৈরি করেছি:

https://github.com/cezbloch/shaderator

এটি ডাইরেক্টএক্স এসডিকে নমুনাগুলির থেকে একটি গণনা শ্যাডারে প্রদর্শিত হবে, কীভাবে সিএল ++ এইচএলএসএল ডিবাগিংয়ের মতো সক্ষম করতে হবে এবং ইউনিট টেস্ট সেটআপ কীভাবে করা যায়।

সিএল + তে জিএলএসএল কম্পিউট শেডার সংকলন এইচএলএসএল থেকে সহজ দেখায়। মূলত এইচএলএসএলে সিনট্যাক্স নির্মাণের কারণে। আমি একটি জিএলএসএল রশ্মি ট্রেসার কম্পিউট শ্যাডারে এক্সিকিউটেবল ইউনিট টেস্টের একটি তুচ্ছ উদাহরণ যুক্ত করেছি যা আপনি উপরের লিঙ্কের অধীনে শ্যাডেটর প্রকল্পের উত্সগুলিতেও পেতে পারেন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.