|
@@ -70,6 +70,8 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
var driver : DriverInstance;
|
|
|
var shaders : Map<Int,CompiledShader>;
|
|
|
|
|
|
+ var hasDeviceError = false;
|
|
|
+
|
|
|
var defaultTarget : RenderTargetView;
|
|
|
var defaultDepth : DepthBuffer;
|
|
|
var defaultDepthInst : h3d.mat.DepthBuffer;
|
|
@@ -84,18 +86,18 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
var currentIndex : IndexBuffer;
|
|
|
var currentDepth : DepthBuffer;
|
|
|
var currentTargets = new hl.NativeArray<RenderTargetView>(16);
|
|
|
- var vertexShader = new PipelineState(Vertex);
|
|
|
- var pixelShader = new PipelineState(Pixel);
|
|
|
+ var vertexShader : PipelineState;
|
|
|
+ var pixelShader : PipelineState;
|
|
|
var currentVBuffers = new hl.NativeArray<dx.Resource>(16);
|
|
|
var frame : Int;
|
|
|
var currentMaterialBits = -1;
|
|
|
var targetsCount = 1;
|
|
|
var allowDraw = false;
|
|
|
|
|
|
- var depthStates : Map<Int,DepthStencilState> = new Map();
|
|
|
- var blendStates : Map<Int,BlendState> = new Map();
|
|
|
- var rasterStates : Map<Int,RasterState> = new Map();
|
|
|
- var samplerStates : Map<Int,SamplerState> = new Map();
|
|
|
+ var depthStates : Map<Int,DepthStencilState>;
|
|
|
+ var blendStates : Map<Int,BlendState>;
|
|
|
+ var rasterStates : Map<Int,RasterState>;
|
|
|
+ var samplerStates : Map<Int,SamplerState>;
|
|
|
var currentDepthState : DepthStencilState;
|
|
|
var currentBlendState : BlendState;
|
|
|
var currentRasterState : RasterState;
|
|
@@ -111,13 +113,40 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
|
|
|
var mapCount : Int;
|
|
|
var updateResCount : Int;
|
|
|
+ var onContextLost : Void -> Void;
|
|
|
|
|
|
public var backBufferFormat : dx.Format = R8G8B8A8_UNORM;
|
|
|
public var depthStencilFormat : dx.Format = D24_UNORM_S8_UINT;
|
|
|
|
|
|
public function new() {
|
|
|
- shaders = new Map();
|
|
|
window = @:privateAccess dx.Window.windows[0];
|
|
|
+ Driver.setErrorHandler(onDXError);
|
|
|
+ reset();
|
|
|
+ }
|
|
|
+
|
|
|
+ function reset() {
|
|
|
+ allowDraw = false;
|
|
|
+ targetsCount = 1;
|
|
|
+ currentMaterialBits = -1;
|
|
|
+ if( shaders != null ) {
|
|
|
+ for( s in shaders ) {
|
|
|
+ s.fragment.shader.release();
|
|
|
+ s.vertex.shader.release();
|
|
|
+ s.layout.release();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if( depthStates != null ) for( s in depthStates ) if( s != null ) s.release();
|
|
|
+ if( blendStates != null ) for( s in blendStates ) if( s != null ) s.release();
|
|
|
+ if( rasterStates != null ) for( s in rasterStates ) if( s != null ) s.release();
|
|
|
+ if( samplerStates != null ) for( s in samplerStates ) if( s != null ) s.release();
|
|
|
+ shaders = new Map();
|
|
|
+ depthStates = new Map();
|
|
|
+ blendStates = new Map();
|
|
|
+ rasterStates = new Map();
|
|
|
+ samplerStates = new Map();
|
|
|
+ vertexShader = new PipelineState(Vertex);
|
|
|
+ pixelShader = new PipelineState(Pixel);
|
|
|
+
|
|
|
var options : dx.Driver.DriverInitFlags = None;
|
|
|
#if debug
|
|
|
options |= DebugLayer;
|
|
@@ -126,7 +155,7 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
try
|
|
|
driver = Driver.create(window, backBufferFormat, options)
|
|
|
catch( e : Dynamic )
|
|
|
- throw "Failed to initialize DirectX driver (" + e+")";
|
|
|
+ throw "Failed to initialize DirectX driver (" + e + ")";
|
|
|
|
|
|
if( driver == null ) throw "Failed to initialize DirectX driver";
|
|
|
|
|
@@ -143,6 +172,18 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
blendFactors[i] = 0;
|
|
|
}
|
|
|
|
|
|
+ override function dispose() {
|
|
|
+ Driver.disposeDriver(driver);
|
|
|
+ driver = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ function onDXError(code:Int,reason:Int,line:Int) {
|
|
|
+ if( code != 0x887A0005 /*DXGI_ERROR_DEVICE_REMOVED*/ )
|
|
|
+ throw "DXError "+StringTools.hex(code)+" line "+line;
|
|
|
+ //if( !hasDeviceError ) trace("DX_REMOVED "+StringTools.hex(reason)+":"+line);
|
|
|
+ hasDeviceError = true;
|
|
|
+ }
|
|
|
+
|
|
|
override function resize(width:Int, height:Int) {
|
|
|
if( defaultDepth != null ) {
|
|
|
defaultDepth.view.release();
|
|
@@ -197,10 +238,11 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
}
|
|
|
|
|
|
override function isDisposed() {
|
|
|
- return false;
|
|
|
+ return hasDeviceError;
|
|
|
}
|
|
|
|
|
|
override function init( onCreate : Bool -> Void, forceSoftware = false ) {
|
|
|
+ onContextLost = onCreate.bind(true);
|
|
|
haxe.Timer.delay(onCreate.bind(false), 1);
|
|
|
}
|
|
|
|
|
@@ -219,12 +261,25 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
return desc;
|
|
|
}
|
|
|
|
|
|
+ public function forceDeviceError() {
|
|
|
+ hasDeviceError = true;
|
|
|
+ }
|
|
|
+
|
|
|
override function present() {
|
|
|
if( defaultTarget == null ) return;
|
|
|
var old = hxd.System.allowTimeout;
|
|
|
if( old ) hxd.System.allowTimeout = false;
|
|
|
Driver.present(window.vsync ? 1 : 0, None);
|
|
|
if( old ) hxd.System.allowTimeout = true;
|
|
|
+
|
|
|
+ if( hasDeviceError ) {
|
|
|
+ //trace("OnContextLost");
|
|
|
+ hasDeviceError = false;
|
|
|
+ dispose();
|
|
|
+ reset();
|
|
|
+ onContextLost();
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
override function getDefaultDepthBuffer():h3d.mat.DepthBuffer {
|
|
@@ -331,8 +386,8 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
var tt = t.t;
|
|
|
if( tt == null ) return;
|
|
|
t.t = null;
|
|
|
- tt.view.release();
|
|
|
- tt.res.release();
|
|
|
+ if( tt.view != null ) tt.view.release();
|
|
|
+ if( tt.res != null ) tt.res.release();
|
|
|
if( tt.rt != null )
|
|
|
for( rt in tt.rt )
|
|
|
if( rt != null )
|
|
@@ -348,6 +403,7 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
}
|
|
|
|
|
|
override function generateMipMaps(texture:h3d.mat.Texture) {
|
|
|
+ if( hasDeviceError ) return;
|
|
|
Driver.generateMips(texture.t.view);
|
|
|
}
|
|
|
|
|
@@ -363,18 +419,22 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
}
|
|
|
|
|
|
override function uploadIndexBuffer(i:IndexBuffer, startIndice:Int, indiceCount:Int, buf:hxd.IndexBuffer, bufPos:Int) {
|
|
|
+ if( hasDeviceError ) return;
|
|
|
updateBuffer(i.res, hl.Bytes.getArray(buf.getNative()).offset(bufPos << 1), startIndice << 1, indiceCount << 1);
|
|
|
}
|
|
|
|
|
|
override function uploadIndexBytes(i:IndexBuffer, startIndice:Int, indiceCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
|
|
|
+ if( hasDeviceError ) return;
|
|
|
updateBuffer(i.res, @:privateAccess buf.b.offset(bufPos << 1), startIndice << 1, indiceCount << 1);
|
|
|
}
|
|
|
|
|
|
override function uploadVertexBuffer(v:VertexBuffer, startVertex:Int, vertexCount:Int, buf:hxd.FloatBuffer, bufPos:Int) {
|
|
|
+ if( hasDeviceError ) return;
|
|
|
updateBuffer(v.res, hl.Bytes.getArray(buf.getNative()).offset(bufPos<<2), startVertex * v.stride << 2, vertexCount * v.stride << 2);
|
|
|
}
|
|
|
|
|
|
override function uploadVertexBytes(v:VertexBuffer, startVertex:Int, vertexCount:Int, buf:haxe.io.Bytes, bufPos:Int) {
|
|
|
+ if( hasDeviceError ) return;
|
|
|
updateBuffer(v.res, @:privateAccess buf.b.offset(bufPos << 2), startVertex * v.stride << 2, vertexCount * v.stride << 2);
|
|
|
}
|
|
|
|
|
@@ -441,6 +501,7 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
}
|
|
|
|
|
|
override function uploadTextureBitmap(t:h3d.mat.Texture, bmp:hxd.BitmapData, mipLevel:Int, side:Int) {
|
|
|
+ if( hasDeviceError ) return;
|
|
|
var pixels = bmp.getPixels();
|
|
|
uploadTexturePixels(t, pixels, mipLevel, side);
|
|
|
pixels.dispose();
|
|
@@ -449,6 +510,7 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
override function uploadTexturePixels(t:h3d.mat.Texture, pixels:hxd.Pixels, mipLevel:Int, side:Int) {
|
|
|
pixels.convert(RGBA);
|
|
|
pixels.setFlip(false);
|
|
|
+ if( hasDeviceError ) return;
|
|
|
if( mipLevel >= t.t.mips ) throw "Mip level outside texture range : " + mipLevel + " (max = " + (t.t.mips - 1) + ")";
|
|
|
t.t.res.updateSubresource(mipLevel + side * t.t.mips, null, (pixels.bytes:hl.Bytes).offset(pixels.offset), pixels.width * hxd.Pixels.bytesPerPixel(pixels.format), 0);
|
|
|
updateResCount++;
|
|
@@ -561,8 +623,10 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
if( compileOnly )
|
|
|
return { s : null, bytes : bytes };
|
|
|
var s = shader.vertex ? Driver.createVertexShader(bytes) : Driver.createPixelShader(bytes);
|
|
|
- if( s == null )
|
|
|
+ if( s == null ) {
|
|
|
+ if( hasDeviceError ) return null;
|
|
|
throw "Failed to create shader\n" + shader.code;
|
|
|
+ }
|
|
|
|
|
|
var ctx = new ShaderContext(s);
|
|
|
ctx.globalsSize = shader.globalsSize;
|
|
@@ -645,6 +709,8 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
setRenderTarget(null);
|
|
|
return;
|
|
|
}
|
|
|
+ if( hasDeviceError )
|
|
|
+ return;
|
|
|
var tex = textures[0];
|
|
|
curTexture = textures[0];
|
|
|
if( tex.depthBuffer != null && (tex.depthBuffer.width != tex.width || tex.depthBuffer.height != tex.height) )
|
|
@@ -652,8 +718,10 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
currentDepth = @:privateAccess (tex.depthBuffer == null ? null : tex.depthBuffer.b);
|
|
|
for( i in 0...textures.length ) {
|
|
|
var tex = textures[i];
|
|
|
- if( tex.t == null )
|
|
|
+ if( tex.t == null ) {
|
|
|
tex.alloc();
|
|
|
+ if( hasDeviceError ) return;
|
|
|
+ }
|
|
|
if( tex.t.rt == null )
|
|
|
throw "Can't render to texture which is not allocated with Target flag";
|
|
|
var index = mipLevel * 6 + face;
|
|
@@ -713,8 +781,10 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
if( s == null ) {
|
|
|
s = new CompiledShader();
|
|
|
var vertex = compileShader(shader.vertex);
|
|
|
+ var fragment = compileShader(shader.fragment);
|
|
|
+ if( hasDeviceError ) return false;
|
|
|
s.vertex = vertex.s;
|
|
|
- s.fragment = compileShader(shader.fragment).s;
|
|
|
+ s.fragment = fragment.s;
|
|
|
s.inputs = [];
|
|
|
s.offsets = [];
|
|
|
|
|
@@ -771,6 +841,7 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
}
|
|
|
|
|
|
override function selectBuffer(buffer:Buffer) {
|
|
|
+ if( hasDeviceError ) return;
|
|
|
var vbuf = @:privateAccess buffer.buffer.vbuf;
|
|
|
var start = -1, max = -1, position = 0;
|
|
|
for( i in 0...currentShader.inputs.length ) {
|
|
@@ -787,6 +858,7 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
}
|
|
|
|
|
|
override function selectMultiBuffers(bl:Buffer.BufferOffset) {
|
|
|
+ if( hasDeviceError ) return;
|
|
|
var index = 0;
|
|
|
var start = -1, max = -1;
|
|
|
while( bl != null ) {
|
|
@@ -806,6 +878,7 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
}
|
|
|
|
|
|
override function uploadShaderBuffers(buffers:h3d.shader.Buffers, which:h3d.shader.Buffers.BufferKind) {
|
|
|
+ if( hasDeviceError ) return;
|
|
|
uploadBuffers(vertexShader, currentShader.vertex, buffers.vertex, which);
|
|
|
uploadBuffers(pixelShader, currentShader.fragment, buffers.fragment, which);
|
|
|
}
|
|
@@ -870,6 +943,7 @@ class DirectXDriver extends h3d.impl.Driver {
|
|
|
if( t != null && t.t == null && t.realloc != null ) {
|
|
|
t.alloc();
|
|
|
t.realloc();
|
|
|
+ if( hasDeviceError ) return;
|
|
|
}
|
|
|
t.lastFrame = frame;
|
|
|
|