diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp index 8a04f454c6..cfbca35f65 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.cpp @@ -238,6 +238,27 @@ unsigned int GetBackBufferHeight() { return yres; } bool BGRATexturesSupported() { return bgra_textures_supported; } +// Returns the maximum width/height of a texture. This value only depends upon the feature level in DX11 +unsigned int GetMaxTextureSize() +{ + switch (featlevel) + { + case D3D_FEATURE_LEVEL_11_0: + return 16384; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return 8192; + + case D3D_FEATURE_LEVEL_9_3: + return 4096; + + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 2048; + } +} + void Reset() { // release all back buffer references diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h index efcd7c1438..c1a70c803f 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DBase.h @@ -51,6 +51,8 @@ const char* PixelShaderVersionString(); const char* VertexShaderVersionString(); bool BGRATexturesSupported(); +unsigned int GetMaxTextureSize(); + // Ihis function will assign a name to the given resource. // The DirectX debug layer will make it easier to identify resources that way, // e.g. when listing up all resources who have unreleased references. diff --git a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp index 218afd6c9f..8ce9d41255 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp @@ -311,7 +311,7 @@ template AutoState::AutoState(const T* object) : state(object) template AutoState::AutoState(const AutoState &source) { state = source.GetPtr(); - ((IUnknown*)state)->AddRef(); + ((T*)state)->AddRef(); } template AutoState::~AutoState() diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index fd38ef53dd..1ab07b4130 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -700,6 +700,9 @@ void UpdateViewport() // [3] = xorig + width/2 + 342 // [4] = yorig + height/2 + 342 // [5] = 16777215 * farz + const int old_fulltarget_w = s_Fulltarget_width; + const int old_fulltarget_h = s_Fulltarget_height; + int scissorXOff = bpmem.scissorOffset.x * 2; int scissorYOff = bpmem.scissorOffset.y * 2; @@ -739,6 +742,15 @@ void UpdateViewport() } if (sizeChanged) { + // Make sure that the requested size is actually supported by the GFX driver + if (s_Fulltarget_width > (int)D3D::GetMaxTextureSize() || s_Fulltarget_height > (int)D3D::GetMaxTextureSize()) + { + // Skip EFB recreation and viewport setting. Most likely cause glitches in this case, but prevents crashes at least + ERROR_LOG(VIDEO, "Tried to set a viewport which is too wide to emulate with Direct3D11. Requested EFB size is %dx%d\n", s_Fulltarget_width, s_Fulltarget_height); + s_Fulltarget_width = old_fulltarget_w; + s_Fulltarget_height = old_fulltarget_h; + return; + } D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL); FBManager.Destroy(); FBManager.Create(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp index 4ea68869bc..cebcd00211 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp @@ -97,7 +97,7 @@ void FramebufferManager::Create() { hr = s_efb_color_texture->GetSurfaceLevel(0, &s_efb_color_surface); } - CHECK(hr, "Create Color Texture (hr=%#x)", hr); + CHECK(hr, "Create Color Texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format, D3DPOOL_DEFAULT, &s_efb_colorRead_texture, NULL); CHECK(hr, "Create Color Read Texture (hr=%#x)", hr); @@ -128,7 +128,7 @@ void FramebufferManager::Create() if (!FAILED(hr)) break; } - CHECK(hr, "Depth Color Texture (hr=%#x)", hr); + CHECK(hr, "Depth Color Texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); // Get the Surface if(s_efb_depth_texture) { diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index ad8ccfc62e..65fd01aa52 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -823,6 +823,9 @@ void UpdateViewport() // [3] = xorig + width/2 + 342 // [4] = yorig + height/2 + 342 // [5] = 16777215 * farz + const int old_fulltarget_w = s_Fulltarget_width; + const int old_fulltarget_h = s_Fulltarget_height; + int scissorXOff = bpmem.scissorOffset.x * 2; int scissorYOff = bpmem.scissorOffset.y * 2; @@ -877,6 +880,16 @@ void UpdateViewport() } if (sizeChanged) { + D3DCAPS9 caps = D3D::GetCaps(); + // Make sure that the requested size is actually supported by the GFX driver + if (s_Fulltarget_width > caps.MaxTextureWidth || s_Fulltarget_height > caps.MaxTextureHeight) + { + // Skip EFB recreation and viewport setting. Most likely cause glitches in this case, but prevents crashes at least + ERROR_LOG(VIDEO, "Tried to set a viewport which is too wide to emulate with Direct3D9. Requested EFB size is %dx%d\n", s_Fulltarget_width, s_Fulltarget_height); + s_Fulltarget_width = old_fulltarget_w; + s_Fulltarget_height = old_fulltarget_h; + return; + } D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface()); FBManager.Destroy();