DirectXDriver.hx 48 KB

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