GlDriver.hx 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195
  1. package h3d.impl;
  2. import h3d.impl.Driver;
  3. import h3d.mat.Pass;
  4. import h3d.mat.Stencil;
  5. import h3d.mat.Data;
  6. #if (js||hlsdl||usegl)
  7. #if js
  8. import hxd.impl.TypedArray;
  9. private typedef GL = js.html.webgl.GL2;
  10. private typedef Uniform = js.html.webgl.UniformLocation;
  11. private typedef Program = js.html.webgl.Program;
  12. private typedef GLShader = js.html.webgl.Shader;
  13. private typedef Framebuffer = js.html.webgl.Framebuffer;
  14. #elseif hlsdl
  15. import sdl.GL;
  16. private typedef Uniform = sdl.GL.Uniform;
  17. private typedef Program = sdl.GL.Program;
  18. private typedef GLShader = sdl.GL.Shader;
  19. private typedef Framebuffer = sdl.GL.Framebuffer;
  20. private typedef Texture = h3d.impl.Driver.Texture;
  21. private typedef Query = h3d.impl.Driver.Query;
  22. private typedef VertexArray = sdl.GL.VertexArray;
  23. #elseif usegl
  24. import haxe.GLTypes;
  25. private typedef Uniform = haxe.GLTypes.Uniform;
  26. private typedef Program = haxe.GLTypes.Program;
  27. private typedef GLShader = haxe.GLTypes.Shader;
  28. private typedef Framebuffer = haxe.GLTypes.Framebuffer;
  29. private typedef Texture = h3d.impl.Driver.Texture;
  30. private typedef Query = h3d.impl.Driver.Query;
  31. private typedef VertexArray = haxe.GLTypes.VertexArray;
  32. #end
  33. #if usegl
  34. private typedef ShaderCompiler = haxe.GLTypes.ShaderCompiler;
  35. #else
  36. private typedef ShaderCompiler = hxsl.GlslOut;
  37. #end
  38. private class CompiledShader {
  39. public var s : GLShader;
  40. public var kind : hxsl.Ast.FunctionKind;
  41. public var globals : Uniform;
  42. public var params : Uniform;
  43. public var textures : Array<{ u : Uniform, t : hxsl.Ast.Type, mode : Int }>;
  44. public var buffers : Array<Int>;
  45. public var bufferTypes : Array<hxsl.Ast.BufferKind>;
  46. public var shader : hxsl.RuntimeShader.RuntimeShaderData;
  47. public function new(s,kind,shader) {
  48. this.s = s;
  49. this.kind = kind;
  50. this.shader = shader;
  51. }
  52. }
  53. private class CompiledAttribute {
  54. public var index : Int;
  55. public var type : Int;
  56. public var size : Int;
  57. public var divisor : Int;
  58. public function new() {
  59. }
  60. }
  61. private class CompiledProgram {
  62. public var p : Program;
  63. public var vertex : CompiledShader;
  64. public var fragment : CompiledShader;
  65. public var format : hxd.BufferFormat;
  66. public var attribs : Array<CompiledAttribute>;
  67. public var hasAttribIndex : Int;
  68. public function new() {
  69. }
  70. }
  71. @:access(h3d.impl.Shader)
  72. #if (hlsdl||usegl)
  73. @:build(h3d.impl.MacroHelper.replaceGL())
  74. #end
  75. class GlDriver extends Driver {
  76. #if js
  77. var canvas : js.html.CanvasElement;
  78. var mrtExt : { function drawBuffersWEBGL( colors : Array<Int> ) : Void; };
  79. static var UID = 0;
  80. public var gl : GL;
  81. public static var ALLOW_WEBGL2 = true;
  82. #end
  83. #if (hlsdl||usegl)
  84. var commonVA : VertexArray;
  85. #end
  86. var commonFB : Framebuffer;
  87. var curAttribs : Array<Bool> = new Array<Bool>();
  88. var maxIdxCurAttribs : Int = 0;
  89. var curShader : CompiledProgram;
  90. var curBuffer : h3d.Buffer;
  91. var curIndexBuffer : h3d.Buffer;
  92. var curMatBits : Int = -1;
  93. var curStOpBits : Int = -1;
  94. var curStMaskBits : Int = -1;
  95. var curStEnabled : Bool = false;
  96. var defStencil : Stencil;
  97. var programs : Map<Int, CompiledProgram>;
  98. var frame : Int;
  99. var lastActiveIndex : Int = 0;
  100. var curColorMask = -1;
  101. var currentDivisor : Array<Int> = [for( i in 0...32 ) 0];
  102. var useDepthClamp = false;
  103. var bufferWidth : Int;
  104. var bufferHeight : Int;
  105. var curTarget : h3d.mat.Texture;
  106. var curTargets : Array<h3d.mat.Texture> = [];
  107. var numTargets : Int;
  108. var curTargetLayer : Int;
  109. var curTargetMip : Int;
  110. var debug : Bool;
  111. var glDebug : Bool;
  112. var boundTextures : Array<Texture> = [];
  113. var glES : Null<Float>;
  114. var shaderVersion : Null<Int>;
  115. var firstShader = true;
  116. var rightHanded = false;
  117. var hasMultiIndirect = false;
  118. var maxCompressedTexturesSupport = 0;
  119. public static var hasMultiIndirectCount = false;
  120. var drawMode : Int;
  121. var isIntelGpu : Bool;
  122. static var BLACK = new h3d.Vector4(0,0,0,0);
  123. /**
  124. Perform OUT_OF_MEMORY checks when allocating textures/buffers.
  125. Default true, except in WebGL (false)
  126. **/
  127. public static var outOfMemoryCheck = #if js false #else true #end;
  128. public function new(antiAlias=0) {
  129. #if (hlsdl >= version("1.15.0"))
  130. if ( computeEnabled )
  131. sdl.Sdl.setGLVersion(4, 3);
  132. #end
  133. #if js
  134. canvas = @:privateAccess hxd.Window.getInstance().canvas;
  135. var options = {alpha:false,stencil:true,antialias:antiAlias>0};
  136. if(ALLOW_WEBGL2)
  137. gl = cast canvas.getContext("webgl2",options);
  138. if( gl == null )
  139. gl = cast canvas.getContextWebGL(options);
  140. if( gl == null ) throw "Could not acquire GL context";
  141. // debug if webgl_debug.js is included
  142. if( js.Syntax.typeof(untyped WebGLDebugUtils) != "undefined" ) {
  143. gl = untyped WebGLDebugUtils.makeDebugContext(gl);
  144. glDebug = true;
  145. }
  146. #if multidriver
  147. canvas.setAttribute("class", canvas.getAttribute("class") + " _id_" + (UID++));
  148. #end
  149. #end
  150. commonFB = gl.createFramebuffer();
  151. programs = new Map();
  152. defStencil = new Stencil();
  153. frame = hxd.Timer.frameCount;
  154. #if hlsdl
  155. hasMultiIndirect = gl.getConfigParameter(0) > 0;
  156. maxCompressedTexturesSupport = 7;
  157. var driver = getDriverName(false).toLowerCase();
  158. isIntelGpu = ~/intel.*graphics/.match(driver);
  159. #end
  160. #if (hlsdl >= version("1.15.0"))
  161. hasMultiIndirectCount = gl.hasExtension("GL_ARB_indirect_parameters");
  162. #end
  163. #if hlmesa
  164. hasMultiIndirect = true;
  165. maxCompressedTexturesSupport = 7;
  166. #end
  167. var v : String = gl.getParameter(GL.VERSION);
  168. var reg = ~/ES ([0-9]+\.[0-9]+)/;
  169. if( reg.match(v) )
  170. glES = Std.parseFloat(reg.matched(1));
  171. #if !js
  172. if( glES == null ) {
  173. commonVA = gl.createVertexArray();
  174. gl.bindVertexArray( commonVA );
  175. }
  176. #end
  177. var reg = ~/[0-9]+\.[0-9]+/;
  178. var v : String = gl.getParameter(GL.SHADING_LANGUAGE_VERSION);
  179. if( reg.match(v) ) {
  180. #if js
  181. glES = Std.parseFloat(reg.matched(0));
  182. #end
  183. shaderVersion = Math.round( Std.parseFloat(reg.matched(0)) * 100 );
  184. }
  185. #if (hlsdl >= version("1.15.0"))
  186. if ( computeEnabled )
  187. shaderVersion = 430;
  188. #end
  189. drawMode = GL.TRIANGLES;
  190. #if js
  191. // make sure to enable extensions
  192. makeFeatures();
  193. // We need to get instanced rendering by it's ANGLE extension if we are using webgl1
  194. if(hasFeature(InstancedRendering) && glES < 3) {
  195. var extension:js.html.webgl.extension.ANGLEInstancedArrays = cast gl.getExtension("ANGLE_instanced_arrays");
  196. Reflect.setField(gl,"vertexAttribDivisor",extension.vertexAttribDivisorANGLE);
  197. Reflect.setField(gl,"drawElementsInstanced",extension.drawElementsInstancedANGLE);
  198. }
  199. // setup shader optim
  200. hxsl.SharedShader.UNROLL_LOOPS = !hasFeature(ShaderModel3);
  201. #else
  202. gl.enable(GL.TEXTURE_CUBE_MAP_SEAMLESS);
  203. gl.finish(); // prevent glError() on first bufferData
  204. #end
  205. gl.pixelStorei(GL.PACK_ALIGNMENT, 1);
  206. gl.pixelStorei(GL.UNPACK_ALIGNMENT, 1);
  207. }
  208. #if hlsdl
  209. static var computeEnabled : Bool = false;
  210. public static function enableComputeShaders() {
  211. #if (hlsdl >= version("1.15.0"))
  212. computeEnabled = true;
  213. #else
  214. throw "enableComputeShaders() requires hlsdl 1.15+";
  215. #end
  216. }
  217. #end
  218. override function setRenderFlag( r : RenderFlag, value : Int ) {
  219. switch( r ) {
  220. case CameraHandness:
  221. rightHanded = value > 0;
  222. default:
  223. }
  224. }
  225. override function logImpl( str : String ) {
  226. #if js
  227. untyped console.log(str);
  228. #else
  229. Sys.println(str);
  230. #end
  231. }
  232. override function setDebug(d) {
  233. this.debug = d;
  234. }
  235. override function begin(frame) {
  236. this.frame = frame;
  237. resetStream();
  238. gl.useProgram(null);
  239. curShader = null;
  240. curBuffer = null;
  241. }
  242. function makeCompiler() {
  243. var glout = new ShaderCompiler();
  244. glout.glES = glES;
  245. glout.version = shaderVersion;
  246. #if !usegl
  247. @:privateAccess glout.intelDriverFix = isIntelGpu;
  248. #end
  249. return glout;
  250. }
  251. override function getNativeShaderCode( shader : hxsl.RuntimeShader ) {
  252. inline function compile(sh) {
  253. return makeCompiler().run(sh);
  254. }
  255. if( shader.mode == Compute )
  256. return compile(shader.compute.data);
  257. return "// vertex:\n" + compile(shader.vertex.data) + "// fragment:\n" + compile(shader.fragment.data);
  258. }
  259. override public function getDriverName(details:Bool) {
  260. var render = gl.getParameter(GL.RENDERER);
  261. if( details )
  262. render += " GLv" + gl.getParameter(GL.VERSION);
  263. else
  264. render = render.split("/").shift(); // GeForce reports "/PCIe/SSE2" extension
  265. #if js
  266. render = render.split("WebGL ").join("");
  267. #end
  268. return "OpenGL "+render;
  269. }
  270. function compileShader( glout : ShaderCompiler, shader : hxsl.RuntimeShader.RuntimeShaderData ) {
  271. var type = switch( shader.kind ) {
  272. case Vertex: GL.VERTEX_SHADER;
  273. case Fragment: GL.FRAGMENT_SHADER;
  274. #if js
  275. case Main: throw "Compute shader is not supported";
  276. #else
  277. case Main: GL.COMPUTE_SHADER;
  278. #end
  279. default: throw "assert";
  280. };
  281. var s = gl.createShader(type);
  282. if( shader.code == null ){
  283. shader.code = glout.run(shader.data);
  284. #if !heaps_compact_mem
  285. shader.data.funs = null;
  286. #end
  287. }
  288. gl.shaderSource(s, shader.code);
  289. gl.compileShader(s);
  290. if ( gl.getShaderParameter(s, GL.COMPILE_STATUS) != cast 1 ) {
  291. var log = gl.getShaderInfoLog(s);
  292. var lid = Std.parseInt(log.substr(9));
  293. var line = lid == null ? null : shader.code.split("\n")[lid - 1];
  294. if( line == null ) line = "" else line = "(" + StringTools.trim(line) + ")";
  295. var codeLines = shader.code.split("\n");
  296. for( i in 0...codeLines.length )
  297. codeLines[i] = (i+1) + "\t" + codeLines[i];
  298. throw "An error occurred compiling the shaders: " + log + line+"\n\n"+codeLines.join("\n");
  299. }
  300. return new CompiledShader(s, shader.kind, shader);
  301. }
  302. function initShader( p : CompiledProgram, s : CompiledShader, shader : hxsl.RuntimeShader.RuntimeShaderData, rt : hxsl.RuntimeShader ) {
  303. var prefix = switch( s.kind ) {
  304. case Vertex: "vertex";
  305. case Fragment: "fragment";
  306. default: "compute";
  307. }
  308. s.globals = gl.getUniformLocation(p.p, prefix + "Globals");
  309. s.params = gl.getUniformLocation(p.p, prefix + "Params");
  310. s.textures = [];
  311. var index = 0;
  312. var curT = null;
  313. var mode = 0;
  314. var name = "";
  315. var t = shader.textures;
  316. while( t != null ) {
  317. var tt = t.type;
  318. var count = 1;
  319. switch( tt ) {
  320. case TChannel(_): tt = TSampler(T2D,false);
  321. case TArray(t,SConst(n)): tt = t; count = n;
  322. default:
  323. }
  324. if( curT == null || !tt.equals(curT) ) {
  325. curT = tt;
  326. name = switch( tt ) {
  327. case TSampler(dim,arr):
  328. mode = switch( [dim, arr] ) {
  329. case [T2D, false]: GL.TEXTURE_2D;
  330. case [T3D, false]: GL.TEXTURE_3D;
  331. case [TCube, false]: GL.TEXTURE_CUBE_MAP;
  332. case [T2D, true]: GL.TEXTURE_2D_ARRAY;
  333. #if (hlsdl > version("1.15.0"))
  334. case [T1D, false]: GL.TEXTURE_1D;
  335. case [T1D, true]: GL.TEXTURE_1D_ARRAY;
  336. case [TCube, true]: GL.TEXTURE_CUBE_MAP_ARRAY;
  337. #end
  338. default: throw "Texture not supported "+tt;
  339. }
  340. "Textures" + (dim == T2D ? "" : dim.getName().substr(1))+(arr ? "Array" : "");
  341. case TRWTexture(dim, arr, chans):
  342. #if (js || hlsdl < version("1.15.0"))
  343. throw "Texture not supported "+tt;
  344. #else
  345. mode = switch( [dim, arr] ) {
  346. case [T1D, false]: GL.IMAGE_1D;
  347. case [T2D, false]: GL.IMAGE_2D;
  348. case [T3D, false]: GL.IMAGE_3D;
  349. case [TCube, false]: GL.IMAGE_CUBE;
  350. case [T1D, true]: GL.IMAGE_1D_ARRAY;
  351. case [T2D, true]: GL.IMAGE_2D_ARRAY;
  352. case [TCube, true]: GL.IMAGE_CUBE_MAP_ARRAY;
  353. default: throw "Texture not supported "+tt;
  354. };
  355. "TexturesRW" + (dim == T2D ? "" : dim.getName().substr(1))+chans+(arr ? "Array" : "");
  356. #end
  357. default: throw "Unsupported texture type "+tt;
  358. }
  359. index = 0;
  360. }
  361. for( i in 0...count ) {
  362. var loc = gl.getUniformLocation(p.p, prefix+name+"["+index+"]");
  363. /*
  364. This is a texture that is used in HxSL but has been optimized out by GLSL compiler.
  365. While some drivers will correctly report `null` here, some others (AMD) will instead
  366. return a uniform but still mismatch the texture slot, leading to swapped textures or
  367. incorrect rendering. We also don't handle texture skipping in DirectX.
  368. Fix is to make sure HxSL will optimize the texture out.
  369. Alternate fix is to improve HxSL so he does it on its own.
  370. */
  371. if( loc == null )
  372. throw "Texture "+rt.spec.instances[t.instance].shader.data.name+"."+t.name+" is missing from generated shader";
  373. s.textures.push({ u : loc, t : curT, mode : mode });
  374. index++;
  375. }
  376. t = t.next;
  377. }
  378. if( shader.bufferCount > 0 ) {
  379. s.bufferTypes = [];
  380. var bp = s.shader.buffers;
  381. while( bp != null ) {
  382. var kind = switch( bp.type ) {
  383. case TBuffer(_,_,kind): kind;
  384. default: throw "assert";
  385. }
  386. s.bufferTypes.push(kind);
  387. bp = bp.next;
  388. }
  389. s.buffers = [for( i in 0...shader.bufferCount ) {
  390. switch( s.bufferTypes[i] ) {
  391. case Storage:
  392. #if js
  393. throw "Storage buffer not supported in WebGL";
  394. #elseif (hl_ver < version("1.15.0"))
  395. throw "Storage buffer support requires -D hl-ver=1.15.0";
  396. #else
  397. gl.getProgramResourceIndex(p.p,GL.SHADER_STORAGE_BLOCK,(shader.kind==Vertex?"storage_vertex_":"storage_")+"uniform_buffer"+i);
  398. #end
  399. case RW:
  400. #if js
  401. throw "RW buffer not supported in WebGL";
  402. #elseif (hl_ver < version("1.15.0"))
  403. throw "RW buffer support requires -D hl-ver=1.15.0";
  404. #else
  405. gl.getProgramResourceIndex(p.p,GL.SHADER_STORAGE_BLOCK,(shader.kind==Vertex?"rw_vertex_":"rw_")+"uniform_buffer"+i);
  406. #end
  407. case Uniform:
  408. gl.getUniformBlockIndex(p.p,(shader.kind==Vertex?"vertex_":"")+"uniform_buffer"+i);
  409. default:
  410. throw "assert";
  411. }
  412. }];
  413. var start = 0;
  414. if( s.kind == Fragment ) start = rt.vertex.bufferCount;
  415. for( i in 0...shader.bufferCount )
  416. switch( s.bufferTypes[i] ) {
  417. case Uniform:
  418. gl.uniformBlockBinding(p.p,s.buffers[i],i + start);
  419. case RW, Storage:
  420. #if (hl && hl_ver >= version("1.15.0"))
  421. gl.shaderStorageBlockBinding(p.p,s.buffers[i], i + start);
  422. #end
  423. default:
  424. throw "assert";
  425. }
  426. }
  427. }
  428. override function selectShader( shader : hxsl.RuntimeShader ) {
  429. var p = programs.get(shader.id);
  430. if( p == null ) {
  431. p = new CompiledProgram();
  432. var glout = makeCompiler();
  433. p.vertex = compileShader(glout,shader.vertex);
  434. if( shader.fragment != null )
  435. p.fragment = compileShader(glout,shader.fragment);
  436. p.p = gl.createProgram();
  437. #if ((hlsdl || usegl) && !hlmesa)
  438. if( glES == null && shader.fragment != null ) {
  439. var outCount = 0;
  440. for( v in shader.fragment.data.vars )
  441. switch( v.kind ) {
  442. case Output:
  443. gl.bindFragDataLocation(p.p, outCount++, glout.varNames.exists(v.id) ? glout.varNames.get(v.id) : v.name);
  444. default:
  445. }
  446. }
  447. #end
  448. gl.attachShader(p.p, p.vertex.s);
  449. if( p.fragment != null )
  450. gl.attachShader(p.p, p.fragment.s);
  451. var log = null;
  452. try {
  453. gl.linkProgram(p.p);
  454. if( gl.getProgramParameter(p.p, GL.LINK_STATUS) != cast 1 )
  455. log = gl.getProgramInfoLog(p.p);
  456. } catch( e : Dynamic ) {
  457. throw "Shader linkage error: "+Std.string(e)+" ("+getDriverName(false)+")";
  458. }
  459. gl.deleteShader(p.vertex.s);
  460. if( p.fragment != null )
  461. gl.deleteShader(p.fragment.s);
  462. if( log != null ) {
  463. #if js
  464. gl.deleteProgram(p.p);
  465. #end
  466. #if hlsdl
  467. /*
  468. Tentative patch on some driver that report an higher shader version that it's allowed to use.
  469. */
  470. if( log == "" && shaderVersion > 130 && firstShader ) {
  471. shaderVersion -= 10;
  472. return selectShader(shader);
  473. }
  474. #end
  475. throw "Program linkage failure: "+log+"\nVertex=\n"+shader.vertex.code+(shader.fragment == null ? "" : "\n\nFragment=\n"+shader.fragment.code);
  476. }
  477. firstShader = false;
  478. initShader(p, p.vertex, shader.vertex, shader);
  479. if( p.fragment != null )
  480. initShader(p, p.fragment, shader.fragment, shader);
  481. p.attribs = [];
  482. p.hasAttribIndex = 0;
  483. var format : Array<hxd.BufferFormat.BufferInput> = [];
  484. for( v in shader.vertex.data.vars )
  485. switch( v.kind ) {
  486. case Input:
  487. var t = hxd.BufferFormat.InputFormat.fromHXSL(v.type);
  488. var index = gl.getAttribLocation(p.p, glout.varNames.exists(v.id) ? glout.varNames.get(v.id) : v.name);
  489. if( index < 0 )
  490. continue;
  491. if( index >= 32 )
  492. throw "assert";
  493. var a = new CompiledAttribute();
  494. a.type = GL.FLOAT;
  495. a.index = index;
  496. a.size = t.getSize();
  497. switch( v.type ) {
  498. case TBytes(n):
  499. a.type = GL.BYTE;
  500. a.size = n;
  501. default:
  502. }
  503. a.divisor = 0;
  504. if( v.qualifiers != null ) {
  505. for( q in v.qualifiers )
  506. switch( q ) {
  507. case PerInstance(n): a.divisor = n;
  508. default:
  509. }
  510. }
  511. p.attribs.push(a);
  512. p.hasAttribIndex |= 1 << a.index;
  513. format.push({ name : v.name, type : t });
  514. default:
  515. }
  516. p.format = hxd.BufferFormat.make(format);
  517. programs.set(shader.id, p);
  518. }
  519. if( curShader == p ) return false;
  520. setProgram(p);
  521. return true;
  522. }
  523. function setProgram( p : CompiledProgram ) {
  524. gl.useProgram(p.p);
  525. for( a in p.attribs )
  526. if( !curAttribs[a.index] ) {
  527. gl.enableVertexAttribArray(a.index);
  528. curAttribs[a.index] = true;
  529. if (maxIdxCurAttribs < a.index) {
  530. maxIdxCurAttribs = a.index;
  531. }
  532. }
  533. var lastIdxCurAttribTrue = 0;
  534. for( i in 0...maxIdxCurAttribs+1 ) {
  535. if( curAttribs[i] && p.hasAttribIndex & (1 << i) == 0) {
  536. gl.disableVertexAttribArray(i);
  537. curAttribs[i] = false;
  538. } else if (curAttribs[i]) {
  539. lastIdxCurAttribTrue = i;
  540. }
  541. }
  542. maxIdxCurAttribs = lastIdxCurAttribTrue;
  543. curShader = p;
  544. curBuffer = null;
  545. for( i in 0...boundTextures.length )
  546. boundTextures[i] = null;
  547. }
  548. override function uploadShaderBuffers( buf : h3d.shader.Buffers, which : h3d.shader.Buffers.BufferKind ) {
  549. uploadBuffer(buf, curShader.vertex, buf.vertex, which);
  550. if( curShader.fragment != null )
  551. uploadBuffer(buf, curShader.fragment, buf.fragment, which);
  552. }
  553. function uploadBuffer( buffer : h3d.shader.Buffers, s : CompiledShader, buf : h3d.shader.Buffers.ShaderBuffers, which : h3d.shader.Buffers.BufferKind ) {
  554. switch( which ) {
  555. case Globals:
  556. if( s.globals != null ) {
  557. #if hl
  558. gl.uniform4fv(s.globals, streamData(hl.Bytes.getArray(buf.globals.toData()), 0, s.shader.globalsSize * 16), 0, s.shader.globalsSize * 4);
  559. #else
  560. var a = buf.globals.subarray(0, s.shader.globalsSize * 4);
  561. gl.uniform4fv(s.globals, a);
  562. #end
  563. }
  564. case Params:
  565. if( s.params != null ) {
  566. #if hl
  567. gl.uniform4fv(s.params, streamData(hl.Bytes.getArray(buf.params.toData()), 0, s.shader.paramsSize * 16), 0, s.shader.paramsSize * 4);
  568. #else
  569. var a = buf.params.subarray(0, s.shader.paramsSize * 4);
  570. gl.uniform4fv(s.params, a);
  571. #end
  572. }
  573. case Buffers:
  574. if( s.buffers != null ) {
  575. var start = 0;
  576. if( s.kind == Fragment && curShader.vertex.buffers != null )
  577. start = curShader.vertex.buffers.length;
  578. for( i in 0...s.buffers.length )
  579. switch( s.bufferTypes[i] ) {
  580. case Uniform:
  581. gl.bindBufferBase(GL.UNIFORM_BUFFER, i + start, buf.buffers[i].vbuf);
  582. case Storage:
  583. gl.bindBufferBase(0x90D2 /*GL.SHADER STORAGE BUFFER*/, i + start, buf.buffers[i].vbuf);
  584. case RW:
  585. if ( !buf.buffers[i].flags.has(ReadWriteBuffer) )
  586. throw "Buffer was allocated without ReadWriteBuffer flag";
  587. gl.bindBufferBase(0x90D2 /*GL.SHADER STORAGE BUFFER*/, i + start, buf.buffers[i].vbuf);
  588. default:
  589. throw "assert";
  590. }
  591. }
  592. case Textures:
  593. var imageBindingIdx = 0;
  594. for( i in 0...s.textures.length ) {
  595. var t = buf.tex[i];
  596. var pt = s.textures[i];
  597. if( t == null || t.isDisposed() ) {
  598. switch( pt.t ) {
  599. case TSampler(TCube, false):
  600. t = h3d.mat.Texture.defaultCubeTexture();
  601. case TSampler(T3D, false):
  602. t = h3d.mat.Texture3D.default3DTexture();
  603. case TSampler(_, false):
  604. var color = h3d.mat.Defaults.loadingTextureColor;
  605. t = h3d.mat.Texture.fromColor(color, (color >>> 24) / 255);
  606. default:
  607. throw "Missing texture";
  608. }
  609. }
  610. if( t != null && t.t == null && t.realloc != null ) {
  611. var s = curShader;
  612. t.alloc();
  613. t.realloc();
  614. if( curShader != s ) {
  615. // realloc triggered a shader change !
  616. // we need to reset the original shader and reupload everything
  617. setProgram(s);
  618. uploadShaderBuffers(buffer,Globals);
  619. uploadShaderBuffers(buffer,Params);
  620. uploadShaderBuffers(buffer,Textures);
  621. return;
  622. }
  623. }
  624. t.lastFrame = frame;
  625. if( pt.u == null ) continue;
  626. #if !js
  627. switch( pt.t ) {
  628. case TRWTexture(dim,arr,chans):
  629. var tdim : hxsl.Ast.TexDimension = t.flags.has(Cube) ? TCube : dim;
  630. var fmt;
  631. if( (arr != t.flags.has(IsArray)) || dim != tdim )
  632. fmt = 0;
  633. else {
  634. // we suppose it's possible to map from one pixel format to shader declared 32f
  635. fmt = switch( [chans,t.format] ) {
  636. case [1, R8]: GL.R8;
  637. case [2, RG8]: GL.RG8;
  638. case [4, RGBA]: GL.RGBA8;
  639. case [1, R16F]: GL.R16F;
  640. case [2, RG16F]: GL.RG16F;
  641. case [4, RGBA16F]: GL.RGBA16F;
  642. case [1, R32F]: GL.R32F;
  643. case [2, RG32F]: GL.RG32F;
  644. case [4, RGBA32F]: GL.RGBA32F;
  645. default: 0;
  646. }
  647. }
  648. if( fmt == 0 )
  649. throw "Texture format does not match: "+t+"["+t.format+"] should be "+hxsl.Ast.Tools.toString(pt.t);
  650. #if (hlsdl < version("1.15.0"))
  651. throw "RWTextures support requires hlsdl 1.15+";
  652. #else
  653. gl.bindImageTexture(imageBindingIdx++, cast t.t.t, 0, tdim == T3D ? true : false, 0, GL.READ_WRITE, fmt);
  654. #end
  655. boundTextures[i] = null;
  656. continue;
  657. default:
  658. }
  659. #end
  660. var idx = s.kind == Fragment ? curShader.vertex.textures.length + i : i;
  661. if( boundTextures[idx] != t.t ) {
  662. boundTextures[idx] = t.t;
  663. #if multidriver
  664. if( t.t.driver != this )
  665. throw "Invalid texture context";
  666. #end
  667. var mode = getBindType(t);
  668. if( mode != pt.mode )
  669. throw "Texture format mismatch: "+t+" should be "+pt.t;
  670. gl.activeTexture(GL.TEXTURE0 + idx);
  671. gl.uniform1i(pt.u, idx);
  672. gl.bindTexture(mode, t.t.t);
  673. lastActiveIndex = idx;
  674. }
  675. var mip = Type.enumIndex(t.mipMap);
  676. var filter = Type.enumIndex(t.filter);
  677. var wrap = Type.enumIndex(t.wrap);
  678. var bits = mip | (filter << 3) | (wrap << 6);
  679. if( bits != t.t.bits ) {
  680. t.t.bits = bits;
  681. var flags = TFILTERS[mip][filter];
  682. var mode = pt.mode;
  683. gl.texParameteri(mode, GL.TEXTURE_MAG_FILTER, flags[0]);
  684. gl.texParameteri(mode, GL.TEXTURE_MIN_FILTER, flags[1]);
  685. gl.texParameteri(mode, GL.TEXTURE_COMPARE_MODE, GL.NONE);
  686. var w = TWRAP[wrap];
  687. gl.texParameteri(mode, GL.TEXTURE_WRAP_S, w);
  688. gl.texParameteri(mode, GL.TEXTURE_WRAP_T, w);
  689. gl.texParameteri(mode, GL.TEXTURE_WRAP_R, w);
  690. }
  691. if( t.t.startMip != t.startingMip ) {
  692. gl.texParameteri(pt.mode, GL.TEXTURE_BASE_LEVEL, t.startingMip);
  693. t.t.startMip = t.startingMip;
  694. }
  695. #if !js
  696. if( t.lodBias != t.t.bias ) {
  697. t.t.bias = t.lodBias;
  698. gl.texParameterf(pt.mode, GL.TEXTURE_LOD_BIAS, t.lodBias);
  699. }
  700. #end
  701. }
  702. }
  703. }
  704. override function selectMaterial( pass : Pass ) {
  705. var bits = @:privateAccess pass.bits;
  706. /*
  707. When rendering to a render target, our output will be flipped in Y to match
  708. output texture coordinates. We also need to flip our culling.
  709. The result is inverted if we are using a right handed camera.
  710. */
  711. if( (curTarget == null) == rightHanded ) {
  712. switch( pass.culling ) {
  713. case Back: bits = (bits & ~Pass.culling_mask) | (2 << Pass.culling_offset);
  714. case Front: bits = (bits & ~Pass.culling_mask) | (1 << Pass.culling_offset);
  715. default:
  716. }
  717. }
  718. selectMaterialBits(bits);
  719. if( curColorMask != pass.colorMask ) {
  720. var m = pass.colorMask;
  721. gl.colorMask(m & 1 != 0, m & 2 != 0, m & 4 != 0, m & 8 != 0);
  722. var mi = m >> 4;
  723. if ( mi > 0 ) {
  724. #if (hl && hl_ver >= version("1.14.0"))
  725. var i = 1;
  726. do {
  727. if ( mi & 15 > 0 ) {
  728. gl.colorMaski(i, mi & 1 != 0, mi & 2 != 0, mi & 4 != 0, mi & 8 != 0);
  729. }
  730. mi = mi >> 4;
  731. i++;
  732. } while ( mi > 0 );
  733. #else
  734. throw "GL ColorMaski support requires hlsdl 1.14+";
  735. #end
  736. }
  737. curColorMask = m;
  738. }
  739. var s = defStencil;
  740. if( pass.stencil == null ) {
  741. if( curStEnabled ) {
  742. gl.disable(GL.STENCIL_TEST);
  743. curStEnabled = false;
  744. }
  745. } else {
  746. s = pass.stencil;
  747. if( !curStEnabled ) {
  748. gl.enable(GL.STENCIL_TEST);
  749. curStEnabled = true;
  750. }
  751. }
  752. @:privateAccess selectStencilBits(s.opBits, s.maskBits);
  753. // TODO : Blend Op value sync
  754. }
  755. function selectMaterialBits( bits : Int ) {
  756. var diff = bits ^ curMatBits;
  757. if( curMatBits < 0 ) diff = -1;
  758. if( diff == 0 )
  759. return;
  760. var wireframe = bits & Pass.wireframe_mask != 0;
  761. #if hlsdl
  762. if ( wireframe ) {
  763. gl.polygonMode(GL.FRONT_AND_BACK, GL.LINE);
  764. // Force set to cull = None
  765. bits = (bits & ~Pass.culling_mask);
  766. diff |= Pass.culling_mask;
  767. } else {
  768. gl.polygonMode(GL.FRONT_AND_BACK, GL.FILL);
  769. }
  770. #else
  771. var fallback = true;
  772. #if (js && haxe_ver >= 5)
  773. var extension:js.html.webgl.extension.WEBGLPolygonMode = cast gl.getExtension("WEBGL_polygon_mode");
  774. if(extension != null) {
  775. if(wireframe) {
  776. extension.polygonModeWEBGL(GL.FRONT_AND_BACK, js.html.webgl.extension.WEBGLPolygonMode.LINE_WEBGL);
  777. } else {
  778. extension.polygonModeWEBGL(GL.FRONT_AND_BACK, js.html.webgl.extension.WEBGLPolygonMode.FILL_WEBGL);
  779. }
  780. fallback = false;
  781. }
  782. #end
  783. if(fallback) {
  784. drawMode = wireframe ? GL.LINE_STRIP : GL.TRIANGLES;
  785. }
  786. #end
  787. if( diff & Pass.culling_mask != 0 ) {
  788. var cull = Pass.getCulling(bits);
  789. if( cull == 0 )
  790. gl.disable(GL.CULL_FACE);
  791. else {
  792. if( curMatBits < 0 || Pass.getCulling(curMatBits) == 0 )
  793. gl.enable(GL.CULL_FACE);
  794. gl.cullFace(FACES[cull]);
  795. }
  796. }
  797. if( diff & (Pass.blendSrc_mask | Pass.blendDst_mask | Pass.blendAlphaSrc_mask | Pass.blendAlphaDst_mask) != 0 ) {
  798. var csrc = Pass.getBlendSrc(bits);
  799. var cdst = Pass.getBlendDst(bits);
  800. var asrc = Pass.getBlendAlphaSrc(bits);
  801. var adst = Pass.getBlendAlphaDst(bits);
  802. if( csrc == asrc && cdst == adst ) {
  803. if( csrc == 0 && cdst == 1 )
  804. gl.disable(GL.BLEND);
  805. else {
  806. if( curMatBits < 0 || (Pass.getBlendSrc(curMatBits) == 0 && Pass.getBlendDst(curMatBits) == 1) ) gl.enable(GL.BLEND);
  807. gl.blendFunc(BLEND[csrc], BLEND[cdst]);
  808. }
  809. } else {
  810. if( curMatBits < 0 || (Pass.getBlendSrc(curMatBits) == 0 && Pass.getBlendDst(curMatBits) == 1) ) gl.enable(GL.BLEND);
  811. gl.blendFuncSeparate(BLEND[csrc], BLEND[cdst], BLEND[asrc], BLEND[adst]);
  812. }
  813. }
  814. if( diff & (Pass.blendOp_mask | Pass.blendAlphaOp_mask) != 0 ) {
  815. var cop = Pass.getBlendOp(bits);
  816. var aop = Pass.getBlendAlphaOp(bits);
  817. if( cop == aop ) {
  818. gl.blendEquation(OP[cop]);
  819. }
  820. else
  821. gl.blendEquationSeparate(OP[cop], OP[aop]);
  822. }
  823. if( diff & Pass.depthWrite_mask != 0 )
  824. gl.depthMask(Pass.getDepthWrite(bits) != 0);
  825. if( diff & Pass.depthTest_mask != 0 ) {
  826. var cmp = Pass.getDepthTest(bits);
  827. if( cmp == 0 )
  828. gl.disable(GL.DEPTH_TEST);
  829. else {
  830. if( curMatBits < 0 || Pass.getDepthTest(curMatBits) == 0 ) gl.enable(GL.DEPTH_TEST);
  831. gl.depthFunc(COMPARE[cmp]);
  832. }
  833. }
  834. #if !js
  835. if ( (!useDepthClamp && diff & Pass.depthClamp_mask != 0) ) {
  836. if ( Pass.getDepthClamp(bits) != 0 )
  837. gl.enable(GL.DEPTH_CLAMP);
  838. else
  839. gl.disable(GL.DEPTH_CLAMP);
  840. }
  841. #end
  842. curMatBits = bits;
  843. }
  844. function selectStencilBits( opBits : Int, maskBits : Int ) {
  845. var diffOp = opBits ^ curStOpBits;
  846. var diffMask = maskBits ^ curStMaskBits;
  847. if ( (diffOp | diffMask) == 0 ) return;
  848. if( diffOp & (Stencil.frontSTfail_mask | Stencil.frontDPfail_mask | Stencil.frontPass_mask) != 0 ) {
  849. gl.stencilOpSeparate(
  850. FACES[Type.enumIndex(Front)],
  851. STENCIL_OP[Stencil.getFrontSTfail(opBits)],
  852. STENCIL_OP[Stencil.getFrontDPfail(opBits)],
  853. STENCIL_OP[Stencil.getFrontPass(opBits)]);
  854. }
  855. if( diffOp & (Stencil.backSTfail_mask | Stencil.backDPfail_mask | Stencil.backPass_mask) != 0 ) {
  856. gl.stencilOpSeparate(
  857. FACES[Type.enumIndex(Back)],
  858. STENCIL_OP[Stencil.getBackSTfail(opBits)],
  859. STENCIL_OP[Stencil.getBackDPfail(opBits)],
  860. STENCIL_OP[Stencil.getBackPass(opBits)]);
  861. }
  862. if( (diffOp & Stencil.frontTest_mask) | (diffMask & (Stencil.reference_mask | Stencil.readMask_mask)) != 0 ) {
  863. gl.stencilFuncSeparate(
  864. FACES[Type.enumIndex(Front)],
  865. COMPARE[Stencil.getFrontTest(opBits)],
  866. Stencil.getReference(maskBits),
  867. Stencil.getReadMask(maskBits));
  868. }
  869. if( (diffOp & Stencil.backTest_mask) | (diffMask & (Stencil.reference_mask | Stencil.readMask_mask)) != 0 ) {
  870. gl.stencilFuncSeparate(
  871. FACES[Type.enumIndex(Back)],
  872. COMPARE[Stencil.getBackTest(opBits)],
  873. Stencil.getReference(maskBits),
  874. Stencil.getReadMask(maskBits));
  875. }
  876. if( diffMask & Stencil.writeMask_mask != 0 ) {
  877. var w = Stencil.getWriteMask(maskBits);
  878. gl.stencilMaskSeparate(FACES[Type.enumIndex(Front)], w);
  879. gl.stencilMaskSeparate(FACES[Type.enumIndex(Back)], w);
  880. }
  881. curStOpBits = opBits;
  882. curStMaskBits = maskBits;
  883. }
  884. override function clear( ?color : h3d.Vector4, ?depth : Float, ?stencil : Int ) {
  885. var bits = 0;
  886. if( color != null ) {
  887. gl.colorMask(true, true, true, true);
  888. curColorMask = 15;
  889. #if hlsdl
  890. // clear does not take gamma correction into account in GL/Windows
  891. if( curTarget != null && curTarget.isSRGB() )
  892. gl.clearColor(Math.pow(color.r, 1/2.2), Math.pow(color.g, 1/2.2), Math.pow(color.b, 1/2.2), color.a);
  893. else
  894. #end
  895. gl.clearColor(color.r, color.g, color.b, color.a);
  896. bits |= GL.COLOR_BUFFER_BIT;
  897. }
  898. if( depth != null ) {
  899. gl.depthMask(true);
  900. if( curMatBits >= 0 ) curMatBits |= Pass.depthWrite_mask;
  901. gl.clearDepth(depth);
  902. bits |= GL.DEPTH_BUFFER_BIT;
  903. }
  904. if( stencil != null ) {
  905. // reset stencil mask when we allow to change it
  906. @:privateAccess selectStencilBits(defStencil.opBits, defStencil.maskBits);
  907. gl.clearStencil(stencil);
  908. bits |= GL.STENCIL_BUFFER_BIT;
  909. }
  910. if( bits != 0 ) gl.clear(bits);
  911. if( curTarget != null ) curTarget.flags.set(WasCleared);
  912. }
  913. override function resize(width, height) {
  914. #if js
  915. // prevent infinite grow if pixelRatio != 1
  916. if( canvas.style.width == "" ) {
  917. canvas.style.width = Std.int(width / js.Browser.window.devicePixelRatio)+"px";
  918. canvas.style.height = Std.int(height / js.Browser.window.devicePixelRatio)+"px";
  919. }
  920. canvas.width = width;
  921. canvas.height = height;
  922. #end
  923. bufferWidth = width;
  924. bufferHeight = height;
  925. gl.viewport(0, 0, width, height);
  926. @:privateAccess if( defaultDepth != null ) {
  927. disposeDepthBuffer(defaultDepth);
  928. defaultDepth.width = this.bufferWidth;
  929. defaultDepth.height = this.bufferHeight;
  930. defaultDepth.t = allocDepthBuffer(defaultDepth);
  931. }
  932. }
  933. function getChannels( t : Texture ) {
  934. return switch( t.internalFmt ) {
  935. case GL.RGBA32F, GL.RGBA16F: GL.RGBA;
  936. #if !js
  937. case GL.SRGB_ALPHA, GL.SRGB8_ALPHA: GL.RGBA;
  938. case GL.RGBA8: GL.BGRA;
  939. #end
  940. case GL.SRGB, GL.SRGB8: GL.RGB;
  941. case GL.RGBA: GL.RGBA;
  942. case GL.RGB: GL.RGB;
  943. case GL.R11F_G11F_B10F: GL.RGB;
  944. case GL.RGB10_A2: GL.RGBA;
  945. case GL.RED, GL.R8, GL.R16F, GL.R32F, 0x822A: GL.RED;
  946. case GL.RG, GL.RG8, GL.RG16F, GL.RG32F, 0x822C: GL.RG;
  947. case GL.RGB16F, GL.RGB32F, 0x8054, 0x8E8F: GL.RGB;
  948. case 0x83F1, 0x83F2, 0x83F3, 0x805B, 0x8E8C: GL.RGBA;
  949. default: throw "Invalid format " + t.internalFmt;
  950. }
  951. }
  952. override function isSupportedFormat( fmt : h3d.mat.Data.TextureFormat ) {
  953. return switch( fmt ) {
  954. case RGBA: true;
  955. case RGBA16F, RGBA32F: hasFeature(FloatTextures);
  956. case SRGB, SRGB_ALPHA: hasFeature(SRGBTextures);
  957. case R8, RG8, RGB8, R16F, RG16F, RGB16F, R32F, RG32F, RGB32F, RG11B10UF, RGB10A2: #if js glES >= 3 #else true #end;
  958. case S3TC(n): n <= maxCompressedTexturesSupport;
  959. default: false;
  960. }
  961. }
  962. function getBindType( t : h3d.mat.Texture ) {
  963. if ( t.flags.has(Is3D) )
  964. return GL.TEXTURE_3D;
  965. var isArray = t.flags.has(IsArray);
  966. if( t.flags.has(Cube) )
  967. return #if (hlsdl > version("1.15.0")) isArray ? GL.TEXTURE_CUBE_MAP_ARRAY : #end GL.TEXTURE_CUBE_MAP;
  968. return isArray ? GL.TEXTURE_2D_ARRAY : GL.TEXTURE_2D;
  969. }
  970. override function allocTexture( t : h3d.mat.Texture ) : Texture {
  971. discardError();
  972. var tt = gl.createTexture();
  973. var bind = getBindType(t);
  974. var tt : Texture = { t : tt, width : t.width, height : t.height, internalFmt : GL.RGBA, pixelFmt : GL.UNSIGNED_BYTE, bits : -1, bind : bind, bias : 0, startMip : t.startingMip #if multidriver, driver : this #end };
  975. switch( t.format ) {
  976. case RGBA:
  977. // default
  978. case RGBA32F if( hasFeature(FloatTextures) ):
  979. tt.internalFmt = GL.RGBA32F;
  980. tt.pixelFmt = GL.FLOAT;
  981. case RGBA16F if( hasFeature(FloatTextures) ):
  982. tt.pixelFmt = GL.HALF_FLOAT;
  983. tt.internalFmt = GL.RGBA16F;
  984. case BGRA:
  985. tt.internalFmt = GL.RGBA8;
  986. case SRGB:
  987. tt.internalFmt = GL.SRGB8;
  988. #if !js
  989. case SRGB_ALPHA:
  990. tt.internalFmt = GL.SRGB8_ALPHA;
  991. #end
  992. case RGB8:
  993. tt.internalFmt = GL.RGB;
  994. case R8:
  995. tt.internalFmt = GL.R8;
  996. case RG8:
  997. tt.internalFmt = GL.RG8;
  998. case R16F:
  999. tt.internalFmt = GL.R16F;
  1000. tt.pixelFmt = GL.HALF_FLOAT;
  1001. case RG16F:
  1002. tt.internalFmt = GL.RG16F;
  1003. tt.pixelFmt = GL.HALF_FLOAT;
  1004. case R16U:
  1005. tt.internalFmt = 0x822A; // GL.R16
  1006. tt.pixelFmt = GL.UNSIGNED_SHORT;
  1007. case RG16U:
  1008. tt.internalFmt = 0x822C; // GL.RG16
  1009. tt.pixelFmt = GL.UNSIGNED_SHORT;
  1010. case RGB16U:
  1011. tt.internalFmt = 0x8054; // GL.RGB16
  1012. tt.pixelFmt = GL.UNSIGNED_SHORT;
  1013. case RGBA16U:
  1014. tt.internalFmt = 0x805B; // GL.RGBA16
  1015. tt.pixelFmt = GL.UNSIGNED_SHORT;
  1016. case R32F:
  1017. tt.internalFmt = GL.R32F;
  1018. tt.pixelFmt = GL.FLOAT;
  1019. case RG32F:
  1020. tt.internalFmt = GL.RG32F;
  1021. tt.pixelFmt = GL.FLOAT;
  1022. case RGB16F:
  1023. tt.internalFmt = GL.RGB16F;
  1024. tt.pixelFmt = GL.HALF_FLOAT;
  1025. case RGB32F:
  1026. tt.internalFmt = GL.RGB32F;
  1027. tt.pixelFmt = GL.FLOAT;
  1028. case RGB10A2:
  1029. tt.internalFmt = GL.RGB10_A2;
  1030. tt.pixelFmt = GL.UNSIGNED_INT_2_10_10_10_REV;
  1031. case RG11B10UF:
  1032. tt.internalFmt = GL.R11F_G11F_B10F;
  1033. tt.pixelFmt = GL.UNSIGNED_INT_10F_11F_11F_REV;
  1034. case S3TC(n) if( n <= maxCompressedTexturesSupport ):
  1035. if( t.width&3 != 0 || t.height&3 != 0 )
  1036. throw "Compressed texture "+t+" has size "+t.width+"x"+t.height+" - must be a multiple of 4";
  1037. switch( n ) {
  1038. case 1: tt.internalFmt = 0x83F1; // COMPRESSED_RGBA_S3TC_DXT1_EXT
  1039. case 2: tt.internalFmt = 0x83F2; // COMPRESSED_RGBA_S3TC_DXT3_EXT
  1040. case 3: tt.internalFmt = 0x83F3; // COMPRESSED_RGBA_S3TC_DXT5_EXT
  1041. case 6: tt.internalFmt = 0x8E8F; // COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT
  1042. case 7: tt.internalFmt = 0x8E8C; // COMPRESSED_RGBA_BPTC_UNORM
  1043. default: throw "Unsupported texture format "+t.format;
  1044. }
  1045. default:
  1046. throw "Unsupported texture format "+t.format;
  1047. }
  1048. #if js
  1049. if( tt.pixelFmt == GL.UNSIGNED_SHORT && !has16Bits )
  1050. throw "16 bit textures requires EXT_texture_norm16 extension";
  1051. #end
  1052. t.lastFrame = frame;
  1053. t.flags.unset(WasCleared);
  1054. gl.bindTexture(bind, tt.t);
  1055. var outOfMem = false;
  1056. inline function checkError() {
  1057. if( !outOfMemoryCheck ) return false;
  1058. var err = gl.getError();
  1059. if( err == GL.OUT_OF_MEMORY ) {
  1060. outOfMem = true;
  1061. return true;
  1062. }
  1063. if( err != 0 ) throw "Failed to alloc texture "+t.format+"(error "+err+")";
  1064. return false;
  1065. }
  1066. #if (js || (hlsdl >= version("1.12.0")))
  1067. gl.texParameteri(bind, GL.TEXTURE_BASE_LEVEL, t.startingMip);
  1068. gl.texParameteri(bind, GL.TEXTURE_MAX_LEVEL, t.mipLevels-1);
  1069. #end
  1070. #if js
  1071. // Modern texture allocation that supports both compressed and uncompressed texture in WebGL
  1072. // texStorate2D/3D is only defined in OpenGL 4.2 but is defined in openGL ES 3 which the js target targets
  1073. // Patch RGBA to be RGBA8 because texStorage expect a "Sized Internal Format"
  1074. var sizedFormat = tt.internalFmt == GL.RGBA ? GL.RGBA8 : tt.internalFmt;
  1075. if( ( t.flags.has(IsArray) || t.flags.has(Is3D) ) && !t.flags.has(Cube) ) {
  1076. gl.texStorage3D(bind, t.mipLevels, sizedFormat, tt.width, tt.height, t.layerCount);
  1077. checkError();
  1078. } else {
  1079. gl.texStorage2D(bind, t.mipLevels, sizedFormat, tt.width, tt.height);
  1080. checkError();
  1081. }
  1082. #else
  1083. for(mip in 0...t.mipLevels) {
  1084. var w = hxd.Math.imax(1, tt.width >> mip);
  1085. var h = hxd.Math.imax(1, tt.height >> mip);
  1086. var d = hxd.Math.imax(1, t.layerCount >> mip);
  1087. if( t.flags.has(Cube) ) {
  1088. for( i in 0...6 ) {
  1089. gl.texImage2D(CUBE_FACES[i], mip, tt.internalFmt, w, h, 0, getChannels(tt), tt.pixelFmt, null);
  1090. if( checkError() ) break;
  1091. }
  1092. } else if( t.flags.has(IsArray) ) {
  1093. gl.texImage3D(bind, mip, tt.internalFmt, w, h, t.layerCount, 0, getChannels(tt), tt.pixelFmt, null);
  1094. checkError();
  1095. } else if ( t.flags.has(Is3D) ) {
  1096. gl.texImage3D(bind, mip, tt.internalFmt, w, h, d, 0, getChannels(tt), tt.pixelFmt, null);
  1097. checkError();
  1098. } else {
  1099. gl.texImage2D(bind, mip, tt.internalFmt, w, h, 0, getChannels(tt), tt.pixelFmt, null);
  1100. checkError();
  1101. }
  1102. }
  1103. #end
  1104. restoreBind();
  1105. if( outOfMem ) {
  1106. gl.deleteTexture(tt.t);
  1107. return null;
  1108. }
  1109. return tt;
  1110. }
  1111. function restoreBind() {
  1112. var t = boundTextures[lastActiveIndex];
  1113. if( t == null )
  1114. gl.bindTexture(GL.TEXTURE_2D, null);
  1115. else
  1116. gl.bindTexture(t.bind, t.t);
  1117. }
  1118. override function allocDepthBuffer( t : h3d.mat.Texture ) : Texture {
  1119. var tt = gl.createTexture();
  1120. var tt : Texture = { t : tt, width : t.width, height : t.height, internalFmt : GL.RGBA, pixelFmt : GL.UNSIGNED_BYTE, bits : -1, bind : GL.TEXTURE_2D, bias : 0, startMip: 0 #if multidriver, driver : this #end };
  1121. var fmt = GL.DEPTH_COMPONENT;
  1122. switch( t.format ) {
  1123. case Depth16:
  1124. tt.internalFmt = GL.DEPTH_COMPONENT16;
  1125. case Depth24 #if js if( glES >= 3 ) #end: tt.internalFmt = GL.DEPTH_COMPONENT;
  1126. case Depth24Stencil8:
  1127. tt.internalFmt = GL.DEPTH24_STENCIL8;
  1128. tt.pixelFmt = GL.UNSIGNED_INT_24_8;
  1129. fmt = GL.DEPTH_STENCIL;
  1130. case Depth32:
  1131. tt.internalFmt = GL.DEPTH_COMPONENT32F;
  1132. default:
  1133. throw "Unsupported depth format "+ t.format;
  1134. }
  1135. t.lastFrame = frame;
  1136. t.flags.unset(WasCleared);
  1137. gl.bindTexture(tt.bind, tt.t);
  1138. #if (js || (hlsdl >= version("1.12.0")))
  1139. gl.texParameteri(tt.bind, GL.TEXTURE_MIN_FILTER, GL.NEAREST);
  1140. gl.texParameteri(tt.bind, GL.TEXTURE_MAG_FILTER, GL.NEAREST);
  1141. gl.texParameteri(tt.bind, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE);
  1142. gl.texParameteri(tt.bind, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE);
  1143. #end
  1144. gl.texImage2D(tt.bind, 0, tt.internalFmt, tt.width, tt.height, 0, fmt, tt.pixelFmt, null);
  1145. restoreBind();
  1146. return tt;
  1147. }
  1148. override function disposeDepthBuffer( b : h3d.mat.Texture ) {
  1149. @:privateAccess if( b.t != null && b.t.t != null ) {
  1150. gl.deleteTexture(b.t.t);
  1151. b.t = null;
  1152. }
  1153. }
  1154. var defaultDepth : h3d.mat.Texture;
  1155. override function getDefaultDepthBuffer() : h3d.mat.Texture {
  1156. // Unfortunately there is no way to bind the depth buffer of the default frame buffer to a frame buffer object.
  1157. if( defaultDepth != null )
  1158. return defaultDepth;
  1159. defaultDepth = new h3d.mat.Texture(0, 0, Depth24Stencil8);
  1160. defaultDepth.name = "defaultDepthBuffer";
  1161. @:privateAccess {
  1162. defaultDepth.width = this.bufferWidth;
  1163. defaultDepth.height = this.bufferHeight;
  1164. defaultDepth.t = allocDepthBuffer(defaultDepth);
  1165. }
  1166. return defaultDepth;
  1167. }
  1168. inline function discardError() {
  1169. if( outOfMemoryCheck ) gl.getError(); // make sure to reset error flag
  1170. }
  1171. override function allocBuffer( b : h3d.Buffer ) : GPUBuffer {
  1172. discardError();
  1173. var vb = gl.createBuffer();
  1174. var type = b.flags.has(IndexBuffer) ? GL.ELEMENT_ARRAY_BUFFER : GL.ARRAY_BUFFER;
  1175. gl.bindBuffer(type, vb);
  1176. if( b.vertices * b.format.stride == 0 ) throw "assert";
  1177. #if js
  1178. gl.bufferData(type, b.getMemSize(), b.flags.has(Dynamic) ? GL.DYNAMIC_DRAW : GL.STATIC_DRAW);
  1179. #elseif hl
  1180. gl.bufferDataSize(type, b.getMemSize(), b.flags.has(Dynamic) ? GL.DYNAMIC_DRAW : GL.STATIC_DRAW);
  1181. #else
  1182. var tmp = new Uint8Array(b.getMemSize());
  1183. gl.bufferData(type, tmp, b.flags.has(Dynamic) ? GL.DYNAMIC_DRAW : GL.STATIC_DRAW);
  1184. #end
  1185. #if multidriver
  1186. @:privateAccess if( b.engine.driver != this )
  1187. throw "Invalid buffer context";
  1188. #end
  1189. var outOfMem = outOfMemoryCheck && gl.getError() == GL.OUT_OF_MEMORY;
  1190. gl.bindBuffer(type, null);
  1191. if( b.flags.has(IndexBuffer) )
  1192. curIndexBuffer = null;
  1193. if( outOfMem ) {
  1194. gl.deleteBuffer(vb);
  1195. return null;
  1196. }
  1197. return vb;
  1198. }
  1199. override function disposeTexture( t : h3d.mat.Texture ) {
  1200. var tt = t.t;
  1201. if( tt == null ) return;
  1202. t.t = null;
  1203. for( i in 0...boundTextures.length )
  1204. if( boundTextures[i] == tt )
  1205. boundTextures[i] = null;
  1206. gl.deleteTexture(tt.t);
  1207. }
  1208. override function disposeBuffer( b : h3d.Buffer ) {
  1209. gl.deleteBuffer(b.vbuf);
  1210. }
  1211. override function generateMipMaps( t : h3d.mat.Texture ) {
  1212. var bind = getBindType(t);
  1213. gl.bindTexture(bind, t.t.t);
  1214. gl.generateMipmap(bind);
  1215. restoreBind();
  1216. }
  1217. override function uploadTextureBitmap( t : h3d.mat.Texture, bmp : hxd.BitmapData, mipLevel : Int, side : Int ) {
  1218. #if hl
  1219. var pixels = bmp.getPixels();
  1220. uploadTexturePixels(t, pixels, mipLevel, side);
  1221. pixels.dispose();
  1222. #else
  1223. if( t.format != RGBA || t.layerCount != 1 ) {
  1224. var pixels = bmp.getPixels();
  1225. uploadTexturePixels(t, pixels, mipLevel, side);
  1226. pixels.dispose();
  1227. } else {
  1228. var img = bmp.toNative();
  1229. gl.bindTexture(GL.TEXTURE_2D, t.t.t);
  1230. gl.texSubImage2D(GL.TEXTURE_2D, mipLevel, 0, 0, getChannels(t.t), t.t.pixelFmt, img.getImageData(0, 0, bmp.width, bmp.height));
  1231. restoreBind();
  1232. }
  1233. #end
  1234. }
  1235. /*
  1236. GL async model create crashes if the GC free the memory that we send it.
  1237. Instead, we will copy the data into a temp location before uploading.
  1238. */
  1239. static inline var STREAM_POS = #if hl 0 #else 1 #end;
  1240. #if hl
  1241. var streamKeep : Array<{ f : Int, b : hl.Bytes }> = [];
  1242. var streamBytes : hl.Bytes;
  1243. var streamLen : Int;
  1244. var streamPos : Int;
  1245. function expandStream(needed:Int) {
  1246. GL.finish();
  1247. // too much data in our tmp buffer, let's flush it
  1248. if( streamPos > (needed >> 1) && needed > 16 << 20 ) {
  1249. needed -= streamPos;
  1250. streamPos = 0;
  1251. if( needed < streamLen )
  1252. return;
  1253. }
  1254. var newLen = streamLen == 0 ? 0x10000 : streamLen;
  1255. while( newLen < needed )
  1256. newLen = (newLen * 3) >> 1;
  1257. var newBytes = new hl.Bytes(newLen);
  1258. if( streamPos > 0 )
  1259. newBytes.blit(0, streamBytes, 0, streamPos);
  1260. streamLen = newLen;
  1261. if( streamBytes != null ) streamKeep.push({ f : frame, b : streamBytes });
  1262. streamBytes = newBytes;
  1263. }
  1264. #end
  1265. function resetStream() {
  1266. #if hl
  1267. streamPos = 0;
  1268. // keep during 2 frames
  1269. while( streamKeep.length > 0 && streamKeep[0].f < frame - 1 ) streamKeep.shift();
  1270. #end
  1271. }
  1272. inline function streamData(data, pos:Int, length:Int) {
  1273. #if hl
  1274. var needed = streamPos + length;
  1275. var total = (needed + 7) & ~7; // align on 8 bytes
  1276. var alen = total - streamPos;
  1277. if( total > streamLen ) expandStream(total);
  1278. streamBytes.blit(streamPos, data, pos, length);
  1279. data = streamBytes.offset(streamPos);
  1280. streamPos += alen;
  1281. #end
  1282. return data;
  1283. }
  1284. override function uploadTexturePixels( t : h3d.mat.Texture, pixels : hxd.Pixels, mipLevel : Int, side : Int ) {
  1285. var cubic = t.flags.has(Cube);
  1286. var face = GL.TEXTURE_2D;
  1287. if ( cubic )
  1288. face = CUBE_FACES[side];
  1289. if ( t.flags.has(IsArray) )
  1290. face = GL.TEXTURE_2D_ARRAY
  1291. else if ( t.flags.has(Is3D) )
  1292. face = GL.TEXTURE_3D;
  1293. var bind = getBindType(t);
  1294. gl.bindTexture(bind, t.t.t);
  1295. pixels.convert(t.format);
  1296. var dataLen = pixels.dataSize;
  1297. #if hl
  1298. var stream = streamData(pixels.bytes.getData(),pixels.offset,dataLen);
  1299. if( t.format.match(S3TC(_)) ) {
  1300. if( t.flags.has(IsArray) || t.flags.has(Is3D) )
  1301. #if (hlsdl >= version("1.12.0"))
  1302. gl.compressedTexSubImage3D(face, mipLevel, 0, 0, side, pixels.width, pixels.height, 1, t.t.internalFmt, dataLen, stream);
  1303. #else throw "TextureArray support requires hlsdl 1.12+"; #end
  1304. else
  1305. gl.compressedTexImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, dataLen, stream);
  1306. } else {
  1307. if( t.flags.has(IsArray) || t.flags.has(Is3D) )
  1308. #if (hlsdl >= version("1.12.0"))
  1309. gl.texSubImage3D(face, mipLevel, 0, 0, side, pixels.width, pixels.height, 1, getChannels(t.t), t.t.pixelFmt, stream);
  1310. #else throw "TextureArray support requires hlsdl 1.12+"; #end
  1311. else
  1312. gl.texImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, getChannels(t.t), t.t.pixelFmt, stream);
  1313. }
  1314. #elseif js
  1315. #if hxnodejs
  1316. if( (pixels:Dynamic).bytes.b.hxBytes != null ) {
  1317. // if the pixels are a nodejs buffer, their might be GC'ed while upload !
  1318. // might be some problem with Node/WebGL relation
  1319. // let's clone the pixels in order to have a fresh JS bytes buffer
  1320. pixels = pixels.clone();
  1321. }
  1322. #end
  1323. var buffer : ArrayBufferView = switch( t.format ) {
  1324. case RGBA32F, R32F, RG32F, RGB32F: new Float32Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, dataLen>>2);
  1325. case RGBA16F, R16F, RG16F, RGB16F, RGBA16U, R16U, RG16U, RGB16U: new Uint16Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, dataLen>>1);
  1326. case RGB10A2, RG11B10UF: new Uint32Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, dataLen>>2);
  1327. default: new Uint8Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, dataLen);
  1328. }
  1329. if( t.format.match(S3TC(_)) ) {
  1330. if( t.flags.has(IsArray) || t.flags.has(Is3D) )
  1331. gl.compressedTexSubImage3D(face, mipLevel, 0, 0, side, pixels.width, pixels.height, 1, t.t.internalFmt, buffer);
  1332. else
  1333. gl.compressedTexSubImage2D(face, mipLevel, 0, 0, pixels.width, pixels.height, t.t.internalFmt, buffer);
  1334. } else {
  1335. if( t.flags.has(IsArray) || t.flags.has(Is3D) )
  1336. gl.texSubImage3D(face, mipLevel, 0, 0, side, pixels.width, pixels.height, 1, getChannels(t.t), t.t.pixelFmt, buffer);
  1337. else
  1338. gl.texSubImage2D(face, mipLevel, 0, 0, pixels.width, pixels.height, getChannels(t.t), t.t.pixelFmt, buffer);
  1339. }
  1340. #else
  1341. throw "Not implemented";
  1342. #end
  1343. t.flags.set(WasCleared);
  1344. restoreBind();
  1345. }
  1346. override function uploadBufferData( b : h3d.Buffer, startVertex : Int, vertexCount : Int, buf : hxd.FloatBuffer, bufPos : Int ) {
  1347. var stride = b.format.strideBytes;
  1348. gl.bindBuffer(GL.ARRAY_BUFFER, b.vbuf);
  1349. #if hl
  1350. var data = #if hl hl.Bytes.getArray(buf.getNative()) #else buf.getNative() #end;
  1351. gl.bufferSubData(GL.ARRAY_BUFFER, startVertex * stride, streamData(data,bufPos * 4,vertexCount * stride), bufPos * 4 * STREAM_POS, vertexCount * stride);
  1352. #else
  1353. var buf : Float32Array = buf.getNative();
  1354. var sub = new Float32Array(buf.buffer, bufPos * 4, (vertexCount * stride) >> 2);
  1355. gl.bufferSubData(GL.ARRAY_BUFFER, startVertex * stride, sub);
  1356. #end
  1357. gl.bindBuffer(GL.ARRAY_BUFFER, null);
  1358. }
  1359. override function uploadBufferBytes( b : h3d.Buffer, startVertex : Int, vertexCount : Int, buf : haxe.io.Bytes, bufPos : Int ) {
  1360. var stride = b.format.strideBytes;
  1361. var type = b.flags.has(IndexBuffer) ? GL.ELEMENT_ARRAY_BUFFER : GL.ARRAY_BUFFER;
  1362. gl.bindBuffer(type, b.vbuf);
  1363. #if hl
  1364. gl.bufferSubData(type, startVertex * stride, streamData(buf.getData(),bufPos,vertexCount * stride), bufPos * STREAM_POS, vertexCount * stride);
  1365. #else
  1366. var sub = new Uint8Array(buf.getData(), bufPos, vertexCount * stride);
  1367. gl.bufferSubData(type, startVertex * stride, sub);
  1368. #end
  1369. gl.bindBuffer(type, null);
  1370. if( b.flags.has(IndexBuffer) ) curIndexBuffer = null;
  1371. }
  1372. override function readBufferBytes(b:h3d.Buffer, startVertex:Int, vertexCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
  1373. var stride = b.format.strideBytes;
  1374. var totalSize = vertexCount*stride;
  1375. var type = b.flags.has(IndexBuffer) ? GL.ELEMENT_ARRAY_BUFFER : GL.ARRAY_BUFFER;
  1376. gl.bindBuffer(type, b.vbuf);
  1377. gl.getBufferSubData(type, startVertex*stride, @:privateAccess buf.b, bufPos*STREAM_POS, totalSize);
  1378. gl.bindBuffer(type, null);
  1379. }
  1380. override function uploadIndexData( i : h3d.Buffer, startIndice : Int, indiceCount : Int, buf : hxd.IndexBuffer, bufPos : Int ) {
  1381. var bits = i.format.strideBytes >> 1;
  1382. gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, i.vbuf);
  1383. #if hl
  1384. var data = #if hl hl.Bytes.getArray(buf.getNative()) #else buf.getNative() #end;
  1385. gl.bufferSubData(GL.ELEMENT_ARRAY_BUFFER, startIndice << bits, streamData(data,bufPos << bits,indiceCount << bits), (bufPos << bits) * STREAM_POS, indiceCount << bits);
  1386. #else
  1387. var buf = new Uint16Array(buf.getNative());
  1388. var sub = new Uint16Array(buf.buffer, bufPos << bits, indiceCount);
  1389. gl.bufferSubData(GL.ELEMENT_ARRAY_BUFFER, startIndice << bits, sub);
  1390. #end
  1391. gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, null);
  1392. curIndexBuffer = null;
  1393. }
  1394. inline function updateDivisor( a : CompiledAttribute ) {
  1395. if( currentDivisor[a.index] != a.divisor ) {
  1396. currentDivisor[a.index] = a.divisor;
  1397. gl.vertexAttribDivisor(a.index, a.divisor);
  1398. }
  1399. }
  1400. override function selectBuffer( b : h3d.Buffer ) {
  1401. if( b == curBuffer )
  1402. return;
  1403. if( curShader == null )
  1404. throw "No shader selected";
  1405. #if multidriver
  1406. if( @:privateAccess b.engine.driver != this )
  1407. throw "Invalid buffer context";
  1408. #end
  1409. gl.bindBuffer(GL.ARRAY_BUFFER, b.vbuf);
  1410. curBuffer = b;
  1411. var strideBytes = b.format.strideBytes;
  1412. var map = b.format.resolveMapping(curShader.format);
  1413. for( i => a in curShader.attribs ) {
  1414. var inf = map[i];
  1415. var norm = false;
  1416. gl.vertexAttribPointer(a.index, a.size, switch( inf.precision ) {
  1417. case F32: a.type;
  1418. case F16: GL.HALF_FLOAT;
  1419. case S8: norm = true; GL.BYTE;
  1420. case U8: norm = true; GL.UNSIGNED_BYTE;
  1421. }, norm, strideBytes, inf.offset);
  1422. updateDivisor(a);
  1423. }
  1424. }
  1425. override function selectMultiBuffers( format : hxd.BufferFormat.MultiFormat, buffers : Array<h3d.Buffer> ) {
  1426. var map = format.resolveMapping(curShader.format);
  1427. for( i => a in curShader.attribs ) {
  1428. var inf = map[i];
  1429. var b = buffers[inf.bufferIndex];
  1430. if( curBuffer != b ) {
  1431. gl.bindBuffer(GL.ARRAY_BUFFER, b.vbuf);
  1432. curBuffer = b;
  1433. }
  1434. var norm = false;
  1435. gl.vertexAttribPointer(a.index, a.size, switch( inf.precision ) {
  1436. case F32: a.type;
  1437. case F16: GL.HALF_FLOAT;
  1438. case S8: norm = true; GL.BYTE;
  1439. case U8: norm = true; GL.UNSIGNED_BYTE;
  1440. }, norm, b.format.strideBytes, inf.offset);
  1441. updateDivisor(a);
  1442. }
  1443. }
  1444. override function draw( ibuf : h3d.Buffer, startIndex : Int, ntriangles : Int ) {
  1445. if( ibuf != curIndexBuffer ) {
  1446. curIndexBuffer = ibuf;
  1447. gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, ibuf.vbuf);
  1448. }
  1449. if( ibuf.format.strideBytes == 4 )
  1450. gl.drawElements(drawMode, ntriangles * 3, GL.UNSIGNED_INT, startIndex * 4);
  1451. else
  1452. gl.drawElements(drawMode, ntriangles * 3, GL.UNSIGNED_SHORT, startIndex * 2);
  1453. }
  1454. override function allocInstanceBuffer( b : InstanceBuffer, bytes : haxe.io.Bytes ) {
  1455. #if hl
  1456. if( hasMultiIndirect ) {
  1457. var buf = gl.createBuffer();
  1458. gl.bindBuffer(GL.DRAW_INDIRECT_BUFFER, buf);
  1459. gl.bufferData(GL.DRAW_INDIRECT_BUFFER, b.commandCount * 20, streamData(bytes.getData(),0, b.commandCount * 20), GL.DYNAMIC_DRAW);
  1460. gl.bindBuffer(GL.DRAW_INDIRECT_BUFFER, null);
  1461. b.data = buf;
  1462. return;
  1463. }
  1464. #end
  1465. var data = [];
  1466. for( i in 0...b.commandCount ) {
  1467. var p = i * 5 * 4;
  1468. var indexCount = bytes.getInt32(p);
  1469. var instanceCount = bytes.getInt32(p+4);
  1470. var offIndex = bytes.getInt32(p+8);
  1471. var offVertex = bytes.getInt32(p+12);
  1472. var offInstance = bytes.getInt32(p+16);
  1473. if( offVertex != 0 || offInstance != 0 )
  1474. throw "baseVertex and baseInstance must be zero on this platform";
  1475. data.push(indexCount);
  1476. data.push(offIndex);
  1477. data.push(instanceCount);
  1478. }
  1479. b.data = data;
  1480. }
  1481. override function uploadInstanceBufferBytes(b : InstanceBuffer, startVertex : Int, vertexCount : Int, buf : haxe.io.Bytes, bufPos : Int ) {
  1482. var stride = 5*4;
  1483. #if hl
  1484. var type = GL.DRAW_INDIRECT_BUFFER;
  1485. gl.bindBuffer(type, b.data);
  1486. gl.bufferSubData(type, startVertex * stride, streamData(buf.getData(),bufPos,vertexCount * stride), bufPos * STREAM_POS, vertexCount * stride);
  1487. #else
  1488. var type = GL.ARRAY_BUFFER;
  1489. var sub = new Uint8Array(buf.getData(), bufPos, vertexCount * stride);
  1490. gl.bufferSubData(type, startVertex * stride, sub);
  1491. #end
  1492. gl.bindBuffer(type, null);
  1493. }
  1494. override function disposeInstanceBuffer(b:InstanceBuffer) {
  1495. b.data = null;
  1496. }
  1497. override function drawInstanced( ibuf : h3d.Buffer, commands : InstanceBuffer ) {
  1498. if( ibuf != curIndexBuffer ) {
  1499. curIndexBuffer = ibuf;
  1500. gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, ibuf.vbuf);
  1501. }
  1502. var kind, size;
  1503. if( ibuf.format.strideBytes == 4 ) {
  1504. kind = GL.UNSIGNED_INT;
  1505. size = 4;
  1506. } else {
  1507. kind = GL.UNSIGNED_SHORT;
  1508. size = 2;
  1509. }
  1510. #if !js
  1511. if( hasMultiIndirect && commands.data != null ) {
  1512. #if (haxe_ver < 5)
  1513. var arr = new hl.NativeArray<Int>(1);
  1514. arr[0] = commands.offset * InstanceBuffer.ELEMENT_SIZE;
  1515. var commandOffset : hl.Bytes = (cast arr : hl.NativeArray<hl.Bytes>)[0];
  1516. #else
  1517. var commandOffset : hl.Bytes = hl.Api.unsafeCast(commands.offset * InstanceBuffer.ELEMENT_SIZE);
  1518. #end
  1519. gl.bindBuffer(GL.DRAW_INDIRECT_BUFFER, commands.data);
  1520. #if (hlsdl >= version("1.15.0"))
  1521. if ( commands.countBuffer != null && hasMultiIndirectCount ) {
  1522. #if (haxe_ver < 5)
  1523. var arr = new hl.NativeArray<Int>(1);
  1524. arr[0] = commands.countOffset * 4;
  1525. var countOffset : hl.Bytes = (cast arr : hl.NativeArray<hl.Bytes>)[0];
  1526. #else
  1527. var countOffset : hl.Bytes = hl.Api.unsafeCast(commands.countOffset * 4);
  1528. #end
  1529. gl.bindBuffer(GL.PARAMETER_BUFFER, commands.countBuffer);
  1530. gl.multiDrawElementsIndirectCount(drawMode, kind, commandOffset, countOffset, commands.commandCount, 0);
  1531. } else
  1532. #end
  1533. gl.multiDrawElementsIndirect(drawMode, kind, commandOffset, commands.commandCount, 0);
  1534. gl.bindBuffer(GL.DRAW_INDIRECT_BUFFER, null);
  1535. return;
  1536. }
  1537. #end
  1538. var args : Array<Int> = commands.data;
  1539. if( args != null ) {
  1540. var p = 0;
  1541. for( i in 0...Std.int(args.length/3) )
  1542. gl.drawElementsInstanced(drawMode, args[p++], kind, args[p++]*size, args[p++]);
  1543. } else
  1544. gl.drawElementsInstanced(drawMode, commands.indexCount, kind, commands.startIndex*size, commands.commandCount);
  1545. }
  1546. override function end() {
  1547. // no gl finish or flush !
  1548. }
  1549. override function present() {
  1550. #if hlsdl
  1551. @:privateAccess hxd.Window.inst.window.present();
  1552. #elseif usesys
  1553. haxe.System.present();
  1554. #end
  1555. }
  1556. override function isDisposed() {
  1557. return gl.isContextLost();
  1558. }
  1559. override function setRenderZone( x : Int, y : Int, width : Int, height : Int ) {
  1560. if( x == 0 && y == 0 && width < 0 && height < 0 )
  1561. gl.disable(GL.SCISSOR_TEST);
  1562. else {
  1563. gl.enable(GL.SCISSOR_TEST);
  1564. if( curTarget == null )
  1565. y = bufferHeight - (y + height);
  1566. gl.scissor(x, y, width, height);
  1567. }
  1568. }
  1569. function setDrawBuffers( k : Int ) {
  1570. #if js
  1571. if( glES >= 3 )
  1572. gl.drawBuffers(CBUFFERS[k]);
  1573. else if( mrtExt != null )
  1574. mrtExt.drawBuffersWEBGL(CBUFFERS[k]);
  1575. #elseif (hlsdl || usegl)
  1576. gl.drawBuffers(k, CBUFFERS);
  1577. #end
  1578. }
  1579. function unbindTargets() {
  1580. if( curTarget != null && numTargets > 1 ) {
  1581. while( numTargets > 1 ) {
  1582. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0 + (--numTargets), GL.TEXTURE_2D, null, 0);
  1583. curTargets[numTargets] = null;
  1584. }
  1585. setDrawBuffers(1);
  1586. }
  1587. }
  1588. override function capturePixels(tex:h3d.mat.Texture, layer:Int, mipLevel:Int, ?region:h2d.col.IBounds) {
  1589. var pixels : hxd.Pixels;
  1590. var x : Int, y : Int, w : Int, h : Int;
  1591. if (region != null) {
  1592. if (region.xMax > tex.width) region.xMax = tex.width;
  1593. if (region.yMax > tex.height) region.yMax = tex.height;
  1594. if (region.xMin < 0) region.xMin = 0;
  1595. if (region.yMin < 0) region.yMin = 0;
  1596. w = region.width;
  1597. h = region.height;
  1598. x = region.xMin;
  1599. y = region.yMin;
  1600. } else {
  1601. w = tex.width;
  1602. h = tex.height;
  1603. x = 0;
  1604. y = 0;
  1605. }
  1606. w >>= mipLevel;
  1607. h >>= mipLevel;
  1608. if( w == 0 ) w = 1;
  1609. if( h == 0 ) h = 1;
  1610. pixels = hxd.Pixels.alloc(w, h, tex.format);
  1611. var old = curTarget;
  1612. var oldCount = numTargets;
  1613. var oldLayer = curTargetLayer;
  1614. var oldMip = curTargetMip;
  1615. if( oldCount > 1 ) {
  1616. numTargets = 1;
  1617. for( i in 1...oldCount )
  1618. if( curTargets[i] == tex )
  1619. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0+i,GL.TEXTURE_2D,null,0);
  1620. }
  1621. setRenderTarget(tex, layer, mipLevel);
  1622. captureSubRenderBuffer(pixels, x, y);
  1623. setRenderTarget(old, oldLayer, oldMip);
  1624. if( oldCount > 1 ) {
  1625. for( i in 1...oldCount )
  1626. if( curTargets[i] == tex )
  1627. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0+i,GL.TEXTURE_2D,tex.t.t,0);
  1628. setDrawBuffers(oldCount);
  1629. numTargets = oldCount;
  1630. }
  1631. return pixels;
  1632. }
  1633. override function setRenderTarget( tex : h3d.mat.Texture, layer = 0, mipLevel = 0, depthBinding : h3d.Engine.DepthBinding = ReadWrite ) {
  1634. unbindTargets();
  1635. curTarget = tex;
  1636. if( tex == null ) {
  1637. gl.bindFramebuffer(GL.FRAMEBUFFER, null);
  1638. gl.viewport(0, 0, bufferWidth, bufferHeight);
  1639. return;
  1640. }
  1641. if( tex.depthBuffer != null && (tex.depthBuffer.width != tex.width || tex.depthBuffer.height != tex.height) )
  1642. throw "Invalid depth buffer size : does not match render target size";
  1643. if( mipLevel > 0 && glES == 1 ) throw "Cannot render to mipLevel in WebGL1, use upload() instead";
  1644. if( tex.t == null )
  1645. tex.alloc();
  1646. if( tex.flags.has(MipMapped) && !tex.flags.has(WasCleared) ) {
  1647. var bind = getBindType(tex);
  1648. gl.bindTexture(bind, tex.t.t);
  1649. gl.generateMipmap(bind);
  1650. restoreBind();
  1651. }
  1652. tex.lastFrame = frame;
  1653. curTargetLayer = layer;
  1654. curTargetMip = mipLevel;
  1655. #if multidriver
  1656. if( tex.t.driver != this )
  1657. throw "Invalid texture context";
  1658. #end
  1659. gl.bindFramebuffer(GL.FRAMEBUFFER, commonFB);
  1660. if( tex.flags.has(IsArray) || tex.flags.has(Is3D) )
  1661. gl.framebufferTextureLayer(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, tex.t.t, mipLevel, layer);
  1662. else
  1663. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, tex.flags.has(Cube) ? CUBE_FACES[layer] : GL.TEXTURE_2D, tex.t.t, mipLevel);
  1664. if( tex.depthBuffer != null && depthBinding != NotBound ) {
  1665. // Depthbuffer and stencilbuffer are combined in one buffer, created with GL.DEPTH_STENCIL
  1666. if(tex.depthBuffer.hasStencil() && tex.depthBuffer.format == Depth24Stencil8) {
  1667. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_STENCIL_ATTACHMENT, GL.TEXTURE_2D,@:privateAccess tex.depthBuffer.t.t, 0);
  1668. } else {
  1669. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_STENCIL_ATTACHMENT, GL.TEXTURE_2D,null,0);
  1670. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.TEXTURE_2D, @:privateAccess tex.depthBuffer.t.t,0);
  1671. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.STENCIL_ATTACHMENT, GL.TEXTURE_2D,tex.depthBuffer.hasStencil() ? @:privateAccess tex.depthBuffer.t.t : null,0);
  1672. }
  1673. } else {
  1674. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_STENCIL_ATTACHMENT, GL.TEXTURE_2D,null,0);
  1675. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.TEXTURE_2D, null,0);
  1676. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.STENCIL_ATTACHMENT, GL.TEXTURE_2D, null,0);
  1677. }
  1678. var w = tex.width >> mipLevel; if( w == 0 ) w = 1;
  1679. var h = tex.height >> mipLevel; if( h == 0 ) h = 1;
  1680. gl.viewport(0, 0, w, h);
  1681. for( i in 0...boundTextures.length )
  1682. boundTextures[i] = null;
  1683. if( !tex.flags.has(WasCleared) ) {
  1684. tex.flags.set(WasCleared); // once we draw to, do not clear again
  1685. clear(BLACK);
  1686. }
  1687. #if js
  1688. if( glDebug ) {
  1689. var code = gl.checkFramebufferStatus(GL.FRAMEBUFFER);
  1690. if( code != GL.FRAMEBUFFER_COMPLETE )
  1691. throw "Invalid frame buffer: "+code;
  1692. }
  1693. #end
  1694. }
  1695. override function setRenderTargets( textures : Array<h3d.mat.Texture>, depthBinding : h3d.Engine.DepthBinding = ReadWrite ) {
  1696. unbindTargets();
  1697. setRenderTarget(textures[0], depthBinding);
  1698. if( textures.length < 2 )
  1699. return;
  1700. numTargets = textures.length;
  1701. var needClear = false;
  1702. for( i in 1...textures.length ) {
  1703. var tex = textures[i];
  1704. if( tex.t == null )
  1705. tex.alloc();
  1706. #if multidriver
  1707. if( tex.t.driver != this )
  1708. throw "Invalid texture context";
  1709. #end
  1710. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0 + i, GL.TEXTURE_2D, tex.t.t, 0);
  1711. curTargets[i] = tex;
  1712. tex.lastFrame = frame;
  1713. if( !tex.flags.has(WasCleared) ) {
  1714. tex.flags.set(WasCleared); // once we draw to, do not clear again
  1715. needClear = true;
  1716. }
  1717. }
  1718. setDrawBuffers(textures.length);
  1719. if( needClear ) clear(BLACK);
  1720. }
  1721. override function setDepth( depthBuffer : h3d.mat.Texture ) {
  1722. unbindTargets();
  1723. curTarget = depthBuffer;
  1724. depthBuffer.lastFrame = frame;
  1725. curTargetLayer = 0;
  1726. curTargetMip = 0;
  1727. #if multidriver
  1728. if( depthBuffer.t.driver != this )
  1729. throw "Invalid texture context";
  1730. #end
  1731. gl.bindFramebuffer(GL.FRAMEBUFFER, commonFB);
  1732. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, null, 0);
  1733. if(depthBuffer.hasStencil() && depthBuffer.format == Depth24Stencil8) {
  1734. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_STENCIL_ATTACHMENT, GL.TEXTURE_2D,@:privateAccess depthBuffer.t.t, 0);
  1735. } else {
  1736. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_STENCIL_ATTACHMENT, GL.TEXTURE_2D,null,0);
  1737. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.TEXTURE_2D, @:privateAccess depthBuffer.t.t,0);
  1738. gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.STENCIL_ATTACHMENT, GL.TEXTURE_2D,depthBuffer.hasStencil() ? @:privateAccess depthBuffer.t.t : null,0);
  1739. }
  1740. var w = depthBuffer.width; if( w == 0 ) w = 1;
  1741. var h = depthBuffer.height; if( h == 0 ) h = 1;
  1742. gl.viewport(0, 0, w, h);
  1743. for( i in 0...boundTextures.length )
  1744. boundTextures[i] = null;
  1745. #if js
  1746. if( glDebug ) {
  1747. var code = gl.checkFramebufferStatus(GL.FRAMEBUFFER);
  1748. if( code != GL.FRAMEBUFFER_COMPLETE )
  1749. throw "Invalid frame buffer: "+code;
  1750. }
  1751. #end
  1752. }
  1753. override function setDepthClamp( enabled : Bool ) {
  1754. #if !js
  1755. useDepthClamp = enabled;
  1756. if ( useDepthClamp )
  1757. gl.enable(GL.DEPTH_CLAMP);
  1758. else
  1759. gl.disable(GL.DEPTH_CLAMP);
  1760. #end
  1761. }
  1762. override function setDepthBias( depthBias : Float, slopeScaledBias : Float ) {
  1763. if ( depthBias != 0 || slopeScaledBias != 0 ) {
  1764. gl.enable(GL.POLYGON_OFFSET_FILL);
  1765. gl.polygonOffset(slopeScaledBias, depthBias);
  1766. } else
  1767. gl.disable(GL.POLYGON_OFFSET_FILL);
  1768. }
  1769. override function init( onCreate : Bool -> Void, forceSoftware = false ) {
  1770. #if js
  1771. // wait until all assets have properly load
  1772. if( js.Browser.document.readyState == 'complete' )
  1773. haxe.Timer.delay(onCreate.bind(false), 1);
  1774. else {
  1775. function onLoad() {
  1776. js.Browser.window.removeEventListener("load", onLoad);
  1777. onCreate(false);
  1778. }
  1779. js.Browser.window.addEventListener("load", onLoad);
  1780. }
  1781. #else
  1782. haxe.Timer.delay(onCreate.bind(false), 1);
  1783. #end
  1784. }
  1785. override function hasFeature( f : Feature ) : Bool {
  1786. #if js
  1787. return features.get(f);
  1788. #else
  1789. return true;
  1790. #end
  1791. }
  1792. #if js
  1793. var features : Map<Feature,Bool> = new Map();
  1794. var has16Bits : Bool;
  1795. function makeFeatures() {
  1796. for( f in Type.allEnums(Feature) )
  1797. features.set(f,checkFeature(f));
  1798. if( gl.getExtension("WEBGL_compressed_texture_s3tc") != null ) {
  1799. maxCompressedTexturesSupport = 3;
  1800. if( gl.getExtension("EXT_texture_compression_bptc") != null )
  1801. maxCompressedTexturesSupport = 7;
  1802. }
  1803. if( glES < 3 )
  1804. gl.getExtension("WEBGL_depth_texture");
  1805. has16Bits = gl.getExtension("EXT_texture_norm16") != null; // 16 bit textures
  1806. }
  1807. function checkFeature( f : Feature ) {
  1808. return switch( f ) {
  1809. case HardwareAccelerated, AllocDepthBuffer, BottomLeftCoords, Wireframe:
  1810. true;
  1811. case StandardDerivatives, MultipleRenderTargets, SRGBTextures if( glES >= 3 ):
  1812. true;
  1813. case ShaderModel3 if( glES >= 3 ):
  1814. true;
  1815. case FloatTextures if( glES >= 3 ):
  1816. gl.getExtension('EXT_color_buffer_float') != null && gl.getExtension("OES_texture_float_linear") != null; // allow render to 16f/32f textures (not standard in webgl 2)
  1817. case StandardDerivatives:
  1818. gl.getExtension('OES_standard_derivatives') != null;
  1819. case FloatTextures:
  1820. gl.getExtension('OES_texture_float') != null && gl.getExtension('OES_texture_float_linear') != null &&
  1821. gl.getExtension('OES_texture_half_float') != null && gl.getExtension('OES_texture_half_float_linear') != null;
  1822. case SRGBTextures:
  1823. gl.getExtension('EXT_sRGB') != null;
  1824. case MultipleRenderTargets:
  1825. mrtExt != null || (mrtExt = gl.getExtension('WEBGL_draw_buffers')) != null;
  1826. case InstancedRendering:
  1827. return (glES >= 3) ? true : gl.getExtension("ANGLE_instanced_arrays") != null;
  1828. default:
  1829. false;
  1830. }
  1831. }
  1832. // Draws video element directly onto Texture. Used for video rendering.
  1833. private function uploadTextureVideoElement( t : h3d.mat.Texture, v : js.html.VideoElement, mipLevel : Int, side : Int ) {
  1834. var cubic = t.flags.has(Cube);
  1835. var bind = getBindType(t);
  1836. if( t.flags.has(IsArray) ) throw "TODO:texImage3D";
  1837. var face = cubic ? CUBE_FACES[side] : GL.TEXTURE_2D;
  1838. gl.bindTexture(bind, t.t.t);
  1839. gl.texSubImage2D(face, mipLevel, 0, 0, v.videoWidth, v.videoHeight, getChannels(t.t), t.t.pixelFmt, untyped v);
  1840. restoreBind();
  1841. }
  1842. #end
  1843. override function captureRenderBuffer( pixels : hxd.Pixels ) {
  1844. captureSubRenderBuffer(pixels, 0, 0);
  1845. }
  1846. function captureSubRenderBuffer( pixels : hxd.Pixels, x : Int, y : Int ) {
  1847. if( curTarget == null )
  1848. throw "Can't capture main render buffer in GL";
  1849. gl.getError(); // always discard
  1850. #if js
  1851. var buffer : ArrayBufferView = @:privateAccess pixels.bytes.b;
  1852. switch( curTarget.format ) {
  1853. case RGBA32F, R32F, RG32F, RGB32F: buffer = new Float32Array(buffer.buffer);
  1854. case RGBA16F, R16F, RG16F, RGB16F, RGBA16U, R16U, RG16U, RGB16U: buffer = new Uint16Array(buffer.buffer);
  1855. case RGB10A2, RG11B10UF: buffer = new Uint32Array(buffer.buffer);
  1856. default:
  1857. }
  1858. #else
  1859. var buffer = @:privateAccess pixels.bytes.b;
  1860. #end
  1861. #if (js || hl)
  1862. gl.readPixels(x, y, pixels.width, pixels.height, getChannels(curTarget.t), curTarget.t.pixelFmt, buffer);
  1863. var error = gl.getError();
  1864. if( error != 0 ) throw "Failed to capture pixels (error "+error+")";
  1865. @:privateAccess pixels.innerFormat = curTarget.format;
  1866. #end
  1867. }
  1868. #if hl
  1869. override function computeDispatch(x:Int = 1, y:Int = 1, z:Int = 1, barrier:Bool = true) {
  1870. GL.dispatchCompute(x,y,z);
  1871. if( barrier )
  1872. memoryBarrier();
  1873. }
  1874. override function memoryBarrier(){
  1875. GL.memoryBarrier(GL.BUFFER_UPDATE_BARRIER_BIT | GL.TEXTURE_FETCH_BARRIER_BIT);
  1876. }
  1877. override function allocQuery(kind:QueryKind) {
  1878. return { q : GL.createQuery(), kind : kind };
  1879. }
  1880. override function deleteQuery( q : Query ) {
  1881. GL.deleteQuery(q.q);
  1882. q.q = null;
  1883. }
  1884. override function beginQuery( q : Query ) {
  1885. switch( q.kind ) {
  1886. case TimeStamp:
  1887. throw "use endQuery() for timestamp queries";
  1888. case Samples:
  1889. GL.beginQuery(GL.SAMPLES_PASSED, q.q);
  1890. case TimeElapsed:
  1891. GL.beginQuery(GL.TIME_ELAPSED, q.q);
  1892. }
  1893. }
  1894. override function endQuery( q : Query ) {
  1895. switch( q.kind ) {
  1896. case TimeStamp:
  1897. GL.queryCounter(q.q, GL.TIMESTAMP);
  1898. case Samples:
  1899. GL.endQuery(GL.SAMPLES_PASSED);
  1900. case TimeElapsed:
  1901. GL.endQuery(GL.TIME_ELAPSED);
  1902. }
  1903. }
  1904. override function queryResultAvailable(q:Query) {
  1905. return GL.queryResultAvailable(q.q);
  1906. }
  1907. override function queryResult(q:Query) {
  1908. return GL.queryResult(q.q);
  1909. }
  1910. inline function debugCheckError() {
  1911. if(!debug) return;
  1912. var err = gl.getError();
  1913. if(err != GL.NO_ERROR) {
  1914. switch(err) {
  1915. case GL.INVALID_ENUM: throw "INVALID_ENUM";
  1916. case GL.INVALID_VALUE: throw "INVALID_VALUE";
  1917. case GL.INVALID_OPERATION: throw "INVALID_OPERATION";
  1918. case 1286: throw "INVALID_FRAMEBUFFER_OPERATION";
  1919. default: throw "Error: " + err;
  1920. }
  1921. }
  1922. }
  1923. #end
  1924. static var TFILTERS = [
  1925. [[GL.NEAREST,GL.NEAREST],[GL.LINEAR,GL.LINEAR]],
  1926. [[GL.NEAREST,GL.NEAREST_MIPMAP_NEAREST],[GL.LINEAR,GL.LINEAR_MIPMAP_NEAREST]],
  1927. [[GL.NEAREST,GL.NEAREST_MIPMAP_LINEAR],[GL.LINEAR,GL.LINEAR_MIPMAP_LINEAR]],
  1928. ];
  1929. static var TWRAP = [
  1930. GL.CLAMP_TO_EDGE,
  1931. GL.REPEAT,
  1932. ];
  1933. static var FACES = [
  1934. 0,
  1935. GL.FRONT,
  1936. GL.BACK,
  1937. GL.FRONT_AND_BACK,
  1938. ];
  1939. static var BLEND = [
  1940. GL.ONE,
  1941. GL.ZERO,
  1942. GL.SRC_ALPHA,
  1943. GL.SRC_COLOR,
  1944. GL.DST_ALPHA,
  1945. GL.DST_COLOR,
  1946. GL.ONE_MINUS_SRC_ALPHA,
  1947. GL.ONE_MINUS_SRC_COLOR,
  1948. GL.ONE_MINUS_DST_ALPHA,
  1949. GL.ONE_MINUS_DST_COLOR,
  1950. GL.CONSTANT_COLOR,
  1951. GL.CONSTANT_ALPHA,
  1952. GL.ONE_MINUS_CONSTANT_COLOR,
  1953. GL.ONE_MINUS_CONSTANT_ALPHA,
  1954. GL.SRC_ALPHA_SATURATE,
  1955. ];
  1956. static var COMPARE = [
  1957. GL.ALWAYS,
  1958. GL.NEVER,
  1959. GL.EQUAL,
  1960. GL.NOTEQUAL,
  1961. GL.GREATER,
  1962. GL.GEQUAL,
  1963. GL.LESS,
  1964. GL.LEQUAL,
  1965. ];
  1966. static var STENCIL_OP = [
  1967. GL.KEEP,
  1968. GL.ZERO,
  1969. GL.REPLACE,
  1970. GL.INCR,
  1971. GL.INCR_WRAP,
  1972. GL.DECR,
  1973. GL.DECR_WRAP,
  1974. GL.INVERT,
  1975. ];
  1976. static var OP = [
  1977. GL.FUNC_ADD,
  1978. GL.FUNC_SUBTRACT,
  1979. GL.FUNC_REVERSE_SUBTRACT,
  1980. #if js GL.MIN #else GL.FUNC_MIN #end,
  1981. #if js GL.MAX #else GL.FUNC_MAX #end,
  1982. ];
  1983. static var CUBE_FACES = [
  1984. GL.TEXTURE_CUBE_MAP_POSITIVE_X,
  1985. GL.TEXTURE_CUBE_MAP_NEGATIVE_X,
  1986. GL.TEXTURE_CUBE_MAP_POSITIVE_Y,
  1987. GL.TEXTURE_CUBE_MAP_NEGATIVE_Y,
  1988. GL.TEXTURE_CUBE_MAP_POSITIVE_Z,
  1989. GL.TEXTURE_CUBE_MAP_NEGATIVE_Z,
  1990. ];
  1991. static var CBUFFERS =
  1992. #if (hlsdl || usegl)
  1993. hl.Bytes.getArray([for( i in 0...32 ) GL.COLOR_ATTACHMENT0 + i]);
  1994. #elseif js
  1995. [for( i in 0...32 ) [for( k in 0...i ) GL.COLOR_ATTACHMENT0 + k]];
  1996. #else
  1997. null;
  1998. #end
  1999. }
  2000. #end