DirectXDriver.hx 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918
  1. package h3d.impl;
  2. #if hldx
  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 paramsContent : hl.Bytes;
  12. public var globals : dx.Resource;
  13. public var params : dx.Resource;
  14. #if debug
  15. public var debugSource : String;
  16. #end
  17. public function new(shader) {
  18. this.shader = shader;
  19. }
  20. }
  21. private class CompiledShader {
  22. public var vertex : ShaderContext;
  23. public var fragment : ShaderContext;
  24. public var layout : Layout;
  25. public var inputs : Array<String>;
  26. public var offsets : Array<Int>;
  27. public function new() {
  28. }
  29. }
  30. enum PipelineKind {
  31. Vertex;
  32. Pixel;
  33. }
  34. class PipelineState {
  35. public var kind : PipelineKind;
  36. public var samplers = new hl.NativeArray<SamplerState>(64);
  37. public var samplerBits = new Array<Int>();
  38. public var resources = new hl.NativeArray<ShaderResourceView>(64);
  39. public var buffers = new hl.NativeArray<dx.Resource>(16);
  40. public function new(kind) {
  41. this.kind = kind;
  42. for(i in 0...64 ) samplerBits[i] = -1;
  43. }
  44. }
  45. class DirectXDriver extends h3d.impl.Driver {
  46. static inline var NTARGETS = 8;
  47. static inline var VIEWPORTS_ELTS = 6 * NTARGETS;
  48. static inline var RECTS_ELTS = 4 * NTARGETS;
  49. static inline var BLEND_FACTORS = NTARGETS;
  50. var driver : DriverInstance;
  51. var shaders : Map<Int,CompiledShader>;
  52. var defaultTarget : RenderTargetView;
  53. var defaultDepth : DepthBuffer;
  54. var defaultDepthInst : h3d.mat.DepthBuffer;
  55. var extraDepthInst : h3d.mat.DepthBuffer;
  56. var viewport : hl.BytesAccess<hl.F32> = new hl.Bytes(4 * VIEWPORTS_ELTS);
  57. var rects : hl.BytesAccess<Int> = new hl.Bytes(4 * RECTS_ELTS);
  58. var box = new dx.Resource.ResourceBox();
  59. var strides : Array<Int> = [];
  60. var offsets : Array<Int> = [];
  61. var currentShader : CompiledShader;
  62. var currentIndex : IndexBuffer;
  63. var currentDepth : DepthBuffer;
  64. var currentTargets = new hl.NativeArray<RenderTargetView>(16);
  65. var vertexShader = new PipelineState(Vertex);
  66. var pixelShader = new PipelineState(Pixel);
  67. var currentVBuffers = new hl.NativeArray<dx.Resource>(16);
  68. var frame : Int;
  69. var currentMaterialBits = -1;
  70. var depthStates : Map<Int,DepthStencilState> = new Map();
  71. var blendStates : Map<Int,BlendState> = new Map();
  72. var rasterStates : Map<Int,RasterState> = new Map();
  73. var samplerStates : Map<Int,SamplerState> = new Map();
  74. var currentDepthState : DepthStencilState;
  75. var currentBlendState : BlendState;
  76. var currentRasterState : RasterState;
  77. var blendFactors : hl.BytesAccess<hl.F32> = new hl.Bytes(4 * BLEND_FACTORS);
  78. var outputWidth : Int;
  79. var outputHeight : Int;
  80. var hasScissor = false;
  81. var shaderVersion : String;
  82. var window : dx.Window;
  83. var curTexture : h3d.mat.Texture;
  84. var mapCount : Int;
  85. var updateResCount : Int;
  86. public var backBufferFormat : dx.Format = R8G8B8A8_UNORM;
  87. public var depthStencilFormat : dx.Format = D24_UNORM_S8_UINT;
  88. public function new() {
  89. shaders = new Map();
  90. window = @:privateAccess dx.Window.windows[0];
  91. var options : dx.Driver.DriverInitFlags = None;
  92. #if debug
  93. options |= DebugLayer;
  94. #end
  95. driver = Driver.create(window, backBufferFormat, options);
  96. if( driver == null ) throw "Failed to initialize DirectX driver";
  97. var version = Driver.getSupportedVersion();
  98. shaderVersion = if( version < 10 ) "3_0" else if( version < 11 ) "4_0" else "5_0";
  99. Driver.iaSetPrimitiveTopology(TriangleList);
  100. defaultDepthInst = new h3d.mat.DepthBuffer(-1, -1);
  101. for( i in 0...VIEWPORTS_ELTS )
  102. viewport[i] = 0;
  103. for( i in 0...RECTS_ELTS )
  104. rects[i] = 0;
  105. for( i in 0...BLEND_FACTORS )
  106. blendFactors[i] = 0;
  107. }
  108. override function resize(width:Int, height:Int) {
  109. if( defaultDepth != null ) {
  110. defaultDepth.view.release();
  111. defaultDepth.res.release();
  112. }
  113. if( defaultTarget != null ) {
  114. defaultTarget.release();
  115. defaultTarget = null;
  116. }
  117. if( !Driver.resize(width, height, backBufferFormat) )
  118. throw "Failed to resize backbuffer to " + width + "x" + height;
  119. var depthDesc = new Texture2dDesc();
  120. depthDesc.width = width;
  121. depthDesc.height = height;
  122. depthDesc.format = depthStencilFormat;
  123. depthDesc.bind = DepthStencil;
  124. var depth = Driver.createTexture2d(depthDesc);
  125. if( depth == null ) throw "Failed to create depthBuffer";
  126. var depthView = Driver.createDepthStencilView(depth,depthStencilFormat);
  127. defaultDepth = { res : depth, view : depthView };
  128. @:privateAccess {
  129. defaultDepthInst.b = defaultDepth;
  130. defaultDepthInst.width = width;
  131. defaultDepthInst.height = height;
  132. }
  133. var buf = Driver.getBackBuffer();
  134. defaultTarget = Driver.createRenderTargetView(buf);
  135. buf.release();
  136. outputWidth = width;
  137. outputHeight = height;
  138. setRenderTarget(null);
  139. if( extraDepthInst != null ) @:privateAccess {
  140. extraDepthInst.width = width;
  141. extraDepthInst.height = height;
  142. extraDepthInst.dispose();
  143. extraDepthInst.b = allocDepthBuffer(extraDepthInst);
  144. }
  145. }
  146. override function begin(frame:Int) {
  147. mapCount = 0;
  148. updateResCount = 0;
  149. this.frame = frame;
  150. }
  151. override function isDisposed() {
  152. return false;
  153. }
  154. override function init( onCreate : Bool -> Void, forceSoftware = false ) {
  155. haxe.Timer.delay(onCreate.bind(false), 1);
  156. }
  157. override function clear(?color:h3d.Vector, ?depth:Float, ?stencil:Int) {
  158. if( color != null )
  159. Driver.clearColor(currentTargets[0], color.r, color.g, color.b, color.a);
  160. if( depth != null || stencil != null )
  161. Driver.clearDepthStencilView(currentDepth.view, depth, stencil);
  162. }
  163. override function getDriverName(details:Bool) {
  164. var desc = "DirectX" + Driver.getSupportedVersion();
  165. if( details ) desc += " " + Driver.getDeviceName();
  166. return desc;
  167. }
  168. override function present() {
  169. Driver.present(window.vsync ? 1 : 0, None);
  170. }
  171. override function getDefaultDepthBuffer():h3d.mat.DepthBuffer {
  172. if( extraDepthInst == null )
  173. extraDepthInst = new h3d.mat.DepthBuffer(outputWidth, outputHeight);
  174. return extraDepthInst;
  175. }
  176. override function allocVertexes(m:ManagedBuffer):VertexBuffer {
  177. var res = dx.Driver.createBuffer(m.size * m.stride * 4, Default, VertexBuffer, None, None, 0, null);
  178. if( res == null ) return null;
  179. return { res : res, count : m.size, stride : m.stride };
  180. }
  181. override function allocIndexes( count : Int ) : IndexBuffer {
  182. var res = dx.Driver.createBuffer(count << 1, Default, IndexBuffer, None, None, 0, null);
  183. if( res == null ) return null;
  184. return { res : res, count : count };
  185. }
  186. override function allocDepthBuffer(b:h3d.mat.DepthBuffer):DepthBuffer {
  187. var depthDesc = new Texture2dDesc();
  188. depthDesc.width = b.width;
  189. depthDesc.height = b.height;
  190. depthDesc.format = D24_UNORM_S8_UINT;
  191. depthDesc.bind = DepthStencil;
  192. var depth = Driver.createTexture2d(depthDesc);
  193. if( depth == null )
  194. return null;
  195. return { res : depth, view : Driver.createDepthStencilView(depth,depthDesc.format) };
  196. }
  197. override function disposeDepthBuffer(b:h3d.mat.DepthBuffer) @:privateAccess {
  198. var d = b.b;
  199. b.b = null;
  200. d.view.release();
  201. d.res.release();
  202. }
  203. override function captureRenderBuffer( pixels : hxd.Pixels ) {
  204. var rt = curTexture;
  205. if( rt == null )
  206. throw "Can't capture main render buffer in DirectX";
  207. var desc = new Texture2dDesc();
  208. desc.width = rt.width;
  209. desc.height = rt.height;
  210. desc.access = CpuRead | CpuWrite;
  211. desc.usage = Staging;
  212. desc.format = getTextureFormat(rt);
  213. var tmp = dx.Driver.createTexture2d(desc);
  214. if( tmp == null )
  215. throw "Capture failed: can't create tmp texture";
  216. tmp.copyResource(rt.t.res);
  217. var pitch = 0;
  218. var ptr = tmp.map(0, Read, true, pitch);
  219. if( pitch == desc.width * 4 )
  220. @:privateAccess pixels.bytes.b.blit(0, ptr, 0, desc.width * desc.height * 4);
  221. else {
  222. for( i in 0...desc.height )
  223. @:privateAccess pixels.bytes.b.blit(i * desc.width * 4, ptr, i * pitch, desc.width * 4);
  224. }
  225. tmp.unmap(0);
  226. tmp.release();
  227. }
  228. function getTextureFormat( t : h3d.mat.Texture ) : dx.Format {
  229. return switch( t.format ) {
  230. case RGBA: R8G8B8A8_UNORM;
  231. case RGBA16F: R16G16B16A16_UNORM;
  232. case ALPHA32F: R32_FLOAT;
  233. case ALPHA16F: R16_FLOAT;
  234. case ALPHA8: R8_UNORM;
  235. default: throw "Unsupported texture format " + t.format;
  236. }
  237. }
  238. override function allocTexture(t:h3d.mat.Texture):Texture {
  239. var mips = 1;
  240. if( t.flags.has(MipMapped) ) {
  241. while( t.width >= 1 << mips || t.height >= 1 << mips ) mips++;
  242. }
  243. var rt = t.flags.has(Target);
  244. var isCube = t.flags.has(Cube);
  245. var desc = new Texture2dDesc();
  246. desc.width = t.width;
  247. desc.height = t.height;
  248. desc.format = getTextureFormat(t);
  249. desc.usage = Default;
  250. desc.bind = ShaderResource;
  251. desc.mipLevels = mips;
  252. if( rt )
  253. desc.bind |= RenderTarget;
  254. if( isCube ) {
  255. desc.arraySize = 6;
  256. desc.misc |= TextureCube;
  257. }
  258. if( t.flags.has(MipMapped) && !t.flags.has(ManualMipMapGen) ) {
  259. desc.bind |= RenderTarget;
  260. desc.misc |= GenerateMips;
  261. }
  262. var tex = Driver.createTexture2d(desc);
  263. if( tex == null )
  264. return null;
  265. t.lastFrame = frame;
  266. t.flags.unset(WasCleared);
  267. var vdesc = new ShaderResourceViewDesc();
  268. vdesc.format = desc.format;
  269. vdesc.dimension = isCube ? TextureCube : Texture2D;
  270. vdesc.arraySize = desc.arraySize;
  271. vdesc.start = 0; // top mip level
  272. vdesc.count = -1; // all mip levels
  273. var view = Driver.createShaderResourceView(tex, vdesc);
  274. var rtView = rt ? Driver.createRenderTargetView(tex) : null;
  275. return { res : tex, view : view, rt : rtView, mips : mips };
  276. }
  277. override function disposeTexture( t : h3d.mat.Texture ) {
  278. var tt = t.t;
  279. if( tt == null ) return;
  280. t.t = null;
  281. tt.view.release();
  282. tt.res.release();
  283. if( tt.rt != null ) tt.rt.release();
  284. }
  285. override function disposeVertexes(v:VertexBuffer) {
  286. v.res.release();
  287. }
  288. override function disposeIndexes(i:IndexBuffer) {
  289. i.res.release();
  290. }
  291. override function generateMipMaps(texture:h3d.mat.Texture) {
  292. Driver.generateMips(texture.t.view);
  293. }
  294. function updateBuffer( res : dx.Resource, bytes : hl.Bytes, startByte : Int, bytesCount : Int ) {
  295. box.left = startByte;
  296. box.top = 0;
  297. box.front = 0;
  298. box.right = startByte + bytesCount;
  299. box.bottom = 1;
  300. box.back = 1;
  301. res.updateSubresource(0, box, bytes, 0, 0);
  302. updateResCount++;
  303. }
  304. override function uploadIndexBuffer(i:IndexBuffer, startIndice:Int, indiceCount:Int, buf:hxd.IndexBuffer, bufPos:Int) {
  305. updateBuffer(i.res, hl.Bytes.getArray(buf.getNative()).offset(bufPos << 1), startIndice << 1, indiceCount << 1);
  306. }
  307. override function uploadIndexBytes(i:IndexBuffer, startIndice:Int, indiceCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
  308. updateBuffer(i.res, @:privateAccess buf.b.offset(bufPos << 1), startIndice << 1, indiceCount << 1);
  309. }
  310. override function uploadVertexBuffer(v:VertexBuffer, startVertex:Int, vertexCount:Int, buf:hxd.FloatBuffer, bufPos:Int) {
  311. updateBuffer(v.res, hl.Bytes.getArray(buf.getNative()).offset(bufPos<<2), startVertex * v.stride << 2, vertexCount * v.stride << 2);
  312. }
  313. override function uploadVertexBytes(v:VertexBuffer, startVertex:Int, vertexCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
  314. updateBuffer(v.res, @:privateAccess buf.b.offset(bufPos << 2), startVertex * v.stride << 2, vertexCount * v.stride << 2);
  315. }
  316. override function readIndexBytes(v:IndexBuffer, startIndice:Int, indiceCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
  317. var tmp = dx.Driver.createBuffer(indiceCount << 1, Staging, None, CpuRead | CpuWrite, None, 0, null);
  318. box.left = startIndice << 1;
  319. box.top = 0;
  320. box.front = 0;
  321. box.right = (startIndice + indiceCount) << 1;
  322. box.bottom = 1;
  323. box.back = 1;
  324. tmp.copySubresourceRegion(0, 0, 0, 0, v.res, 0, box);
  325. var ptr = tmp.map(0, Read, true, null);
  326. @:privateAccess buf.b.blit(bufPos, ptr, 0, indiceCount << 1);
  327. tmp.unmap(0);
  328. tmp.release();
  329. }
  330. override function readVertexBytes(v:VertexBuffer, startVertex:Int, vertexCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
  331. var tmp = dx.Driver.createBuffer(vertexCount * v.stride * 4, Staging, None, CpuRead | CpuWrite, None, 0, null);
  332. box.left = startVertex * v.stride * 4;
  333. box.top = 0;
  334. box.front = 0;
  335. box.right = (startVertex + vertexCount) * 4 * v.stride;
  336. box.bottom = 1;
  337. box.back = 1;
  338. tmp.copySubresourceRegion(0, 0, 0, 0, v.res, 0, box);
  339. var ptr = tmp.map(0, Read, true, null);
  340. @:privateAccess buf.b.blit(bufPos, ptr, 0, vertexCount * v.stride * 4);
  341. tmp.unmap(0);
  342. tmp.release();
  343. }
  344. override function uploadTextureBitmap(t:h3d.mat.Texture, bmp:hxd.BitmapData, mipLevel:Int, side:Int) {
  345. var pixels = bmp.getPixels();
  346. uploadTexturePixels(t, pixels, mipLevel, side);
  347. pixels.dispose();
  348. }
  349. override function uploadTexturePixels(t:h3d.mat.Texture, pixels:hxd.Pixels, mipLevel:Int, side:Int) {
  350. pixels.convert(RGBA);
  351. if( mipLevel >= t.t.mips ) throw "Mip level outside texture range : " + mipLevel + " (max = " + (t.t.mips - 1) + ")";
  352. t.t.res.updateSubresource(mipLevel + side * t.t.mips, null, pixels.bytes, pixels.width << 2, 0);
  353. updateResCount++;
  354. }
  355. static inline var SCISSOR_BIT = 1 << (Pass.colorMask_offset + 4);
  356. override public function selectMaterial(pass:h3d.mat.Pass) {
  357. var bits = @:privateAccess pass.bits;
  358. if( hasScissor ) bits |= SCISSOR_BIT;
  359. if( bits == currentMaterialBits )
  360. return;
  361. currentMaterialBits = bits;
  362. var depthBits = bits & (Pass.depthWrite_mask | Pass.depthTest_mask);
  363. if( pass.stencil != null ) throw "TODO";
  364. var depth = depthStates.get(depthBits);
  365. if( depth == null ) {
  366. var cmp = Pass.getDepthTest(bits);
  367. var desc = new DepthStencilDesc();
  368. desc.depthEnable = cmp != 0;
  369. desc.depthFunc = COMPARE[cmp];
  370. desc.depthWrite = Pass.getDepthWrite(bits) != 0;
  371. depth = Driver.createDepthStencilState(desc);
  372. depthStates.set(depthBits, depth);
  373. }
  374. if( depth != currentDepthState ) {
  375. currentDepthState = depth;
  376. Driver.omSetDepthStencilState(depth);
  377. }
  378. var rasterBits = bits & (Pass.culling_mask | SCISSOR_BIT);
  379. var raster = rasterStates.get(rasterBits);
  380. if( raster == null ) {
  381. var desc = new RasterizerDesc();
  382. desc.fillMode = Solid;
  383. desc.cullMode = CULL[Pass.getCulling(bits)];
  384. if( pass.culling == Both ) throw "Culling:Both Not supported in DirectX";
  385. desc.depthClipEnable = true;
  386. desc.scissorEnable = bits & SCISSOR_BIT != 0;
  387. raster = Driver.createRasterizerState(desc);
  388. rasterStates.set(rasterBits, raster);
  389. }
  390. if( raster != currentRasterState ) {
  391. currentRasterState = raster;
  392. Driver.rsSetState(raster);
  393. }
  394. var blendBits = bits & (Pass.blendSrc_mask | Pass.blendDst_mask | Pass.blendAlphaSrc_mask | Pass.blendAlphaDst_mask | Pass.blendOp_mask | Pass.blendAlphaOp_mask | Pass.colorMask_mask);
  395. var blend = blendStates.get(blendBits);
  396. if( blend == null ) {
  397. var desc = new RenderTargetBlendDesc();
  398. desc.srcBlend = BLEND[Pass.getBlendSrc(bits)];
  399. desc.destBlend = BLEND[Pass.getBlendDst(bits)];
  400. desc.srcBlendAlpha = BLEND_ALPHA[Pass.getBlendAlphaSrc(bits)];
  401. desc.destBlendAlpha = BLEND_ALPHA[Pass.getBlendAlphaDst(bits)];
  402. desc.blendOp = BLEND_OP[Pass.getBlendOp(bits)];
  403. desc.blendOpAlpha = BLEND_OP[Pass.getBlendAlphaOp(bits)];
  404. desc.renderTargetWriteMask = Pass.getColorMask(bits);
  405. desc.blendEnable = !(desc.srcBlend == One && desc.srcBlendAlpha == One && desc.destBlend == Zero && desc.destBlendAlpha == Zero && desc.blendOp == Add && desc.blendOpAlpha == Add);
  406. var tmp = new hl.NativeArray(1);
  407. tmp[0] = desc;
  408. blend = Driver.createBlendState(false, false, tmp, 1);
  409. blendStates.set(blendBits, blend);
  410. }
  411. if( blend != currentBlendState ) {
  412. currentBlendState = blend;
  413. Driver.omSetBlendState(blend, blendFactors, -1);
  414. }
  415. }
  416. function compileShader( shader : hxsl.RuntimeShader.RuntimeShaderData, compileOnly = false ) {
  417. var h = new hxsl.HlslOut();
  418. var source = h.run(shader.data);
  419. var bytes = try dx.Driver.compileShader(source, "", "main", (shader.vertex?"vs_":"ps_")+shaderVersion, OptimizationLevel3) catch( err : String ) {
  420. err = ~/^\(([0-9]+),([0-9]+)-([0-9]+)\)/gm.map(err, function(r) {
  421. var line = Std.parseInt(r.matched(1));
  422. var char = Std.parseInt(r.matched(2));
  423. var end = Std.parseInt(r.matched(3));
  424. return "\n<< " + source.split("\n")[line - 1].substr(char-1,end - char + 1) +" >>";
  425. });
  426. throw "Shader compilation error " + err + "\n\nin\n\n" + source;
  427. }
  428. if( compileOnly )
  429. return { s : null, bytes : bytes };
  430. var s = shader.vertex ? Driver.createVertexShader(bytes) : Driver.createPixelShader(bytes);
  431. if( s == null )
  432. throw "Failed to create shader\n" + source;
  433. var ctx = new ShaderContext(s);
  434. ctx.globalsSize = shader.globalsSize;
  435. ctx.paramsSize = shader.paramsSize;
  436. ctx.paramsContent = new hl.Bytes(shader.paramsSize * 16);
  437. ctx.paramsContent.fill(0, shader.paramsSize * 16, 0xDD);
  438. ctx.texturesCount = shader.textures2DCount + shader.texturesCubeCount;
  439. ctx.globals = dx.Driver.createBuffer(shader.globalsSize * 16, Dynamic, ConstantBuffer, CpuWrite, None, 0, null);
  440. ctx.params = dx.Driver.createBuffer(shader.paramsSize * 16, Dynamic, ConstantBuffer, CpuWrite, None, 0, null);
  441. #if debug
  442. ctx.debugSource = source;
  443. #end
  444. return { s : ctx, bytes : bytes };
  445. }
  446. override function getNativeShaderCode( shader : hxsl.RuntimeShader ) {
  447. var v = compileShader(shader.vertex, true).bytes;
  448. var f = compileShader(shader.fragment, true).bytes;
  449. return Driver.disassembleShader(v, None, null) + "\n" + Driver.disassembleShader(f, None, null);
  450. //return "// vertex:\n" + new hxsl.HlslOut().run(shader.vertex.data) + "// fragment:\n" + new hxsl.HlslOut().run(shader.fragment.data);
  451. }
  452. override function hasFeature(f:Feature) {
  453. return switch(f) {
  454. case StandardDerivatives, FloatTextures, AllocDepthBuffer, HardwareAccelerated, MultipleRenderTargets:
  455. true;
  456. case Queries:
  457. false;
  458. };
  459. }
  460. override function copyTexture(from:h3d.mat.Texture, to:h3d.mat.Texture) {
  461. if( from.t == null || from.format != to.format || from.width != to.width || from.height != to.height )
  462. return false;
  463. if( to.t == null )
  464. to.alloc();
  465. to.t.res.copyResource(from.t.res);
  466. to.flags.set(WasCleared);
  467. return true;
  468. }
  469. var tmpTextures = new Array<h3d.mat.Texture>();
  470. override function setRenderTarget(tex:Null<h3d.mat.Texture>, face = 0, mipLevel = 0) {
  471. if( face != 0 || mipLevel != 0 )
  472. throw "TODO";
  473. if( tex == null ) {
  474. curTexture = null;
  475. currentDepth = defaultDepth;
  476. currentTargets[0] = defaultTarget;
  477. Driver.omSetRenderTargets(1, currentTargets, currentDepth.view);
  478. viewport[2] = outputWidth;
  479. viewport[3] = outputHeight;
  480. viewport[5] = 1.;
  481. Driver.rsSetViewports(1, viewport);
  482. return;
  483. }
  484. tmpTextures[0] = tex;
  485. setRenderTargets(tmpTextures);
  486. }
  487. function unbind( res ) {
  488. for( i in 0...64 ) {
  489. if( vertexShader.resources[i] == res ) {
  490. vertexShader.resources[i] = null;
  491. Driver.vsSetShaderResources(i, 1, vertexShader.resources.getRef().offset(i));
  492. }
  493. if( pixelShader.resources[i] == res ) {
  494. pixelShader.resources[i] = null;
  495. Driver.psSetShaderResources(i, 1, pixelShader.resources.getRef().offset(i));
  496. }
  497. }
  498. }
  499. override function setRenderTargets(textures:Array<h3d.mat.Texture>) {
  500. if( textures.length == 0 ) {
  501. setRenderTarget(null);
  502. return;
  503. }
  504. var tex = textures[0];
  505. curTexture = textures[0];
  506. if( tex.depthBuffer != null && (tex.depthBuffer.width != tex.width || tex.depthBuffer.height != tex.height) )
  507. throw "Invalid depth buffer size : does not match render target size";
  508. currentDepth = @:privateAccess (tex.depthBuffer == null ? null : tex.depthBuffer.b);
  509. for( i in 0...textures.length ) {
  510. var tex = textures[i];
  511. if( tex.t == null )
  512. tex.alloc();
  513. if( tex.t.rt == null )
  514. throw "Can't render to texture which is not allocated with Target flag";
  515. tex.lastFrame = frame;
  516. currentTargets[i] = tex.t.rt;
  517. unbind(tex.t.view);
  518. // prevent garbage
  519. if( !tex.flags.has(WasCleared) ) {
  520. tex.flags.set(WasCleared);
  521. Driver.clearColor(tex.t.rt, 0, 0, 0, 0);
  522. }
  523. }
  524. Driver.omSetRenderTargets(textures.length, currentTargets, currentDepth == null ? null : currentDepth.view);
  525. viewport[2] = tex.width;
  526. viewport[3] = tex.height;
  527. viewport[5] = 1.;
  528. Driver.rsSetViewports(1, viewport);
  529. }
  530. override function setRenderZone(x:Int, y:Int, width:Int, height:Int) {
  531. if( x == 0 && y == 0 && width < 0 && height < 0 ) {
  532. hasScissor = false;
  533. return;
  534. }
  535. if( x < 0 ) {
  536. width += x;
  537. x = 0;
  538. }
  539. if( y < 0 ) {
  540. height += y;
  541. y = 0;
  542. }
  543. if( width < 0 ) width = 0;
  544. if( height < 0 ) height = 0;
  545. hasScissor = true;
  546. rects[0] = x;
  547. rects[1] = y;
  548. rects[2] = x + width;
  549. rects[3] = y + height;
  550. Driver.rsSetScissorRects(1, rects);
  551. }
  552. override function selectShader(shader:hxsl.RuntimeShader) {
  553. var s = shaders.get(shader.id);
  554. if( s == null ) {
  555. s = new CompiledShader();
  556. var vertex = compileShader(shader.vertex);
  557. s.vertex = vertex.s;
  558. s.fragment = compileShader(shader.fragment).s;
  559. s.inputs = [];
  560. s.offsets = [];
  561. var layout = [], offset = 0;
  562. for( v in shader.vertex.data.vars )
  563. if( v.kind == Input ) {
  564. var e = new LayoutElement();
  565. e.semanticName = @:privateAccess v.name.toUtf8();
  566. e.inputSlot = layout.length;
  567. e.format = switch( v.type ) {
  568. case TFloat: R32_FLOAT;
  569. case TVec(2, VFloat): R32G32_FLOAT;
  570. case TVec(3, VFloat): R32G32B32_FLOAT;
  571. case TVec(4, VFloat): R32G32B32A32_FLOAT;
  572. case TBytes(4): R8G8B8A8_UINT;
  573. default:
  574. throw "Unsupported input type " + hxsl.Ast.Tools.toString(v.type);
  575. };
  576. e.inputSlotClass = PerVertexData;
  577. layout.push(e);
  578. s.offsets.push(offset);
  579. s.inputs.push(v.name);
  580. var size = switch( v.type ) {
  581. case TVec(n, _): n;
  582. case TBytes(n): n;
  583. case TFloat: 1;
  584. default: throw "assert " + v.type;
  585. }
  586. offset += size;
  587. }
  588. var n = new hl.NativeArray(layout.length);
  589. for( i in 0...layout.length )
  590. n[i] = layout[i];
  591. s.layout = Driver.createInputLayout(n, vertex.bytes, vertex.bytes.length);
  592. if( s.layout == null )
  593. throw "Failed to create input layout";
  594. shaders.set(shader.id, s);
  595. }
  596. if( s == currentShader )
  597. return false;
  598. currentShader = s;
  599. dx.Driver.vsSetShader(s.vertex.shader);
  600. dx.Driver.psSetShader(s.fragment.shader);
  601. dx.Driver.iaSetInputLayout(s.layout);
  602. return true;
  603. }
  604. override function getShaderInputNames():Array<String> {
  605. return currentShader.inputs;
  606. }
  607. override function selectBuffer(buffer:Buffer) {
  608. var vbuf = @:privateAccess buffer.buffer.vbuf;
  609. var start = -1, max = -1, position = 0;
  610. for( i in 0...currentShader.inputs.length ) {
  611. if( currentVBuffers[i] != vbuf.res || offsets[i] != currentShader.offsets[i] << 2 ) {
  612. currentVBuffers[i] = vbuf.res;
  613. strides[i] = buffer.buffer.stride << 2;
  614. offsets[i] = currentShader.offsets[i] << 2;
  615. if( start < 0 ) start = i;
  616. max = i;
  617. }
  618. }
  619. if( max >= 0 )
  620. Driver.iaSetVertexBuffers(start, max - start + 1, currentVBuffers.getRef().offset(start), hl.Bytes.getArray(strides).offset(start << 2), hl.Bytes.getArray(offsets).offset(start << 2));
  621. }
  622. override function selectMultiBuffers(bl:Buffer.BufferOffset) {
  623. var index = 0;
  624. var start = -1, max = -1;
  625. while( bl != null ) {
  626. var vbuf = @:privateAccess bl.buffer.buffer.vbuf;
  627. if( currentVBuffers[index] != vbuf.res || offsets[index] != bl.offset << 2 ) {
  628. currentVBuffers[index] = vbuf.res;
  629. offsets[index] = bl.offset << 2;
  630. strides[index] = bl.buffer.buffer.stride << 2;
  631. if( start < 0 ) start = index;
  632. max = index;
  633. }
  634. index++;
  635. bl = bl.next;
  636. }
  637. if( max >= 0 )
  638. Driver.iaSetVertexBuffers(start, max - start + 1, currentVBuffers.getRef().offset(start), hl.Bytes.getArray(strides).offset(start << 2), hl.Bytes.getArray(offsets).offset(start << 2));
  639. }
  640. override function uploadShaderBuffers(buffers:h3d.shader.Buffers, which:h3d.shader.Buffers.BufferKind) {
  641. uploadBuffers(vertexShader, currentShader.vertex, buffers.vertex, which);
  642. uploadBuffers(pixelShader, currentShader.fragment, buffers.fragment, which);
  643. }
  644. function uploadShaderBuffer( sbuffer : dx.Resource, buffer : haxe.ds.Vector<hxd.impl.Float32>, size : Int, prevContent : hl.Bytes ) {
  645. if( size == 0 ) return;
  646. var data = hl.Bytes.getArray(buffer.toData());
  647. var bytes = size << 4;
  648. if( prevContent != null ) {
  649. if( prevContent.compare(0, data, 0, bytes) == 0 )
  650. return;
  651. prevContent.blit(0, data, 0, bytes);
  652. mapCount++;
  653. }
  654. var ptr = sbuffer.map(0, WriteDiscard, true, null);
  655. if( ptr == null ) throw "Can't map buffer " + sbuffer;
  656. ptr.blit(0, data, 0, bytes);
  657. sbuffer.unmap(0);
  658. }
  659. function uploadBuffers( state : PipelineState, shader : ShaderContext, buffers : h3d.shader.Buffers.ShaderBuffers, which : h3d.shader.Buffers.BufferKind ) {
  660. switch( which ) {
  661. case Globals:
  662. if( shader.globalsSize > 0 ) {
  663. uploadShaderBuffer(shader.globals, buffers.globals, shader.globalsSize, null);
  664. if( state.buffers[0] != shader.globals ) {
  665. state.buffers[0] = shader.globals;
  666. switch( state.kind ) {
  667. case Vertex:
  668. Driver.vsSetConstantBuffers(0, 1, state.buffers);
  669. case Pixel:
  670. Driver.psSetConstantBuffers(0, 1, state.buffers);
  671. }
  672. }
  673. }
  674. case Params:
  675. if( shader.paramsSize > 0 ) {
  676. uploadShaderBuffer(shader.params, buffers.params, shader.paramsSize, shader.paramsContent);
  677. if( state.buffers[1] != shader.params ) {
  678. state.buffers[1] = shader.params;
  679. switch( state.kind ) {
  680. case Vertex:
  681. Driver.vsSetConstantBuffers(1, 1, state.buffers.getRef().offset(1));
  682. case Pixel:
  683. Driver.psSetConstantBuffers(1, 1, state.buffers.getRef().offset(1));
  684. }
  685. }
  686. }
  687. case Textures:
  688. var start = -1, max = -1;
  689. var sstart = -1, smax = -1;
  690. for( i in 0...shader.texturesCount ) {
  691. var t = buffers.tex[i];
  692. if( t == null || t.isDisposed() ) {
  693. var color = h3d.mat.Defaults.loadingTextureColor;
  694. t = h3d.mat.Texture.fromColor(color,(color>>>24)/255);
  695. }
  696. if( t != null && t.t == null && t.realloc != null ) {
  697. t.alloc();
  698. t.realloc();
  699. }
  700. t.lastFrame = frame;
  701. var view = t.t.view;
  702. if( view != state.resources[i] ) {
  703. state.resources[i] = view;
  704. max = i;
  705. if( start < 0 ) start = i;
  706. }
  707. var bits = @:privateAccess t.bits;
  708. if( bits != state.samplerBits[i] ) {
  709. var ss = samplerStates.get(bits);
  710. if( ss == null ) {
  711. var desc = new SamplerDesc();
  712. desc.filter = FILTER[t.mipMap.getIndex()][t.filter.getIndex()];
  713. desc.addressU = desc.addressV = desc.addressW = WRAP[t.wrap.getIndex()];
  714. if( t.mipMap == None ) {
  715. desc.minLod = desc.maxLod = 0;
  716. } else {
  717. desc.minLod = 0;
  718. desc.maxLod = 1e30;
  719. }
  720. ss = Driver.createSamplerState(desc);
  721. samplerStates.set(bits, ss);
  722. }
  723. state.samplerBits[i] = bits;
  724. state.samplers[i] = ss;
  725. smax = i;
  726. if( sstart < 0 ) sstart = i;
  727. }
  728. }
  729. switch( state.kind) {
  730. case Vertex:
  731. if( max >= 0 ) Driver.vsSetShaderResources(start, max - start + 1, state.resources.getRef().offset(start));
  732. if( smax >= 0 ) Driver.vsSetSamplers(sstart, smax - sstart + 1, state.samplers.getRef().offset(sstart));
  733. case Pixel:
  734. if( max >= 0 ) Driver.psSetShaderResources(start, max - start + 1, state.resources.getRef().offset(start));
  735. if( smax >= 0 ) Driver.psSetSamplers(sstart, smax - sstart + 1, state.samplers.getRef().offset(sstart));
  736. }
  737. }
  738. }
  739. override function draw(ibuf:IndexBuffer, startIndex:Int, ntriangles:Int) {
  740. if( currentIndex != ibuf ) {
  741. currentIndex = ibuf;
  742. dx.Driver.iaSetIndexBuffer(ibuf.res,false,0);
  743. }
  744. dx.Driver.drawIndexed(ntriangles * 3, startIndex, 0);
  745. }
  746. static var COMPARE : Array<ComparisonFunc> = [
  747. Always,
  748. Never,
  749. Equal,
  750. NotEqual,
  751. Greater,
  752. GreaterEqual,
  753. Less,
  754. LessEqual
  755. ];
  756. static var CULL : Array<CullMode> = [
  757. None,
  758. Back,
  759. Front,
  760. ];
  761. static var BLEND : Array<Blend> = [
  762. One,
  763. Zero,
  764. SrcAlpha,
  765. SrcColor,
  766. DestAlpha,
  767. DestColor,
  768. InvSrcAlpha,
  769. InvSrcColor,
  770. InvDestAlpha,
  771. InvDestColor,
  772. Src1Color,
  773. Src1Alpha,
  774. InvSrc1Color,
  775. InvSrc1Alpha,
  776. SrcAlphaSat,
  777. // BlendFactor/InvBlendFactor : not supported by Heaps for now
  778. ];
  779. static var BLEND_ALPHA : Array<Blend> = [
  780. One,
  781. Zero,
  782. SrcAlpha,
  783. SrcAlpha,
  784. DestAlpha,
  785. DestAlpha,
  786. InvSrcAlpha,
  787. InvSrcAlpha,
  788. InvDestAlpha,
  789. InvDestAlpha,
  790. Src1Alpha,
  791. Src1Alpha,
  792. InvSrc1Alpha,
  793. InvSrc1Alpha,
  794. SrcAlphaSat,
  795. // BlendFactor/InvBlendFactor : not supported by Heaps for now
  796. ];
  797. static var BLEND_OP : Array<BlendOp> = [
  798. Add,
  799. Subtract,
  800. RevSubstract,
  801. // Min / Max : not supported by Heaps for now
  802. ];
  803. static var FILTER : Array<Array<Filter>> = [
  804. [MinMagMipPoint,MinMagMipLinear],
  805. [MinMagMipPoint,MinMagLinearMipPoint],
  806. [MinMagPointMipLinear, MinMagMipLinear],
  807. // Anisotropic , Comparison, Minimum, Maximum
  808. ];
  809. static var WRAP : Array<AddressMode> = [
  810. Clamp,
  811. Wrap,
  812. //Mirror , Border , MirrorOnce
  813. ];
  814. }
  815. #end