WebGL GPU கமாண்ட் பஃபரின் நுட்பங்களை ஆராயுங்கள். லோ-லெவல் கிராபிக்ஸ் கமாண்ட் பதிவு மற்றும் செயல்படுத்துவதன் மூலம் ரெண்டரிங் செயல்திறனை மேம்படுத்துவது எப்படி என்று அறிக.
WebGL GPU கமாண்ட் பஃபரை மாஸ்டர் செய்தல்: லோ-லெவல் கிராபிக்ஸ் பதிவில் ஒரு ஆழமான பார்வை
வலை கிராபிக்ஸ் உலகில், Three.js அல்லது Babylon.js போன்ற உயர்நிலை நூலகங்களுடன் நாம் அடிக்கடி வேலை செய்கிறோம், அவை அடிப்படையான ரெண்டரிங் APIகளின் சிக்கல்களை மறைக்கின்றன. இருப்பினும், அதிகபட்ச செயல்திறனை உண்மையிலேயே வெளிக்கொணரவும், திரைக்குப் பின்னால் என்ன நடக்கிறது என்பதைப் புரிந்துகொள்ளவும், நாம் அடுக்குகளைப் பிரித்துப் பார்க்க வேண்டும். WebGL உட்பட எந்தவொரு நவீன கிராபிக்ஸ் API இன் மையத்திலும் ஒரு அடிப்படைக் கருத்து உள்ளது: அதுதான் GPU கமாண்ட் பஃபர்.
கமாண்ட் பஃபரைப் புரிந்துகொள்வது வெறும் கல்வி சார்ந்த பயிற்சி மட்டுமல்ல. செயல்திறன் சிக்கல்களைக் கண்டறிவதற்கும், மிகவும் திறமையான ரெண்டரிங் குறியீட்டை எழுதுவதற்கும், WebGPU போன்ற புதிய APIகளை நோக்கிய கட்டடக்கலை மாற்றத்தைப் புரிந்துகொள்வதற்கும் இது ஒரு திறவுகோலாகும். இந்தக் கட்டுரை உங்களை WebGL கமாண்ட் பஃபரில் ஆழமாக அழைத்துச் செல்லும், அதன் பங்கு, அதன் செயல்திறன் தாக்கங்கள் மற்றும் கமாண்ட்-மைய சிந்தனை எவ்வாறு உங்களை மிகவும் பயனுள்ள கிராபிக்ஸ் புரோகிராமராக மாற்றும் என்பதை ஆராயும்.
GPU கமாண்ட் பஃபர் என்றால் என்ன? ஒரு உயர்-நிலை கண்ணோட்டம்
அதன் மையத்தில், ஒரு GPU கமாண்ட் பஃபர் என்பது கிராபிக்ஸ் பிராசசிங் யூனிட் (GPU) செயல்படுத்துவதற்கான கட்டளைகளின் தொடர்ச்சியான பட்டியலைச் சேமிக்கும் ஒரு நினைவகப் பகுதியாகும். உங்கள் JavaScript குறியீட்டில் gl.drawArrays() அல்லது gl.clear() போன்ற ஒரு WebGL அழைப்பை நீங்கள் செய்யும்போது, GPU க்கு இப்போது ஏதாவது செய்யுமாறு நேரடியாகக் கட்டளையிடுவதில்லை. அதற்குப் பதிலாக, தொடர்புடைய கட்டளையை ஒரு பஃபரில் பதிவு செய்ய உலாவியின் கிராபிக்ஸ் இயந்திரத்திற்கு நீங்கள் அறிவுறுத்துகிறீர்கள்.
CPU (உங்கள் JavaScript ஐ இயக்குகிறது) மற்றும் GPU (கிராபிக்ஸ் ரெண்டரிங் செய்கிறது) ஆகியவற்றுக்கு இடையேயான உறவை ஒரு போர்க்களத்தில் ஒரு தளபதிக்கும் ஒரு சிப்பாய்க்கும் உள்ள உறவாகக் கருதலாம். CPU தளபதி, முழு நடவடிக்கையையும் மூலோபாயமாகத் திட்டமிடுகிறது. இது தொடர்ச்சியான ஆணைகளை எழுதுகிறது — 'இங்கே முகாம் அமை', 'இந்த டெக்ஸ்சரைக் கட்டு', 'இந்த முக்கோணங்களை வரை', 'ஆழ சோதனை செயல்படுத்த'. இந்த ஆணைகளின் பட்டியல் தான் கமாண்ட் பஃபர்.
கொடுக்கப்பட்ட ஒரு பிரேமிற்கான பட்டியல் முடிந்ததும், CPU இந்த பஃபரை GPU க்கு 'சமர்ப்பிக்கிறது'. GPU, சுறுசுறுப்பான சிப்பாய், பட்டியலை எடுத்து ஒவ்வொரு கட்டளையையும் CPU ஐச் சாராமல் ஒன்றன்பின் ஒன்றாகச் செயல்படுத்துகிறது. இந்த ஒத்திசைவற்ற கட்டமைப்பு நவீன உயர்-செயல்திறன் கிராபிக்ஸின் அடிப்படையாகும். GPU தற்போதைய பிரேமில் வேலை செய்யும் போது, அடுத்த பிரேமின் கட்டளைகளைத் தயாரிக்க CPU க்கு இது உதவுகிறது, ஒரு இணையான செயலாக்க குழாய்த்திட்டத்தை உருவாக்குகிறது.
WebGL இல், இந்த செயல்முறை பெரும்பாலும் மறைமுகமானது. நீங்கள் API அழைப்புகளைச் செய்கிறீர்கள், மேலும் உலாவி மற்றும் கிராபிக்ஸ் இயக்கி உங்களுக்காக கமாண்ட் பஃபரை உருவாக்குவதையும் சமர்ப்பிப்பதையும் நிர்வகிக்கின்றன. இது WebGPU அல்லது Vulkan போன்ற புதிய APIகளுக்கு மாறாக உள்ளது, அங்கு டெவலப்பர்கள் கமாண்ட் பஃபர்களை உருவாக்குதல், பதிவு செய்தல் மற்றும் சமர்ப்பிப்பதில் வெளிப்படையான கட்டுப்பாட்டைக் கொண்டுள்ளனர். இருப்பினும், அடிப்படைக் கோட்பாடுகள் ஒரே மாதிரியானவை, மேலும் WebGL இன் சூழலில் அவற்றைப் புரிந்துகொள்வது செயல்திறன் சரிசெய்தலுக்கு மிக முக்கியம்.
ஒரு டிராயிங் அழைப்பின் பயணம்: JavaScript இலிருந்து பிக்சல்களுக்கு
கமாண்ட் பஃபரை உண்மையிலேயே பாராட்ட, ஒரு வழக்கமான ரெண்டரிங் பிரேமின் வாழ்க்கைச் சுழற்சியைக் கண்டறிவோம். இது CPU மற்றும் GPU உலகங்களுக்கிடையேயான எல்லையை பலமுறை கடக்கும் ஒரு பல-நிலை பயணம்.
1. CPU பக்கம்: உங்கள் JavaScript குறியீடு
எல்லாம் உங்கள் JavaScript பயன்பாட்டில் தொடங்குகிறது. உங்கள் requestAnimationFrame சுழற்சிக்குள், உங்கள் காட்சியை ரெண்டர் செய்ய தொடர்ச்சியான WebGL அழைப்புகளை வெளியிடுகிறீர்கள். உதாரணமாக:
function render(time) {
// 1. Set up global state
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clearColor(0.1, 0.2, 0.3, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);
// 2. Use a specific shader program
gl.useProgram(myShaderProgram);
// 3. Bind buffers and set uniforms for an object
gl.bindVertexArray(myObjectVAO);
gl.uniformMatrix4fv(locationOfModelViewMatrix, false, modelViewMatrix);
gl.uniformMatrix4fv(locationOfProjectionMatrix, false, projectionMatrix);
// 4. Issue the draw command
const primitiveType = gl.TRIANGLES;
const offset = 0;
const count = 36; // e.g., for a cube
gl.drawArrays(primitiveType, offset, count);
requestAnimationFrame(render);
}
முக்கியமாக, இந்த அழைப்புகள் எதுவும் உடனடியாக ரெண்டரிங் செய்யத் தூண்டுவதில்லை. gl.useProgram அல்லது gl.uniformMatrix4fv போன்ற ஒவ்வொரு செயல்பாட்டு அழைப்பும், உலாவியின் உள் கமாண்ட் பஃபரில் வரிசைப்படுத்தப்படும் ஒன்று அல்லது அதற்கு மேற்பட்ட கட்டளைகளாக மாற்றப்படுகின்றன. நீங்கள் வெறுமனே பிரேமிற்கான செய்முறையை உருவாக்குகிறீர்கள்.
2. டிரைவர் பக்கம்: மொழிபெயர்ப்பு மற்றும் சரிபார்ப்பு
உலாவியின் WebGL செயலாக்கம் ஒரு இடைநிலை அடுக்காக செயல்படுகிறது. இது உங்கள் உயர்-நிலை JavaScript அழைப்புகளை எடுத்து பல முக்கியமான பணிகளைச் செய்கிறது:
- சரிபார்ப்பு: உங்கள் API அழைப்புகள் செல்லுபடியாகுமா என்று இது சரிபார்க்கிறது. ஒரு யூனிபார்மை அமைக்கும் முன் ஒரு நிரலைக் கட்டினீர்களா? பஃபர் ஆஃப்செட்கள் மற்றும் எண்ணிக்கைகள் சரியான வரம்புகளுக்குள் உள்ளதா? அதனால்தான்
"WebGL: INVALID_OPERATION: useProgram: program not valid"போன்ற கன்சோல் பிழைகள் உங்களுக்குக் கிடைக்கின்றன. இந்த சரிபார்ப்பு படிநிலை GPU ஐ தவறான கட்டளைகளிலிருந்து பாதுகாக்கிறது, அவை ஒரு செயலிழப்பு அல்லது சிஸ்டம் நிலைத்தன்மையின்மைக்கு காரணமாக இருக்கலாம். - நிலை கண்காணிப்பு: WebGL ஒரு நிலை இயந்திரம். தேவையற்ற கட்டளைகளைத் தவிர்க்க இயக்கி தற்போதைய நிலையைக் கண்காணிக்கிறது (எந்த நிரல் செயலில் உள்ளது, எந்த டெக்ஸ்சர் யூனிட் 0 உடன் பிணைக்கப்பட்டுள்ளது போன்றவை).
- மொழிபெயர்ப்பு: சரிபார்க்கப்பட்ட WebGL அழைப்புகள் அடிப்படை இயக்க முறைமையின் நேட்டிவ் கிராபிக்ஸ் API ஆக மொழிபெயர்க்கப்படுகின்றன. இது Windows இல் DirectX, macOS/iOS இல் Metal, அல்லது Linux மற்றும் Android இல் OpenGL/Vulkan ஆக இருக்கலாம். கட்டளைகள் இந்த நேட்டிவ் வடிவத்தில் டிரைவர்-நிலை கமாண்ட் பஃபரில் வரிசைப்படுத்தப்படுகின்றன.
3. GPU பக்கம்: ஒத்திசைவற்ற செயலாக்கம்
சில கட்டத்தில், பொதுவாக உங்கள் ரெண்டர் லூப்பை உருவாக்கும் JavaScript பணியின் முடிவில், உலாவி கமாண்ட் பஃபரை ஃப்ளஷ் செய்யும். அதாவது, பதிவு செய்யப்பட்ட கட்டளைகளின் முழு தொகுப்பையும் எடுத்து கிராபிக்ஸ் டிரைவருக்கு சமர்ப்பிக்கும், இது GPU ஹார்டுவேருக்கு அதைக் கையளிக்கும்.
பின்னர் GPU அதன் வரிசையிலிருந்து கட்டளைகளை எடுத்து அவற்றைச் செயல்படுத்தத் தொடங்குகிறது. அதன் அதிக இணையான கட்டமைப்பு, வெர்டெக்ஸ் ஷேடரில் வெர்டெக்ஸ்களைச் செயலாக்கவும், முக்கோணங்களை துண்டுகளாக ராஸ்டரைஸ் செய்யவும், மற்றும் மில்லியன் கணக்கான பிக்சல்களில் துண்டு ஷேடரை ஒரே நேரத்தில் இயக்கவும் அனுமதிக்கிறது. இது நடக்கும்போது, CPU ஏற்கனவே அடுத்த பிரேமிற்கான தர்க்கத்தைச் செயலாக்கத் தொடங்குகிறது - இயற்பியலைக் கணக்கிடுவது, AI ஐ இயக்குவது, மற்றும் அடுத்த கமாண்ட் பஃபரை உருவாக்குவது. இந்த இணைப்பிரிவு தான் மென்மையான, உயர்-பிரேம்-வீத ரெண்டரிங்கிற்கு அனுமதிக்கிறது.
GPU இலிருந்து தரவுகளைத் திரும்பப் பெறுதல் (எ.கா., gl.readPixels()) போன்ற இந்த இணையான தன்மையை உடைக்கும் எந்தவொரு செயலும், அதன் வேலையை முடிக்க GPU க்காக CPU காத்திருக்க கட்டாயப்படுத்துகிறது. இது ஒரு CPU-GPU ஒத்திசைவு அல்லது ஒரு பைப்பேலைன் ஸ்தம்பித்தல் என்று அழைக்கப்படுகிறது, மேலும் இது செயல்திறன் சிக்கல்களின் முக்கிய காரணமாகும்.
பஃபர் உள்ளே: நாம் என்ன கட்டளைகளைப் பற்றி பேசுகிறோம்?
ஒரு GPU கமாண்ட் பஃபர் என்பது புரிந்துகொள்ள முடியாத குறியீட்டின் ஒற்றைப் பெரிய தொகுதி அல்ல. இது பல வகைகளாகப் பிரிக்கப்படும் தனித்த செயல்பாடுகளின் கட்டமைக்கப்பட்ட தொடர்ச்சியாகும். இந்த வகைகளைப் புரிந்துகொள்வது அவற்றை எவ்வாறு உருவாக்குவதை மேம்படுத்துவது என்பதற்கான முதல் படியாகும்.
-
நிலை-அமைவு கட்டளைகள்: இந்தக் கட்டளைகள் GPU இன் நிலையான-செயல்பாட்டு பைப்பேலைன் மற்றும் புரோகிராம் செய்யக்கூடிய நிலைகளை உள்ளமைக்கின்றன. அவை எதையும் நேரடியாக வரைவதில்லை ஆனால் அடுத்தடுத்த டிராயிங் கட்டளைகள் எப்படி செயல்படுத்தப்படும் என்பதை வரையறுக்கின்றன. எடுத்துக்காட்டுகள் அடங்கும்:
gl.useProgram(program): செயலில் உள்ள வெர்டெக்ஸ் மற்றும் துண்டு ஷேடர்களை அமைக்கிறது.gl.enable() / gl.disable(): ஆழ சோதனை, பிளெண்டிங் அல்லது கல்லிங் போன்ற அம்சங்களை ஆன் அல்லது ஆஃப் செய்கிறது.gl.viewport(x, y, w, h): ரெண்டர் செய்ய வேண்டிய பிரேம்பஃபரின் பகுதியைக் குறிக்கிறது.gl.depthFunc(func): ஆழ சோதனைக்கான நிபந்தனையை அமைக்கிறது (எ.கா.,gl.LESS).gl.blendFunc(sfactor, dfactor): வெளிப்படைத்தன்மைக்காக நிறங்கள் எவ்வாறு கலக்கப்படுகின்றன என்பதை உள்ளமைக்கிறது.
-
வள பிணைப்பு கட்டளைகள்: இந்தக் கட்டளைகள் உங்கள் தரவுகளை (மெஷ்கள், டெக்ஸ்சர்கள், யூனிபார்ம்கள்) ஷேடர் நிரல்களுடன் இணைக்கின்றன. GPU க்கு அது செயலாக்கத் தேவையான தரவுகளை எங்கு கண்டறிவது என்று தெரிய வேண்டும்.
gl.bindBuffer(target, buffer): ஒரு வெர்டெக்ஸ் அல்லது இன்டெக்ஸ் பஃபரை பிணைக்கிறது.gl.bindTexture(target, texture): ஒரு டெக்ஸ்சரை செயலில் உள்ள டெக்ஸ்சர் யூனிட்டுடன் பிணைக்கிறது.gl.bindFramebuffer(target, fb): ரெண்டர் இலக்கை அமைக்கிறது.gl.uniform*(): யூனிபார்ம் தரவுகளை (மேட்ரிக்ஸ்கள் அல்லது நிறங்கள் போன்றவை) தற்போதைய ஷேடர் நிரலுக்குப் பதிவேற்றுகிறது.gl.vertexAttribPointer(): ஒரு பஃபர் உள்ள வெர்டெக்ஸ் தரவின் அமைப்பை வரையறுக்கிறது. (அடிக்கடி ஒரு வெர்டெக்ஸ் அரே ஆப்ஜெக்ட், அல்லது VAO இல் சுற்றப்பட்டுள்ளது).
-
டிராயிங் கட்டளைகள்: இவை தான் செயல்பாட்டுக் கட்டளைகள். அவைதான் GPU ஐ ரெண்டரிங் பைப்பேலைனைத் தொடங்க தூண்டுகின்றன, தற்போது பிணைக்கப்பட்ட நிலை மற்றும் வளங்களைப் பயன்படுத்தி பிக்சல்களை உருவாக்குகின்றன.
gl.drawArrays(mode, first, count): அணி தரவிலிருந்து முதன்மை வடிவங்களை ரெண்டர் செய்கிறது.gl.drawElements(mode, count, type, offset): ஒரு இன்டெக்ஸ் பஃபரைப் பயன்படுத்தி முதன்மை வடிவங்களை ரெண்டர் செய்கிறது.gl.drawArraysInstanced() / gl.drawElementsInstanced(): ஒரே கட்டளையுடன் ஒரே புவியியலின் பல பிரதிகளை ரெண்டர் செய்கிறது.
-
தெளிவாக்கும் கட்டளைகள்: பிரேம்பஃபரின் நிறம், ஆழம் அல்லது ஸ்டென்சில் பஃபர்களைத் தெளிவாக்கப் பயன்படுத்தப்படும் ஒரு சிறப்பு வகைக் கட்டளை, பொதுவாக ஒரு பிரேமின் தொடக்கத்தில்.
gl.clear(mask): தற்போது பிணைக்கப்பட்ட பிரேம்பஃபரைத் தெளிவாக்குகிறது.
கமாண்ட் வரிசையின் முக்கியத்துவம்
GPU இந்த கட்டளைகளை பஃபரில் தோன்றும் வரிசையில் செயல்படுத்துகிறது. இந்த தொடர்ச்சியான சார்புத்தன்மை மிக முக்கியமானது. தேவையான நிலையை முதலில் அமைக்காமல் gl.drawArrays கட்டளையை வெளியிட்டால் அது சரியாக வேலை செய்யும் என்று எதிர்பார்க்க முடியாது. சரியான வரிசை எப்போதும்: நிலையை அமை -> வளங்களை பிணை -> வரை. அதன் யூனிபார்ம்களை அமைக்கும் அல்லது அதைக் கொண்டு வரையும் முன் gl.useProgram ஐ அழைக்க மறந்துவிடுவது ஆரம்பநிலையாளர்களுக்கு ஒரு பொதுவான பிழை. மன மாதிரி இப்படி இருக்க வேண்டும்: 'நான் GPU இன் சூழலைத் தயார் செய்கிறேன், பின்னர் அந்த சூழலில் ஒரு செயலைச் செய்யச் சொல்கிறேன்'.
கமாண்ட் பஃபருக்காக மேம்படுத்துதல்: நல்லதிலிருந்து சிறந்ததற்கு
இப்போது நமது விவாதத்தின் மிகவும் நடைமுறைப் பகுதிக்கு வந்துவிட்டோம். செயல்திறன் என்பது GPU க்கான கட்டளைகளின் திறமையான பட்டியலை உருவாக்குவதைப் பற்றி இருந்தால், நாம் அதை எப்படி செய்வது? அடிப்படைக் கொள்கை எளிது: GPU இன் வேலையை எளிதாக்குங்கள். அதாவது, குறைவான, அதிக அர்த்தமுள்ள கட்டளைகளை அனுப்புவது மற்றும் அதை நிறுத்தி காத்திருக்க வைக்கும் பணிகளைத் தவிர்ப்பது.
1. நிலை மாற்றங்களைக் குறைத்தல்
சிக்கல்: ஒவ்வொரு நிலை-அமைவு கட்டளையும் (gl.useProgram, gl.bindTexture, gl.enable) கமாண்ட் பஃபரில் ஒரு அறிவுறுத்தலாகும். சில நிலை மாற்றங்கள் மலிவானவை என்றாலும், மற்றவை விலை உயர்ந்ததாக இருக்கலாம். ஒரு ஷேடர் நிரலை மாற்றுவது, உதாரணமாக, GPU அதன் உள் பைப்பேலைன்களை ஃப்ளஷ் செய்து புதிய அறிவுறுத்தல்களை ஏற்ற வேண்டியிருக்கும். டிராயிங் அழைப்புகளுக்கு இடையில் தொடர்ந்து நிலைகளை மாற்றுவது ஒரு தொழிற்சாலை தொழிலாளியை அவர்கள் உற்பத்தி செய்யும் ஒவ்வொரு பொருளுக்கும் தங்கள் இயந்திரத்தை மீண்டும் கருவி செய்யச் சொல்வது போன்றது - இது நம்பமுடியாத அளவிற்கு திறமையற்றது.
தீர்வு: ரெண்டர் வரிசையாக்கம் (அல்லது நிலை அடிப்படையில் தொகுதிப்படுத்துதல்)
இங்கு மிகவும் சக்திவாய்ந்த மேம்படுத்துதல் நுட்பம் உங்கள் டிராயிங் அழைப்புகளை அவற்றின் நிலையின் அடிப்படையில் குழுவாக்குவதாகும். உங்கள் காட்சியை தோன்றும் வரிசையில் பொருள் வாரியாக ரெண்டர் செய்வதற்குப் பதிலாக, ஒரே பொருளை (ஷேடர், டெக்ஸ்சர்கள், பிளெண்ட் நிலை) பகிரும் அனைத்து பொருட்களையும் ஒன்றாக ரெண்டர் செய்ய உங்கள் ரெண்டர் சுழற்சியை மறுசீரமைக்கிறீர்கள்.
இரண்டு ஷேடர்கள் (ஷேடர் A மற்றும் ஷேடர் B) மற்றும் நான்கு பொருட்கள் கொண்ட ஒரு காட்சியைக் கவனியுங்கள்:
திறமையற்ற அணுகுமுறை (பொருள் வாரியாக):
- ஷேடர் A ஐப் பயன்படுத்து
- பொருள் 1 க்கான வளங்களை பிணை
- பொருள் 1 ஐ வரை
- ஷேடர் B ஐப் பயன்படுத்து
- பொருள் 2 க்கான வளங்களை பிணை
- பொருள் 2 ஐ வரை
- ஷேடர் A ஐப் பயன்படுத்து
- பொருள் 3 க்கான வளங்களை பிணை
- பொருள் 3 ஐ வரை
- ஷேடர் B ஐப் பயன்படுத்து
- பொருள் 4 க்கான வளங்களை பிணை
- பொருள் 4 ஐ வரை
இது 4 ஷேடர் மாற்றங்களுக்கு வழிவகுக்கிறது (useProgram அழைப்புகள்).
திறமையான அணுகுமுறை (ஷேடரால் வரிசைப்படுத்தப்பட்டது):
- ஷேடர் A ஐப் பயன்படுத்து
- பொருள் 1 க்கான வளங்களை பிணை
- பொருள் 1 ஐ வரை
- பொருள் 3 க்கான வளங்களை பிணை
- பொருள் 3 ஐ வரை
- ஷேடர் B ஐப் பயன்படுத்து
- பொருள் 2 க்கான வளங்களை பிணை
- பொருள் 2 ஐ வரை
- பொருள் 4 க்கான வளங்களை பிணை
- பொருள் 4 ஐ வரை
இது வெறும் 2 ஷேடர் மாற்றங்களுக்கு வழிவகுக்கிறது. அதே தர்க்கம் டெக்ஸ்சர்கள், பிளெண்ட் முறைகள் மற்றும் பிற நிலைகளுக்கும் பொருந்தும். உயர்-செயல்திறன் ரெண்டரர்கள் பெரும்பாலும் பல-நிலை வரிசையாக்க விசையைப் பயன்படுத்துகின்றன (எ.கா., வெளிப்படைத்தன்மையால் வரிசைப்படுத்துதல், பின்னர் ஷேடரால், பின்னர் டெக்ஸ்சரால்) நிலை மாற்றங்களை முடிந்தவரை குறைக்க.
2. டிராயிங் அழைப்புகளைக் குறைத்தல் (புவியியல் அடிப்படையில் தொகுதிப்படுத்துதல்)
சிக்கல்: ஒவ்வொரு டிராயிங் அழைப்பும் (gl.drawArrays, gl.drawElements) ஒரு குறிப்பிட்ட அளவு CPU ஓவர்ஹெட்டைக் கொண்டுள்ளது. உலாவி அழைப்பைச் சரிபார்க்க வேண்டும், பதிவு செய்ய வேண்டும், மற்றும் இயக்கி அதைச் செயலாக்க வேண்டும். சிறிய பொருட்களுக்காக ஆயிரக்கணக்கான டிராயிங் அழைப்புகளை வெளியிடுவது CPU ஐ விரைவாக மூழ்கடித்து, கட்டளைகளுக்காக GPU காத்திருக்கச் செய்யும். இது CPU-bound என்று அழைக்கப்படுகிறது.
தீர்வு:
- நிலையான தொகுதிப்படுத்துதல்: உங்கள் காட்சியில் ஒரே பொருளை (எ.கா., ஒரு காட்டில் மரங்கள், ஒரு இயந்திரத்தில் ஆணிகள்) பகிரும் பல சிறிய, நிலையான பொருட்கள் இருந்தால், ரெண்டரிங் தொடங்குவதற்கு முன் அவற்றின் புவியியலை ஒரு பெரிய வெர்டெக்ஸ் பஃபர் ஆப்ஜெக்ட் (VBO) ஆக இணைக்கவும். 1000 மரங்களை 1000 டிராயிங் அழைப்புகளுடன் வரைவதற்குப் பதிலாக, ஒரு பெரிய 1000 மரங்களின் மெஷை ஒரு டிராயிங் அழைப்புடன் வரைகிறீர்கள். இது CPU ஓவர்ஹெட்டை வியத்தகு முறையில் குறைக்கிறது.
- இன்ஸ்டன்சிங்: இது ஒரே மெஷின் பல பிரதிகளை வரைய முதன்மையான நுட்பமாகும்.
gl.drawElementsInstancedஉடன், நீங்கள் மெஷின் புவியியலின் ஒரு பிரதியையும், ஒரு-நிகழ்வு தரவுகளை (நிலை, சுழற்சி, நிறம் போன்றவை) கொண்ட ஒரு தனி பஃபரையும் வழங்குகிறீர்கள். பின்னர் நீங்கள் ஒரு ஒற்றை டிராயிங் அழைப்பை வெளியிடுகிறீர்கள், அது GPU க்கு சொல்கிறது: "இந்த மெஷை N முறை வரை, மற்றும் ஒவ்வொரு பிரதிக்கும், நிகழ்வு பஃபரிலிருந்து தொடர்புடைய தரவைப் பயன்படுத்து." இது துகள் அமைப்புகள், கூட்டங்கள் அல்லது இலைக்காடுகளை ரெண்டரிங் செய்ய ஏற்றது.
3. பஃபர் ஃப்ளஷ்களைப் புரிந்துகொள்வது மற்றும் தவிர்ப்பது
சிக்கல்: குறிப்பிட்டது போல, CPU மற்றும் GPU இணையான முறையில் வேலை செய்கின்றன. CPU கமாண்ட் பஃபரை நிரப்புகிறது, அதே நேரத்தில் GPU அதை வடிகட்டுகிறது. இருப்பினும், சில WebGL செயல்பாடுகள் இந்த இணையான தன்மையை உடைக்கின்றன. gl.readPixels() அல்லது gl.finish() போன்ற செயல்பாடுகள் GPU இலிருந்து ஒரு முடிவைக் கோருகின்றன. இந்த முடிவை வழங்க, GPU அதன் வரிசையில் உள்ள அனைத்து நிலுவையிலுள்ள கட்டளைகளையும் முடிக்க வேண்டும். கோரிக்கை விடுத்த CPU, பின்னர் GPU ஐப் பிடித்துக்கொண்டு தரவை வழங்குவதற்காக காத்திருக்க வேண்டும். இந்த பைப்பேலைன் ஸ்தம்பித்தல் உங்கள் பிரேம் வீதத்தை அழிக்கக்கூடும்.
தீர்வு: ஒத்திசைவான செயல்பாடுகளைத் தவிர்க்கவும்
- உங்கள் முக்கிய ரெண்டர் சுழற்சிக்குள்
gl.readPixels(),gl.getParameter(), அல்லதுgl.checkFramebufferStatus()ஐ ஒருபோதும் பயன்படுத்த வேண்டாம். இவை சக்திவாய்ந்த பிழைத்திருத்த கருவிகள், ஆனால் அவை செயல்திறன் கொலையாளிகள். - GPU இலிருந்து தரவுகளை மீண்டும் படிக்க உங்களுக்கு முற்றிலும் தேவைப்பட்டால் (எ.கா., GPU அடிப்படையிலான தேர்வு அல்லது கணக்கீட்டு பணிகளுக்கு), பிக்சல் பஃபர் ஆப்ஜெக்ட்கள் (PBOs) அல்லது WebGL 2 இன் சின்க் ஆப்ஜெக்ட்கள் போன்ற ஒத்திசைவற்ற வழிமுறைகளைப் பயன்படுத்தவும், அவை தரவு பரிமாற்றத்தைத் உடனடியாக முடிக்கக் காத்திருக்காமல் தொடங்க அனுமதிக்கின்றன.
4. திறமையான தரவு பதிவேற்றம் மற்றும் மேலாண்மை
சிக்கல்: gl.bufferData() அல்லது gl.texImage2D() உடன் GPU க்கு தரவுகளைப் பதிவேற்றுவதும் ஒரு கட்டளை தான். ஒவ்வொரு பிரேமிலும் CPU இலிருந்து GPU க்கு அதிக அளவு தரவுகளை அனுப்புவது அவற்றுக்கிடையேயான தகவல்தொடர்பு பஸ்ஸை (பொதுவாக PCIe) நிறைவுறச் செய்யலாம்.
தீர்வு: உங்கள் தரவு பரிமாற்றங்களைத் திட்டமிடுங்கள்
- நிலையான தரவு: ஒருபோதும் மாறாத தரவுகளுக்கு (எ.கா., நிலையான மாதிரி புவியியல்), அதைத் தொடக்கத்தில்
gl.STATIC_DRAWஐப் பயன்படுத்தி ஒருமுறை பதிவேற்றி GPU இல் விடவும். - மாறும் தரவு: ஒவ்வொரு பிரேமிலும் மாறும் தரவுகளுக்கு (எ.கா., துகள் நிலைகள்), பஃபரை ஒருமுறை
gl.bufferDataமற்றும் ஒருgl.DYNAMIC_DRAWஅல்லதுgl.STREAM_DRAWகுறிப்புடன் ஒதுக்கவும். பின்னர், உங்கள் ரெண்டர் சுழற்சியில்,gl.bufferSubDataஉடன் அதன் உள்ளடக்கத்தைப் புதுப்பிக்கவும். இது ஒவ்வொரு பிரேமிலும் GPU நினைவகத்தை மீண்டும் ஒதுக்கும் ஓவர்ஹெட்டைத் தவிர்க்கிறது.
எதிர்காலம் வெளிப்படையானது: WebGL இன் கமாண்ட் பஃபர் vs. WebGPU இன் கமாண்ட் என்கோடர்
WebGL இல் உள்ள மறைமுக கமாண்ட் பஃபரைப் புரிந்துகொள்வது வலை கிராபிக்ஸின் அடுத்த தலைமுறையைப் பாராட்ட சரியான அடித்தளத்தை வழங்குகிறது: WebGPU.
WebGL கமாண்ட் பஃபரை உங்களிடமிருந்து மறைத்தாலும், WebGPU அதை API இன் முதல்-தர குடிமகனாக வெளிப்படுத்துகிறது. இது டெவலப்பர்களுக்கு ஒரு புரட்சிகரமான கட்டுப்பாட்டு நிலை மற்றும் செயல்திறன் திறனை வழங்குகிறது.
WebGL: மறைமுக மாதிரி
WebGL இல், கமாண்ட் பஃபர் ஒரு கருப்பு பெட்டி. நீங்கள் செயல்பாடுகளை அழைக்கிறீர்கள், உலாவி அவற்றை திறமையாக பதிவு செய்ய சிறந்ததைச் செய்கிறது. WebGL சூழல் அதனுடன் பிணைக்கப்பட்டுள்ளதால், இந்த வேலை அனைத்தும் முக்கிய த்ரெடில் நடக்க வேண்டும். இது சிக்கலான பயன்பாடுகளில் ஒரு சிக்கலாக மாறக்கூடும், ஏனெனில் அனைத்து ரெண்டரிங் தர்க்கமும் UI புதுப்பிப்புகள், பயனர் உள்ளீடு மற்றும் பிற JavaScript பணிகளுடன் போட்டியிடுகிறது.
WebGPU: வெளிப்படையான மாதிரி
WebGPU இல், செயல்முறை வெளிப்படையானது மற்றும் மிகவும் சக்தி வாய்ந்தது:
- நீங்கள் ஒரு
GPUCommandEncoderபொருளை உருவாக்குகிறீர்கள். இது உங்கள் தனிப்பட்ட கமாண்ட் ரெக்கார்டர். - நீங்கள் ஒரு 'பாஸ்' (எ.கா., ஒரு
GPURenderPassEncoder) தொடங்குகிறீர்கள், இது ரெண்டர் இலக்குகளையும் தெளிவான மதிப்புகளையும் அமைக்கிறது. - பாஸ் உள்ளே, நீங்கள்
setPipeline(),setVertexBuffer(), மற்றும்draw()போன்ற கட்டளைகளைப் பதிவு செய்கிறீர்கள். இது WebGL அழைப்புகளைச் செய்வது போலவே உணர்கிறது. - நீங்கள் என்கோடரில்
.finish()ஐ அழைக்கிறீர்கள், இது ஒரு முழுமையான, தெளிவற்றGPUCommandBufferபொருளைத் தருகிறது. - கடைசியாக, இந்த கமாண்ட் பஃபர்களின் ஒரு அணியை சாதனத்தின் வரிசைக்கு சமர்ப்பிக்கிறீர்கள்:
device.queue.submit([commandBuffer]).
இந்த வெளிப்படையான கட்டுப்பாடு பல விளையாட்டு மாற்றும் நன்மைகளைத் திறக்கிறது:
- பல-திரெடட் ரெண்டரிங்: கமாண்ட் பஃபர்கள் சமர்ப்பிப்பதற்கு முன் வெறும் தரவுப் பொருட்களாக இருப்பதால், அவை தனித்தனி வலைப் பணியாளர்களில் உருவாக்கப்பட்டு பதிவு செய்யப்படலாம். உங்கள் காட்சியில் வெவ்வேறு பகுதிகளை (எ.கா., நிழல்களுக்கு ஒன்று, ஒளிபுகா பொருட்களுக்கு ஒன்று, UI க்கு ஒன்று) இணையான முறையில் பல பணியாளர்கள் தயாரிக்கலாம். இது முக்கிய-திரெட் சுமையை வியத்தகு முறையில் குறைக்கலாம், இது மிகவும் மென்மையான பயனர் அனுபவத்திற்கு வழிவகுக்கும்.
- மறுபயன்பாடு: உங்கள் காட்சியில் ஒரு நிலையான பகுதிக்காக (அல்லது ஒரு ஒற்றைப் பொருளுக்காகவும்) ஒரு கமாண்ட் பஃபரை முன்-பதிவு செய்யலாம், பின்னர் கட்டளைகளை மீண்டும் பதிவு செய்யாமல் ஒவ்வொரு பிரேமிலும் அதே பஃபரை மீண்டும் சமர்ப்பிக்கலாம். இது WebGPU இல் ஒரு ரெண்டர் பண்டில் என்று அழைக்கப்படுகிறது, மேலும் நிலையான புவியியலுக்கு நம்பமுடியாத அளவிற்கு திறமையானது.
- குறைக்கப்பட்ட ஓவர்ஹெட்: பெரும்பாலான சரிபார்ப்பு வேலை பணியாளர் திரெட்களில் பதிவு செய்யும் கட்டத்தில் செய்யப்படுகிறது. முக்கிய திரெடில் இறுதி சமர்ப்பிப்பு மிகவும் லேசான செயல்பாடு ஆகும், இது ஒவ்வொரு பிரேமிற்கும் மிகவும் கணிக்கக்கூடிய மற்றும் குறைந்த CPU ஓவர்ஹெட்டை வழிவகுக்கிறது.
WebGL இல் உள்ள மறைமுக கமாண்ட் பஃபரைப் பற்றி சிந்திக்கக் கற்றுக்கொள்வதன் மூலம், WebGPU இன் வெளிப்படையான, பல-திரெடட் மற்றும் உயர்-செயல்திறன் உலகிற்கு நீங்கள் உங்களைச் சிறப்பாகத் தயார்படுத்துகிறீர்கள்.
முடிவுரை: கட்டளைகளில் சிந்திப்பது
GPU கமாண்ட் பஃபர் WebGL இன் கண்ணுக்குத் தெரியாத முதுகெலும்பாகும். நீங்கள் அதை நேரடியாக ஒருபோதும் தொடர்பு கொள்ளாவிட்டாலும், நீங்கள் எடுக்கும் ஒவ்வொரு செயல்திறன் முடிவும் இறுதியில் GPU க்கான இந்த அறிவுறுத்தல்கள் பட்டியலை எவ்வளவு திறமையாக உருவாக்குகிறீர்கள் என்பதில்தான் வந்து சேர்கிறது.
முக்கிய குறிப்புகளை மீண்டும் பார்ப்போம்:
- WebGL API அழைப்புகள் உடனடியாக செயல்படுத்துவதில்லை; அவை கட்டளைகளை ஒரு பஃபரில் பதிவு செய்கின்றன.
- CPU மற்றும் GPU இணையான முறையில் வேலை செய்ய வடிவமைக்கப்பட்டுள்ளன. ஒன்று மற்றொன்றுக்குக் காத்திருக்கச் செய்யாமல் இரண்டையும் பரபரப்பாக வைத்திருப்பதே உங்கள் குறிக்கோள்.
- செயல்திறன் மேம்படுத்துதல் என்பது ஒரு மெலிந்த மற்றும் திறமையான கமாண்ட் பஃபரை உருவாக்கும் கலையாகும்.
- ரெண்டர் வரிசையாக்கம் மூலம் நிலை மாற்றங்களைக் குறைத்தல் மற்றும் புவியியல் தொகுதிப்படுத்துதல் மற்றும் இன்ஸ்டன்சிங் மூலம் டிராயிங் அழைப்புகளைக் குறைத்தல் ஆகியவை மிகவும் தாக்கம் கொண்ட உத்திகளாகும்.
- WebGL இல் உள்ள இந்த மறைமுக மாதிரியைப் புரிந்துகொள்வது WebGPU போன்ற நவீன APIகளின் வெளிப்படையான, மிகவும் சக்திவாய்ந்த கமாண்ட் பஃபர் கட்டமைப்பை மாஸ்டர் செய்வதற்கான நுழைவாயில் ஆகும்.
அடுத்த முறை நீங்கள் ரெண்டரிங் குறியீட்டை எழுதும்போது, உங்கள் மன மாதிரியை மாற்ற முயற்சிக்கவும். "நான் ஒரு மெஷை வரைய ஒரு செயல்பாட்டை அழைக்கிறேன்" என்று மட்டும் நினைக்காதீர்கள். அதற்குப் பதிலாக, "நான் தொடர்ச்சியான நிலை, வள, மற்றும் டிராயிங் கட்டளைகளை GPU இறுதியாக செயல்படுத்தும் ஒரு பட்டியலில் சேர்க்கிறேன்" என்று சிந்தியுங்கள். இந்த கமாண்ட்-மைய பார்வை ஒரு மேம்பட்ட கிராபிக்ஸ் புரோகிராமரின் அடையாளம் மற்றும் உங்கள் விரல் நுனியில் உள்ள வன்பொருளின் முழு திறனைத் திறப்பதற்கான திறவுகோலாகும்.