From e063be3043f3786498f3cae7bf35e30cae2d35b3 Mon Sep 17 00:00:00 2001 From: KrossX Date: Thu, 20 Sep 2018 19:14:59 +0200 Subject: [PATCH] GSdx-d3d: Port mipmap max_layer calculation from opengl to direct3d. Fixes texture corruption on direct3d when full mipmapping was used. --- plugins/GSdx/GSDevice11.cpp | 11 +++++++++-- plugins/GSdx/GSDevice11.h | 2 ++ plugins/GSdx/GSDevice9.cpp | 9 +++++++-- plugins/GSdx/GSDevice9.h | 2 ++ plugins/GSdx/GSTexture11.cpp | 22 ++++++++++++++++----- plugins/GSdx/GSTexture11.h | 3 +++ plugins/GSdx/GSTexture9.cpp | 38 ++++++++++++++++++++++++++++++++---- plugins/GSdx/GSTexture9.h | 5 +++++ 8 files changed, 79 insertions(+), 13 deletions(-) diff --git a/plugins/GSdx/GSDevice11.cpp b/plugins/GSdx/GSDevice11.cpp index 9b1f1bfe6c..53ba6801da 100644 --- a/plugins/GSdx/GSDevice11.cpp +++ b/plugins/GSdx/GSDevice11.cpp @@ -39,6 +39,8 @@ GSDevice11::GSDevice11() m_state.topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; m_state.bf = -1; + m_mipmap = theApp.GetConfigI("mipmap"); + if (theApp.GetConfigB("UserHacks")) { UserHacks_unscale_pt_ln = theApp.GetConfigB("UserHacks_unscale_point_line"); UserHacks_disable_NV_hack = theApp.GetConfigB("UserHacks_DisableNVhack"); @@ -514,6 +516,10 @@ GSTexture* GSDevice11::CreateSurface(int type, int w, int h, bool msaa, int form desc.SampleDesc = m_msaa_desc; } + // mipmap = m_mipmap > 1 || m_filter != TriFiltering::None; + bool mipmap = m_mipmap > 1; + int layers = mipmap && format == DXGI_FORMAT_R8G8B8A8_UNORM ? (int)log2(std::max(w,h)) : 1; + switch(type) { case GSTexture::RenderTarget: @@ -524,6 +530,7 @@ GSTexture* GSDevice11::CreateSurface(int type, int w, int h, bool msaa, int form break; case GSTexture::Texture: desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.MipLevels = layers; break; case GSTexture::Offscreen: desc.Usage = D3D11_USAGE_STAGING; @@ -709,14 +716,14 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* GSSelector sel; //Don't use shading for stretching, we're just passing through - Note: With Win10 it seems to cause other bugs when shading is off if any of the coords is greater than 0 //I really don't know whats going on there, but this seems to resolve it mostly (if not all, not tester a lot of games, only BIOS, FFXII and VP2) - //sel.iip = (sRect.y > 0.0f || sRect.w > 0.0f) ? 1 : 0; + //sel.iip = (sRect.y > 0.0f || sRect.w > 0.0f) ? 1 : 0; //sel.prim = 2; //Triangle Strip //SetupGS(sel); GSSetShader(NULL, NULL); /*END OF HACK*/ - + // // ps diff --git a/plugins/GSdx/GSDevice11.h b/plugins/GSdx/GSDevice11.h index 92e7e05dfd..05f5073637 100644 --- a/plugins/GSdx/GSDevice11.h +++ b/plugins/GSdx/GSDevice11.h @@ -60,6 +60,8 @@ class GSDevice11 : public GSDeviceDX bool UserHacks_unscale_pt_ln; bool UserHacks_disable_NV_hack; + int m_mipmap; + struct { ID3D11Buffer* vb; diff --git a/plugins/GSdx/GSDevice9.cpp b/plugins/GSdx/GSDevice9.cpp index cbc8069102..18b4c17978 100644 --- a/plugins/GSdx/GSDevice9.cpp +++ b/plugins/GSdx/GSDevice9.cpp @@ -32,6 +32,7 @@ GSDevice9::GSDevice9() FXAA_Compiled = false; ExShader_Compiled = false; + m_mipmap = theApp.GetConfigI("mipmap"); memset(&m_pp, 0, sizeof(m_pp)); memset(&m_d3dcaps, 0, sizeof(m_d3dcaps)); @@ -695,6 +696,10 @@ GSTexture* GSDevice9::CreateSurface(int type, int w, int h, bool msaa, int forma CComPtr texture; CComPtr surface; + // mipmap = m_mipmap > 1 || m_filter != TriFiltering::None; + bool mipmap = m_mipmap > 1; + int layers = mipmap && format == D3DFMT_A8R8G8B8 ? (int)log2(std::max(w,h)) : 1; + switch(type) { case GSTexture::RenderTarget: @@ -706,7 +711,7 @@ GSTexture* GSDevice9::CreateSurface(int type, int w, int h, bool msaa, int forma else hr = m_dev->CreateDepthStencilSurface(w, h, (D3DFORMAT)format, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL); break; case GSTexture::Texture: - hr = m_dev->CreateTexture(w, h, 1, 0, (D3DFORMAT)format, D3DPOOL_MANAGED, &texture, NULL); + hr = m_dev->CreateTexture(w, h, layers, 0, (D3DFORMAT)format, D3DPOOL_MANAGED, &texture, NULL); break; case GSTexture::Offscreen: hr = m_dev->CreateOffscreenPlainSurface(w, h, (D3DFORMAT)format, D3DPOOL_SYSTEMMEM, &surface, NULL); @@ -981,7 +986,7 @@ void GSDevice9::DoExternalFX(GSTexture* sTex, GSTexture* dTex) GSVector4 dRect(0, 0, s.x, s.y); ExternalFXConstantBuffer cb; - + InitExternalFX(); cb.xyFrame = GSVector2((float)s.x, (float)s.y); diff --git a/plugins/GSdx/GSDevice9.h b/plugins/GSdx/GSDevice9.h index 560b030dd2..2f9b545ebf 100644 --- a/plugins/GSdx/GSDevice9.h +++ b/plugins/GSdx/GSDevice9.h @@ -97,6 +97,8 @@ class GSDevice9 : public GSDeviceDX bool m_lost; D3DFORMAT m_depth_format; + int m_mipmap; + struct { IDirect3DVertexBuffer9* vb; diff --git a/plugins/GSdx/GSTexture11.cpp b/plugins/GSdx/GSTexture11.cpp index 6372b3a9fd..41068b7498 100644 --- a/plugins/GSdx/GSTexture11.cpp +++ b/plugins/GSdx/GSTexture11.cpp @@ -24,7 +24,7 @@ #include "GSPng.h" GSTexture11::GSTexture11(ID3D11Texture2D* texture) - : m_texture(texture) + : m_texture(texture), m_layer(0) { ASSERT(m_texture); @@ -44,15 +44,21 @@ GSTexture11::GSTexture11(ID3D11Texture2D* texture) m_format = (int)m_desc.Format; m_msaa = m_desc.SampleDesc.Count > 1; + + m_max_layer = m_desc.MipLevels; } bool GSTexture11::Update(const GSVector4i& r, const void* data, int pitch, int layer) { + if(layer >= m_max_layer) + return true; + if(m_dev && m_texture) { D3D11_BOX box = { (UINT)r.left, (UINT)r.top, 0U, (UINT)r.right, (UINT)r.bottom, 1U }; + UINT subresource = layer; // MipSlice + (ArraySlice * MipLevels). - m_ctx->UpdateSubresource(m_texture, 0, &box, data, pitch, 0); + m_ctx->UpdateSubresource(m_texture, subresource, &box, data, pitch, 0); return true; } @@ -65,19 +71,24 @@ bool GSTexture11::Map(GSMap& m, const GSVector4i* r, int layer) if(r != NULL) { // ASSERT(0); // not implemented - return false; } + if(layer >= m_max_layer) + return false; + if(m_texture && m_desc.Usage == D3D11_USAGE_STAGING) { D3D11_MAPPED_SUBRESOURCE map; + UINT subresource = layer; - if(SUCCEEDED(m_ctx->Map(m_texture, 0, D3D11_MAP_READ_WRITE, 0, &map))) + if(SUCCEEDED(m_ctx->Map(m_texture, subresource, D3D11_MAP_READ_WRITE, 0, &map))) { m.bits = (uint8*)map.pData; m.pitch = (int)map.RowPitch; + m_layer = layer; + return true; } } @@ -89,7 +100,8 @@ void GSTexture11::Unmap() { if(m_texture) { - m_ctx->Unmap(m_texture, 0); + UINT subresource = m_layer; + m_ctx->Unmap(m_texture, subresource); } } diff --git a/plugins/GSdx/GSTexture11.h b/plugins/GSdx/GSTexture11.h index 221eb3f775..366f353a93 100644 --- a/plugins/GSdx/GSTexture11.h +++ b/plugins/GSdx/GSTexture11.h @@ -34,6 +34,9 @@ class GSTexture11 : public GSTexture CComPtr m_rtv; CComPtr m_dsv; + int m_layer; + int m_max_layer; + public: explicit GSTexture11(ID3D11Texture2D* texture); diff --git a/plugins/GSdx/GSTexture9.cpp b/plugins/GSdx/GSTexture9.cpp index ea3ebdec36..be17a806ec 100644 --- a/plugins/GSdx/GSTexture9.cpp +++ b/plugins/GSdx/GSTexture9.cpp @@ -24,17 +24,20 @@ #include "GSPng.h" GSTexture9::GSTexture9(IDirect3DSurface9* surface) + : m_surface(surface), m_layer(0), m_generate_mipmap(true) { - m_surface = surface; - surface->GetDevice(&m_dev); surface->GetDesc(&m_desc); + m_max_layer = 1; + if(m_desc.Type != D3DRTYPE_SURFACE) { surface->GetContainer(__uuidof(IDirect3DTexture9), (void**)&m_texture); ASSERT(m_texture != NULL); + + m_max_layer = m_texture->GetLevelCount(); } m_size.x = (int)m_desc.Width; @@ -51,9 +54,8 @@ GSTexture9::GSTexture9(IDirect3DSurface9* surface) } GSTexture9::GSTexture9(IDirect3DTexture9* texture) + : m_texture(texture), m_layer(0), m_generate_mipmap(true) { - m_texture = texture; - texture->GetDevice(&m_dev); texture->GetLevelDesc(0, &m_desc); texture->GetSurfaceLevel(0, &m_surface); @@ -71,6 +73,8 @@ GSTexture9::GSTexture9(IDirect3DTexture9* texture) m_format = (int)m_desc.Format; m_msaa = m_desc.MultiSampleType > 1; + + m_max_layer = m_texture->GetLevelCount(); } GSTexture9::~GSTexture9() @@ -79,6 +83,16 @@ GSTexture9::~GSTexture9() bool GSTexture9::Update(const GSVector4i& r, const void* data, int pitch, int layer) { + if(layer >= m_max_layer) + return true; + + if(m_texture) + { + m_surface = nullptr; + + m_texture->GetSurfaceLevel(layer, &m_surface); + } + if(m_surface) { D3DLOCKED_RECT lr; @@ -107,6 +121,8 @@ bool GSTexture9::Update(const GSVector4i& r, const void* data, int pitch, int la m_surface->UnlockRect(); + m_generate_mipmap = true; + return true; } } @@ -118,6 +134,16 @@ bool GSTexture9::Map(GSMap& m, const GSVector4i* r, int layer) { HRESULT hr; + if(layer >= m_max_layer) + return false; + + if(m_texture) + { + m_surface = nullptr; + + m_texture->GetSurfaceLevel(layer, &m_surface); + } + if(m_surface) { D3DLOCKED_RECT lr; @@ -127,6 +153,8 @@ bool GSTexture9::Map(GSMap& m, const GSVector4i* r, int layer) m.bits = (uint8*)lr.pBits; m.pitch = (int)lr.Pitch; + m_layer = layer; + return true; } } @@ -139,6 +167,8 @@ void GSTexture9::Unmap() if(m_surface) { m_surface->UnlockRect(); + + m_generate_mipmap = true; } } diff --git a/plugins/GSdx/GSTexture9.h b/plugins/GSdx/GSTexture9.h index a071b6a4f0..d82a3a18b8 100644 --- a/plugins/GSdx/GSTexture9.h +++ b/plugins/GSdx/GSTexture9.h @@ -30,6 +30,11 @@ class GSTexture9 : public GSTexture CComPtr m_texture; D3DSURFACE_DESC m_desc; + bool m_generate_mipmap; + + int m_layer; + int m_max_layer; + public: explicit GSTexture9(IDirect3DSurface9* surface); explicit GSTexture9(IDirect3DTexture9* texture);