DirectXDriver.hx 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526
  1. package h3d.impl;
  2. #if (hldx && !dx12)
  3. import h3d.impl.Driver;
  4. import dx.Driver;
  5. import h3d.mat.Pass;
  6. private class ShaderContext {
  7. public var shader : Shader;
  8. public var globalsSize : Int;
  9. public var paramsSize : Int;
  10. public var texturesCount : Int;
  11. public var bufferCount : Int;
  12. public var paramsContent : hl.Bytes;
  13. public var globals : dx.Resource;
  14. public var params : dx.Resource;
  15. public var samplersMap : Array<Int>;
  16. public var texturesTypes : Array<hxsl.Ast.Type>;
  17. #if debug
  18. public var debugSource : String;
  19. #end
  20. public function new(shader) {
  21. this.shader = shader;
  22. }
  23. }
  24. private class CompiledShader {
  25. public var vertex : ShaderContext;
  26. public var fragment : ShaderContext;
  27. public var format : hxd.BufferFormat;
  28. public var perInst : Array<Int>;
  29. public var layouts : Map<Int, Layout>;
  30. public var vertexBytes : haxe.io.Bytes;
  31. public function new() {
  32. }
  33. }
  34. enum PipelineKind {
  35. Vertex;
  36. Pixel;
  37. }
  38. class PipelineState {
  39. public var kind : PipelineKind;
  40. public var samplers = new hl.NativeArray<SamplerState>(64);
  41. public var samplerBits = new Array<Int>();
  42. public var resources = new hl.NativeArray<ShaderResourceView>(64);
  43. public var buffers = new hl.NativeArray<dx.Resource>(16);
  44. public function new(kind) {
  45. this.kind = kind;
  46. for(i in 0...64 ) samplerBits[i] = -1;
  47. }
  48. }
  49. class DirectXDriver extends h3d.impl.Driver {
  50. static inline var NTARGETS = 8;
  51. static inline var VIEWPORTS_ELTS = 6 * NTARGETS;
  52. static inline var RECTS_ELTS = 4 * NTARGETS;
  53. static inline var BLEND_FACTORS = NTARGETS;
  54. var driver : DriverInstance;
  55. var shaders : Map<Int,CompiledShader>;
  56. var hasDeviceError = false;
  57. var defaultTarget : RenderTargetView;
  58. var defaultDepth : Texture;
  59. var defaultDepthInst : h3d.mat.Texture;
  60. var extraDepthInst : h3d.mat.Texture;
  61. var viewport : hl.BytesAccess<hl.F32> = new hl.Bytes(4 * VIEWPORTS_ELTS);
  62. var rects : hl.BytesAccess<Int> = new hl.Bytes(4 * RECTS_ELTS);
  63. var box = new dx.Resource.ResourceBox();
  64. var strides : Array<Int> = [];
  65. var offsets : Array<Int> = [];
  66. var currentShader : CompiledShader;
  67. var currentIndex : h3d.Buffer;
  68. var currentDepth : Texture;
  69. var currentLayout : Layout;
  70. var currentTargets = new hl.NativeArray<RenderTargetView>(16);
  71. var currentTargetResources = new hl.NativeArray<ShaderResourceView>(16);
  72. var vertexShader : PipelineState;
  73. var pixelShader : PipelineState;
  74. var currentVBuffers = new hl.NativeArray<dx.Resource>(16);
  75. var frame : Int;
  76. var currentMaterialBits = -1;
  77. var currentStencilMaskBits = -1;
  78. var currentStencilOpBits = -1;
  79. var currentStencilRef = 0;
  80. var currentColorMask = -1;
  81. var currentColorMaskIndex = -1;
  82. var colorMaskIndexes : Map<Int, Int>;
  83. var colorMaskIndex = 1;
  84. var targetsCount = 1;
  85. var allowDraw = false;
  86. var maxSamplers = 16;
  87. var depthStates : Map<Int,{ def : DepthStencilState, stencils : Array<{ op : Int, mask : Int, state : DepthStencilState }> }>;
  88. var blendStates : Map<Int,BlendState>;
  89. var rasterStates : Map<Int,RasterState>;
  90. var samplerStates : Map<Int,SamplerState>;
  91. var currentDepthState : DepthStencilState;
  92. var currentBlendState : BlendState;
  93. var currentRasterState : RasterState;
  94. var blendFactors : hl.BytesAccess<hl.F32> = new hl.Bytes(4 * BLEND_FACTORS);
  95. var outputWidth : Int;
  96. var outputHeight : Int;
  97. var hasScissor = false;
  98. var shaderVersion : String;
  99. var window : dx.Window;
  100. var curTexture : h3d.mat.Texture;
  101. var mapCount : Int;
  102. var updateResCount : Int;
  103. var onContextLost : Void -> Void;
  104. public var backBufferFormat : dx.Format = R8G8B8A8_UNORM;
  105. public var depthStencilFormat : dx.Format = D24_UNORM_S8_UINT;
  106. public function new() {
  107. window = @:privateAccess dx.Window.windows[0];
  108. Driver.setErrorHandler(onDXError);
  109. reset();
  110. }
  111. public dynamic function getDriverFlags() : dx.Driver.DriverInitFlags {
  112. var options : dx.Driver.DriverInitFlags = None;
  113. #if debug
  114. options |= DebugLayer;
  115. #end
  116. return options;
  117. }
  118. function reset() {
  119. allowDraw = false;
  120. targetsCount = 1;
  121. currentMaterialBits = -1;
  122. currentStencilMaskBits = -1;
  123. currentStencilOpBits = -1;
  124. if( shaders != null ) {
  125. for( s in shaders ) {
  126. s.fragment.shader.release();
  127. s.vertex.shader.release();
  128. for( l in s.layouts )
  129. l.release();
  130. s.layouts = [];
  131. }
  132. }
  133. if( depthStates != null ) for( s in depthStates ) { if( s.def != null ) s.def.release(); for( s in s.stencils ) if( s.state != null ) s.state.release(); }
  134. if( blendStates != null ) for( s in blendStates ) if( s != null ) s.release();
  135. if( rasterStates != null ) for( s in rasterStates ) if( s != null ) s.release();
  136. if( samplerStates != null ) for( s in samplerStates ) if( s != null ) s.release();
  137. shaders = new Map();
  138. depthStates = new Map();
  139. blendStates = new Map();
  140. rasterStates = new Map();
  141. samplerStates = new Map();
  142. vertexShader = new PipelineState(Vertex);
  143. pixelShader = new PipelineState(Pixel);
  144. colorMaskIndexes = new Map();
  145. try
  146. driver = Driver.create(window, backBufferFormat, getDriverFlags())
  147. catch( e : Dynamic )
  148. throw "Failed to initialize DirectX driver (" + e + ")";
  149. if( driver == null ) throw "Failed to initialize DirectX driver";
  150. var version = Driver.getSupportedVersion();
  151. shaderVersion = if( version < 10 ) "3_0" else if( version < 11 ) "4_0" else "5_0";
  152. Driver.iaSetPrimitiveTopology(TriangleList);
  153. // Create a default depth buffer to mimic opengl.
  154. defaultDepthInst = new h3d.mat.Texture(-1, -1, Depth24Stencil8);
  155. defaultDepthInst.name = "defaultDepth";
  156. for( i in 0...VIEWPORTS_ELTS )
  157. viewport[i] = 0;
  158. for( i in 0...RECTS_ELTS )
  159. rects[i] = 0;
  160. for( i in 0...BLEND_FACTORS )
  161. blendFactors[i] = 0;
  162. }
  163. override function dispose() {
  164. Driver.disposeDriver(driver);
  165. driver = null;
  166. }
  167. function onDXError(code:Int,reason:Int,line:Int) {
  168. if( code != 0x887A0005 /*DXGI_ERROR_DEVICE_REMOVED*/ )
  169. throw "DXError "+StringTools.hex(code)+" line "+line;
  170. //if( !hasDeviceError ) trace("DX_REMOVED "+StringTools.hex(reason)+":"+line);
  171. hasDeviceError = true;
  172. }
  173. override function resize(width:Int, height:Int) {
  174. if( defaultDepth != null ) {
  175. defaultDepth.depthView.release();
  176. defaultDepth.readOnlyDepthView.release();
  177. defaultDepth.view.release();
  178. defaultDepth.res.release();
  179. }
  180. if( defaultTarget != null ) {
  181. defaultTarget.release();
  182. defaultTarget = null;
  183. }
  184. if( !Driver.resize(width, height, backBufferFormat) )
  185. throw "Failed to resize backbuffer to " + width + "x" + height;
  186. var depthDesc = new Texture2dDesc();
  187. depthDesc.width = width;
  188. depthDesc.height = height;
  189. depthDesc.format = R24G8_TYPELESS;
  190. depthDesc.usage = Default;
  191. depthDesc.mipLevels = 1;
  192. depthDesc.arraySize = 1;
  193. depthDesc.sampleCount = 1;
  194. depthDesc.sampleQuality = 0;
  195. depthDesc.bind = DepthStencil | ShaderResource;
  196. var depth = Driver.createTexture2d(depthDesc);
  197. if( depth == null ) throw "Failed to create depthBuffer";
  198. var depthView = Driver.createDepthStencilView(depth,D24_UNORM_S8_UINT, false);
  199. var readOnlyDepthView = Driver.createDepthStencilView(depth, D24_UNORM_S8_UINT, true);
  200. var vdesc = new ShaderResourceViewDesc();
  201. vdesc.format = R24_UNORM_X8_TYPELESS;
  202. vdesc.dimension = Texture2D;
  203. vdesc.arraySize = 1;
  204. vdesc.start = 0;
  205. vdesc.count = -1;
  206. var shaderView = Driver.createShaderResourceView(depth, vdesc);
  207. defaultDepth = { res : depth, view : shaderView, depthView : depthView, readOnlyDepthView : readOnlyDepthView, rt : null, mips : 0 };
  208. @:privateAccess {
  209. defaultDepthInst.t = defaultDepth;
  210. defaultDepthInst.width = width;
  211. defaultDepthInst.height = height;
  212. }
  213. var buf = Driver.getBackBuffer();
  214. defaultTarget = Driver.createRenderTargetView(buf);
  215. Driver.clearColor(defaultTarget, 0, 0, 0, 0);
  216. buf.release();
  217. outputWidth = width;
  218. outputHeight = height;
  219. setRenderTarget(null);
  220. if( extraDepthInst != null ) @:privateAccess {
  221. extraDepthInst.width = width;
  222. extraDepthInst.height = height;
  223. if( extraDepthInst.t != null ) disposeDepthBuffer(extraDepthInst);
  224. extraDepthInst.t = allocDepthBuffer(extraDepthInst);
  225. }
  226. }
  227. override function begin(frame:Int) {
  228. mapCount = 0;
  229. updateResCount = 0;
  230. this.frame = frame;
  231. setRenderTarget(null);
  232. }
  233. override function isDisposed() {
  234. return hasDeviceError;
  235. }
  236. override function init( onCreate : Bool -> Void, forceSoftware = false ) {
  237. onContextLost = onCreate.bind(true);
  238. haxe.Timer.delay(onCreate.bind(false), 1);
  239. }
  240. override function clear(?color:h3d.Vector4, ?depth:Float, ?stencil:Int) {
  241. if( color != null ) {
  242. for( i in 0...targetsCount )
  243. Driver.clearColor(currentTargets[i], color.r, color.g, color.b, color.a);
  244. if (targetsCount == 0)
  245. Driver.clearColor(defaultTarget, color.r, color.g, color.b, color.a);
  246. }
  247. if( currentDepth != null && (depth != null || stencil != null) )
  248. Driver.clearDepthStencilView(currentDepth.depthView, depth, stencil);
  249. }
  250. override function getDriverName(details:Bool) {
  251. var desc = "DirectX" + Driver.getSupportedVersion();
  252. if( details ) desc += " " + Driver.getDeviceName();
  253. return desc;
  254. }
  255. public function forceDeviceError() {
  256. hasDeviceError = true;
  257. }
  258. override function present() {
  259. if( defaultTarget == null ) return;
  260. var old = hxd.System.allowTimeout;
  261. if( old ) hxd.System.allowTimeout = false;
  262. Driver.present(window.vsync ? 1 : 0, None);
  263. if( old ) hxd.System.allowTimeout = true;
  264. if( hasDeviceError ) {
  265. Sys.println("----------- OnContextLost ----------");
  266. hasDeviceError = false;
  267. dispose();
  268. reset();
  269. onContextLost();
  270. }
  271. }
  272. override function getDefaultDepthBuffer():h3d.mat.Texture {
  273. // Create an extra depth buffer to fit opengl default frame buffer.
  274. if( extraDepthInst == null ) @:privateAccess {
  275. extraDepthInst = new h3d.mat.Texture(0, 0, Depth24Stencil8);
  276. extraDepthInst.name = "extraDepth";
  277. extraDepthInst.width = outputWidth;
  278. extraDepthInst.height = outputHeight;
  279. extraDepthInst.t = allocDepthBuffer(extraDepthInst);
  280. }
  281. return extraDepthInst;
  282. }
  283. override function allocBuffer(b:Buffer):GPUBuffer {
  284. var size = b.getMemSize();
  285. var res = b.flags.has(UniformBuffer) ? dx.Driver.createBuffer(size, Dynamic, ConstantBuffer, CpuWrite, None, 0, null) :
  286. dx.Driver.createBuffer(size, Default, b.flags.has(IndexBuffer) ? IndexBuffer : VertexBuffer, None, None, 0, null);
  287. if( res == null ) return null;
  288. return res;
  289. }
  290. override function allocDepthBuffer( b : h3d.mat.Texture ) : Texture {
  291. var depthDesc = new Texture2dDesc();
  292. depthDesc.width = b.width;
  293. depthDesc.height = b.height;
  294. depthDesc.mipLevels = 1;
  295. depthDesc.arraySize = 1;
  296. depthDesc.format = R24G8_TYPELESS;
  297. depthDesc.sampleCount = 1;
  298. depthDesc.sampleQuality = 0;
  299. depthDesc.usage = Default;
  300. depthDesc.bind = DepthStencil | ShaderResource;
  301. var depth = Driver.createTexture2d(depthDesc);
  302. if( depth == null )
  303. return null;
  304. var vdesc = new ShaderResourceViewDesc();
  305. vdesc.format = R24_UNORM_X8_TYPELESS;
  306. vdesc.dimension = Texture2D;
  307. vdesc.arraySize = 1;
  308. vdesc.start = 0;
  309. vdesc.count = -1;
  310. var srv = Driver.createShaderResourceView(depth,vdesc);
  311. var depthView = Driver.createDepthStencilView(depth,D24_UNORM_S8_UINT, false);
  312. var readOnlyDepthView = Driver.createDepthStencilView(depth, D24_UNORM_S8_UINT, true);
  313. return { res : depth, view : srv, depthView : depthView, readOnlyDepthView : readOnlyDepthView, rt : null, mips : 0 };
  314. }
  315. override function disposeDepthBuffer(b:h3d.mat.Texture) @:privateAccess {
  316. var d = b.t;
  317. b.t = null;
  318. d.depthView.release();
  319. d.readOnlyDepthView.release();
  320. d.view.release();
  321. d.res.release();
  322. }
  323. override function captureRenderBuffer( pixels : hxd.Pixels ) {
  324. var rt = curTexture;
  325. if( rt == null )
  326. throw "Can't capture main render buffer in DirectX";
  327. captureTexPixels(pixels, rt, 0, 0);
  328. }
  329. override function isSupportedFormat( fmt : hxd.PixelFormat ) {
  330. return switch( fmt ) {
  331. case RGB8, RGB16F, ARGB, BGRA, SRGB, RGB16U: false;
  332. default: true;
  333. }
  334. }
  335. function getTextureFormat( t : h3d.mat.Texture ) : dx.Format {
  336. return switch( t.format ) {
  337. case RGBA: R8G8B8A8_UNORM;
  338. case RGBA16F: R16G16B16A16_FLOAT;
  339. case RGBA32F: R32G32B32A32_FLOAT;
  340. case R32F: R32_FLOAT;
  341. case R16F: R16_FLOAT;
  342. case R8: R8_UNORM;
  343. case RG8: R8G8_UNORM;
  344. case RG16F: R16G16_FLOAT;
  345. case RG32F: R32G32_FLOAT;
  346. case RGB32F: R32G32B32_FLOAT;
  347. case RGB10A2: R10G10B10A2_UNORM;
  348. case RG11B10UF: R11G11B10_FLOAT;
  349. case SRGB_ALPHA: R8G8B8A8_UNORM_SRGB;
  350. case R16U: R16_UNORM;
  351. case RG16U: R16G16_UNORM;
  352. case RGBA16U: R16G16B16A16_UNORM;
  353. case S3TC(n):
  354. switch( n ) {
  355. case 1: BC1_UNORM;
  356. case 2: BC2_UNORM;
  357. case 3: BC3_UNORM;
  358. case 4: BC4_UNORM;
  359. case 5: BC5_UNORM;
  360. case 6: BC6H_UF16;
  361. case 7: BC7_UNORM;
  362. default: throw "assert";
  363. }
  364. default: throw "Unsupported texture format " + t.format;
  365. }
  366. }
  367. override function allocTexture(t:h3d.mat.Texture):Texture {
  368. var mips = 1;
  369. if( t.flags.has(MipMapped) )
  370. mips = t.mipLevels;
  371. var rt = t.flags.has(Target);
  372. var isCube = t.flags.has(Cube);
  373. var isArray = t.flags.has(IsArray);
  374. var desc = new Texture2dDesc();
  375. desc.width = t.width;
  376. desc.height = t.height;
  377. desc.format = getTextureFormat(t);
  378. if( t.format.match(S3TC(_)) && (t.width & 3 != 0 || t.height & 3 != 0) )
  379. throw t+" is compressed "+t.width+"x"+t.height+" but should be a 4x4 multiple";
  380. desc.usage = Default;
  381. desc.bind = ShaderResource;
  382. desc.mipLevels = mips;
  383. if( rt )
  384. desc.bind |= RenderTarget;
  385. if( isCube ) {
  386. desc.arraySize = 6;
  387. desc.misc |= TextureCube;
  388. }
  389. if( isArray )
  390. desc.arraySize = t.layerCount;
  391. if( t.flags.has(MipMapped) && !t.flags.has(ManualMipMapGen) ) {
  392. if( t.format.match(S3TC(_)) )
  393. throw "Cannot generate mipmaps for compressed texture "+t;
  394. desc.bind |= RenderTarget;
  395. desc.misc |= GenerateMips;
  396. }
  397. var tex = Driver.createTexture2d(desc);
  398. if( tex == null )
  399. return null;
  400. t.lastFrame = frame;
  401. t.flags.unset(WasCleared);
  402. return { res : tex, view : makeTexView(t, tex, 0), rt : rt ? [] : null, mips : mips };
  403. }
  404. function makeTexView( t : h3d.mat.Texture, tex, startMip ) {
  405. var isCube = t.flags.has(Cube);
  406. var isArray = t.flags.has(IsArray);
  407. var vdesc = new ShaderResourceViewDesc();
  408. vdesc.format = getTextureFormat(t);
  409. vdesc.dimension = isCube ? TextureCube : isArray ? Texture2DArray : Texture2D;
  410. vdesc.arraySize = isArray ? t.layerCount : isCube ? 6 : 0;
  411. vdesc.start = startMip; // top mip level
  412. vdesc.count = -1; // all mip levels
  413. return Driver.createShaderResourceView(tex, vdesc);
  414. }
  415. override function disposeTexture( t : h3d.mat.Texture ) {
  416. var tt = t.t;
  417. if( tt == null ) return;
  418. t.t = null;
  419. if( tt.view != null ) tt.view.release();
  420. if( tt.res != null ) tt.res.release();
  421. if( tt.views != null )
  422. for( v in tt.views )
  423. if( v != null )
  424. v.release();
  425. if( tt.rt != null )
  426. for( rt in tt.rt )
  427. if( rt != null )
  428. rt.release();
  429. }
  430. override function disposeBuffer(b:Buffer) {
  431. b.vbuf.release();
  432. }
  433. override function generateMipMaps(texture:h3d.mat.Texture) {
  434. if( hasDeviceError ) return;
  435. Driver.generateMips(texture.t.view);
  436. }
  437. function updateBuffer( res : dx.Resource, bytes : hl.Bytes, startByte : Int, bytesCount : Int ) {
  438. box.left = startByte;
  439. box.top = 0;
  440. box.front = 0;
  441. box.right = startByte + bytesCount;
  442. box.bottom = 1;
  443. box.back = 1;
  444. res.updateSubresource(0, box, bytes, 0, 0);
  445. updateResCount++;
  446. }
  447. override function uploadIndexData(i:Buffer, startIndice:Int, indiceCount:Int, buf:hxd.IndexBuffer, bufPos:Int) {
  448. if( hasDeviceError ) return;
  449. var bits = i.format.strideBytes >> 1;
  450. updateBuffer(i.vbuf, hl.Bytes.getArray(buf.getNative()).offset(bufPos << bits), startIndice << bits, indiceCount << bits);
  451. }
  452. override function uploadBufferData(b:Buffer, startVertex:Int, vertexCount:Int, buf:hxd.FloatBuffer, bufPos:Int) {
  453. if( hasDeviceError ) return;
  454. var data = hl.Bytes.getArray(buf.getNative()).offset(bufPos<<2);
  455. if( b.flags.has(UniformBuffer) ) {
  456. if( startVertex != 0 ) throw "assert";
  457. var ptr = b.vbuf.map(0, WriteDiscard, true, null);
  458. if( ptr == null ) throw "Can't map buffer";
  459. ptr.blit(0, data, 0, vertexCount * b.format.strideBytes);
  460. b.vbuf.unmap(0);
  461. return;
  462. }
  463. updateBuffer(b.vbuf, data, startVertex * b.format.strideBytes, vertexCount * b.format.strideBytes);
  464. }
  465. override function uploadBufferBytes(b:Buffer, startVertex:Int, vertexCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
  466. if( hasDeviceError ) return;
  467. if( b.flags.has(UniformBuffer) ) {
  468. if( startVertex != 0 ) throw "assert";
  469. var ptr = b.vbuf.map(0, WriteDiscard, true, null);
  470. if( ptr == null ) throw "Can't map buffer";
  471. ptr.blit(0, buf, 0, vertexCount * b.format.strideBytes);
  472. b.vbuf.unmap(0);
  473. return;
  474. }
  475. updateBuffer(b.vbuf, @:privateAccess buf.b.offset(bufPos), startVertex * b.format.strideBytes, vertexCount * b.format.strideBytes);
  476. }
  477. override function readBufferBytes(b:Buffer, startVertex:Int, vertexCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
  478. var stride = b.format.strideBytes;
  479. var tmp = dx.Driver.createBuffer(vertexCount * stride, Staging, None, CpuRead | CpuWrite, None, 0, null);
  480. box.left = startVertex * stride;
  481. box.top = 0;
  482. box.front = 0;
  483. box.right = (startVertex + vertexCount) * stride;
  484. box.bottom = 1;
  485. box.back = 1;
  486. tmp.copySubresourceRegion(0, 0, 0, 0, b.vbuf, 0, box);
  487. var ptr = tmp.map(0, Read, true, null);
  488. @:privateAccess buf.b.blit(bufPos, ptr, 0, vertexCount * stride);
  489. tmp.unmap(0);
  490. tmp.release();
  491. }
  492. override function capturePixels(tex:h3d.mat.Texture, layer:Int, mipLevel:Int, ?region:h2d.col.IBounds) : hxd.Pixels {
  493. var pixels : hxd.Pixels;
  494. if (region != null) {
  495. if (region.xMax > tex.width) region.xMax = tex.width;
  496. if (region.yMax > tex.height) region.yMax = tex.height;
  497. if (region.xMin < 0) region.xMin = 0;
  498. if (region.yMin < 0) region.yMin = 0;
  499. var w = region.width >> mipLevel;
  500. var h = region.height >> mipLevel;
  501. if( w == 0 ) w = 1;
  502. if( h == 0 ) h = 1;
  503. pixels = hxd.Pixels.alloc(w, h, tex.format);
  504. captureTexPixels(pixels, tex, layer, mipLevel, region.xMin, region.yMin);
  505. } else {
  506. var w = tex.width >> mipLevel;
  507. var h = tex.height >> mipLevel;
  508. if( w == 0 ) w = 1;
  509. if( h == 0 ) h = 1;
  510. pixels = hxd.Pixels.alloc(w, h, tex.format);
  511. captureTexPixels(pixels, tex, layer, mipLevel);
  512. }
  513. return pixels;
  514. }
  515. function captureTexPixels( pixels: hxd.Pixels, tex:h3d.mat.Texture, layer:Int, mipLevel:Int, x : Int = 0, y : Int = 0) {
  516. if( pixels.width == 0 || pixels.height == 0 )
  517. return pixels;
  518. var desc = new Texture2dDesc();
  519. desc.width = pixels.width;
  520. desc.height = pixels.height;
  521. desc.access = CpuRead | CpuWrite;
  522. desc.usage = Staging;
  523. desc.format = getTextureFormat(tex);
  524. if( hasDeviceError ) throw "Can't capture if device disposed";
  525. var tmp = dx.Driver.createTexture2d(desc);
  526. if( tmp == null )
  527. throw "Capture failed: can't create tmp texture";
  528. if (x != 0 || y != 0) {
  529. box.left = x;
  530. box.right = x + desc.width;
  531. box.top = y;
  532. box.bottom = y + desc.height;
  533. box.back = 1;
  534. box.front = 0;
  535. tmp.copySubresourceRegion(0,0,0,0,tex.t.res,tex.t.mips * layer + mipLevel, box);
  536. } else {
  537. tmp.copySubresourceRegion(0,0,0,0,tex.t.res,tex.t.mips * layer + mipLevel, null);
  538. }
  539. var pitch = 0;
  540. var stride = hxd.Pixels.calcStride(desc.width, tex.format);
  541. var ptr = tmp.map(0, Read, true, pitch);
  542. if( hasDeviceError ) throw "Device was disposed during capturePixels";
  543. if( pitch == stride )
  544. @:privateAccess pixels.bytes.b.blit(0, ptr, 0, desc.height * stride);
  545. else {
  546. for( i in 0...desc.height )
  547. @:privateAccess pixels.bytes.b.blit(i * stride, ptr, i * pitch, stride);
  548. }
  549. tmp.unmap(0);
  550. tmp.release();
  551. return pixels;
  552. }
  553. override function uploadTextureBitmap(t:h3d.mat.Texture, bmp:hxd.BitmapData, mipLevel:Int, side:Int) {
  554. if( hasDeviceError ) return;
  555. var pixels = bmp.getPixels();
  556. uploadTexturePixels(t, pixels, mipLevel, side);
  557. pixels.dispose();
  558. }
  559. override function uploadTexturePixels(t:h3d.mat.Texture, pixels:hxd.Pixels, mipLevel:Int, side:Int) {
  560. pixels.convert(t.format);
  561. if( hasDeviceError ) return;
  562. if( mipLevel >= t.t.mips ) throw "Mip level outside texture range : " + mipLevel + " (max = " + (t.t.mips - 1) + ")";
  563. var stride = @:privateAccess pixels.stride;
  564. switch( t.format ) {
  565. case S3TC(n): stride = pixels.width * ((n == 1 || n == 4) ? 2 : 4); // "uncompressed" stride ?
  566. default:
  567. }
  568. t.t.res.updateSubresource(mipLevel + side * t.t.mips, null, (pixels.bytes:hl.Bytes).offset(pixels.offset), stride, 0);
  569. updateResCount++;
  570. t.flags.set(WasCleared);
  571. }
  572. static inline var SCISSOR_BIT = Pass.reserved_mask;
  573. override public function selectMaterial(pass:h3d.mat.Pass) {
  574. var bits = @:privateAccess pass.bits;
  575. var mask = pass.colorMask;
  576. if( hasScissor ) bits |= SCISSOR_BIT;
  577. var stOpBits = pass.stencil != null ? @:privateAccess pass.stencil.opBits : -1;
  578. var stMaskBits = pass.stencil != null ? @:privateAccess pass.stencil.maskBits : -1;
  579. if( bits == currentMaterialBits && stOpBits == currentStencilOpBits && stMaskBits == currentStencilMaskBits && mask == currentColorMask )
  580. return;
  581. currentMaterialBits = bits;
  582. currentStencilOpBits = stOpBits;
  583. currentStencilMaskBits = stMaskBits;
  584. var depthBits = bits & (Pass.depthWrite_mask | Pass.depthTest_mask);
  585. var depths = depthStates.get(depthBits);
  586. var depth = null;
  587. var st = pass.stencil;
  588. if( depths != null ) {
  589. if( st == null )
  590. depth = depths.def;
  591. else {
  592. for( s in depths.stencils )
  593. @:privateAccess if( s.op == st.opBits && s.mask == (st.maskBits & ~h3d.mat.Stencil.reference_mask) ) {
  594. depth = s.state;
  595. break;
  596. }
  597. }
  598. }
  599. if( depth == null ) {
  600. var cmp = Pass.getDepthTest(bits);
  601. var desc = new DepthStencilDesc();
  602. desc.depthEnable = cmp != 0;
  603. desc.depthFunc = COMPARE[cmp];
  604. desc.depthWrite = Pass.getDepthWrite(bits) != 0;
  605. if( st != null ) {
  606. desc.stencilEnable = true;
  607. desc.stencilReadMask = st.readMask;
  608. desc.stencilWriteMask = st.writeMask;
  609. desc.frontFaceFunc = COMPARE[st.frontTest.getIndex()];
  610. desc.frontFacePass = STENCIL_OP[st.frontPass.getIndex()];
  611. desc.frontFaceFail = STENCIL_OP[st.frontSTfail.getIndex()];
  612. desc.frontFaceDepthFail = STENCIL_OP[st.frontDPfail.getIndex()];
  613. desc.backFaceFunc = COMPARE[st.backTest.getIndex()];
  614. desc.backFacePass = STENCIL_OP[st.backPass.getIndex()];
  615. desc.backFaceFail = STENCIL_OP[st.backSTfail.getIndex()];
  616. desc.backFaceDepthFail = STENCIL_OP[st.backDPfail.getIndex()];
  617. }
  618. depth = Driver.createDepthStencilState(desc);
  619. if( depths == null ) {
  620. depths = { def : null, stencils : [] };
  621. depthStates.set(depthBits, depths);
  622. }
  623. if( pass.stencil == null )
  624. depths.def = depth;
  625. else
  626. depths.stencils.push(@:privateAccess { op : st.opBits, mask : st.maskBits & ~h3d.mat.Stencil.reference_mask, state : depth });
  627. }
  628. if( depth != currentDepthState || (st != null && st.reference != currentStencilRef) ) {
  629. var ref = st == null ? 0 : st.reference;
  630. currentDepthState = depth;
  631. currentStencilRef = ref;
  632. Driver.omSetDepthStencilState(depth, ref);
  633. }
  634. var rasterBits = bits & (Pass.culling_mask | SCISSOR_BIT | Pass.wireframe_mask);
  635. var raster = rasterStates.get(rasterBits);
  636. if( raster == null ) {
  637. var desc = new RasterizerDesc();
  638. if ( pass.wireframe ) {
  639. desc.fillMode = WireFrame;
  640. desc.cullMode = None;
  641. } else {
  642. desc.fillMode = Solid;
  643. desc.cullMode = CULL[Pass.getCulling(bits)];
  644. }
  645. desc.depthClipEnable = true;
  646. desc.scissorEnable = bits & SCISSOR_BIT != 0;
  647. raster = Driver.createRasterizerState(desc);
  648. rasterStates.set(rasterBits, raster);
  649. }
  650. allowDraw = pass.culling != Both;
  651. if( raster != currentRasterState ) {
  652. currentRasterState = raster;
  653. Driver.rsSetState(raster);
  654. }
  655. var bitsMask = Pass.blendSrc_mask | Pass.blendDst_mask | Pass.blendAlphaSrc_mask | Pass.blendAlphaDst_mask | Pass.blendOp_mask | Pass.blendAlphaOp_mask;
  656. if ( currentColorMask != mask ) {
  657. currentColorMaskIndex = colorMaskIndexes.get(mask);
  658. if ( currentColorMaskIndex == 0 ) {
  659. if ( bitsMask & colorMaskIndex != 0 )
  660. throw "Too many color mask configurations";
  661. currentColorMaskIndex = colorMaskIndex++;
  662. colorMaskIndexes.set(mask, currentColorMaskIndex);
  663. }
  664. }
  665. currentColorMask = mask;
  666. var blendBits = (bits & bitsMask) | currentColorMaskIndex;
  667. var blend = blendStates.get(blendBits);
  668. if( blend == null ) {
  669. var desc = new RenderTargetBlendDesc();
  670. desc.srcBlend = BLEND[Pass.getBlendSrc(bits)];
  671. desc.destBlend = BLEND[Pass.getBlendDst(bits)];
  672. desc.srcBlendAlpha = BLEND_ALPHA[Pass.getBlendAlphaSrc(bits)];
  673. desc.destBlendAlpha = BLEND_ALPHA[Pass.getBlendAlphaDst(bits)];
  674. desc.blendOp = BLEND_OP[Pass.getBlendOp(bits)];
  675. desc.blendOpAlpha = BLEND_OP[Pass.getBlendAlphaOp(bits)];
  676. desc.renderTargetWriteMask = mask & 15;
  677. desc.blendEnable = !(desc.srcBlend == One && desc.srcBlendAlpha == One && desc.destBlend == Zero && desc.destBlendAlpha == Zero && desc.blendOp == Add && desc.blendOpAlpha == Add);
  678. var maski = mask >> 4;
  679. if ( maski > 0 ) {
  680. var tmp = new hl.NativeArray(targetsCount);
  681. tmp[0] = desc;
  682. for ( i in 1...targetsCount ) {
  683. if ( maski & 15 > 0 ) {
  684. var desci = new RenderTargetBlendDesc();
  685. desci.srcBlend = desc.srcBlend;
  686. desci.destBlend = desc.destBlend;
  687. desci.srcBlendAlpha = desc.srcBlendAlpha;
  688. desci.destBlendAlpha = desc.destBlendAlpha;
  689. desci.blendOp = desc.blendOp;
  690. desci.blendOpAlpha = desc.blendOpAlpha;
  691. desci.renderTargetWriteMask = maski & 15;
  692. desci.blendEnable = desc.blendEnable;
  693. tmp[i] = desci;
  694. } else {
  695. tmp[i] = desc;
  696. }
  697. maski = maski >> 4;
  698. }
  699. blend = Driver.createBlendState(false, true, tmp, targetsCount);
  700. } else {
  701. var tmp = new hl.NativeArray(1);
  702. tmp[0] = desc;
  703. blend = Driver.createBlendState(false, false, tmp, 1);
  704. }
  705. blendStates.set(blendBits, blend);
  706. }
  707. if( blend != currentBlendState ) {
  708. currentBlendState = blend;
  709. Driver.omSetBlendState(blend, blendFactors, -1);
  710. }
  711. }
  712. function getBinaryPayload( vertex : Bool, code : String ) {
  713. var bin = code.indexOf("//BIN=");
  714. if( bin >= 0 ) {
  715. var end = code.indexOf("#", bin);
  716. if( end >= 0 )
  717. return haxe.crypto.Base64.decode(code.substr(bin + 6, end - bin - 6));
  718. }
  719. if( shaderCache != null ) {
  720. var bytes = shaderCache.resolveShaderBinary(code, shaderVersion);
  721. if( bytes != null ) {
  722. try {
  723. var sh = vertex ? Driver.createVertexShader(bytes) : Driver.createPixelShader(bytes);
  724. // shader can't be compiled !
  725. if( sh == null )
  726. return null;
  727. }
  728. catch( d : Dynamic)
  729. return null;
  730. return bytes;
  731. }
  732. }
  733. return null;
  734. }
  735. function addBinaryPayload( bytes ) {
  736. return "\n//BIN=" + haxe.crypto.Base64.encode(bytes) + "#\n";
  737. }
  738. function compileShader( shader : hxsl.RuntimeShader.RuntimeShaderData, compileOnly = false ) {
  739. var h = new hxsl.HlslOut();
  740. if( shader.code == null ){
  741. shader.code = h.run(shader.data);
  742. #if !heaps_compact_mem
  743. shader.data.funs = null;
  744. #end
  745. }
  746. var bytes = getBinaryPayload(shader.kind == Vertex, shader.code);
  747. if( bytes == null ) {
  748. bytes = try dx.Driver.compileShader(shader.code, "", "main", (shader.kind==Vertex?"vs_":"ps_") + shaderVersion, OptimizationLevel3) catch( err : String ) {
  749. err = ~/^\(([0-9]+),([0-9]+)-([0-9]+)\)/gm.map(err, function(r) {
  750. var line = Std.parseInt(r.matched(1));
  751. var char = Std.parseInt(r.matched(2));
  752. var end = Std.parseInt(r.matched(3));
  753. return "\n<< " + shader.code.split("\n")[line - 1].substr(char-1,end - char + 1) +" >>";
  754. });
  755. throw "Shader compilation error " + err + "\n\nin\n\n" + shader.code;
  756. }
  757. if( shaderCache == null )
  758. shader.code += addBinaryPayload(bytes);
  759. }
  760. if( compileOnly )
  761. return { s : null, bytes : bytes };
  762. var s = shader.kind == Vertex ? Driver.createVertexShader(bytes) : Driver.createPixelShader(bytes);
  763. if( s == null ) {
  764. if( hasDeviceError ) return null;
  765. throw "Failed to create shader\n" + shader.code;
  766. }
  767. if( shaderCache != null )
  768. shaderCache.saveCompiledShader(shader.code, bytes, shaderVersion);
  769. var ctx = new ShaderContext(s);
  770. ctx.globalsSize = shader.globalsSize;
  771. ctx.paramsSize = shader.paramsSize;
  772. ctx.paramsContent = new hl.Bytes(shader.paramsSize * 16);
  773. ctx.paramsContent.fill(0, shader.paramsSize * 16, 0xDD);
  774. ctx.texturesCount = shader.texturesCount;
  775. ctx.texturesTypes = [];
  776. var p = shader.textures;
  777. while( p != null ) {
  778. switch( p.type ) {
  779. case TArray( t = TSampler(_) | TRWTexture(_) | TChannel(_), SConst(n) ):
  780. for( i in 0...n )
  781. ctx.texturesTypes.push(t);
  782. case TSampler(_), TRWTexture(_), TChannel(_):
  783. ctx.texturesTypes.push(p.type);
  784. default:
  785. }
  786. p = p.next;
  787. }
  788. ctx.bufferCount = shader.bufferCount;
  789. ctx.globals = dx.Driver.createBuffer(shader.globalsSize * 16, Dynamic, ConstantBuffer, CpuWrite, None, 0, null);
  790. ctx.params = dx.Driver.createBuffer(shader.paramsSize * 16, Dynamic, ConstantBuffer, CpuWrite, None, 0, null);
  791. ctx.samplersMap = [];
  792. var samplers = new hxsl.HlslOut.Samplers();
  793. for( v in shader.data.vars )
  794. samplers.make(v, ctx.samplersMap);
  795. #if debug
  796. ctx.debugSource = shader.code;
  797. #end
  798. return { s : ctx, bytes : bytes };
  799. }
  800. override function getNativeShaderCode( shader : hxsl.RuntimeShader ) {
  801. function dumpShader(s:hxsl.RuntimeShader.RuntimeShaderData) {
  802. var code = new hxsl.HlslOut().run(s.data);
  803. try {
  804. var scomp = compileShader(s, true).bytes;
  805. code += "\n// ASM=\n" + Driver.disassembleShader(scomp, None, null) + "\n\n";
  806. } catch( e : Dynamic ) {
  807. }
  808. return code;
  809. }
  810. return dumpShader(shader.vertex)+"\n\n"+dumpShader(shader.fragment);
  811. }
  812. override function hasFeature(f:Feature) {
  813. return switch(f) {
  814. case Queries, BottomLeftCoords:
  815. false;
  816. default:
  817. true;
  818. };
  819. }
  820. override function copyTexture(from:h3d.mat.Texture, to:h3d.mat.Texture) {
  821. if( from.t == null || from.format != to.format || from.width != to.width || from.height != to.height || from.layerCount != to.layerCount )
  822. return false;
  823. if( to.t == null ) {
  824. var prev = from.lastFrame;
  825. from.preventAutoDispose();
  826. to.alloc();
  827. from.lastFrame = prev;
  828. if( from.t == null ) throw "assert";
  829. if( to.t == null ) return false;
  830. }
  831. to.t.res.copyResource(from.t.res);
  832. to.flags.set(WasCleared);
  833. return true;
  834. }
  835. var tmpTextures = new Array<h3d.mat.Texture>();
  836. override function setRenderTarget(tex:Null<h3d.mat.Texture>, layer = 0, mipLevel = 0, depthBinding : h3d.Engine.DepthBinding = ReadWrite) {
  837. if( tex == null ) {
  838. curTexture = null;
  839. currentDepth = defaultDepth;
  840. currentTargets[0] = defaultTarget;
  841. currentTargetResources[0] = null;
  842. targetsCount = 1;
  843. var depthView = switch (depthBinding) {
  844. case NotBound:
  845. null;
  846. case ReadOnly:
  847. currentDepth.readOnlyDepthView;
  848. default:
  849. currentDepth.depthView;
  850. }
  851. Driver.omSetRenderTargets(1, currentTargets, depthView);
  852. viewport[2] = outputWidth;
  853. viewport[3] = outputHeight;
  854. viewport[5] = 1.;
  855. Driver.rsSetViewports(1, viewport);
  856. return;
  857. }
  858. tmpTextures[0] = tex;
  859. _setRenderTargets(tmpTextures, layer, mipLevel, depthBinding);
  860. }
  861. function unbind( res ) {
  862. for( i in 0...64 ) {
  863. if( vertexShader.resources[i] == res ) {
  864. vertexShader.resources[i] = null;
  865. Driver.vsSetShaderResources(i, 1, vertexShader.resources.getRef().offset(i));
  866. }
  867. if( pixelShader.resources[i] == res ) {
  868. pixelShader.resources[i] = null;
  869. Driver.psSetShaderResources(i, 1, pixelShader.resources.getRef().offset(i));
  870. }
  871. }
  872. }
  873. override function setRenderTargets(textures:Array<h3d.mat.Texture>, depthBinding : h3d.Engine.DepthBinding = ReadWrite) {
  874. _setRenderTargets(textures, 0, 0, depthBinding);
  875. }
  876. function _setRenderTargets( textures:Array<h3d.mat.Texture>, layer : Int, mipLevel : Int, depthBinding : h3d.Engine.DepthBinding = ReadWrite ) {
  877. if( textures.length == 0 ) {
  878. setRenderTarget(null, depthBinding);
  879. return;
  880. }
  881. if( hasDeviceError )
  882. return;
  883. var tex = textures[0];
  884. curTexture = textures[0];
  885. if( tex.depthBuffer != null && (tex.depthBuffer.width != tex.width || tex.depthBuffer.height != tex.height) )
  886. throw "Invalid depth buffer size : does not match render target size";
  887. currentDepth = @:privateAccess (tex.depthBuffer == null ? null : tex.depthBuffer.t);
  888. for( i in 0...textures.length ) {
  889. var tex = textures[i];
  890. if( tex.t == null ) {
  891. tex.alloc();
  892. if( hasDeviceError ) return;
  893. }
  894. if( tex.t.rt == null )
  895. throw "Can't render to texture which is not allocated with Target flag";
  896. var index = mipLevel * tex.layerCount + layer;
  897. var rt = tex.t.rt[index];
  898. if( rt == null ) {
  899. var arr = tex.flags.has(Cube) || tex.flags.has(IsArray);
  900. var v = new dx.Driver.RenderTargetDesc(getTextureFormat(tex), arr ? Texture2DArray : Texture2D);
  901. v.mipMap = mipLevel;
  902. v.firstSlice = layer;
  903. v.sliceCount = 1;
  904. rt = Driver.createRenderTargetView(tex.t.res, v);
  905. tex.t.rt[index] = rt;
  906. }
  907. tex.lastFrame = frame;
  908. currentTargets[i] = rt;
  909. currentTargetResources[i] = tex.t.view;
  910. unbind(tex.t.view);
  911. // prevent garbage
  912. if( !tex.flags.has(WasCleared) ) {
  913. tex.flags.set(WasCleared);
  914. Driver.clearColor(rt, 0, 0, 0, 0);
  915. }
  916. }
  917. var depthView = if ( currentDepth == null )
  918. null;
  919. else {
  920. switch ( depthBinding ) {
  921. case NotBound:
  922. null;
  923. case ReadOnly:
  924. currentDepth.readOnlyDepthView;
  925. default:
  926. currentDepth.depthView;
  927. }
  928. }
  929. Driver.omSetRenderTargets(textures.length, currentTargets, depthView);
  930. targetsCount = textures.length;
  931. var w = tex.width >> mipLevel; if( w == 0 ) w = 1;
  932. var h = tex.height >> mipLevel; if( h == 0 ) h = 1;
  933. viewport[2] = w;
  934. viewport[3] = h;
  935. viewport[5] = 1.;
  936. Driver.rsSetViewports(1, viewport);
  937. }
  938. override function setDepth( depthBuffer : h3d.mat.Texture ) {
  939. if( hasDeviceError )
  940. return;
  941. currentDepth = @:privateAccess (depthBuffer == null ? null : depthBuffer.t);
  942. depthBuffer.lastFrame = frame;
  943. unbind(currentDepth.view);
  944. Driver.omSetRenderTargets(0, null, currentDepth.depthView);
  945. targetsCount = 0;
  946. var w = depthBuffer.width; if( w == 0 ) w = 1;
  947. var h = depthBuffer.height; if( h == 0 ) h = 1;
  948. viewport[2] = w;
  949. viewport[3] = h;
  950. viewport[5] = 1.;
  951. Driver.rsSetViewports(1, viewport);
  952. }
  953. override function setRenderZone(x:Int, y:Int, width:Int, height:Int) {
  954. if( x == 0 && y == 0 && width < 0 && height < 0 ) {
  955. hasScissor = false;
  956. return;
  957. }
  958. if( x < 0 ) {
  959. width += x;
  960. x = 0;
  961. }
  962. if( y < 0 ) {
  963. height += y;
  964. y = 0;
  965. }
  966. if( width < 0 ) width = 0;
  967. if( height < 0 ) height = 0;
  968. hasScissor = true;
  969. rects[0] = x;
  970. rects[1] = y;
  971. rects[2] = x + width;
  972. rects[3] = y + height;
  973. Driver.rsSetScissorRects(1, rects);
  974. }
  975. override function selectShader(shader:hxsl.RuntimeShader) {
  976. var s = shaders.get(shader.id);
  977. if( s == null ) {
  978. s = new CompiledShader();
  979. var vertex = compileShader(shader.vertex);
  980. var fragment = compileShader(shader.fragment);
  981. if( hasDeviceError ) return false;
  982. s.vertex = vertex.s;
  983. s.fragment = fragment.s;
  984. s.vertexBytes = vertex.bytes;
  985. s.perInst = [];
  986. s.layouts = new Map();
  987. var format : Array<hxd.BufferFormat.BufferInput> = [];
  988. for( v in shader.vertex.data.vars )
  989. if( v.kind == Input ) {
  990. var perInst = 0;
  991. if( v.qualifiers != null )
  992. for( q in v.qualifiers )
  993. switch( q ) {
  994. case PerInstance(k): perInst = k;
  995. default:
  996. }
  997. s.perInst.push(perInst);
  998. var t = hxd.BufferFormat.InputFormat.fromHXSL(v.type);
  999. format.push({ name : v.name, type : t });
  1000. }
  1001. s.format = hxd.BufferFormat.make(format);
  1002. shaders.set(shader.id, s);
  1003. }
  1004. if( s == currentShader )
  1005. return false;
  1006. setShader(s);
  1007. return true;
  1008. }
  1009. function setShader( s : CompiledShader ) {
  1010. currentShader = s;
  1011. dx.Driver.vsSetShader(s.vertex.shader);
  1012. dx.Driver.psSetShader(s.fragment.shader);
  1013. currentLayout = null;
  1014. }
  1015. function makeLayout( mapping : Array<hxd.BufferFormat.BufferMapping> ) {
  1016. var layout = new hl.NativeArray(mapping.length);
  1017. for( index => input in @:privateAccess currentShader.format.inputs ) {
  1018. var inf = mapping[index];
  1019. var e = new LayoutElement();
  1020. var name = hxsl.HlslOut.semanticName(input.name);
  1021. e.semanticName = @:privateAccess name.toUtf8();
  1022. e.inputSlot = index;
  1023. e.format = switch( [input.type, inf.precision] ) {
  1024. case [DFloat, F32]: R32_FLOAT;
  1025. case [DFloat, F16]: R16_FLOAT;
  1026. case [DVec2, F32]: R32G32_FLOAT;
  1027. case [DVec2, F16]: R16G16_FLOAT;
  1028. case [DVec3, F32]: R32G32B32_FLOAT;
  1029. case [DVec4, F32]: R32G32B32A32_FLOAT;
  1030. case [DVec3|DVec4, S8]: R8G8B8A8_SNORM;
  1031. case [DVec3|DVec4, U8]: R8G8B8A8_UNORM;
  1032. case [DVec3|DVec4, F16]: R16G16B16A16_FLOAT;
  1033. case [DBytes4, F32]: R8G8B8A8_UINT;
  1034. default:
  1035. throw "Unsupported input type " + input.type+"."+inf.precision;
  1036. };
  1037. var perInst = currentShader.perInst[index];
  1038. if( perInst > 0 ) {
  1039. e.inputSlotClass = PerInstanceData;
  1040. e.instanceDataStepRate = perInst;
  1041. } else
  1042. e.inputSlotClass = PerVertexData;
  1043. layout[index] = e;
  1044. }
  1045. var l = Driver.createInputLayout(layout, currentShader.vertexBytes, currentShader.vertexBytes.length);
  1046. if( l == null )
  1047. throw "Failed to create input layout";
  1048. return l;
  1049. }
  1050. override function selectBuffer(buffer:Buffer) {
  1051. if( hasDeviceError ) return;
  1052. // select layout
  1053. var layout = currentShader.layouts.get(buffer.format.uid);
  1054. if( layout == null ) {
  1055. layout = makeLayout(buffer.format.resolveMapping(currentShader.format));
  1056. currentShader.layouts.set(buffer.format.uid, layout);
  1057. }
  1058. if( layout != currentLayout ) {
  1059. dx.Driver.iaSetInputLayout(layout);
  1060. currentLayout = layout;
  1061. }
  1062. var map = buffer.format.resolveMapping(currentShader.format);
  1063. var vbuf = buffer.vbuf;
  1064. var start = -1, max = -1;
  1065. var stride = buffer.format.strideBytes;
  1066. for( i in 0...map.length ) {
  1067. var inf = map[i];
  1068. if( currentVBuffers[i] != vbuf || offsets[i] != inf.offset || strides[i] != stride ) {
  1069. currentVBuffers[i] = vbuf;
  1070. strides[i] = stride;
  1071. offsets[i] = inf.offset;
  1072. if( start < 0 ) start = i;
  1073. max = i;
  1074. }
  1075. }
  1076. if( max >= 0 )
  1077. Driver.iaSetVertexBuffers(start, max - start + 1, currentVBuffers.getRef().offset(start), hl.Bytes.getArray(strides).offset(start << 2), hl.Bytes.getArray(offsets).offset(start << 2));
  1078. }
  1079. override function selectMultiBuffers(formats:hxd.BufferFormat.MultiFormat,buffers:Array<Buffer>) {
  1080. if( hasDeviceError ) return;
  1081. var layout = currentShader.layouts.get(-formats.uid-1);
  1082. if( layout == null ) {
  1083. layout = makeLayout(formats.resolveMapping(currentShader.format));
  1084. currentShader.layouts.set(-formats.uid-1, layout);
  1085. }
  1086. if( layout != currentLayout ) {
  1087. dx.Driver.iaSetInputLayout(layout);
  1088. currentLayout = layout;
  1089. }
  1090. var map = formats.resolveMapping(currentShader.format);
  1091. var start = -1, max = -1, force = false;
  1092. for( i in 0...map.length ) {
  1093. var inf = map[i];
  1094. var buf = buffers[inf.bufferIndex];
  1095. if( currentVBuffers[i] != buf.vbuf || offsets[i] != inf.offset || strides[i] != buf.format.strideBytes ) {
  1096. currentVBuffers[i] = buf.vbuf;
  1097. strides[i] = buf.format.strideBytes;
  1098. offsets[i] = inf.offset;
  1099. if( start < 0 ) start = i;
  1100. max = i;
  1101. }
  1102. }
  1103. if( max >= 0 )
  1104. Driver.iaSetVertexBuffers(start, max - start + 1, currentVBuffers.getRef().offset(start), hl.Bytes.getArray(strides).offset(start << 2), hl.Bytes.getArray(offsets).offset(start << 2));
  1105. }
  1106. override function uploadShaderBuffers(buffers:h3d.shader.Buffers, which:h3d.shader.Buffers.BufferKind) {
  1107. if( hasDeviceError ) return;
  1108. uploadBuffers(buffers, vertexShader, currentShader.vertex, buffers.vertex, which);
  1109. uploadBuffers(buffers, pixelShader, currentShader.fragment, buffers.fragment, which);
  1110. }
  1111. function uploadShaderBuffer( sbuffer : dx.Resource, buffer : haxe.ds.Vector<hxd.impl.Float32>, size : Int, prevContent : hl.Bytes ) {
  1112. if( size == 0 ) return;
  1113. var data = hl.Bytes.getArray(buffer.toData());
  1114. var bytes = size << 4;
  1115. if( prevContent != null ) {
  1116. if( prevContent.compare(0, data, 0, bytes) == 0 )
  1117. return;
  1118. prevContent.blit(0, data, 0, bytes);
  1119. mapCount++;
  1120. }
  1121. var ptr = sbuffer.map(0, WriteDiscard, true, null);
  1122. if( ptr == null ) throw "Can't map buffer " + sbuffer;
  1123. ptr.blit(0, data, 0, bytes);
  1124. sbuffer.unmap(0);
  1125. }
  1126. function uploadBuffers( buf : h3d.shader.Buffers, state : PipelineState, shader : ShaderContext, buffers : h3d.shader.Buffers.ShaderBuffers, which : h3d.shader.Buffers.BufferKind ) {
  1127. switch( which ) {
  1128. case Globals:
  1129. if( shader.globalsSize > 0 ) {
  1130. uploadShaderBuffer(shader.globals, buffers.globals, shader.globalsSize, null);
  1131. if( state.buffers[0] != shader.globals ) {
  1132. state.buffers[0] = shader.globals;
  1133. switch( state.kind ) {
  1134. case Vertex:
  1135. Driver.vsSetConstantBuffers(0, 1, state.buffers);
  1136. case Pixel:
  1137. Driver.psSetConstantBuffers(0, 1, state.buffers);
  1138. }
  1139. }
  1140. }
  1141. case Params:
  1142. if( shader.paramsSize > 0 ) {
  1143. uploadShaderBuffer(shader.params, buffers.params, shader.paramsSize, shader.paramsContent);
  1144. if( state.buffers[1] != shader.params ) {
  1145. state.buffers[1] = shader.params;
  1146. switch( state.kind ) {
  1147. case Vertex:
  1148. Driver.vsSetConstantBuffers(1, 1, state.buffers.getRef().offset(1));
  1149. case Pixel:
  1150. Driver.psSetConstantBuffers(1, 1, state.buffers.getRef().offset(1));
  1151. }
  1152. }
  1153. }
  1154. case Buffers:
  1155. var first = -1;
  1156. var max = -1;
  1157. for( i in 0...shader.bufferCount ) {
  1158. var buf = buffers.buffers[i].vbuf;
  1159. var tid = i + 2;
  1160. if( buf != state.buffers[tid] ) {
  1161. state.buffers[tid] = buf;
  1162. if( first < 0 ) first = tid;
  1163. max = tid;
  1164. }
  1165. }
  1166. if( max >= 0 )
  1167. switch( state.kind ) {
  1168. case Vertex:
  1169. Driver.vsSetConstantBuffers(first,max-first+1,state.buffers.getRef().offset(first));
  1170. case Pixel:
  1171. Driver.psSetConstantBuffers(first,max-first+1,state.buffers.getRef().offset(first));
  1172. }
  1173. case Textures:
  1174. var start = -1, max = -1;
  1175. var sstart = -1, smax = -1;
  1176. for( i in 0...shader.texturesCount ) {
  1177. var t = buffers.tex[i];
  1178. var tt = shader.texturesTypes[i];
  1179. if( t == null || t.isDisposed() ) {
  1180. switch( tt ) {
  1181. case TSampler(T2D,_):
  1182. var color = h3d.mat.Defaults.loadingTextureColor;
  1183. t = h3d.mat.Texture.fromColor(color, (color >>> 24) / 255);
  1184. case TSampler(TCube,_):
  1185. t = h3d.mat.Texture.defaultCubeTexture();
  1186. default:
  1187. throw "Missing texture";
  1188. }
  1189. }
  1190. if( t != null && t.t == null && t.realloc != null ) {
  1191. var s = currentShader;
  1192. t.alloc();
  1193. t.realloc();
  1194. if( hasDeviceError ) return;
  1195. if( s != currentShader ) {
  1196. // realloc triggered a shader change !
  1197. // we need to reset the original shader and reupload everything
  1198. setShader(s);
  1199. uploadShaderBuffers(buf,Globals);
  1200. uploadShaderBuffers(buf,Params);
  1201. uploadShaderBuffers(buf,Textures);
  1202. return;
  1203. }
  1204. }
  1205. t.lastFrame = frame;
  1206. var view = t.t.view;
  1207. if( t.startingMip > 0 ) {
  1208. if( t.t.views == null ) t.t.views = [];
  1209. view = t.t.views[t.startingMip];
  1210. if( view == null ) {
  1211. view = makeTexView(t, t.t.res, t.startingMip);
  1212. t.t.views[t.startingMip] = view;
  1213. }
  1214. }
  1215. if( view != state.resources[i] || t.t.depthView != null ) {
  1216. state.resources[i] = view;
  1217. max = i;
  1218. if( start < 0 ) start = i;
  1219. }
  1220. var sidx = shader.samplersMap[i];
  1221. var bits = @:privateAccess t.bits;
  1222. if( t.lodBias != 0 )
  1223. bits |= Std.int((t.lodBias + 32)*32) << 10;
  1224. if( sidx < maxSamplers && bits != state.samplerBits[sidx] ) {
  1225. var ss = samplerStates.get(bits);
  1226. if( ss == null ) {
  1227. var desc = new SamplerDesc();
  1228. desc.filter = FILTER[t.mipMap.getIndex()][t.filter.getIndex()];
  1229. desc.addressU = desc.addressV = desc.addressW = WRAP[t.wrap.getIndex()];
  1230. // if mipMap = None && hasMipmaps : don't set per-sampler maxLod !
  1231. // only the first sampler maxLod seems to be taken into account :'(
  1232. desc.minLod = 0;
  1233. desc.maxLod = 1e30;
  1234. desc.mipLodBias = t.lodBias;
  1235. ss = Driver.createSamplerState(desc);
  1236. samplerStates.set(bits, ss);
  1237. }
  1238. state.samplerBits[sidx] = bits;
  1239. state.samplers[sidx] = ss;
  1240. if( sidx > smax ) smax = sidx;
  1241. if( sstart < 0 || sidx < sstart ) sstart = sidx;
  1242. }
  1243. }
  1244. switch( state.kind) {
  1245. case Vertex:
  1246. if( max >= 0 ) {
  1247. #if dxdebug
  1248. for( i in 0...max )
  1249. for( r in 0...targetsCount )
  1250. if( currentTargetResources[r] == state.resources[i] )
  1251. throw "Texture bound in output is set in shader";
  1252. #end
  1253. Driver.vsSetShaderResources(start, max - start + 1, state.resources.getRef().offset(start));
  1254. }
  1255. if( smax >= 0 ) Driver.vsSetSamplers(sstart, smax - sstart + 1, state.samplers.getRef().offset(sstart));
  1256. case Pixel:
  1257. if( max >= 0 ) {
  1258. #if dxdebug
  1259. for( i in 0...max )
  1260. for( r in 0...targetsCount )
  1261. if( currentTargetResources[r] == state.resources[i] )
  1262. throw "Texture bound in output is set in shader";
  1263. #end
  1264. Driver.psSetShaderResources(start, max - start + 1, state.resources.getRef().offset(start));
  1265. }
  1266. if( smax >= 0 ) Driver.psSetSamplers(sstart, smax - sstart + 1, state.samplers.getRef().offset(sstart));
  1267. }
  1268. }
  1269. }
  1270. override function draw(ibuf:Buffer, startIndex:Int, ntriangles:Int) {
  1271. if( !allowDraw )
  1272. return;
  1273. if( currentIndex != ibuf ) {
  1274. currentIndex = ibuf;
  1275. dx.Driver.iaSetIndexBuffer(ibuf.vbuf,ibuf.format.strideBytes == 4,0);
  1276. }
  1277. dx.Driver.drawIndexed(ntriangles * 3, startIndex, 0);
  1278. }
  1279. override function allocInstanceBuffer(b:InstanceBuffer, buf : haxe.io.Bytes) {
  1280. b.data = dx.Driver.createBuffer(b.commandCount * 5 * 4, Default, UnorderedAccess, None, DrawIndirectArgs, 4, buf);
  1281. }
  1282. override function uploadInstanceBufferBytes(b : InstanceBuffer, startVertex : Int, vertexCount : Int, buf : haxe.io.Bytes, bufPos : Int ) {
  1283. if( hasDeviceError ) return;
  1284. var strideBytes = 5 * 4;
  1285. updateBuffer(b.data, @:privateAccess buf.b.offset(bufPos), startVertex * strideBytes, vertexCount * strideBytes);
  1286. }
  1287. override function disposeInstanceBuffer(b:InstanceBuffer) {
  1288. (b.data : dx.Resource).release();
  1289. b.data = null;
  1290. }
  1291. override function drawInstanced(ibuf:Buffer, commands:InstanceBuffer) {
  1292. if( !allowDraw )
  1293. return;
  1294. if( currentIndex != ibuf ) {
  1295. currentIndex = ibuf;
  1296. dx.Driver.iaSetIndexBuffer(ibuf.vbuf,ibuf.format.strideBytes == 4,0);
  1297. }
  1298. if( commands.data == null ) {
  1299. #if( (hldx == "1.8.0") || (hldx == "1.9.0") )
  1300. throw "Requires HLDX 1.10+";
  1301. #else
  1302. dx.Driver.drawIndexedInstanced(commands.indexCount, commands.commandCount, commands.startIndex, 0, 0);
  1303. #end
  1304. } else {
  1305. for( i in 0...commands.commandCount )
  1306. dx.Driver.drawIndexedInstancedIndirect(commands.data,i * 20);
  1307. }
  1308. }
  1309. static var COMPARE : Array<ComparisonFunc> = [
  1310. Always,
  1311. Never,
  1312. Equal,
  1313. NotEqual,
  1314. Greater,
  1315. GreaterEqual,
  1316. Less,
  1317. LessEqual
  1318. ];
  1319. static var CULL : Array<CullMode> = [
  1320. None,
  1321. Back,
  1322. Front,
  1323. None,
  1324. ];
  1325. static var STENCIL_OP : Array<StencilOp> = [
  1326. Keep,
  1327. Zero,
  1328. Replace,
  1329. IncrSat,
  1330. Incr,
  1331. DecrSat,
  1332. Decr,
  1333. Invert,
  1334. ];
  1335. static var BLEND : Array<Blend> = [
  1336. One,
  1337. Zero,
  1338. SrcAlpha,
  1339. SrcColor,
  1340. DestAlpha,
  1341. DestColor,
  1342. InvSrcAlpha,
  1343. InvSrcColor,
  1344. InvDestAlpha,
  1345. InvDestColor,
  1346. Src1Color,
  1347. Src1Alpha,
  1348. InvSrc1Color,
  1349. InvSrc1Alpha,
  1350. SrcAlphaSat,
  1351. // BlendFactor/InvBlendFactor : not supported by Heaps for now
  1352. ];
  1353. static var BLEND_ALPHA : Array<Blend> = [
  1354. One,
  1355. Zero,
  1356. SrcAlpha,
  1357. SrcAlpha,
  1358. DestAlpha,
  1359. DestAlpha,
  1360. InvSrcAlpha,
  1361. InvSrcAlpha,
  1362. InvDestAlpha,
  1363. InvDestAlpha,
  1364. Src1Alpha,
  1365. Src1Alpha,
  1366. InvSrc1Alpha,
  1367. InvSrc1Alpha,
  1368. SrcAlphaSat,
  1369. // BlendFactor/InvBlendFactor : not supported by Heaps for now
  1370. ];
  1371. static var BLEND_OP : Array<BlendOp> = [
  1372. Add,
  1373. Subtract,
  1374. RevSubstract,
  1375. Min,
  1376. Max
  1377. ];
  1378. static var FILTER : Array<Array<Filter>> = [
  1379. [MinMagMipPoint,MinMagMipLinear],
  1380. [MinMagMipPoint,MinMagLinearMipPoint],
  1381. [MinMagPointMipLinear, MinMagMipLinear],
  1382. // Anisotropic , Comparison, Minimum, Maximum
  1383. ];
  1384. static var WRAP : Array<AddressMode> = [
  1385. Clamp,
  1386. Wrap,
  1387. //Mirror , Border , MirrorOnce
  1388. ];
  1389. }
  1390. #end