D3D9: Make sure to use powers of two as render target dimensions if it's needed by the device.
Some other cleanups. Possibly fixes issue 3256. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6725 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
4b15325acd
commit
ecf92f5c3c
|
@ -27,15 +27,6 @@ TextureCache *g_texture_cache;
|
|||
u8 *TextureCache::temp;
|
||||
TextureCache::TexCache TextureCache::textures;
|
||||
|
||||
// returns the exponent of the smallest power of two which is greater than val
|
||||
unsigned int GetPow2(unsigned int val)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
for (; val; val >>= 1)
|
||||
++ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase::~TCacheEntryBase()
|
||||
{
|
||||
if (0 == addr)
|
||||
|
|
|
@ -181,4 +181,13 @@ inline u32 Z24ToZ16ToZ24(u32 src)
|
|||
return (src & 0xFFFF00) | (src >> 16);
|
||||
}
|
||||
|
||||
// returns the exponent of the smallest power of two which is greater than val
|
||||
static unsigned int GetPow2(unsigned int val)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
for (; val; val >>= 1)
|
||||
++ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // _VIDEOCOMMON_H
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "Render.h"
|
||||
#include "XFStructs.h"
|
||||
#include "StringUtil.h"
|
||||
#include "VideoCommon.h"
|
||||
|
||||
// D3DX
|
||||
HINSTANCE hD3DXDll = NULL;
|
||||
|
@ -434,6 +435,29 @@ const D3DCAPS9 &GetCaps()
|
|||
return caps;
|
||||
}
|
||||
|
||||
// returns true if size was changed
|
||||
bool FixTextureSize(int& width, int& height)
|
||||
{
|
||||
int oldw = width, oldh = height;
|
||||
|
||||
// conditional nonpow2 support should work fine for us
|
||||
if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
|
||||
{
|
||||
// all texture dimensions need to be powers of two
|
||||
width = GetPow2(width);
|
||||
height = GetPow2(height);
|
||||
}
|
||||
if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
|
||||
{
|
||||
width = height = max(width, height);
|
||||
}
|
||||
|
||||
width = min(width, (int)caps.MaxTextureWidth);
|
||||
height = min(height, (int)caps.MaxTextureHeight);
|
||||
|
||||
return (width != oldw) || (height != oldh);
|
||||
}
|
||||
|
||||
const char *VertexShaderVersionString()
|
||||
{
|
||||
static const char *versions[5] = {"ERROR", "vs_1_4", "vs_2_0", "vs_3_0", "vs_4_0"};
|
||||
|
|
|
@ -71,6 +71,9 @@ const char *PixelShaderVersionString();
|
|||
const char *VertexShaderVersionString();
|
||||
void ShowD3DError(HRESULT err);
|
||||
|
||||
// returns true if size was changed
|
||||
bool FixTextureSize(int& width, int& height);
|
||||
|
||||
// The following are "filtered" versions of the corresponding D3Ddev-> functions.
|
||||
void SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture);
|
||||
void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value);
|
||||
|
|
|
@ -192,9 +192,6 @@ const int TS[6][2] =
|
|||
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
|
||||
};
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 ps_old = NULL;
|
||||
static LPDIRECT3DVERTEXSHADER9 vs_old = NULL;
|
||||
|
||||
void RestoreShaders()
|
||||
{
|
||||
D3D::SetTexture(0, 0);
|
||||
|
@ -339,22 +336,6 @@ int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, flo
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2)
|
||||
{
|
||||
struct Q2DVertex { float x,y,z,rhw;u32 color;float u,v,w,h; } coords[4] = {
|
||||
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
|
||||
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
|
||||
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
|
||||
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
|
||||
};
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
dev->SetVertexDeclaration(NULL);
|
||||
dev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
|
||||
dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex));
|
||||
RestoreShaders();
|
||||
}
|
||||
|
||||
/* Explanation of texture copying via drawShadedTexQuad and drawShadedTexSubQuad:
|
||||
From MSDN: "When rendering 2D output using pre-transformed vertices,
|
||||
care must be taken to ensure that each texel area correctly corresponds
|
||||
|
|
|
@ -33,25 +33,6 @@ FramebufferManager::Efb FramebufferManager::s_efb;
|
|||
|
||||
FramebufferManager::FramebufferManager()
|
||||
{
|
||||
s_efb.color_texture = NULL;
|
||||
s_efb.colorRead_texture = NULL;
|
||||
s_efb.depth_texture = NULL;
|
||||
s_efb.depthRead_texture = NULL;
|
||||
|
||||
s_efb.depth_surface = NULL;
|
||||
s_efb.color_surface = NULL;
|
||||
s_efb.color_ReadBuffer = NULL;
|
||||
s_efb.depth_ReadBuffer = NULL;
|
||||
s_efb.color_OffScreenReadBuffer = NULL;
|
||||
s_efb.depth_OffScreenReadBuffer = NULL;
|
||||
|
||||
s_efb.color_reinterpret_texture = NULL;
|
||||
s_efb.color_reinterpret_surface = NULL;
|
||||
|
||||
s_efb.color_surface_Format = D3DFMT_FORCE_DWORD;
|
||||
s_efb.depth_surface_Format = D3DFMT_FORCE_DWORD;
|
||||
s_efb.depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD;
|
||||
|
||||
// Simplest possible setup to start with.
|
||||
int target_width = Renderer::GetFullTargetWidth();
|
||||
int target_height = Renderer::GetFullTargetHeight();
|
||||
|
|
|
@ -105,6 +105,13 @@ private:
|
|||
|
||||
static struct Efb
|
||||
{
|
||||
Efb() : color_texture(NULL), colorRead_texture(NULL), depth_texture(NULL), depthRead_texture(NULL),
|
||||
color_reinterpret_texture(NULL), color_reinterpret_surface(NULL),
|
||||
depth_surface(NULL), color_surface(NULL), color_ReadBuffer(NULL), depth_ReadBuffer(NULL),
|
||||
color_OffScreenReadBuffer(NULL), depth_OffScreenReadBuffer(NULL),
|
||||
color_surface_Format(D3DFMT_UNKNOWN), depth_surface_Format(D3DFMT_UNKNOWN),
|
||||
depth_ReadBuffer_Format(D3DFMT_UNKNOWN) {}
|
||||
|
||||
LPDIRECT3DTEXTURE9 color_texture;//Texture thats contains the color data of the render target
|
||||
LPDIRECT3DTEXTURE9 colorRead_texture;//1 pixel texture for temporal data store
|
||||
LPDIRECT3DTEXTURE9 depth_texture;//Texture thats contains the depth data of the render target
|
||||
|
|
|
@ -283,13 +283,16 @@ Renderer::Renderer()
|
|||
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
|
||||
|
||||
CalculateXYScale(dst_rect);
|
||||
|
||||
|
||||
s_LastAA = g_ActiveConfig.iMultisampleMode;
|
||||
int SupersampleCoeficient = s_LastAA + 1;
|
||||
|
||||
s_LastEFBScale = g_ActiveConfig.iEFBScale;
|
||||
CalculateTargetSize(SupersampleCoeficient);
|
||||
|
||||
|
||||
// Make sure to use valid texture sizes
|
||||
D3D::FixTextureSize(s_Fulltarget_width, s_Fulltarget_height);
|
||||
|
||||
s_bLastFrameDumped = false;
|
||||
s_bAVIDumping = false;
|
||||
|
||||
|
@ -317,8 +320,8 @@ Renderer::Renderer()
|
|||
|
||||
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
|
||||
vp.X = (s_Fulltarget_width - s_target_width) / 2;
|
||||
vp.Y = (s_Fulltarget_height - s_target_height) / 2;
|
||||
vp.X = TargetStrideX();
|
||||
vp.Y = TargetStrideY();
|
||||
vp.Width = s_target_width;
|
||||
vp.Height = s_target_height;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
|
@ -766,18 +769,24 @@ void Renderer::UpdateViewport()
|
|||
}
|
||||
if (sizeChanged)
|
||||
{
|
||||
D3DCAPS9 caps = D3D::GetCaps();
|
||||
// Make sure that the requested size is actually supported by the GFX driver
|
||||
if (Renderer::GetFullTargetWidth() > (int)caps.MaxTextureWidth || Renderer::GetFullTargetHeight() > (int)caps.MaxTextureHeight)
|
||||
{
|
||||
// Skip EFB recreation and viewport setting. Most likely causes 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, keeping the %dx%d EFB now\n", Renderer::GetFullTargetWidth(), Renderer::GetFullTargetHeight(), old_fulltarget_w, old_fulltarget_h);
|
||||
const int ideal_width = s_Fulltarget_width;
|
||||
const int ideal_height = s_Fulltarget_height;
|
||||
|
||||
// Fix the viewport to fit to the old EFB size
|
||||
X *= (old_fulltarget_w-1) / (Renderer::GetFullTargetWidth()-1);
|
||||
Y *= (old_fulltarget_h-1) / (Renderer::GetFullTargetHeight()-1);
|
||||
Width *= (old_fulltarget_w-1) / (Renderer::GetFullTargetWidth()-1);
|
||||
Height *= (old_fulltarget_h-1) / (Renderer::GetFullTargetHeight()-1);
|
||||
// Make sure that the requested size is actually supported by the GFX driver
|
||||
D3D::FixTextureSize(s_Fulltarget_width, s_Fulltarget_height);
|
||||
|
||||
// If the new EFB size is big enough for the requested viewport, we just recreate the internal buffer.
|
||||
// Otherwise we use a hack to make the viewport fit into the smaller buffer by rendering at a lower resolution.
|
||||
if (s_Fulltarget_width < ideal_width || s_Fulltarget_height < ideal_height)
|
||||
{
|
||||
// HACK: Skip EFB recreation and viewport setting. Most likely causes 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, keeping the %dx%d EFB now\n", ideal_width, ideal_height, old_fulltarget_w, old_fulltarget_h);
|
||||
|
||||
// Modify the viewport to fit to the old EFB size (effectively makes us render at a lower resolution)
|
||||
X = X * old_fulltarget_w / ideal_width;
|
||||
Y = Y * old_fulltarget_h / ideal_height;
|
||||
Width = Width * old_fulltarget_w / ideal_width;
|
||||
Height = Height * old_fulltarget_h / ideal_height;
|
||||
|
||||
s_Fulltarget_width = old_fulltarget_w;
|
||||
s_Fulltarget_height = old_fulltarget_h;
|
||||
|
@ -786,7 +795,7 @@ void Renderer::UpdateViewport()
|
|||
{
|
||||
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
|
||||
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
|
||||
|
||||
|
||||
delete g_framebuffer_manager;
|
||||
g_framebuffer_manager = new FramebufferManager;
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool bFromZBuffer, bool bScaleB
|
|||
texture->GetSurfaceLevel(0, &Rendersurf);
|
||||
D3D::dev->SetDepthStencilSurface(NULL);
|
||||
D3D::dev->SetRenderTarget(0, Rendersurf);
|
||||
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
|
||||
// Stretch picture with increased internal resolution
|
||||
|
|
Loading…
Reference in New Issue