আমার একটি জিএলএসএল প্রোগ্রাম ডিবাগ করতে হবে তবে কীভাবে মধ্যবর্তী ফলাফল আউটপুট করবেন তা আমি জানি না। জিএলএসএল দিয়ে কিছু ডিবাগ ট্রেস (প্রিন্টফের মতো) করা কি সম্ভব?
আমার একটি জিএলএসএল প্রোগ্রাম ডিবাগ করতে হবে তবে কীভাবে মধ্যবর্তী ফলাফল আউটপুট করবেন তা আমি জানি না। জিএলএসএল দিয়ে কিছু ডিবাগ ট্রেস (প্রিন্টফের মতো) করা কি সম্ভব?
উত্তর:
আপনি সহজেই জিএলএসএল থেকে সিপিইউতে ফিরে যোগাযোগ করতে পারবেন না। GlslDevil বা অন্যান্য সরঞ্জাম ব্যবহার করা আপনার সেরা বাজি।
একটি প্রিন্টফের জন্য জিপিএসএল জিপিএসএল কোডটি চালিয়ে সিপিইউতে ফিরে যাওয়ার চেষ্টা করা দরকার। পরিবর্তে, আপনি প্রদর্শন এগিয়ে ধাক্কা চেষ্টা করতে পারেন। পাঠ্য আউটপুট দেওয়ার চেষ্টা করার পরিবর্তে স্ক্রিনের জন্য দৃশ্যমান স্বতন্ত্র কিছু আউটপুট। উদাহরণস্বরূপ, আপনি কেবলমাত্র আপনার কোডের যে বিন্দুতে প্রিন্টফ যুক্ত করতে চান সেখানে পৌঁছালেই আপনি নির্দিষ্ট কিছু রঙ করতে পারেন। আপনার যদি কোনও মান মুদ্রণ করতে হয় তবে আপনি সেই মান অনুযায়ী রঙ সেট করতে পারেন।
void main(){
float bug=0.0;
vec3 tile=texture2D(colMap, coords.st).xyz;
vec4 col=vec4(tile, 1.0);
if(something) bug=1.0;
col.x+=bug;
gl_FragColor=col;
}
আমি ট্রান্সফর্ম মতামত পেয়েছিভার্সটেক্স শেডারগুলি ডিবাগ করার জন্য একটি দরকারী সরঞ্জাম হিসাবে । আপনি ভিএস আউটপুটগুলির মানগুলি ক্যাপচার করতে এটি ব্যবহার করতে পারেন এবং রাস্টারাইজারের বাইরে না গিয়ে সেগুলি আবার সিপিইউয়ের পাশে পড়তে পারেন।
ট্রান্সফর্ম ফিডব্যাকের টিউটোরিয়ালের আরও একটি লিঙ্ক এখানে ।
আপনি যদি স্ক্রীন জুড়ে কোনও মানের বিভিন্নতার চিত্র দেখতে চান তবে আপনি এর অনুরূপ হিটম্যাপ ফাংশনটি ব্যবহার করতে পারেন (আমি এটি hlsl এ লিখেছি, তবে glsl এর সাথে খাপ খাইয়ে নেওয়া সহজ):
float4 HeatMapColor(float value, float minValue, float maxValue)
{
#define HEATMAP_COLORS_COUNT 6
float4 colors[HEATMAP_COLORS_COUNT] =
{
float4(0.32, 0.00, 0.32, 1.00),
float4(0.00, 0.00, 1.00, 1.00),
float4(0.00, 1.00, 0.00, 1.00),
float4(1.00, 1.00, 0.00, 1.00),
float4(1.00, 0.60, 0.00, 1.00),
float4(1.00, 0.00, 0.00, 1.00),
};
float ratio=(HEATMAP_COLORS_COUNT-1.0)*saturate((value-minValue)/(maxValue-minValue));
float indexMin=floor(ratio);
float indexMax=min(indexMin+1,HEATMAP_COLORS_COUNT-1);
return lerp(colors[indexMin], colors[indexMax], ratio-indexMin);
}
তারপরে আপনার পিক্সেল শেডারে আপনি ঠিক এমন কিছু আউটপুট পান:
return HeatMapColor(myValue, 0.00, 50.00);
এবং এটি আপনার পিক্সেল জুড়ে কীভাবে পরিবর্তিত হয় তার একটি ধারণা পেতে পারেন:
অবশ্যই আপনি পছন্দ মতো যে কোনও রঙের সেট ব্যবহার করতে পারেন।
শেডারের জন্য জিএলএসএল স্যান্ডবক্সটি আমার কাছে বেশ কার্যকর।
প্রতি সেবাতে ডিবাগিং নয় (যা অক্ষম হিসাবে জবাব দেওয়া হয়েছে) তবে আউটপুটের পরিবর্তনগুলি দ্রুত দেখার জন্য সহজ।
আপনি এটি চেষ্টা করতে পারেন: https://github.com/msqrt/shader-printf যা একটি বাস্তবায়ন যাকে যথাযথভাবে "GLSL এর জন্য সিম্পল প্রিন্টফ কার্যকারিতা" বলা হয়।
আপনি শ্যাডারটয় চেষ্টা করে দেখতেও পারেন এবং সম্ভবত "আর্ট অফ কোড" ইউটিউব চ্যানেল থেকে এই জাতীয় ( https://youtu.be/EBrAdahFtuo ) ভিডিও দেখতে পারেন যেখানে আপনি কিছু কৌশলগুলি দেখতে পারেন যেগুলি ডিবাগিংয়ের জন্য ভাল কাজ করে এবং visualizing। আমি তার চ্যানেলের দৃ strongly়তার সাথে সুপারিশ করতে পারি কারণ তিনি কিছু সত্যই ভাল জিনিস লিখেছেন এবং উপন্যাসে জটিল ধারণা উপস্থাপন, অত্যন্ত আকর্ষক এবং ফর্ম্যাটগুলি হজম করার পক্ষেও তার একটি দক্ষতা রয়েছে (তাঁর ম্যান্ডেলব্রোট ভিডিও হুবহু এক চমত্কার উদাহরণ: https: // youtu.be/6IWXkV82oyY )
আমি আশা করি এই দেরির উত্তরটি কেউ আপত্তি করবে না, তবে জিএলএসএল ডিবাগিংয়ের জন্য গুগল অনুসন্ধানে প্রশ্নটি শীর্ষে রয়েছে এবং 9 বছরের মধ্যে অবশ্যই পরিবর্তন হয়েছে :-)
পিএস: অন্যান্য বিকল্পগুলি এনভিআইডিএ এনসাইট এবং এএমডি শ্যাডারআনলাইজার হতে পারে যা শেডারগুলির জন্য একটি পুরো স্টেপিং ডিবাগার দেয়।
আমি একটি খণ্ড শেডার উদাহরণ ভাগ করছি, আমি কীভাবে আসলে ডিবাগ করব।
#version 410 core
uniform sampler2D samp;
in VS_OUT
{
vec4 color;
vec2 texcoord;
} fs_in;
out vec4 color;
void main(void)
{
vec4 sampColor;
if( texture2D(samp, fs_in.texcoord).x > 0.8f) //Check if Color contains red
sampColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); //If yes, set it to white
else
sampColor = texture2D(samp, fs_in.texcoord); //else sample from original
color = sampColor;
}
এই উত্তরের নীচে জিএলএসএল কোডের একটি উদাহরণ যা 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);
স্ক্রিনে এটি পাওয়ার পরে, আপনি কেবল যে কোনও রঙ চয়নকারী নিতে পারেন, রঙটি এইচটিএমএল হিসাবে ফর্ম্যাট করতে পারেন ( উচ্চতর নির্ভুলতার প্রয়োজন না হলে মানকে সংযোজন 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.;
}
কোনও টেক্সচারে অফলাইন রেন্ডারিং করুন এবং জমিনের ডেটা মূল্যায়ন করুন। "টেক্সচারে রেন্ডার করুন" ওপেনগলের জন্য গুগল করে আপনি সম্পর্কিত কোডটি সন্ধান করতে পারেন তারপরে আউটপুটটিকে একটি অ্যারেতে পড়তে এবং তার উপর দৃ as় সম্পাদন করতে glReadPixels ব্যবহার করুন (যেহেতু ডিবাগারে এত বিশাল অ্যারের সন্ধান করা সাধারণত কার্যকর হয় না)।
এছাড়াও আপনি 0 এবং 1 এর মধ্যে নয় এমন আউটপুট মানগুলিতে ক্ল্যাম্পিং অক্ষম করতে চাইতে পারেন যা কেবলমাত্র ভাসমান পয়েন্ট টেক্সচারের জন্য সমর্থিত ।
আমি ব্যক্তিগতভাবে কিছুক্ষণের জন্য ছায়ারগুলিকে সঠিকভাবে ডিবাগ করার সমস্যা দ্বারা বিরক্ত হয়েছিল। ভাল উপায় বলে মনে হচ্ছে না - যদি কেউ কোনও ভাল (এবং পুরানো / অবহেলিত নয়) ডিবাগারটি খুঁজে পান তবে দয়া করে আমাকে জানান।
বিদ্যমান উত্তরগুলি সমস্ত ভাল স্টাফ, তবে আমি আরও একটি ছোট মণি ভাগ করতে চেয়েছিলাম যা একটি জিএলএসএল শেডারে জটিল নির্ভুলতার বিষয়গুলি ডিবাগ করার জন্য মূল্যবান। ভাসমান পয়েন্ট হিসাবে প্রতিনিধিত্ব করা খুব বড় সংখ্যক সংখ্যার সাথে, একটিকে সঠিক অবধি বৃত্তাকার () প্রয়োগ করতে সঠিকভাবে ফ্লোর (এন) এবং ফ্লোর (এন + 0.5) ব্যবহার করা উচিত। তারপরে আর, জি, এবং বি আউটপুট মানগুলিতে বাইট উপাদানগুলিকে প্যাক করার জন্য নিম্নোক্ত যুক্তি অনুসারে একটি সঠিক ফ্ল্যাট মান প্রদান করা সম্ভব।
// Break components out of 24 bit float with rounded int value
// scaledWOB = (offset >> 8) & 0xFFFF
float scaledWOB = floor(offset / 256.0);
// c2 = (scaledWOB >> 8) & 0xFF
float c2 = floor(scaledWOB / 256.0);
// c0 = offset - (scaledWOB << 8)
float c0 = offset - floor(scaledWOB * 256.0);
// c1 = scaledWOB - (c2 << 8)
float c1 = scaledWOB - floor(c2 * 256.0);
// Normalize to byte range
vec4 pix;
pix.r = c0 / 255.0;
pix.g = c1 / 255.0;
pix.b = c2 / 255.0;
pix.a = 1.0;
gl_FragColor = pix;