GSdx-d3d: Port mipmap max_layer calculation from opengl to direct3d.

Fixes texture corruption on direct3d when full mipmapping was used.
This commit is contained in:
KrossX 2018-09-20 19:14:59 +02:00 committed by lightningterror
parent a275cf8e57
commit e063be3043
8 changed files with 79 additions and 13 deletions

View File

@ -39,6 +39,8 @@ GSDevice11::GSDevice11()
m_state.topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; m_state.topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
m_state.bf = -1; m_state.bf = -1;
m_mipmap = theApp.GetConfigI("mipmap");
if (theApp.GetConfigB("UserHacks")) { if (theApp.GetConfigB("UserHacks")) {
UserHacks_unscale_pt_ln = theApp.GetConfigB("UserHacks_unscale_point_line"); UserHacks_unscale_pt_ln = theApp.GetConfigB("UserHacks_unscale_point_line");
UserHacks_disable_NV_hack = theApp.GetConfigB("UserHacks_DisableNVhack"); 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; 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) switch(type)
{ {
case GSTexture::RenderTarget: case GSTexture::RenderTarget:
@ -524,6 +530,7 @@ GSTexture* GSDevice11::CreateSurface(int type, int w, int h, bool msaa, int form
break; break;
case GSTexture::Texture: case GSTexture::Texture:
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.MipLevels = layers;
break; break;
case GSTexture::Offscreen: case GSTexture::Offscreen:
desc.Usage = D3D11_USAGE_STAGING; desc.Usage = D3D11_USAGE_STAGING;
@ -709,14 +716,14 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
GSSelector sel; 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 //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) //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 //sel.prim = 2; //Triangle Strip
//SetupGS(sel); //SetupGS(sel);
GSSetShader(NULL, NULL); GSSetShader(NULL, NULL);
/*END OF HACK*/ /*END OF HACK*/
// //
// ps // ps

View File

@ -60,6 +60,8 @@ class GSDevice11 : public GSDeviceDX
bool UserHacks_unscale_pt_ln; bool UserHacks_unscale_pt_ln;
bool UserHacks_disable_NV_hack; bool UserHacks_disable_NV_hack;
int m_mipmap;
struct struct
{ {
ID3D11Buffer* vb; ID3D11Buffer* vb;

View File

@ -32,6 +32,7 @@ GSDevice9::GSDevice9()
FXAA_Compiled = false; FXAA_Compiled = false;
ExShader_Compiled = false; ExShader_Compiled = false;
m_mipmap = theApp.GetConfigI("mipmap");
memset(&m_pp, 0, sizeof(m_pp)); memset(&m_pp, 0, sizeof(m_pp));
memset(&m_d3dcaps, 0, sizeof(m_d3dcaps)); 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<IDirect3DTexture9> texture; CComPtr<IDirect3DTexture9> texture;
CComPtr<IDirect3DSurface9> surface; CComPtr<IDirect3DSurface9> 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) switch(type)
{ {
case GSTexture::RenderTarget: 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); else hr = m_dev->CreateDepthStencilSurface(w, h, (D3DFORMAT)format, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
break; break;
case GSTexture::Texture: 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; break;
case GSTexture::Offscreen: case GSTexture::Offscreen:
hr = m_dev->CreateOffscreenPlainSurface(w, h, (D3DFORMAT)format, D3DPOOL_SYSTEMMEM, &surface, NULL); 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); GSVector4 dRect(0, 0, s.x, s.y);
ExternalFXConstantBuffer cb; ExternalFXConstantBuffer cb;
InitExternalFX(); InitExternalFX();
cb.xyFrame = GSVector2((float)s.x, (float)s.y); cb.xyFrame = GSVector2((float)s.x, (float)s.y);

View File

@ -97,6 +97,8 @@ class GSDevice9 : public GSDeviceDX
bool m_lost; bool m_lost;
D3DFORMAT m_depth_format; D3DFORMAT m_depth_format;
int m_mipmap;
struct struct
{ {
IDirect3DVertexBuffer9* vb; IDirect3DVertexBuffer9* vb;

View File

@ -24,7 +24,7 @@
#include "GSPng.h" #include "GSPng.h"
GSTexture11::GSTexture11(ID3D11Texture2D* texture) GSTexture11::GSTexture11(ID3D11Texture2D* texture)
: m_texture(texture) : m_texture(texture), m_layer(0)
{ {
ASSERT(m_texture); ASSERT(m_texture);
@ -44,15 +44,21 @@ GSTexture11::GSTexture11(ID3D11Texture2D* texture)
m_format = (int)m_desc.Format; m_format = (int)m_desc.Format;
m_msaa = m_desc.SampleDesc.Count > 1; 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) 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) if(m_dev && m_texture)
{ {
D3D11_BOX box = { (UINT)r.left, (UINT)r.top, 0U, (UINT)r.right, (UINT)r.bottom, 1U }; 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; return true;
} }
@ -65,19 +71,24 @@ bool GSTexture11::Map(GSMap& m, const GSVector4i* r, int layer)
if(r != NULL) if(r != NULL)
{ {
// ASSERT(0); // not implemented // ASSERT(0); // not implemented
return false; return false;
} }
if(layer >= m_max_layer)
return false;
if(m_texture && m_desc.Usage == D3D11_USAGE_STAGING) if(m_texture && m_desc.Usage == D3D11_USAGE_STAGING)
{ {
D3D11_MAPPED_SUBRESOURCE map; 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.bits = (uint8*)map.pData;
m.pitch = (int)map.RowPitch; m.pitch = (int)map.RowPitch;
m_layer = layer;
return true; return true;
} }
} }
@ -89,7 +100,8 @@ void GSTexture11::Unmap()
{ {
if(m_texture) if(m_texture)
{ {
m_ctx->Unmap(m_texture, 0); UINT subresource = m_layer;
m_ctx->Unmap(m_texture, subresource);
} }
} }

View File

@ -34,6 +34,9 @@ class GSTexture11 : public GSTexture
CComPtr<ID3D11RenderTargetView> m_rtv; CComPtr<ID3D11RenderTargetView> m_rtv;
CComPtr<ID3D11DepthStencilView> m_dsv; CComPtr<ID3D11DepthStencilView> m_dsv;
int m_layer;
int m_max_layer;
public: public:
explicit GSTexture11(ID3D11Texture2D* texture); explicit GSTexture11(ID3D11Texture2D* texture);

View File

@ -24,17 +24,20 @@
#include "GSPng.h" #include "GSPng.h"
GSTexture9::GSTexture9(IDirect3DSurface9* surface) GSTexture9::GSTexture9(IDirect3DSurface9* surface)
: m_surface(surface), m_layer(0), m_generate_mipmap(true)
{ {
m_surface = surface;
surface->GetDevice(&m_dev); surface->GetDevice(&m_dev);
surface->GetDesc(&m_desc); surface->GetDesc(&m_desc);
m_max_layer = 1;
if(m_desc.Type != D3DRTYPE_SURFACE) if(m_desc.Type != D3DRTYPE_SURFACE)
{ {
surface->GetContainer(__uuidof(IDirect3DTexture9), (void**)&m_texture); surface->GetContainer(__uuidof(IDirect3DTexture9), (void**)&m_texture);
ASSERT(m_texture != NULL); ASSERT(m_texture != NULL);
m_max_layer = m_texture->GetLevelCount();
} }
m_size.x = (int)m_desc.Width; m_size.x = (int)m_desc.Width;
@ -51,9 +54,8 @@ GSTexture9::GSTexture9(IDirect3DSurface9* surface)
} }
GSTexture9::GSTexture9(IDirect3DTexture9* texture) GSTexture9::GSTexture9(IDirect3DTexture9* texture)
: m_texture(texture), m_layer(0), m_generate_mipmap(true)
{ {
m_texture = texture;
texture->GetDevice(&m_dev); texture->GetDevice(&m_dev);
texture->GetLevelDesc(0, &m_desc); texture->GetLevelDesc(0, &m_desc);
texture->GetSurfaceLevel(0, &m_surface); texture->GetSurfaceLevel(0, &m_surface);
@ -71,6 +73,8 @@ GSTexture9::GSTexture9(IDirect3DTexture9* texture)
m_format = (int)m_desc.Format; m_format = (int)m_desc.Format;
m_msaa = m_desc.MultiSampleType > 1; m_msaa = m_desc.MultiSampleType > 1;
m_max_layer = m_texture->GetLevelCount();
} }
GSTexture9::~GSTexture9() GSTexture9::~GSTexture9()
@ -79,6 +83,16 @@ GSTexture9::~GSTexture9()
bool GSTexture9::Update(const GSVector4i& r, const void* data, int pitch, int layer) 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) if(m_surface)
{ {
D3DLOCKED_RECT lr; D3DLOCKED_RECT lr;
@ -107,6 +121,8 @@ bool GSTexture9::Update(const GSVector4i& r, const void* data, int pitch, int la
m_surface->UnlockRect(); m_surface->UnlockRect();
m_generate_mipmap = true;
return true; return true;
} }
} }
@ -118,6 +134,16 @@ bool GSTexture9::Map(GSMap& m, const GSVector4i* r, int layer)
{ {
HRESULT hr; HRESULT hr;
if(layer >= m_max_layer)
return false;
if(m_texture)
{
m_surface = nullptr;
m_texture->GetSurfaceLevel(layer, &m_surface);
}
if(m_surface) if(m_surface)
{ {
D3DLOCKED_RECT lr; D3DLOCKED_RECT lr;
@ -127,6 +153,8 @@ bool GSTexture9::Map(GSMap& m, const GSVector4i* r, int layer)
m.bits = (uint8*)lr.pBits; m.bits = (uint8*)lr.pBits;
m.pitch = (int)lr.Pitch; m.pitch = (int)lr.Pitch;
m_layer = layer;
return true; return true;
} }
} }
@ -139,6 +167,8 @@ void GSTexture9::Unmap()
if(m_surface) if(m_surface)
{ {
m_surface->UnlockRect(); m_surface->UnlockRect();
m_generate_mipmap = true;
} }
} }

View File

@ -30,6 +30,11 @@ class GSTexture9 : public GSTexture
CComPtr<IDirect3DTexture9> m_texture; CComPtr<IDirect3DTexture9> m_texture;
D3DSURFACE_DESC m_desc; D3DSURFACE_DESC m_desc;
bool m_generate_mipmap;
int m_layer;
int m_max_layer;
public: public:
explicit GSTexture9(IDirect3DSurface9* surface); explicit GSTexture9(IDirect3DSurface9* surface);
explicit GSTexture9(IDirect3DTexture9* texture); explicit GSTexture9(IDirect3DTexture9* texture);