Rebase immediate-removal on master

This commit is contained in:
Ryan Houdek 2012-10-27 17:22:48 -05:00
commit c1fd640964
3455 changed files with 111686 additions and 608809 deletions

View file

@ -46,7 +46,7 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@ -57,7 +57,6 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@ -118,7 +117,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -128,7 +127,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -138,7 +137,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -150,7 +149,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -162,7 +161,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -174,7 +173,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>

View file

@ -595,7 +595,7 @@ void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
// only upload the data to VRAM if it changed
if (stsq_observer ||
memcmp(rDest, &tex_sub_quad_data.rdest, sizeof(rDest)) != 0 ||
memcmp(rDest, &tex_sub_quad_data.rdest, sizeof(*rDest)) != 0 ||
tex_sub_quad_data.u1 != u1 || tex_sub_quad_data.v1 != v1 ||
tex_sub_quad_data.u2 != u2 || tex_sub_quad_data.v2 != v2 || tex_sub_quad_data.G != G)
{

View file

@ -187,14 +187,15 @@ bool LineGeometryShader::SetShader(u32 components, float lineWidth,
p = GenerateVSOutputStruct(p, components, API_D3D11);
p += sprintf(p, "\n%s", LINE_GS_COMMON);
std::stringstream numTexCoordsStr;
numTexCoordsStr << xfregs.numTexGen.numTexGens;
std::stringstream numTexCoordsStream;
numTexCoordsStream << xfregs.numTexGen.numTexGens;
INFO_LOG(VIDEO, "Compiling line geometry shader for components 0x%.08X (num texcoords %d)",
components, xfregs.numTexGen.numTexGens);
const std::string& numTexCoordsStr = numTexCoordsStream.str();
D3D_SHADER_MACRO macros[] = {
{ "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() },
{ "NUM_TEXCOORDS", numTexCoordsStr.c_str() },
{ NULL, NULL }
};
ID3D11GeometryShader* newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros);

View file

@ -156,18 +156,34 @@ static const char EFB_ENCODE_PS[] =
"return (a << 16) | b;\n"
"}\n"
"uint Float8ToUint3(float v) {\n"
"return (uint)(v*255.0) >> 5;\n"
"}\n"
"uint Float8ToUint4(float v) {\n"
"return (uint)(v*255.0) >> 4;\n"
"}\n"
"uint Float8ToUint5(float v) {\n"
"return (uint)(v*255.0) >> 3;\n"
"}\n"
"uint Float8ToUint6(float v) {\n"
"return (uint)(v*255.0) >> 2;\n"
"}\n"
"uint EncodeRGB5A3(float4 pixel) {\n"
"if (pixel.a >= 224.0/255.0) {\n"
// Encode to ARGB1555
"return UINT_1555(1, pixel.r*31, pixel.g*31, pixel.b*31);\n"
"return UINT_1555(1, Float8ToUint5(pixel.r), Float8ToUint5(pixel.g), Float8ToUint5(pixel.b));\n"
"} else {\n"
// Encode to ARGB3444
"return UINT_3444(pixel.a*7, pixel.r*15, pixel.g*15, pixel.b*15);\n"
"return UINT_3444(Float8ToUint3(pixel.a), Float8ToUint4(pixel.r), Float8ToUint4(pixel.g), Float8ToUint4(pixel.b));\n"
"}\n"
"}\n"
"uint EncodeRGB565(float4 pixel) {\n"
"return UINT_565(pixel.r*31, pixel.g*63, pixel.b*31);\n"
"return UINT_565(Float8ToUint5(pixel.r), Float8ToUint6(pixel.g), Float8ToUint5(pixel.b));\n"
"}\n"
"float2 CalcTexCoord(float2 coord)\n"
@ -385,14 +401,14 @@ static const char EFB_ENCODE_PS[] =
"uint dw[4];\n"
"for (uint i = 0; i < 4; ++i) {\n"
"dw[i] = UINT_44444444_BE(\n"
"15*sample[8*i+0].r,\n"
"15*sample[8*i+1].r,\n"
"15*sample[8*i+2].r,\n"
"15*sample[8*i+3].r,\n"
"15*sample[8*i+4].r,\n"
"15*sample[8*i+5].r,\n"
"15*sample[8*i+6].r,\n"
"15*sample[8*i+7].r\n"
"Float8ToUint4(sample[8*i+0].r),\n"
"Float8ToUint4(sample[8*i+1].r),\n"
"Float8ToUint4(sample[8*i+2].r),\n"
"Float8ToUint4(sample[8*i+3].r),\n"
"Float8ToUint4(sample[8*i+4].r),\n"
"Float8ToUint4(sample[8*i+5].r),\n"
"Float8ToUint4(sample[8*i+6].r),\n"
"Float8ToUint4(sample[8*i+7].r)\n"
");\n"
"}\n"
@ -460,28 +476,28 @@ static const char EFB_ENCODE_PS[] =
"float4 sampleF = SampleEFB(subBlockUL+float2(7,1));\n"
"uint dw0 = UINT_44444444_BE(\n"
"15*sample0.a, 15*sample0.r,\n"
"15*sample1.a, 15*sample1.r,\n"
"15*sample2.a, 15*sample2.r,\n"
"15*sample3.a, 15*sample3.r\n"
"Float8ToUint4(sample0.a), Float8ToUint4(sample0.r),\n"
"Float8ToUint4(sample1.a), Float8ToUint4(sample1.r),\n"
"Float8ToUint4(sample2.a), Float8ToUint4(sample2.r),\n"
"Float8ToUint4(sample3.a), Float8ToUint4(sample3.r)\n"
");\n"
"uint dw1 = UINT_44444444_BE(\n"
"15*sample4.a, 15*sample4.r,\n"
"15*sample5.a, 15*sample5.r,\n"
"15*sample6.a, 15*sample6.r,\n"
"15*sample7.a, 15*sample7.r\n"
"Float8ToUint4(sample4.a), Float8ToUint4(sample4.r),\n"
"Float8ToUint4(sample5.a), Float8ToUint4(sample5.r),\n"
"Float8ToUint4(sample6.a), Float8ToUint4(sample6.r),\n"
"Float8ToUint4(sample7.a), Float8ToUint4(sample7.r)\n"
");\n"
"uint dw2 = UINT_44444444_BE(\n"
"15*sample8.a, 15*sample8.r,\n"
"15*sample9.a, 15*sample9.r,\n"
"15*sampleA.a, 15*sampleA.r,\n"
"15*sampleB.a, 15*sampleB.r\n"
"Float8ToUint4(sample8.a), Float8ToUint4(sample8.r),\n"
"Float8ToUint4(sample9.a), Float8ToUint4(sample9.r),\n"
"Float8ToUint4(sampleA.a), Float8ToUint4(sampleA.r),\n"
"Float8ToUint4(sampleB.a), Float8ToUint4(sampleB.r)\n"
");\n"
"uint dw3 = UINT_44444444_BE(\n"
"15*sampleC.a, 15*sampleC.r,\n"
"15*sampleD.a, 15*sampleD.r,\n"
"15*sampleE.a, 15*sampleE.r,\n"
"15*sampleF.a, 15*sampleF.r\n"
"Float8ToUint4(sampleC.a), Float8ToUint4(sampleC.r),\n"
"Float8ToUint4(sampleD.a), Float8ToUint4(sampleD.r),\n"
"Float8ToUint4(sampleE.a), Float8ToUint4(sampleE.r),\n"
"Float8ToUint4(sampleF.a), Float8ToUint4(sampleF.r)\n"
");\n"
"return uint4(dw0, dw1, dw2, dw3);\n"

View file

@ -41,6 +41,7 @@ namespace DX11
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry;
PIXELSHADERUID PixelShaderCache::last_uid;
LinearDiskCache<PIXELSHADERUID, u8> g_ps_disk_cache;
@ -412,6 +413,11 @@ void PixelShaderCache::Init()
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
PixelShaderCacheInserter inserter;
g_ps_disk_cache.OpenAndRead(cache_filename, inserter);
if (g_Config.bEnableShaderDebugging)
Clear();
last_entry = NULL;
}
// ONLY to be used during shutdown.
@ -420,6 +426,8 @@ void PixelShaderCache::Clear()
for (PSCache::iterator iter = PixelShaders.begin(); iter != PixelShaders.end(); iter++)
iter->second.Destroy();
PixelShaders.clear();
last_entry = NULL;
}
// Used in Swap() when AA mode has changed
@ -454,28 +462,31 @@ void PixelShaderCache::Shutdown()
bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
{
PIXELSHADERUID uid;
GetPixelShaderId(&uid, dstAlphaMode);
GetPixelShaderId(&uid, dstAlphaMode, components);
// Check if the shader is already set
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
if (last_entry)
{
PSCache::const_iterator iter = PixelShaders.find(uid);
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
return (iter != PixelShaders.end() && iter->second.shader);
if (uid == last_uid)
{
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
ValidatePixelShaderIDs(API_D3D11, last_entry->safe_uid, last_entry->code, dstAlphaMode, components);
return (last_entry->shader != NULL);
}
}
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
last_uid = uid;
// Check if the shader is already in the cache
PSCache::iterator iter;
iter = PixelShaders.find(uid);
if (iter != PixelShaders.end())
{
iter->second.frameCount = frameCount;
const PSCacheEntry &entry = iter->second;
last_entry = &entry;
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
ValidatePixelShaderIDs(API_D3D11, entry.safe_uid, entry.code, dstAlphaMode, components);
return (entry.shader != NULL);
}
@ -485,36 +496,38 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
D3DBlob* pbytecode;
if (!D3D::CompilePixelShader(code, (unsigned int)strlen(code), &pbytecode))
{
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
return false;
}
// Insert the bytecode into the caches
g_ps_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size());
g_ps_disk_cache.Sync();
bool result = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
pbytecode->Release();
if (g_ActiveConfig.bEnableShaderDebugging && success)
{
PixelShaders[uid].code = code;
GetSafePixelShaderId(&PixelShaders[uid].safe_uid, dstAlphaMode, components);
}
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
return result;
return success;
}
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const void* bytecode, unsigned int bytecodelen)
{
ID3D11PixelShader* shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
if (shader == NULL)
{
PanicAlert("Failed to create pixel shader at %s %d\n", __FILE__, __LINE__);
return false;
}
// TODO: Somehow make the debug name a bit more specific
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a pixel shader of PixelShaderCache");
// Make an entry in the table
PSCacheEntry newentry;
newentry.shader = shader;
newentry.frameCount = frameCount;
PixelShaders[uid] = newentry;
last_entry = &PixelShaders[uid];

View file

@ -17,11 +17,12 @@
#pragma once
#include <map>
#include "PixelShaderGen.h"
#include <d3d11.h>
class PIXELSHADERUID;
#include <map>
enum DSTALPHA_MODE;
namespace DX11
@ -52,9 +53,11 @@ private:
struct PSCacheEntry
{
ID3D11PixelShader* shader;
int frameCount;
PSCacheEntry() : shader(NULL), frameCount(0) {}
PIXELSHADERUIDSAFE safe_uid;
std::string code;
PSCacheEntry() : shader(NULL) {}
void Destroy() { SAFE_RELEASE(shader); }
};
@ -62,6 +65,7 @@ private:
static PSCache PixelShaders;
static const PSCacheEntry* last_entry;
static PIXELSHADERUID last_uid;
};
} // namespace DX11

View file

@ -181,14 +181,15 @@ bool PointGeometryShader::SetShader(u32 components, float pointSize,
p = GenerateVSOutputStruct(p, components, API_D3D11);
p += sprintf(p, "\n%s", POINT_GS_COMMON);
std::stringstream numTexCoordsStr;
numTexCoordsStr << xfregs.numTexGen.numTexGens;
std::stringstream numTexCoordsStream;
numTexCoordsStream << xfregs.numTexGen.numTexGens;
INFO_LOG(VIDEO, "Compiling point geometry shader for components 0x%.08X (num texcoords %d)",
components, xfregs.numTexGen.numTexGens);
const std::string& numTexCoordsStr = numTexCoordsStream.str();
D3D_SHADER_MACRO macros[] = {
{ "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() },
{ "NUM_TEXCOORDS", numTexCoordsStr.c_str() },
{ NULL, NULL }
};
ID3D11GeometryShader* newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros);

View file

@ -42,6 +42,9 @@
#include "Movie.h"
#include "Television.h"
#include "Host.h"
#include "BPFunctions.h"
#include "AVIDump.h"
#include "FPSCounter.h"
namespace DX11
{
@ -61,6 +64,8 @@ ID3D11BlendState* resetblendstate = NULL;
ID3D11DepthStencilState* resetdepthstate = NULL;
ID3D11RasterizerState* resetraststate = NULL;
static ID3D11Texture2D* s_screenshot_texture = NULL;
// GX pipeline state
struct
{
@ -215,6 +220,7 @@ static const D3D11_TEXTURE_ADDRESS_MODE d3dClamps[4] =
D3D11_TEXTURE_ADDRESS_WRAP //reserved
};
void SetupDeviceObjects()
{
s_television.Init();
@ -295,9 +301,11 @@ void SetupDeviceObjects()
hr = D3D::device->CreateRasterizerState(&rastdesc, &resetraststate);
CHECK(hr==S_OK, "Create rasterizer state for Renderer::ResetAPIState");
D3D::SetDebugObjectName((ID3D11DeviceChild*)resetraststate, "rasterizer state for Renderer::ResetAPIState");
s_screenshot_texture = NULL;
}
// Kill off all POOL_DEFAULT device objects.
// Kill off all device objects
void TeardownDeviceObjects()
{
delete g_framebuffer_manager;
@ -313,15 +321,26 @@ void TeardownDeviceObjects()
SAFE_RELEASE(resetblendstate);
SAFE_RELEASE(resetdepthstate);
SAFE_RELEASE(resetraststate);
SAFE_RELEASE(s_screenshot_texture);
s_television.Shutdown();
}
void CreateScreenshotTexture()
{
D3D11_TEXTURE2D_DESC scrtex_desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, D3D::GetBackBufferWidth(), D3D::GetBackBufferHeight(), 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE);
HRESULT hr = D3D::device->CreateTexture2D(&scrtex_desc, NULL, &s_screenshot_texture);
CHECK(hr==S_OK, "Create screenshot staging texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_screenshot_texture, "staging screenshot texture");
}
Renderer::Renderer()
{
int x, y, w_temp, h_temp;
s_blendMode = 0;
InitFPSCounter();
Host_GetRenderWindowSize(x, y, w_temp, h_temp);
D3D::Create(EmuWindow::GetWnd());
@ -343,6 +362,7 @@ Renderer::Renderer()
SetupDeviceObjects();
// Setup GX pipeline state
memset(&gx_state.blenddc, 0, sizeof(gx_state.blenddc));
gx_state.blenddc.AlphaToCoverageEnable = FALSE;
@ -444,51 +464,9 @@ bool Renderer::CheckForResize()
return false;
}
bool Renderer::SetScissorRect()
void Renderer::SetScissorRect(const TargetRectangle& rc)
{
TargetRectangle rc;
GetScissorRect(rc);
if (rc.left < 0) rc.left = 0;
if (rc.right < 0) rc.right = 0;
if (rc.top < 0) rc.top = 0;
if (rc.bottom < 0) rc.bottom = 0;
if (rc.left > EFB_WIDTH) rc.left = EFB_WIDTH;
if (rc.right > EFB_WIDTH) rc.right = EFB_WIDTH;
if (rc.top > EFB_HEIGHT) rc.top = EFB_HEIGHT;
if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT;
rc.left = EFBToScaledX(rc.left);
rc.right = EFBToScaledX(rc.right);
rc.top = EFBToScaledY(rc.top);
rc.bottom = EFBToScaledY(rc.bottom);
if (rc.left > rc.right)
{
int temp = rc.right;
rc.right = rc.left;
rc.left = temp;
}
if (rc.top > rc.bottom)
{
int temp = rc.bottom;
rc.bottom = rc.top;
rc.top = temp;
}
if (rc.right >= rc.left && rc.bottom >= rc.top)
{
D3D::context->RSSetScissorRects(1, rc.AsRECT());
return true;
}
else
{
//WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom);
*rc.AsRECT() = CD3D11_RECT(0.f, 0.f, s_target_width, s_target_height);
D3D::context->RSSetScissorRects(1, rc.AsRECT());
return false;
}
D3D::context->RSSetScissorRects(1, rc.AsRECT());
}
void Renderer::SetColorMask()
@ -726,15 +704,18 @@ void Renderer::UpdateViewport(Matrix44& vpCorrection)
int Ht = intendedHt;
if (Y + Ht > GetTargetHeight())
Ht = GetTargetHeight() - Y;
// If GX viewport is off the render target, we must clamp our viewport
// within the bounds. Use the correction matrix to compensate.
ViewportCorrectionMatrix(vpCorrection,
intendedX, intendedY, intendedWd, intendedHt,
X, Y, Wd, Ht);
(float)intendedX, (float)intendedY,
(float)intendedWd, (float)intendedHt,
(float)X, (float)Y,
(float)Wd, (float)Ht);
// Some games set invalids values for z min and z max so fix them to the max an min alowed and let the shaders do this work
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(X, Y, Wd, Ht,
D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)X, (float)Y,
(float)Wd, (float)Ht,
0.f, // (xfregs.viewport.farZ - xfregs.viewport.zRange) / 16777216.0f;
1.f); // xfregs.viewport.farZ / 16777216.0f;
D3D::context->RSSetViewports(1, &vp);
@ -779,7 +760,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
else if (convtype == 2) pixel_shader = PixelShaderCache::ReinterpRGBA6ToRGB8(true);
else
{
PanicAlert("Trying to reinterpret pixel data with unsupported conversion type %d", convtype);
ERROR_LOG(VIDEO, "Trying to reinterpret pixel data with unsupported conversion type %d", convtype);
return;
}
@ -875,16 +856,15 @@ void Renderer::SetBlendMode(bool forceUpdate)
bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle &rc)
{
if (!s_screenshot_texture)
CreateScreenshotTexture();
// copy back buffer to system memory
ID3D11Texture2D* buftex;
D3D11_TEXTURE2D_DESC tex_desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, D3D::GetBackBufferWidth(), D3D::GetBackBufferHeight(), 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE);
HRESULT hr = D3D::device->CreateTexture2D(&tex_desc, NULL, &buftex);
if (FAILED(hr)) PanicAlert("Failed to create screenshot buffer texture");
D3D::context->CopyResource(buftex, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex());
D3D::context->CopyResource(s_screenshot_texture, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex());
// D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(buftex, 0, D3D11_MAP_READ_WRITE, 0, &map);
D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map);
for (unsigned int y = 0; y < D3D::GetBackBufferHeight(); ++y)
{
u8* ptr = (u8*)map.pData + y * map.RowPitch + 3;
@ -894,21 +874,38 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle
ptr += 4;
}
}
D3D::context->Unmap(buftex, 0);
D3D::context->Unmap(s_screenshot_texture, 0);
// ready to be saved
hr = PD3DX11SaveTextureToFileA(D3D::context, buftex, D3DX11_IFF_PNG, filename.c_str());
buftex->Release();
HRESULT hr = PD3DX11SaveTextureToFileA(D3D::context, s_screenshot_texture, D3DX11_IFF_PNG, filename.c_str());
return SUCCEEDED(hr);
}
void formatBufferDump(const char *in, char *out, int w, int h, int p)
{
for (int y = 0; y < h; ++y)
{
const u8 *line = (u8*)(in + (h - y - 1) * p);
for (int x = 0; x < w; ++x)
{
out[0] = line[2];
out[1] = line[1];
out[2] = line[0];
out += 3;
line += 4;
}
}
}
// This function has the final picture. We adjust the aspect ratio here.
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma)
{
if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight)
{
if (g_ActiveConfig.bDumpFrames && frame_data)
AVIDump::AddFrame(frame_data);
Core::Callback_VideoCopiedToXFB(false);
return;
}
@ -920,6 +917,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
{
if (g_ActiveConfig.bDumpFrames && frame_data)
AVIDump::AddFrame(frame_data);
Core::Callback_VideoCopiedToXFB(false);
return;
}
@ -929,16 +929,13 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
// Prepare to copy the XFBs to our backbuffer
TargetRectangle dst_rect;
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)s_backbuffer_width, (float)s_backbuffer_height);
D3D::context->RSSetViewports(1, &vp);
float ClearColor[4] = { 0.f, 0.f, 0.f, 1.f };
D3D::context->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV(), ClearColor);
int X = dst_rect.left;
int Y = dst_rect.top;
int Width = dst_rect.right - dst_rect.left;
int Height = dst_rect.bottom - dst_rect.top;
// TODO: Redundant checks...
if (X < 0) X = 0;
if (Y < 0) Y = 0;
if (X > s_backbuffer_width) X = s_backbuffer_width;
@ -947,10 +944,13 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if (Height < 0) Height = 0;
if (Width > (s_backbuffer_width - X)) Width = s_backbuffer_width - X;
if (Height > (s_backbuffer_height - Y)) Height = s_backbuffer_height - Y;
vp = CD3D11_VIEWPORT((float)X, (float)Y, (float)Width, (float)Height);
D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)X, (float)Y, (float)Width, (float)Height);
D3D::context->RSSetViewports(1, &vp);
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL);
float ClearColor[4] = { 0.f, 0.f, 0.f, 1.f };
D3D::context->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV(), ClearColor);
// activate linear filtering for the buffer copies
D3D::SetLinearCopySampler();
@ -1025,6 +1025,67 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
s_bScreenshot = false;
}
// Dump frames
static int w = 0, h = 0;
if (g_ActiveConfig.bDumpFrames)
{
static int s_recordWidth;
static int s_recordHeight;
if (!s_screenshot_texture)
CreateScreenshotTexture();
D3D::context->CopyResource(s_screenshot_texture, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex());
if (!bLastFrameDumped)
{
s_recordWidth = dst_rect.GetWidth();
s_recordHeight = dst_rect.GetHeight();
bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight);
if (!bAVIDumping)
{
PanicAlert("Error dumping frames to AVI.");
}
else
{
char msg [255];
sprintf_s(msg,255, "Dumping Frames to \"%sframedump0.avi\" (%dx%d RGB24)",
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), s_recordWidth, s_recordHeight);
OSD::AddMessage(msg, 2000);
}
}
if (bAVIDumping)
{
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ, 0, &map);
if (!frame_data || w != s_recordWidth || h != s_recordHeight)
{
delete[] frame_data;
frame_data = new char[3 * s_recordWidth * s_recordHeight];
w = s_recordWidth;
h = s_recordHeight;
}
char* source_ptr = (char*)map.pData + dst_rect.left*4 + dst_rect.top*map.RowPitch;
formatBufferDump(source_ptr, frame_data, s_recordWidth, s_recordHeight, map.RowPitch);
AVIDump::AddFrame(frame_data);
D3D::context->Unmap(s_screenshot_texture, 0);
}
bLastFrameDumped = true;
}
else
{
if (bLastFrameDumped && bAVIDumping)
{
SAFE_DELETE_ARRAY(frame_data);
w = h = 0;
AVIDump::Stop();
bAVIDumping = false;
OSD::AddMessage("Stop dumping frames to AVI", 2000);
}
bLastFrameDumped = false;
}
// Finish up the current frame, print some stats
if (g_ActiveConfig.bShowFPS)
{
@ -1063,13 +1124,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
DLCache::ProgressiveCleanup();
TextureCache::Cleanup();
// reload textures if these settings changed
if (g_Config.bSafeTextureCache != g_ActiveConfig.bSafeTextureCache ||
g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips)
TextureCache::Invalidate(false);
// Enable any configuration changes
// Enable configuration changes
UpdateActiveConfig();
TextureCache::OnConfigChanged(g_ActiveConfig);
SetWindowSize(fbWidth, fbHeight);
@ -1089,16 +1146,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
}
// update FPS counter
static int fpscount = 0;
static unsigned long lasttime = 0;
if (Common::Timer::GetTimeMs() - lasttime >= 1000)
{
lasttime = Common::Timer::GetTimeMs();
s_fps = fpscount;
fpscount = 0;
}
if (XFBWrited)
++fpscount;
s_fps = UpdateFPSCounter();
// Begin new frame
// Set default viewport and scissor, for the clear to work correctly
@ -1117,10 +1166,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
s_LastAA = g_ActiveConfig.iMultisampleMode;
PixelShaderCache::InvalidateMSAAShaders();
// TODO: Aren't we still holding a reference to the back buffer right now?
D3D::Reset();
s_backbuffer_width = D3D::GetBackBufferWidth();
s_backbuffer_height = D3D::GetBackBufferHeight();
if (windowResized)
{
// TODO: Aren't we still holding a reference to the back buffer right now?
D3D::Reset();
SAFE_RELEASE(s_screenshot_texture);
s_backbuffer_width = D3D::GetBackBufferWidth();
s_backbuffer_height = D3D::GetBackBufferHeight();
}
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
@ -1130,7 +1183,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
CalculateTargetSize();
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL);
delete g_framebuffer_manager;
g_framebuffer_manager = new FramebufferManager;
float clear_col[4] = { 0.f, 0.f, 0.f, 1.f };
@ -1163,7 +1216,7 @@ void Renderer::RestoreAPIState()
D3D::stateman->PopDepthState();
D3D::stateman->PopRasterizerState();
VertexShaderManager::SetViewportChanged();
SetScissorRect();
BPFunctions::SetScissor();
}
void Renderer::ApplyState(bool bUseDstAlpha)
@ -1375,9 +1428,10 @@ void Renderer::SetSamplerState(int stage, int texindex)
gx_state.sampdc[stage].AddressU = d3dClamps[tm0.wrap_s];
gx_state.sampdc[stage].AddressV = d3dClamps[tm0.wrap_t];
gx_state.sampdc[stage].MipLODBias = (float)tm0.lod_bias/32.0f;
gx_state.sampdc[stage].MaxLOD = (float)tm1.max_lod/16.f;
// When mipfilter is set to "none", just disable mipmapping altogether
gx_state.sampdc[stage].MaxLOD = (mip == TEXF_NONE) ? 0.0f : (float)tm1.max_lod/16.f;
gx_state.sampdc[stage].MinLOD = (float)tm1.min_lod/16.f;
gx_state.sampdc[stage].MipLODBias = (float)tm0.lod_bias/32.0f;
}
void Renderer::SetInterlacingMode()
@ -1385,4 +1439,4 @@ void Renderer::SetInterlacingMode()
// TODO
}
} // namespace DX11
} // namespace DX11

View file

@ -15,7 +15,7 @@ public:
void SetColorMask();
void SetBlendMode(bool forceUpdate);
bool SetScissorRect();
void SetScissorRect(const TargetRectangle& rc);
void SetGenerationMode();
void SetDepthMode();
void SetLogicOpMode();

View file

@ -45,8 +45,16 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage)
D3D::context->PSSetShaderResources(stage, 1, &texture->GetSRV());
}
bool TextureCache::TCacheEntry::Save(const char filename[])
bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
{
// TODO: Somehow implement this (D3DX11 doesn't support dumping individual LODs)
static bool warn_once = true;
if (level && warn_once)
{
WARN_LOG(VIDEO, "Dumping individual LOD not supported by D3D11 backend!");
warn_once = false;
return false;
}
return SUCCEEDED(PD3DX11SaveTextureToFileA(D3D::context, texture->GetTex(), D3DX11_IFF_PNG, filename));
}
@ -102,12 +110,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
const float *colmat)
{
if (!isDynamic || g_ActiveConfig.bCopyEFBToTexture)
if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture)
{
g_renderer->ResetAPIState();
// stretch picture with increased internal resolution
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)virtualW, (float)virtualH);
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)virtual_width, (float)virtual_height);
D3D::context->RSSetViewports(1, &vp);
// set transformation
@ -149,17 +157,17 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
if (!g_ActiveConfig.bCopyEFBToTexture)
{
u8* dst = Memory::GetPointer(dstAddr);
size_t encodeSize = g_encoder->Encode(dst, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf);
hash = GetHash64(dst, encodeSize, g_ActiveConfig.iSafeTextureCache_ColorSamples);
if (g_ActiveConfig.bEFBCopyCacheEnable)
{
// If the texture in RAM is already in the texture cache,
// do not copy it again as it has not changed.
if (TextureCache::Find(dstAddr, hash))
return;
}
size_t encoded_size = g_encoder->Encode(dst, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf);
TextureCache::MakeRangeDynamic(dstAddr, encodeSize);
u64 hash = GetHash64(dst, (int)encoded_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
// Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date
if (!g_ActiveConfig.bEFBCopyCacheEnable)
TextureCache::MakeRangeDynamic(addr, (u32)encoded_size);
else if (!TextureCache::Find(addr, hash))
TextureCache::MakeRangeDynamic(addr, (u32)encoded_size);
this->hash = hash;
}
}

View file

@ -49,7 +49,7 @@ private:
const float *colmat);
void Bind(unsigned int stage);
bool Save(const char filename[]);
bool Save(const char filename[], unsigned int level);
};
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,

View file

@ -39,33 +39,41 @@ namespace DX11
{
// TODO: Find sensible values for these two
const UINT IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE*2 * 16;
const UINT IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * 16 * sizeof(u16);
const UINT VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE * 16;
const UINT MAXVBUFFER_COUNT = 2;
void VertexManager::CreateDeviceObjects()
{
D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(IBUFFER_SIZE,
D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_indexBuffer)),
"Failed to create index buffer.");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_indexBuffer, "index buffer of VertexManager");
bufdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufdesc.ByteWidth = VBUFFER_SIZE;
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_vertexBuffer)),
"Failed to create vertex buffer.");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_vertexBuffer, "vertex buffer of VertexManager");
m_indexBufferCursor = 0;
m_vertexBufferCursor = 0;
m_vertexDrawOffset = 0;
m_triangleDrawIndex = 0;
m_lineDrawIndex = 0;
m_pointDrawIndex = 0;
m_indexBuffers = new PID3D11Buffer[MAXVBUFFER_COUNT];
m_vertexBuffers = new PID3D11Buffer[MAXVBUFFER_COUNT];
for (m_activeIndexBuffer = 0; m_activeIndexBuffer < MAXVBUFFER_COUNT; m_activeIndexBuffer++)
{
m_indexBuffers[m_activeIndexBuffer] = NULL;
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_indexBuffers[m_activeIndexBuffer])),
"Failed to create index buffer.");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_indexBuffers[m_activeIndexBuffer], "index buffer of VertexManager");
}
bufdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufdesc.ByteWidth = VBUFFER_SIZE;
for (m_activeVertexBuffer = 0; m_activeVertexBuffer < MAXVBUFFER_COUNT; m_activeVertexBuffer++)
{
m_vertexBuffers[m_activeVertexBuffer] = NULL;
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_vertexBuffers[m_activeVertexBuffer])),
"Failed to create vertex buffer.");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_vertexBuffers[m_activeVertexBuffer], "Vertex buffer of VertexManager");
}
m_activeVertexBuffer = 0;
m_activeIndexBuffer = 0;
m_indexBufferCursor = IBUFFER_SIZE;
m_vertexBufferCursor = VBUFFER_SIZE;
m_lineShader.Init();
m_pointShader.Init();
}
@ -74,9 +82,12 @@ void VertexManager::DestroyDeviceObjects()
{
m_pointShader.Shutdown();
m_lineShader.Shutdown();
SAFE_RELEASE(m_vertexBuffer);
SAFE_RELEASE(m_indexBuffer);
for (m_activeVertexBuffer = 0; m_activeVertexBuffer < MAXVBUFFER_COUNT; m_activeVertexBuffer++)
{
SAFE_RELEASE(m_vertexBuffers[m_activeVertexBuffer]);
SAFE_RELEASE(m_indexBuffers[m_activeVertexBuffer]);
}
}
VertexManager::VertexManager()
@ -94,42 +105,41 @@ void VertexManager::LoadBuffers()
D3D11_MAPPED_SUBRESOURCE map;
UINT vSize = UINT(s_pCurBufferPointer - LocalVBuffer);
D3D11_MAP MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
if (m_vertexBufferCursor + vSize >= VBUFFER_SIZE)
{
// Wrap around
D3D::context->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
m_activeVertexBuffer = (m_activeVertexBuffer + 1) % MAXVBUFFER_COUNT;
m_vertexBufferCursor = 0;
MapType = D3D11_MAP_WRITE_DISCARD;
}
else
{
// Append data
D3D::context->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map);
}
D3D::context->Map(m_vertexBuffers[m_activeVertexBuffer], 0, MapType, 0, &map);
memcpy((u8*)map.pData + m_vertexBufferCursor, LocalVBuffer, vSize);
D3D::context->Unmap(m_vertexBuffer, 0);
D3D::context->Unmap(m_vertexBuffers[m_activeVertexBuffer], 0);
m_vertexDrawOffset = m_vertexBufferCursor;
m_vertexBufferCursor += vSize;
UINT iCount = IndexGenerator::GetTriangleindexLen() +
IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
if (m_indexBufferCursor + iCount >= IBUFFER_SIZE/2)
MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
if (m_indexBufferCursor + iCount >= (IBUFFER_SIZE / sizeof(u16)))
{
// Wrap around
D3D::context->Map(m_indexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
m_activeIndexBuffer = (m_activeIndexBuffer + 1) % MAXVBUFFER_COUNT;
m_indexBufferCursor = 0;
MapType = D3D11_MAP_WRITE_DISCARD;
}
else
{
// Append data
D3D::context->Map(m_indexBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map);
}
D3D::context->Map(m_indexBuffers[m_activeIndexBuffer], 0, MapType, 0, &map);
m_triangleDrawIndex = m_indexBufferCursor;
m_lineDrawIndex = m_triangleDrawIndex + IndexGenerator::GetTriangleindexLen();
m_pointDrawIndex = m_lineDrawIndex + IndexGenerator::GetLineindexLen();
memcpy((u16*)map.pData + m_triangleDrawIndex, TIBuffer, 2*IndexGenerator::GetTriangleindexLen());
memcpy((u16*)map.pData + m_lineDrawIndex, LIBuffer, 2*IndexGenerator::GetLineindexLen());
memcpy((u16*)map.pData + m_pointDrawIndex, PIBuffer, 2*IndexGenerator::GetPointindexLen());
D3D::context->Unmap(m_indexBuffer, 0);
memcpy((u16*)map.pData + m_triangleDrawIndex, TIBuffer, sizeof(u16) * IndexGenerator::GetTriangleindexLen());
memcpy((u16*)map.pData + m_lineDrawIndex, LIBuffer, sizeof(u16) * IndexGenerator::GetLineindexLen());
memcpy((u16*)map.pData + m_pointDrawIndex, PIBuffer, sizeof(u16) * IndexGenerator::GetPointindexLen());
D3D::context->Unmap(m_indexBuffers[m_activeIndexBuffer], 0);
m_indexBufferCursor += iCount;
}
@ -139,9 +149,9 @@ static const float LINE_PT_TEX_OFFSETS[8] = {
void VertexManager::Draw(UINT stride)
{
D3D::context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &m_vertexDrawOffset);
D3D::context->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0);
D3D::context->IASetVertexBuffers(0, 1, &m_vertexBuffers[m_activeVertexBuffer], &stride, &m_vertexDrawOffset);
D3D::context->IASetIndexBuffer(m_indexBuffers[m_activeIndexBuffer], DXGI_FORMAT_R16_UINT, 0);
if (IndexGenerator::GetNumTriangles() > 0)
{
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
@ -227,13 +237,14 @@ void VertexManager::vFlush()
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
tex.texTlut[i&3].tlut_format,
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8) && g_ActiveConfig.bUseNativeMips,
(tex.texMode1[i&3].max_lod >> 4));
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
tex.texMode1[i&3].max_lod >> 4,
tex.texImage1[i&3].image_type);
if (tentry)
{
// 0s are probably for no manual wrapping needed.
PixelShaderManager::SetTexDims(i, tentry->realW, tentry->realH, 0, 0);
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0);
}
else
ERROR_LOG(VIDEO, "error loading texture");
@ -259,12 +270,11 @@ void VertexManager::vFlush()
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
goto shader_fail;
}
LoadBuffers();
unsigned int stride = g_nativeVertexFmt->GetVertexStride();
g_nativeVertexFmt->SetupVertexPointers();
g_renderer->ApplyState(useDstAlpha);
LoadBuffers();
Draw(stride);
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);

View file

@ -32,10 +32,11 @@ public:
~VertexManager();
NativeVertexFormat* CreateNativeVertexFormat();
private:
void CreateDeviceObjects();
void DestroyDeviceObjects();
private:
void LoadBuffers();
void Draw(UINT stride);
// temp
@ -46,9 +47,12 @@ private:
UINT m_vertexDrawOffset;
UINT m_triangleDrawIndex;
UINT m_lineDrawIndex;
UINT m_pointDrawIndex;
ID3D11Buffer* m_indexBuffer;
ID3D11Buffer* m_vertexBuffer;
UINT m_pointDrawIndex;
UINT m_activeVertexBuffer;
UINT m_activeIndexBuffer;
typedef ID3D11Buffer* PID3D11Buffer;
PID3D11Buffer* m_indexBuffers;
PID3D11Buffer* m_vertexBuffers;
LineGeometryShader m_lineShader;
PointGeometryShader m_pointShader;

View file

@ -37,6 +37,7 @@ namespace DX11 {
VertexShaderCache::VSCache VertexShaderCache::vshaders;
const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry;
VERTEXSHADERUID VertexShaderCache::last_uid;
static ID3D11VertexShader* SimpleVertexShader = NULL;
static ID3D11VertexShader* ClearVertexShader = NULL;
@ -174,6 +175,11 @@ void VertexShaderCache::Init()
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
VertexShaderCacheInserter inserter;
g_vs_disk_cache.OpenAndRead(cache_filename, inserter);
if (g_Config.bEnableShaderDebugging)
Clear();
last_entry = NULL;
}
void VertexShaderCache::Clear()
@ -181,6 +187,8 @@ void VertexShaderCache::Clear()
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter)
iter->second.Destroy();
vshaders.clear();
last_entry = NULL;
}
void VertexShaderCache::Shutdown()
@ -202,22 +210,26 @@ bool VertexShaderCache::SetShader(u32 components)
{
VERTEXSHADERUID uid;
GetVertexShaderId(&uid, components);
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
if (last_entry)
{
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
return (vshaders[uid].shader != NULL);
if (uid == last_uid)
{
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
ValidateVertexShaderIDs(API_D3D11, last_entry->safe_uid, last_entry->code, components);
return (last_entry->shader != NULL);
}
}
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
last_uid = uid;
VSCache::iterator iter = vshaders.find(uid);
if (iter != vshaders.end())
{
iter->second.frameCount = frameCount;
const VSCacheEntry &entry = iter->second;
last_entry = &entry;
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
ValidateVertexShaderIDs(API_D3D11, entry.safe_uid, entry.code, components);
return (entry.shader != NULL);
}
@ -228,34 +240,36 @@ bool VertexShaderCache::SetShader(u32 components)
if (pbytecode == NULL)
{
PanicAlert("Failed to compile Vertex Shader %s %d:\n\n%s", __FILE__, __LINE__, code);
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
return false;
}
g_vs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size());
g_vs_disk_cache.Sync();
bool result = InsertByteCode(uid, pbytecode);
bool success = InsertByteCode(uid, pbytecode);
pbytecode->Release();
if (g_ActiveConfig.bEnableShaderDebugging && success)
{
vshaders[uid].code = code;
GetSafeVertexShaderId(&vshaders[uid].safe_uid, components);
}
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
return result;
return success;
}
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob)
{
ID3D11VertexShader* shader = D3D::CreateVertexShaderFromByteCode(bcodeblob);
if (shader == NULL)
{
PanicAlert("Failed to create vertex shader from %p size %d at %s %d\n", bcodeblob->Data(), bcodeblob->Size(), __FILE__, __LINE__);
return false;
}
// TODO: Somehow make the debug name a bit more specific
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a vertex shader of VertexShaderCache");
// Make an entry in the table
VSCacheEntry entry;
entry.shader = shader;
entry.frameCount = frameCount;
entry.SetByteCode(bcodeblob);
vshaders[uid] = entry;

View file

@ -18,12 +18,12 @@
#ifndef _VERTEXSHADERCACHE_H
#define _VERTEXSHADERCACHE_H
#include <map>
#include "VertexShaderGen.h"
#include "D3DBase.h"
#include "D3DBlob.h"
class VERTEXSHADERUID;
#include <map>
namespace DX11 {
@ -51,9 +51,11 @@ private:
{
ID3D11VertexShader* shader;
D3DBlob* bytecode; // needed to initialize the input layout
int frameCount;
VSCacheEntry() : shader(NULL), bytecode(NULL), frameCount(0) {}
VERTEXSHADERUIDSAFE safe_uid;
std::string code;
VSCacheEntry() : shader(NULL), bytecode(NULL) {}
void SetByteCode(D3DBlob* blob)
{
SAFE_RELEASE(bytecode);
@ -70,6 +72,7 @@ private:
static VSCache vshaders;
static const VSCacheEntry* last_entry;
static VERTEXSHADERUID last_uid;
};
} // namespace DX11

View file

@ -68,9 +68,9 @@ unsigned int VideoBackend::PeekMessages()
void VideoBackend::UpdateFPSDisplay(const char *text)
{
char temp[512];
sprintf_s(temp, sizeof temp, "%s | DX11 | %s", scm_rev_str, text);
SetWindowTextA(EmuWindow::GetWnd(), temp);
TCHAR temp[512];
swprintf_s(temp, sizeof(temp)/sizeof(TCHAR), _T("%hs | DX11 | %hs"), scm_rev_str, text);
EmuWindow::SetWindowText(temp);
}
std::string VideoBackend::GetName()
@ -150,6 +150,7 @@ void VideoBackend::ShowConfig(void *_hParent)
bool VideoBackend::Initialize(void *&window_handle)
{
InitializeShared();
InitBackendInfo();
frameCount = 0;
@ -229,6 +230,7 @@ void VideoBackend::Shutdown()
delete g_texture_cache;
delete g_renderer;
g_renderer = NULL;
g_texture_cache = NULL;
}
}

View file

@ -46,7 +46,7 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@ -57,7 +57,6 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@ -123,7 +122,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ForcedIncludeFiles>stdafx.h</ForcedIncludeFiles>
@ -136,7 +135,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -145,7 +144,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -156,7 +155,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -167,7 +166,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -178,7 +177,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>

View file

@ -28,7 +28,8 @@ D3DXCOMPILESHADERTYPE PD3DXCompileShader = NULL;
namespace DX9
{
static char vsVersions[5][7] = {"ERROR", "vs_1_4", "vs_2_a", "vs_3_0", "vs_4_0"};
static char psVersions[5][7] = {"ERROR", "ps_1_4", "ps_2_a", "ps_3_0", "ps_4_0"};
// D3DX
HINSTANCE hD3DXDll = NULL;
int d3dx_dll_ref = 0;
@ -55,6 +56,7 @@ static bool auto_depth_stencil = false;
#define VENDOR_NVIDIA 4318
#define VENDOR_ATI 4098
#define VENDOR_INTEL 32902
bool bFrameInProgress = false;
@ -112,6 +114,10 @@ bool IsATIDevice()
{
return GetCurAdapter().ident.VendorId == VENDOR_ATI;
}
bool IsIntelDevice()
{
return GetCurAdapter().ident.VendorId == VENDOR_INTEL;
}
HRESULT Init()
@ -139,6 +145,11 @@ HRESULT Init()
int adapter = g_Config.iAdapter;
D3D->GetDeviceCaps((adapter >= 0 && adapter < std::min(MAX_ADAPTERS, numAdapters)) ? adapter : D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
Enumerate();
if(IsIntelDevice()){
// Murder the a because Intel doesn't support 2.0a because the 'a' part was a ATI and Nvidia war going on
psVersions[2][5] = '0';
vsVersions[2][5] = '0';
}
return S_OK;
}
@ -522,16 +533,14 @@ D3DFORMAT GetSupportedDepthSurfaceFormat(D3DFORMAT target_format)
const char *VertexShaderVersionString()
{
static const char *versions[5] = {"ERROR", "vs_1_4", "vs_2_a", "vs_3_0", "vs_4_0"};
int version = ((D3D::caps.VertexShaderVersion >> 8) & 0xFF);
return versions[std::min(4, version)];
return vsVersions[std::min(4, version)];
}
const char *PixelShaderVersionString()
{
static const char *versions[5] = {"ERROR", "ps_1_4", "ps_2_a", "ps_3_0", "ps_4_0"};
int version = ((D3D::caps.PixelShaderVersion >> 8) & 0xFF);
return versions[std::min(4, version)];
return psVersions[std::min(4, version)];
}
LPDIRECT3DSURFACE9 GetBackBufferSurface()

View file

@ -47,6 +47,7 @@ namespace D3D
#define FOURCC_NULL ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')))
bool IsATIDevice();
bool IsIntelDevice();
HRESULT Init();
HRESULT Create(int adapter, HWND wnd, int resolution, int aa_mode, bool auto_depth);
void Close();

View file

@ -383,7 +383,7 @@ void drawShadedTexQuad(IDirect3DTexture9 *texture,
float v2=((float)rSource->bottom) * sh;
float g = 1.0f/Gamma;
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,G; } coords[4] = {
const struct Q2DVertex { float x,y,z,rhw,u,v,w,h,G; } coords[4] = {
{-1.0f - dw,-1.0f + dh, 0.0f,1.0f, u1, v2, sw, sh, g},
{-1.0f - dw, 1.0f + dh, 0.0f,1.0f, u1, v1, sw, sh, g},
{ 1.0f - dw,-1.0f + dh, 0.0f,1.0f, u2, v2, sw, sh, g},
@ -434,15 +434,13 @@ void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
// Fills a certain area of the current render target with the specified color
// Z buffer disabled; destination coordinates normalized to (-1;1)
void drawColorQuad(int DestWidth, int DestHeight, u32 Color, float x1, float y1, float x2, float y2)
void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2)
{
float dw = 1.f / (float)DestWidth;
float dh = 1.f / (float)DestHeight;
struct CQVertex { float x, y, z, rhw; u32 col; } coords[4] = {
{ x1-dw, y2+dh, 0.f, 1.f, Color },
{ x2-dw, y2+dh, 0.f, 1.f, Color },
{ x1-dw, y1+dh, 0.f, 1.f, Color },
{ x2-dw, y1+dh, 0.f, 1.f, Color },
{ x1, y2, 0.f, 1.f, Color },
{ x2, y2, 0.f, 1.f, Color },
{ x1, y1, 0.f, 1.f, Color },
{ x2, y1, 0.f, 1.f, Color },
};
dev->SetVertexShader(VertexShaderCache::GetClearVertexShader());
dev->SetPixelShader(PixelShaderCache::GetClearProgram());
@ -451,15 +449,13 @@ void drawColorQuad(int DestWidth, int DestHeight, u32 Color, float x1, float y1,
RestoreShaders();
}
void drawClearQuad(int DestWidth, int DestHeight, u32 Color, float z, IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader)
void drawClearQuad(u32 Color,float z,IDirect3DPixelShader9 *PShader,IDirect3DVertexShader9 *Vshader)
{
float dw = 1.f / (float)DestWidth;
float dh = 1.f / (float)DestHeight;
struct Q2DVertex { float x,y,z,rhw;u32 color;} coords[4] = {
{-1.0f-dw, 1.0f+dh, z, 1.0f, Color},
{ 1.0f-dw, 1.0f+dh, z, 1.0f, Color},
{ 1.0f-dw, -1.0f+dh, z, 1.0f, Color},
{-1.0f-dw, -1.0f+dh, z, 1.0f, Color}
{-1.0f, 1.0f, z, 1.0f, Color},
{ 1.0f, 1.0f, z, 1.0f, Color},
{ 1.0f, -1.0f, z, 1.0f, Color},
{-1.0f, -1.0f, z, 1.0f, Color}
};
dev->SetVertexShader(Vshader);
dev->SetPixelShader(PShader);

View file

@ -82,8 +82,8 @@ namespace D3D
IDirect3DPixelShader9 *PShader,
IDirect3DVertexShader9 *Vshader,
float Gamma = 1.0f);
void drawClearQuad(int DestWidth, int DestHeight, u32 Color, float z, IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader);
void drawColorQuad(int DestWidth, int DestHeight, u32 Color, float x1, float y1, float x2, float y2);
void drawClearQuad(u32 Color, float z, IDirect3DPixelShader9 *PShader, IDirect3DVertexShader9 *Vshader);
void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2);
void SaveRenderStates();
void RestoreRenderStates();

View file

@ -43,6 +43,7 @@ namespace DX9
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry;
PIXELSHADERUID PixelShaderCache::last_uid;
static LinearDiskCache<PIXELSHADERUID, u8> g_ps_disk_cache;
static std::set<u32> unique_shaders;
@ -233,6 +234,8 @@ static LPDIRECT3DPIXELSHADER9 CreateCopyShader(int copyMatrixType, int depthConv
void PixelShaderCache::Init()
{
last_entry = NULL;
//program used for clear screen
{
char pprog[3072];
@ -283,6 +286,9 @@ void PixelShaderCache::Init()
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
PixelShaderCacheInserter inserter;
g_ps_disk_cache.OpenAndRead(cache_filename, inserter);
if (g_Config.bEnableShaderDebugging)
Clear();
}
// ONLY to be used during shutdown.
@ -292,7 +298,7 @@ void PixelShaderCache::Clear()
iter->second.Destroy();
PixelShaders.clear();
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
last_entry = NULL;
}
void PixelShaderCache::Shutdown()
@ -326,41 +332,47 @@ void PixelShaderCache::Shutdown()
bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
{
const API_TYPE api = ((D3D::GetCaps().PixelShaderVersion >> 8) & 0xFF) < 3 ? API_D3D9_SM20 : API_D3D9_SM30;
PIXELSHADERUID uid;
GetPixelShaderId(&uid, dstAlphaMode);
GetPixelShaderId(&uid, dstAlphaMode, components);
// Check if the shader is already set
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
if (last_entry)
{
PSCache::const_iterator iter = PixelShaders.find(uid);
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
return (iter != PixelShaders.end() && iter->second.shader);
if (uid == last_uid)
{
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
ValidatePixelShaderIDs(api, last_entry->safe_uid, last_entry->code, dstAlphaMode, components);
return last_entry->shader != NULL;
}
}
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
last_uid = uid;
// Check if the shader is already in the cache
PSCache::iterator iter;
iter = PixelShaders.find(uid);
if (iter != PixelShaders.end())
{
iter->second.frameCount = frameCount;
const PSCacheEntry &entry = iter->second;
last_entry = &entry;
if (entry.shader) D3D::SetPixelShader(entry.shader);
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
ValidatePixelShaderIDs(api, entry.safe_uid, entry.code, dstAlphaMode, components);
return (entry.shader != NULL);
}
// Need to compile a new shader
const char *code = GeneratePixelShaderCode(dstAlphaMode, ((D3D::GetCaps().PixelShaderVersion >> 8) & 0xFF) < 3 ? API_D3D9_SM20 : API_D3D9_SM30, components);
const char *code = GeneratePixelShaderCode(dstAlphaMode, api, components);
u32 code_hash = HashAdler32((const u8 *)code, strlen(code));
unique_shaders.insert(code_hash);
SETSTAT(stats.numUniquePixelShaders, unique_shaders.size());
if (g_ActiveConfig.bEnableShaderDebugging)
{
u32 code_hash = HashAdler32((const u8 *)code, strlen(code));
unique_shaders.insert(code_hash);
SETSTAT(stats.numUniquePixelShaders, unique_shaders.size());
}
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
@ -381,14 +393,19 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
// Insert the bytecode into the caches
g_ps_disk_cache.Append(uid, bytecode, bytecodelen);
g_ps_disk_cache.Sync();
// And insert it into the shader cache.
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
bool success = InsertByteCode(uid, bytecode, bytecodelen, true);
delete [] bytecode;
if (g_ActiveConfig.bEnableShaderDebugging && success)
{
PixelShaders[uid].code = code;
GetSafePixelShaderId(&PixelShaders[uid].safe_uid, dstAlphaMode, components);
}
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
return result;
return success;
}
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate)
@ -398,7 +415,6 @@ bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytec
// Make an entry in the table
PSCacheEntry newentry;
newentry.shader = shader;
newentry.frameCount = frameCount;
PixelShaders[uid] = newentry;
last_entry = &PixelShaders[uid];

View file

@ -40,9 +40,11 @@ private:
{
LPDIRECT3DPIXELSHADER9 shader;
bool owns_shader;
int frameCount;
PSCacheEntry() : shader(NULL), owns_shader(true), frameCount(0) {}
PIXELSHADERUIDSAFE safe_uid;
std::string code;
PSCacheEntry() : shader(NULL), owns_shader(true) {}
void Destroy()
{
if (shader && owns_shader)
@ -55,6 +57,7 @@ private:
static PSCache PixelShaders;
static const PSCacheEntry *last_entry;
static PIXELSHADERUID last_uid;
static void Clear();
public:

View file

@ -53,18 +53,14 @@
#include "Debugger.h"
#include "Core.h"
#include "Movie.h"
#include "BPFunctions.h"
#include "FPSCounter.h"
namespace DX9
{
static int s_fps = 0;
static int s_recordWidth;
static int s_recordHeight;
static bool s_bLastFrameDumped;
static bool s_bAVIDumping;
static u32 s_blendMode;
static u32 s_LastAA;
static bool IS_AMD;
@ -229,6 +225,7 @@ void SetupDeviceObjects()
// To avoid shader compilation stutters, read back all shaders from cache.
VertexShaderCache::Init();
PixelShaderCache::Init();
g_vertex_manager->CreateDeviceObjects();
// Texture cache will recreate themselves over time.
}
@ -242,16 +239,19 @@ void TeardownDeviceObjects()
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
delete g_framebuffer_manager;
D3D::font.Shutdown();
TextureCache::Invalidate(false);
TextureCache::Invalidate();
VertexLoaderManager::Shutdown();
VertexShaderCache::Shutdown();
PixelShaderCache::Shutdown();
TextureConverter::Shutdown();
g_vertex_manager->DestroyDeviceObjects();
}
// Init functions
Renderer::Renderer()
{
InitFPSCounter();
st = new char[32768];
int fullScreenRes, x, y, w_temp, h_temp;
@ -296,9 +296,6 @@ Renderer::Renderer()
// Make sure to use valid texture sizes
D3D::FixTextureSize(s_target_width, s_target_height);
s_bLastFrameDumped = false;
s_bAVIDumping = false;
// We're not using fixed function.
// Let's just set the matrices to identity to be sure.
D3DXMATRIX mtx;
@ -341,10 +338,6 @@ Renderer::~Renderer()
D3D::Present();
D3D::Close();
if (s_bAVIDumping)
{
AVIDump::Stop();
}
delete[] st;
}
@ -426,55 +419,9 @@ bool Renderer::CheckForResize()
return false;
}
bool Renderer::SetScissorRect()
void Renderer::SetScissorRect(const TargetRectangle& rc)
{
TargetRectangle rc;
GetScissorRect(rc);
if (rc.left < 0) rc.left = 0;
if (rc.right < 0) rc.right = 0;
if (rc.top < 0) rc.top = 0;
if (rc.bottom < 0) rc.bottom = 0;
if (rc.left > EFB_WIDTH) rc.left = EFB_WIDTH;
if (rc.right > EFB_WIDTH) rc.right = EFB_WIDTH;
if (rc.top > EFB_HEIGHT) rc.top = EFB_HEIGHT;
if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT;
if (rc.left > rc.right)
{
int temp = rc.right;
rc.right = rc.left;
rc.left = temp;
}
if (rc.top > rc.bottom)
{
int temp = rc.bottom;
rc.bottom = rc.top;
rc.top = temp;
}
rc.left = EFBToScaledX(rc.left);
rc.top = EFBToScaledY(rc.top);
rc.right = EFBToScaledX(rc.right);
rc.bottom = EFBToScaledY(rc.bottom);
// Check that the coordinates are good
if (rc.right != rc.left && rc.bottom != rc.top)
{
D3D::dev->SetScissorRect(rc.AsRECT());
return true;
}
else
{
//WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom);
rc.left = 0;
rc.top = 0;
rc.right = s_target_width;
rc.bottom = s_target_height;
D3D::dev->SetScissorRect(rc.AsRECT());
}
return false;
D3D::dev->SetScissorRect(rc.AsRECT());
}
void Renderer::SetColorMask()
@ -680,7 +627,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
{
// TODO: Speed this up by batching pokes?
ResetAPIState();
D3D::drawColorQuad(GetTargetWidth(), GetTargetHeight(), poke_data,
D3D::drawColorQuad(poke_data,
(float)RectToLock.left * 2.f / (float)Renderer::GetTargetWidth() - 1.f,
- (float)RectToLock.top * 2.f / (float)Renderer::GetTargetHeight() + 1.f,
(float)RectToLock.right * 2.f / (float)Renderer::GetTargetWidth() - 1.f,
@ -805,7 +752,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
vp.MinZ = 0.0;
vp.MaxZ = 1.0;
D3D::dev->SetViewport(&vp);
D3D::drawClearQuad(GetTargetWidth(), GetTargetHeight(), color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader());
D3D::drawClearQuad(color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader());
RestoreAPIState();
}
@ -819,7 +766,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
else if (convtype == 2) pixel_shader = PixelShaderCache::ReinterpRGBA6ToRGB8();
else
{
PanicAlert("Trying to reinterpret pixel data with unsupported conversion type %d", convtype);
ERROR_LOG(VIDEO, "Trying to reinterpret pixel data with unsupported conversion type %d", convtype);
return;
}
@ -889,12 +836,11 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle
// This function has the final picture. We adjust the aspect ratio here.
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma)
{
static char* data = 0;
static int w = 0, h = 0;
if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight)
{
if (g_ActiveConfig.bDumpFrames && data)
AVIDump::AddFrame(data);
if (g_ActiveConfig.bDumpFrames && frame_data)
AVIDump::AddFrame(frame_data);
Core::Callback_VideoCopiedToXFB(false);
return;
}
@ -907,6 +853,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
{
if (g_ActiveConfig.bDumpFrames && frame_data)
AVIDump::AddFrame(frame_data);
Core::Callback_VideoCopiedToXFB(false);
return;
}
@ -952,7 +901,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
D3D::dev->SetViewport(&vp);
D3D::drawClearQuad(GetTargetWidth(), GetTargetHeight(), 0, 1.0, PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader());
D3D::drawClearQuad(0, 1.0, PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader());
}
else
{
@ -1072,15 +1021,21 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
SaveScreenshot(s_sScreenshotName, dst_rect);
s_bScreenshot = false;
}
// Dump frames
static int w = 0, h = 0;
if (g_ActiveConfig.bDumpFrames)
{
static int s_recordWidth;
static int s_recordHeight;
HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(),ScreenShootMEMSurface);
if (!s_bLastFrameDumped)
if (!bLastFrameDumped)
{
s_recordWidth = dst_rect.GetWidth();
s_recordHeight = dst_rect.GetHeight();
s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight);
if (!s_bAVIDumping)
bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), s_recordWidth, s_recordHeight);
if (!bAVIDumping)
{
PanicAlert("Error dumping frames to AVI.");
}
@ -1092,40 +1047,40 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
OSD::AddMessage(msg, 2000);
}
}
if (s_bAVIDumping)
if (bAVIDumping)
{
D3DLOCKED_RECT rect;
if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, dst_rect.AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY)))
{
if (!data || w != s_recordWidth || h != s_recordHeight)
if (!frame_data || w != s_recordWidth || h != s_recordHeight)
{
free(data);
data = (char*)malloc(3 * s_recordWidth * s_recordHeight);
delete[] frame_data;
frame_data = new char[3 * s_recordWidth * s_recordHeight];
w = s_recordWidth;
h = s_recordHeight;
}
formatBufferDump((const char*)rect.pBits, data, s_recordWidth, s_recordHeight, rect.Pitch);
AVIDump::AddFrame(data);
formatBufferDump((const char*)rect.pBits, frame_data, s_recordWidth, s_recordHeight, rect.Pitch);
AVIDump::AddFrame(frame_data);
ScreenShootMEMSurface->UnlockRect();
}
}
s_bLastFrameDumped = true;
bLastFrameDumped = true;
}
else
{
if (s_bLastFrameDumped && s_bAVIDumping)
if (bLastFrameDumped && bAVIDumping)
{
if (data)
if (frame_data)
{
free(data);
data = 0;
delete[] frame_data;
frame_data = 0;
w = h = 0;
}
AVIDump::Stop();
s_bAVIDumping = false;
bAVIDumping = false;
OSD::AddMessage("Stop dumping frames to AVI", 2000);
}
s_bLastFrameDumped = false;
bLastFrameDumped = false;
}
// Finish up the current frame, print some stats
@ -1157,20 +1112,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
OSD::DrawMessages();
D3D::EndFrame();
frameCount++;
++frameCount;
GFX_DEBUGGER_PAUSE_AT(NEXT_FRAME, true);
DLCache::ProgressiveCleanup();
TextureCache::Cleanup();
// reload textures if these settings changed
if (g_Config.bSafeTextureCache != g_ActiveConfig.bSafeTextureCache ||
g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips)
TextureCache::Invalidate(false);
// Enable any configuration changes
// Enable configuration changes
UpdateActiveConfig();
TextureCache::OnConfigChanged(g_ActiveConfig);
SetWindowSize(fbWidth, fbHeight);
@ -1222,20 +1173,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
}
// Place messages on the picture, then copy it to the screen
// ---------------------------------------------------------------------
// Count FPS.
// -------------
static int fpscount = 0;
static unsigned long lasttime = 0;
if (Common::Timer::GetTimeMs() - lasttime >= 1000)
{
lasttime = Common::Timer::GetTimeMs();
s_fps = fpscount;
fpscount = 0;
}
if (XFBWrited)
++fpscount;
s_fps = UpdateFPSCounter();
// Begin new frame
// Set default viewport and scissor, for the clear to work correctly
@ -1261,6 +1200,14 @@ void Renderer::ApplyState(bool bUseDstAlpha)
{
D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);
D3D::ChangeRenderState(D3DRS_ALPHABLENDENABLE, false);
if(bpmem.zmode.testenable && bpmem.zmode.updateenable)
{
//This is needed to draw to the correct pixels in multi-pass algorithms
//this avoid z-figthing and grants that you write to the same pixels
//affected by the last pass
D3D::ChangeRenderState(D3DRS_ZWRITEENABLE, false);
D3D::ChangeRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
}
}
}
@ -1268,7 +1215,11 @@ void Renderer::RestoreState()
{
D3D::RefreshRenderState(D3DRS_COLORWRITEENABLE);
D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE);
if(bpmem.zmode.testenable && bpmem.zmode.updateenable)
{
D3D::RefreshRenderState(D3DRS_ZWRITEENABLE);
D3D::RefreshRenderState(D3DRS_ZFUNC);
}
// TODO: Enable this code. Caused glitches for me however (neobrain)
// for (unsigned int i = 0; i < 8; ++i)
// D3D::dev->SetTexture(i, NULL);
@ -1293,7 +1244,7 @@ void Renderer::RestoreAPIState()
D3D::SetRenderState(D3DRS_FILLMODE, g_ActiveConfig.bWireFrame ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
VertexShaderManager::SetViewportChanged();
SetScissorRect();
BPFunctions::SetScissor();
if (bpmem.zmode.testenable) {
D3D::SetRenderState(D3DRS_ZENABLE, TRUE);
if (bpmem.zmode.updateenable)

View file

@ -15,7 +15,7 @@ public:
void SetColorMask();
void SetBlendMode(bool forceUpdate);
bool SetScissorRect();
void SetScissorRect(const TargetRectangle& rc);
void SetGenerationMode();
void SetDepthMode();
void SetLogicOpMode();

View file

@ -21,6 +21,7 @@
#include "Statistics.h"
#include "MemoryUtil.h"
#include "Hash.h"
#include "HW/Memmap.h"
#include "CommonPaths.h"
#include "FileUtil.h"
@ -57,9 +58,17 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage)
D3D::SetTexture(stage, texture);
}
bool TextureCache::TCacheEntry::Save(const char filename[])
bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
{
return SUCCEEDED(PD3DXSaveTextureToFileA(filename, D3DXIFF_PNG, texture, 0));
IDirect3DSurface9* surface;
HRESULT hr = texture->GetSurfaceLevel(level, &surface);
if (FAILED(hr))
return false;
hr = PD3DXSaveSurfaceToFileA(filename, D3DXIFF_PNG, surface, NULL, NULL);
surface->Release();
return SUCCEEDED(hr);
}
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
@ -78,7 +87,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
FramebufferManager::GetEFBDepthTexture() :
FramebufferManager::GetEFBColorTexture();
if (!isDynamic || g_ActiveConfig.bCopyEFBToTexture)
if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture)
{
LPDIRECT3DSURFACE9 Rendersurf = NULL;
texture->GetSurfaceLevel(0, &Rendersurf);
@ -90,15 +99,15 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
// Stretch picture with increased internal resolution
vp.X = 0;
vp.Y = 0;
vp.Width = virtualW;
vp.Height = virtualH;
vp.Width = virtual_width;
vp.Height = virtual_height;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
D3D::dev->SetViewport(&vp);
RECT destrect;
destrect.bottom = virtualH;
destrect.bottom = virtual_height;
destrect.left = 0;
destrect.right = virtualW;
destrect.right = virtual_width;
destrect.top = 0;
PixelShaderManager::SetColorMatrix(colmat); // set transformation
@ -133,7 +142,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
D3D::drawShadedTexQuad(read_texture, &sourcerect,
Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
virtualW, virtualH,
virtual_width, virtual_height,
// TODO: why is D3DFMT_D24X8 singled out here? why not D3DFMT_D24X4S4/D24S8/D24FS8/D32/D16/D15S1 too, or none of them?
PixelShaderCache::GetDepthMatrixProgram(SSAAMode, (srcFormat == PIXELFMT_Z24) && bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8),
VertexShaderCache::GetSimpleVertexShader(SSAAMode));
@ -143,16 +152,27 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
if (!g_ActiveConfig.bCopyEFBToTexture)
{
hash = TextureConverter::EncodeToRamFromTexture(
addr,
read_texture,
Renderer::GetTargetWidth(),
Renderer::GetTargetHeight(),
srcFormat == PIXELFMT_Z24,
isIntensity,
dstFormat,
scaleByHalf,
srcRect);
int encoded_size = TextureConverter::EncodeToRamFromTexture(
addr,
read_texture,
Renderer::GetTargetWidth(),
Renderer::GetTargetHeight(),
srcFormat == PIXELFMT_Z24,
isIntensity,
dstFormat,
scaleByHalf,
srcRect);
u8* dst = Memory::GetPointer(addr);
u64 hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples);
// Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date
if (!g_ActiveConfig.bEFBCopyCacheEnable)
TextureCache::MakeRangeDynamic(addr,encoded_size);
else if (!TextureCache::Find(addr, hash))
TextureCache::MakeRangeDynamic(addr,encoded_size);
this->hash = hash;
}
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);

View file

@ -52,7 +52,7 @@ private:
const float *colmat);
void Bind(unsigned int stage);
bool Save(const char filename[]);
bool Save(const char filename[], unsigned int level);
};
TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height,

View file

@ -252,10 +252,10 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr
s_texConvReadSurface = TrnBuffers[index].ReadSurface;
Rendersurf = TrnBuffers[index].RenderSurface;
hr = D3D::dev->SetDepthStencilSurface(NULL);
hr = D3D::dev->SetRenderTarget(0, Rendersurf);
if (linearFilter)
{
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
@ -290,7 +290,7 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
// .. and then read back the results.
// TODO: make this less slow.
hr = D3D::dev->GetRenderTargetData(Rendersurf,s_texConvReadSurface);
D3DLOCKED_RECT drect;
@ -313,76 +313,7 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr
hr = s_texConvReadSurface->UnlockRect();
}
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
{
u32 format = copyfmt;
if (bFromZBuffer)
{
format |= _GX_TF_ZTF;
if (copyfmt == 11)
format = GX_TF_Z16;
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
format |= _GX_TF_CTF;
}
else
if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt))
format |= _GX_TF_CTF;
LPDIRECT3DPIXELSHADER9 texconv_shader = GetOrCreateEncodingShader(format);
if (!texconv_shader)
return;
u8 *dest_ptr = Memory::GetPointer(address);
LPDIRECT3DTEXTURE9 source_texture = bFromZBuffer ? FramebufferManager::GetEFBDepthTexture() : FramebufferManager::GetEFBColorTexture();
int width = (source.right - source.left) >> bScaleByHalf;
int height = (source.bottom - source.top) >> bScaleByHalf;
int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format);
// Invalidate any existing texture covering this memory range.
// TODO - don't delete the texture if it already exists, just replace the contents.
TextureCache::InvalidateRange(address, size_in_bytes);
u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
u16 samples = TextureConversionShader::GetEncodedSampleCount(format);
// only copy on cache line boundaries
// extra pixels are copied but not displayed in the resulting texture
s32 expandedWidth = (width + blkW) & (~blkW);
s32 expandedHeight = (height + blkH) & (~blkH);
float sampleStride = bScaleByHalf ? 2.f : 1.f;
TextureConversionShader::SetShaderParameters(
(float)expandedWidth,
(float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this?
(float)Renderer::EFBToScaledX(source.left),
(float)Renderer::EFBToScaledY(source.top),
Renderer::EFBToScaledXf(sampleStride),
Renderer::EFBToScaledYf(sampleStride),
(float)Renderer::GetTargetWidth(),
(float)Renderer::GetTargetHeight());
TargetRectangle scaledSource;
scaledSource.top = 0;
scaledSource.bottom = expandedHeight;
scaledSource.left = 0;
scaledSource.right = expandedWidth / samples;
int cacheBytes = 32;
if ((format & 0x0f) == 6)
cacheBytes = 64;
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
g_renderer->ResetAPIState();
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0,1.0f);
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
g_renderer->RestoreAPIState();
}
u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
int EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
{
u32 format = copyfmt;
@ -440,16 +371,7 @@ u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 So
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0,1.0f);
u64 hash = GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples);
if (g_ActiveConfig.bEFBCopyCacheEnable)
{
// If the texture in RAM is already in the texture cache, do not copy it again as it has not changed.
if (TextureCache::Find(address, hash))
return hash;
}
TextureCache::MakeRangeDynamic(address,size_in_bytes);
return hash;
return size_in_bytes; // TODO: D3D11 is calculating this value differently!
}
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight,float Gamma)
@ -490,7 +412,7 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE
destTexture->GetSurfaceLevel(0,&Rendersurf);
D3D::dev->SetDepthStencilSurface(NULL);
D3D::dev->SetRenderTarget(0, Rendersurf);
D3DVIEWPORT9 vp;
// Stretch picture with increased internal resolution

View file

@ -35,15 +35,13 @@ namespace TextureConverter
void Init();
void Shutdown();
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight,float Gamma);
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
// returns size of the encoded data (in bytes)
int EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
}

View file

@ -39,9 +39,12 @@
// internal state for loading vertices
extern NativeVertexFormat *g_nativeVertexFmt;
namespace DX9
{
//This are the initially requeted size for the buffers expresed in elements
const u32 IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * 16;
const u32 VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE * 16;
const u32 MAXVBUFFER_COUNT = 2;
inline void DumpBadShaders()
{
@ -62,8 +65,202 @@ inline void DumpBadShaders()
#endif
}
void VertexManager::Draw(int stride)
void VertexManager::CreateDeviceObjects()
{
NumVBuffers = 0;
VBuffers = NULL;
IBuffers = NULL;
D3DCAPS9 DeviceCaps = D3D::GetCaps();
u32 devicevMaxBufferSize = DeviceCaps.MaxPrimitiveCount * 3 * DeviceCaps.MaxStreamStride;
//Calculate Device Dependant size
CurrentVBufferSize = (VBUFFER_SIZE > devicevMaxBufferSize) ? devicevMaxBufferSize : VBUFFER_SIZE;
CurrentIBufferSize = (IBUFFER_SIZE > DeviceCaps.MaxVertexIndex) ? DeviceCaps.MaxVertexIndex : IBUFFER_SIZE;
//if device caps are not enough for Vbuffer fall back to vertex arrays
if (CurrentIBufferSize < MAXIBUFFERSIZE || CurrentVBufferSize < MAXVBUFFERSIZE) return;
VBuffers = new LPDIRECT3DVERTEXBUFFER9[MAXVBUFFER_COUNT];
IBuffers = new LPDIRECT3DINDEXBUFFER9[MAXVBUFFER_COUNT];
bool Fail = false;
for (CurrentVBuffer = 0; CurrentVBuffer < MAXVBUFFER_COUNT; CurrentVBuffer++)
{
VBuffers[CurrentVBuffer] = NULL;
IBuffers[CurrentVBuffer] = NULL;
}
for (CurrentVBuffer = 0; CurrentVBuffer < MAXVBUFFER_COUNT; CurrentVBuffer++)
{
if(FAILED( D3D::dev->CreateVertexBuffer( CurrentVBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &VBuffers[CurrentVBuffer], NULL ) ) )
{
Fail = true;
break;
}
if( FAILED( D3D::dev->CreateIndexBuffer( CurrentIBufferSize * sizeof(u16), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &IBuffers[CurrentVBuffer], NULL ) ) )
{
Fail = true;
return;
}
}
NumVBuffers = CurrentVBuffer;
CurrentVBuffer = 0;
CurrentIBuffer = 0;
CurrentIBufferIndex = CurrentIBufferSize;
CurrentVBufferIndex = CurrentVBufferSize;
if (Fail)
{
NumVBuffers--;
if (NumVBuffers < 2)
{
//Error creating Vertex buffers. clean and fall to Vertex arrays
NumVBuffers = MAXVBUFFER_COUNT;
DestroyDeviceObjects();
}
}
}
void VertexManager::DestroyDeviceObjects()
{
D3D::dev->SetStreamSource( 0, NULL, 0, 0);
D3D::dev->SetIndices(NULL);
for (int i = 0; i < MAXVBUFFER_COUNT; i++)
{
if(VBuffers)
{
if (VBuffers[i])
{
VBuffers[i]->Release();
VBuffers[i] = NULL;
}
}
if (IBuffers[i])
{
IBuffers[i]->Release();
IBuffers[i] = NULL;
}
}
if(VBuffers)
delete [] VBuffers;
if(IBuffers)
delete [] IBuffers;
VBuffers = NULL;
IBuffers = NULL;
}
void VertexManager::PrepareVBuffers(int stride)
{
if (!NumVBuffers)
{
return;
}
u8* pVertices;
u16* pIndices;
int datasize = IndexGenerator::GetNumVerts() * stride;
int TdataSize = IndexGenerator::GetTriangleindexLen();
int LDataSize = IndexGenerator::GetLineindexLen();
int PDataSize = IndexGenerator::GetPointindexLen();
int IndexDataSize = TdataSize + LDataSize + PDataSize;
DWORD LockMode = D3DLOCK_NOOVERWRITE;
if (CurrentVBufferIndex > CurrentVBufferSize - datasize)
{
LockMode = D3DLOCK_DISCARD;
CurrentVBufferIndex = 0;
CurrentVBuffer = (CurrentVBuffer + 1) % NumVBuffers;
}
if(FAILED(VBuffers[CurrentVBuffer]->Lock(CurrentVBufferIndex, datasize,(VOID**)(&pVertices), LockMode)))
{
DestroyDeviceObjects();
return;
}
memcpy(pVertices, LocalVBuffer, datasize);
VBuffers[CurrentVBuffer]->Unlock();
LockMode = D3DLOCK_NOOVERWRITE;
if (CurrentIBufferIndex > CurrentIBufferSize - IndexDataSize)
{
LockMode = D3DLOCK_DISCARD;
CurrentIBufferIndex = 0;
CurrentIBuffer = (CurrentIBuffer + 1) % NumVBuffers;
}
if(FAILED(IBuffers[CurrentIBuffer]->Lock(CurrentIBufferIndex * sizeof(u16), IndexDataSize * sizeof(u16), (VOID**)(&pIndices), LockMode )))
{
DestroyDeviceObjects();
return;
}
if(TdataSize)
{
memcpy(pIndices, TIBuffer, TdataSize * sizeof(u16));
pIndices += TdataSize;
}
if(LDataSize)
{
memcpy(pIndices, LIBuffer, LDataSize * sizeof(u16));
pIndices += LDataSize;
}
if(PDataSize)
{
memcpy(pIndices, PIBuffer, PDataSize * sizeof(u16));
}
IBuffers[CurrentIBuffer]->Unlock();
D3D::dev->SetStreamSource( 0, VBuffers[CurrentVBuffer], CurrentVBufferIndex, stride);
if(CurrentIBufferIndex == 0)
{
D3D::dev->SetIndices(IBuffers[CurrentIBuffer]);
}
}
void VertexManager::DrawVB(int stride)
{
if (IndexGenerator::GetNumTriangles() > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitive(
D3DPT_TRIANGLELIST,
0,
0,
IndexGenerator::GetNumVerts(),
CurrentIBufferIndex,
IndexGenerator::GetNumTriangles())))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (IndexGenerator::GetNumLines() > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitive(
D3DPT_LINELIST,
0,
0,
IndexGenerator::GetNumVerts(),
CurrentIBufferIndex + IndexGenerator::GetTriangleindexLen(),
IndexGenerator::GetNumLines())))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
if (IndexGenerator::GetNumPoints() > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitive(
D3DPT_POINTLIST,
0,
0,
IndexGenerator::GetNumVerts(),
CurrentIBufferIndex + IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen(),
IndexGenerator::GetNumPoints())))
{
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
}
void VertexManager::DrawVA(int stride)
{
if (IndexGenerator::GetNumTriangles() > 0)
{
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
@ -105,7 +302,7 @@ void VertexManager::Draw(int stride)
DumpBadShaders();
}
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
}
}
}
void VertexManager::vFlush()
@ -136,13 +333,14 @@ void VertexManager::vFlush()
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
tex.texTlut[i&3].tlut_format,
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8) && g_ActiveConfig.bUseNativeMips,
(tex.texMode1[i&3].max_lod >> 4));
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
tex.texMode1[i&3].max_lod >> 4,
tex.texImage1[i&3].image_type);
if (tentry)
{
// 0s are probably for no manual wrapping needed.
PixelShaderManager::SetTexDims(i, tentry->realW, tentry->realH, 0, 0);
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0);
}
else
ERROR_LOG(VIDEO, "error loading texture");
@ -152,7 +350,7 @@ void VertexManager::vFlush()
// set global constants
VertexShaderManager::SetConstants();
PixelShaderManager::SetConstants();
int stride = g_nativeVertexFmt->GetVertexStride();
if (!PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components))
{
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
@ -164,17 +362,14 @@ void VertexManager::vFlush()
goto shader_fail;
}
int stride = g_nativeVertexFmt->GetVertexStride();
g_nativeVertexFmt->SetupVertexPointers();
Draw(stride);
PrepareVBuffers(stride);
g_nativeVertexFmt->SetupVertexPointers();
if(NumVBuffers){ DrawVB(stride);} else { DrawVA(stride);}
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
if (useDstAlpha)
{
DWORD write = 0;
if (!PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS, g_nativeVertexFmt->m_components))
{
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
@ -182,12 +377,17 @@ void VertexManager::vFlush()
}
// update alpha only
g_renderer->ApplyState(true);
Draw(stride);
if(NumVBuffers){ DrawVB(stride);} else { DrawVA(stride);}
g_renderer->RestoreState();
}
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
shader_fail:
if(NumVBuffers)
{
CurrentIBufferIndex += IndexGenerator::GetTriangleindexLen() + IndexGenerator::GetLineindexLen() + IndexGenerator::GetPointindexLen();
CurrentVBufferIndex += IndexGenerator::GetNumVerts() * stride;
}
ResetBuffer();
}

View file

@ -31,9 +31,21 @@ class VertexManager : public ::VertexManager
public:
NativeVertexFormat* CreateNativeVertexFormat();
void GetElements(NativeVertexFormat* format, D3DVERTEXELEMENT9** elems, int* num);
void CreateDeviceObjects();
void DestroyDeviceObjects();
private:
void Draw(int stride);
u32 CurrentVBufferIndex;
u32 CurrentVBufferSize;
u32 CurrentIBufferIndex;
u32 CurrentIBufferSize;
u32 NumVBuffers;
u32 CurrentVBuffer;
u32 CurrentIBuffer;
LPDIRECT3DVERTEXBUFFER9 *VBuffers;
LPDIRECT3DINDEXBUFFER9 *IBuffers;
void PrepareVBuffers(int stride);
void DrawVB(int stride);
void DrawVA(int stride);
// temp
void vFlush();
};

View file

@ -38,6 +38,7 @@ namespace DX9
VertexShaderCache::VSCache VertexShaderCache::vshaders;
const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry;
VERTEXSHADERUID VertexShaderCache::last_uid;
#define MAX_SSAA_SHADERS 3
@ -151,6 +152,11 @@ void VertexShaderCache::Init()
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
VertexShaderCacheInserter inserter;
g_vs_disk_cache.OpenAndRead(cache_filename, inserter);
if (g_Config.bEnableShaderDebugging)
Clear();
last_entry = NULL;
}
void VertexShaderCache::Clear()
@ -159,7 +165,7 @@ void VertexShaderCache::Clear()
iter->second.Destroy();
vshaders.clear();
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
last_entry = NULL;
}
void VertexShaderCache::Shutdown()
@ -184,23 +190,27 @@ bool VertexShaderCache::SetShader(u32 components)
{
VERTEXSHADERUID uid;
GetVertexShaderId(&uid, components);
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
if (last_entry)
{
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
return (vshaders[uid].shader != NULL);
if (uid == last_uid)
{
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
ValidateVertexShaderIDs(API_D3D9, last_entry->safe_uid, last_entry->code, components);
return (last_entry->shader != NULL);
}
}
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
last_uid = uid;
VSCache::iterator iter = vshaders.find(uid);
if (iter != vshaders.end())
{
iter->second.frameCount = frameCount;
const VSCacheEntry &entry = iter->second;
last_entry = &entry;
if (entry.shader) D3D::SetVertexShader(entry.shader);
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
ValidateVertexShaderIDs(API_D3D9, entry.safe_uid, entry.code, components);
return (entry.shader != NULL);
}
@ -213,12 +223,16 @@ bool VertexShaderCache::SetShader(u32 components)
return false;
}
g_vs_disk_cache.Append(uid, bytecode, bytecodelen);
g_vs_disk_cache.Sync();
bool result = InsertByteCode(uid, bytecode, bytecodelen, true);
bool success = InsertByteCode(uid, bytecode, bytecodelen, true);
if (g_ActiveConfig.bEnableShaderDebugging && success)
{
vshaders[uid].code = code;
GetSafeVertexShaderId(&vshaders[uid].safe_uid, components);
}
delete [] bytecode;
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
return result;
return success;
}
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate) {
@ -227,7 +241,6 @@ bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, const u8 *byt
// Make an entry in the table
VSCacheEntry entry;
entry.shader = shader;
entry.frameCount = frameCount;
vshaders[uid] = entry;
last_entry = &vshaders[uid];

View file

@ -34,11 +34,11 @@ private:
struct VSCacheEntry
{
LPDIRECT3DVERTEXSHADER9 shader;
int frameCount;
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string code;
#endif
VSCacheEntry() : shader(NULL), frameCount(0) {}
VERTEXSHADERUIDSAFE safe_uid;
VSCacheEntry() : shader(NULL) {}
void Destroy()
{
if (shader)
@ -51,6 +51,7 @@ private:
static VSCache vshaders;
static const VSCacheEntry *last_entry;
static VERTEXSHADERUID last_uid;
static void Clear();
public:

View file

@ -78,7 +78,7 @@ void VideoBackend::UpdateFPSDisplay(const char *text)
{
TCHAR temp[512];
swprintf_s(temp, sizeof(temp)/sizeof(TCHAR), _T("%hs | DX9 | %hs"), scm_rev_str, text);
SetWindowText(EmuWindow::GetWnd(), temp);
EmuWindow::SetWindowText(temp);
}
std::string VideoBackend::GetName()
@ -132,6 +132,7 @@ void VideoBackend::ShowConfig(void* parent)
bool VideoBackend::Initialize(void *&window_handle)
{
InitializeShared();
InitBackendInfo();
frameCount = 0;
@ -167,9 +168,9 @@ void VideoBackend::Video_Prepare()
s_swapRequested = FALSE;
// internal interfaces
g_renderer = new Renderer;
g_texture_cache = new TextureCache;
g_vertex_manager = new VertexManager;
g_renderer = new Renderer;
g_texture_cache = new TextureCache;
// VideoCommon
BPInit();
Fifo_Init();
@ -207,10 +208,11 @@ void VideoBackend::Shutdown()
// internal interfaces
PixelShaderCache::Shutdown();
VertexShaderCache::Shutdown();
delete g_vertex_manager;
delete g_texture_cache;
delete g_renderer;
delete g_vertex_manager;
g_renderer = NULL;
g_texture_cache = NULL;
}
D3D::Shutdown();
}

View file

@ -22,8 +22,10 @@ if(wxWidgets_FOUND)
set(LIBS ${LIBS} ${wxWidgets_LIBRARIES})
endif(wxWidgets_FOUND)
if(APPLE OR WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
if(WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(LIBS ${LIBS} Cg CgGL)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
list(APPEND LIBS "${CMAKE_SOURCE_DIR}/Externals/Cg/Cg.framework")
endif()
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")

View file

@ -46,7 +46,7 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@ -57,7 +57,6 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@ -118,7 +117,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -130,7 +129,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -142,7 +141,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -156,7 +155,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -170,7 +169,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -184,7 +183,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\include;..\..\..\Externals\GLew\include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -236,7 +235,6 @@
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
<None Include="Src\SConscript" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Externals\zlib\zlib.vcxproj">

View file

@ -74,7 +74,6 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Src\SConscript" />
<None Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>

View file

@ -1,22 +0,0 @@
# -*- python -*-
Import('env')
import os
import sys
files = [
'Src/FramebufferManager.cpp',
'Src/GLUtil.cpp',
'Src/NativeVertexFormat.cpp',
'Src/PixelShaderCache.cpp',
'Src/PostProcessing.cpp',
'Src/RasterFont.cpp',
'Src/Render.cpp',
'Src/TextureCache.cpp',
'Src/TextureConverter.cpp',
'Src/VertexManager.cpp',
'Src/VertexShaderCache.cpp',
'Src/main.cpp',
]
env['LIBS'] += env.StaticLibrary('videoogl', files)

View file

@ -73,8 +73,9 @@ void OpenGL_SetWindowText(const char *text)
#elif defined(__APPLE__)
[GLWin.cocoaWin setTitle: [NSString stringWithUTF8String: text]];
#elif defined(_WIN32)
// TODO convert text to unicode and change SetWindowTextA to SetWindowText
SetWindowTextA(EmuWindow::GetWnd(), text);
TCHAR temp[512];
swprintf_s(temp, sizeof(temp)/sizeof(TCHAR), _T("%hs"), text);
EmuWindow::SetWindowText(temp);
#elif defined(HAVE_X11) && HAVE_X11
// Tell X to ask the window manager to set the window title.
// (X itself doesn't provide window title functionality.)
@ -173,7 +174,7 @@ void XEventThread()
OSDChoice = 1;
// Toggle native resolution
g_Config.iEFBScale = g_Config.iEFBScale + 1;
if (g_Config.iEFBScale > 4) g_Config.iEFBScale = 0;
if (g_Config.iEFBScale > 7) g_Config.iEFBScale = 0;
break;
case XK_4:
OSDChoice = 2;
@ -197,10 +198,6 @@ void XEventThread()
OSDChoice = 4;
g_Config.bDisableFog = !g_Config.bDisableFog;
break;
case XK_7:
OSDChoice = 5;
g_Config.bDisableLighting = !g_Config.bDisableLighting;
break;
default:
break;
}

View file

@ -271,21 +271,13 @@ void GLVertexFormat::EnableComponents(u32 components)
// tex
for (int i = 0; i < 8; ++i)
{
if (!g_ActiveConfig.bDisableTexturing)
{
if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i)))
{
glClientActiveTexture(GL_TEXTURE0 + i);
if (components & (VB_HAS_UV0 << i))
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
else
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
else
if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i)))
{
glClientActiveTexture(GL_TEXTURE0 + i);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (components & (VB_HAS_UV0 << i))
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
else
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}

View file

@ -44,7 +44,8 @@ bool PixelShaderCache::s_displayCompileAlert;
GLuint PixelShaderCache::CurrentShader;
bool PixelShaderCache::ShaderEnabled;
static FRAGMENTSHADER* pShaderLast = NULL;
PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry = NULL;
PIXELSHADERUID PixelShaderCache::last_uid;
GLuint PixelShaderCache::GetDepthMatrixProgram()
{
@ -61,10 +62,9 @@ void PixelShaderCache::Init()
glEnable(GL_FRAGMENT_PROGRAM_ARB);
ShaderEnabled = true;
CurrentShader = 0;
last_entry = NULL;
GL_REPORT_ERRORD();
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
s_displayCompileAlert = true;
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions);
@ -184,38 +184,43 @@ void PixelShaderCache::Shutdown()
FRAGMENTSHADER* PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
{
PIXELSHADERUID uid;
GetPixelShaderId(&uid, dstAlphaMode);
GetPixelShaderId(&uid, dstAlphaMode, components);
// Check if the shader is already set
if (uid == last_pixel_shader_uid && PixelShaders[uid].frameCount == frameCount)
if (last_entry)
{
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
return pShaderLast;
if (uid == last_uid)
{
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
ValidatePixelShaderIDs(API_OPENGL, last_entry->safe_uid, last_entry->shader.strprog, dstAlphaMode, components);
return &last_entry->shader;
}
}
memcpy(&last_pixel_shader_uid, &uid, sizeof(PIXELSHADERUID));
last_uid = uid;
PSCache::iterator iter = PixelShaders.find(uid);
if (iter != PixelShaders.end())
{
iter->second.frameCount = frameCount;
PSCacheEntry &entry = iter->second;
if (&entry.shader != pShaderLast)
{
pShaderLast = &entry.shader;
}
last_entry = &entry;
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
return pShaderLast;
ValidatePixelShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, dstAlphaMode, components);
return &last_entry->shader;
}
// Make an entry in the table
PSCacheEntry& newentry = PixelShaders[uid];
newentry.frameCount = frameCount;
pShaderLast = &newentry.shader;
last_entry = &newentry;
const char *code = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components);
if (g_ActiveConfig.bEnableShaderDebugging && code)
{
GetSafePixelShaderId(&newentry.safe_uid, dstAlphaMode, components);
newentry.shader.strprog = code;
}
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
static int counter = 0;
@ -234,7 +239,7 @@ FRAGMENTSHADER* PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 comp
INCSTAT(stats.numPixelShadersCreated);
SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
return pShaderLast;
return &last_entry->shader;
}
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
@ -247,7 +252,7 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr
#if defined HAVE_CG && HAVE_CG
char stropt[128];
sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions);
sprintf(stropt, "MaxLocalParams=224,NumInstructionSlots=%d", s_nMaxPixelInstructions);
const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
@ -318,9 +323,6 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr
cgDestroyProgram(tempprog);
#endif
#if defined(_DEBUG) || defined(DEBUGFAST)
ps.strprog = pstrprogram;
#endif
return true;
}

View file

@ -39,9 +39,7 @@ struct FRAGMENTSHADER
}
}
GLuint glprogid; // opengl program id
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string strprog;
#endif
};
class PixelShaderCache
@ -49,13 +47,13 @@ class PixelShaderCache
struct PSCacheEntry
{
FRAGMENTSHADER shader;
int frameCount;
PSCacheEntry() : frameCount(0) {}
PSCacheEntry() {}
~PSCacheEntry() {}
void Destroy()
{
shader.Destroy();
}
PIXELSHADERUIDSAFE safe_uid;
};
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
@ -67,6 +65,8 @@ class PixelShaderCache
static bool s_displayCompileAlert;
static GLuint CurrentShader;
static PSCacheEntry* last_entry;
static PIXELSHADERUID last_uid;
static bool ShaderEnabled;

View file

@ -60,6 +60,8 @@
#include "Core.h"
#include "Movie.h"
#include "Host.h"
#include "BPFunctions.h"
#include "FPSCounter.h"
#include "main.h" // Local
#ifdef _WIN32
@ -109,12 +111,6 @@ int s_fps=0;
RasterFont* s_pfont = NULL;
#if defined _WIN32 || defined HAVE_LIBAV
static bool s_bAVIDumping = false;
#else
static File::IOFile f_pFrameDump;
#endif
// 1 for no MSAA. Use s_MSAASamples > 1 to check for MSAA.
static int s_MSAASamples = 1;
static int s_MSAACoverageSamples = 0;
@ -128,6 +124,12 @@ static u32 s_blendMode;
static std::thread scrshotThread;
#endif
// EFB cache related
const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks.
const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up
const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE;
static bool s_efbCacheValid[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT];
static std::vector<u32> s_efbCache[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT]; // 2 for PEEK_Z and PEEK_COLOR
static const GLenum glSrcFactors[8] =
{
@ -249,9 +251,8 @@ Renderer::Renderer()
s_fps=0;
s_blendMode = 0;
#if defined _WIN32 || defined HAVE_LIBAV
s_bAVIDumping = false;
#endif
InitFPSCounter();
#if defined HAVE_CG && HAVE_CG
g_cgcontext = cgCreateContext();
@ -515,19 +516,6 @@ Renderer::~Renderer()
#endif
delete g_framebuffer_manager;
#if defined _WIN32 || defined HAVE_LIBAV
if(s_bAVIDumping)
{
AVIDump::Stop();
s_bLastFrameDumped = false;
s_bAVIDumping = false;
}
#else
if (f_pFrameDump.IsOpen())
f_pFrameDump.Close();
s_bLastFrameDumped = false;
#endif
}
// Create On-Screen-Messages
@ -610,7 +598,7 @@ void Renderer::RenderText(const char *text, int left, int top, u32 color)
{
const int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth();
const int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight();
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
@ -642,49 +630,9 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
// Renderer::GetTargetHeight() = the fixed ini file setting
// donkopunchstania - it appears scissorBR is the bottom right pixel inside the scissor box
// therefore the width and height are (scissorBR + 1) - scissorTL
bool Renderer::SetScissorRect()
void Renderer::SetScissorRect(const TargetRectangle& rc)
{
MathUtil::Rectangle<float> rc;
GetScissorRect(rc);
if (rc.left < 0) rc.left = 0;
if (rc.top < 0) rc.top = 0;
if (rc.right > EFB_WIDTH) rc.right = EFB_WIDTH;
if (rc.bottom > EFB_HEIGHT) rc.bottom = EFB_HEIGHT;
if (rc.left > rc.right)
{
int temp = rc.right;
rc.right = rc.left;
rc.left = temp;
}
if (rc.top > rc.bottom)
{
int temp = rc.bottom;
rc.bottom = rc.top;
rc.top = temp;
}
// Check that the coordinates are good
if (rc.right != rc.left && rc.bottom != rc.top)
{
glScissor(
EFBToScaledX(rc.left), // x = 0 for example
EFBToScaledY(EFB_HEIGHT - rc.bottom), // y = 0 for example
EFBToScaledX(rc.right - rc.left), // width = 640 for example
EFBToScaledY(rc.bottom - rc.top)); // height = 480 for example
return true;
}
else
{
glScissor(
0,
0,
Renderer::GetTargetWidth(),
Renderer::GetTargetHeight()
);
}
return false;
glScissor(rc.left, rc.bottom, rc.GetWidth(), rc.GetHeight());
}
void Renderer::SetColorMask()
@ -698,6 +646,44 @@ void Renderer::SetColorMask()
glColorMask(ColorMask, ColorMask, ColorMask, AlphaMask);
}
void ClearEFBCache()
{
for (u32 i = 0; i < EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT; ++i)
s_efbCacheValid[0][i] = false;
for (u32 i = 0; i < EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT; ++i)
s_efbCacheValid[1][i] = false;
}
void Renderer::UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const u32* data)
{
u32 cacheType = (type == PEEK_Z ? 0 : 1);
if (!s_efbCache[cacheType][cacheRectIdx].size())
s_efbCache[cacheType][cacheRectIdx].resize(EFB_CACHE_RECT_SIZE * EFB_CACHE_RECT_SIZE);
u32 targetPixelRcWidth = targetPixelRc.right - targetPixelRc.left;
u32 efbPixelRcHeight = efbPixelRc.bottom - efbPixelRc.top;
u32 efbPixelRcWidth = efbPixelRc.right - efbPixelRc.left;
for (u32 yCache = 0; yCache < efbPixelRcHeight; ++yCache)
{
u32 yEFB = efbPixelRc.top + yCache;
u32 yPixel = (EFBToScaledY(EFB_HEIGHT - yEFB) + EFBToScaledY(EFB_HEIGHT - yEFB - 1)) / 2;
u32 yData = yPixel - targetPixelRc.bottom;
for (u32 xCache = 0; xCache < efbPixelRcWidth; ++xCache)
{
u32 xEFB = efbPixelRc.left + xCache;
u32 xPixel = (EFBToScaledX(xEFB) + EFBToScaledX(xEFB + 1)) / 2;
u32 xData = xPixel - targetPixelRc.left;
s_efbCache[cacheType][cacheRectIdx][yCache * EFB_CACHE_RECT_SIZE + xCache] = data[yData * targetPixelRcWidth + xData];
}
}
s_efbCacheValid[cacheType][cacheRectIdx] = true;
}
// This function allows the CPU to directly access the EFB.
// There are EFB peeks (which will read the color or depth of a pixel)
// and EFB pokes (which will change the color or depth of a pixel).
@ -717,34 +703,50 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
if (!g_ActiveConfig.bEFBAccessEnable)
return 0;
// Get the rectangular target region covered by the EFB pixel
u32 cacheRectIdx = (y / EFB_CACHE_RECT_SIZE) * EFB_CACHE_WIDTH
+ (x / EFB_CACHE_RECT_SIZE);
// Get the rectangular target region containing the EFB pixel
EFBRectangle efbPixelRc;
efbPixelRc.left = x;
efbPixelRc.top = y;
efbPixelRc.right = x + 1;
efbPixelRc.bottom = y + 1;
efbPixelRc.left = (x / EFB_CACHE_RECT_SIZE) * EFB_CACHE_RECT_SIZE;
efbPixelRc.top = (y / EFB_CACHE_RECT_SIZE) * EFB_CACHE_RECT_SIZE;
efbPixelRc.right = std::min(efbPixelRc.left + EFB_CACHE_RECT_SIZE, (u32)EFB_WIDTH);
efbPixelRc.bottom = std::min(efbPixelRc.top + EFB_CACHE_RECT_SIZE, (u32)EFB_HEIGHT);
TargetRectangle targetPixelRc = ConvertEFBRectangle(efbPixelRc);
u32 targetPixelRcWidth = targetPixelRc.right - targetPixelRc.left;
u32 targetPixelRcHeight = targetPixelRc.top - targetPixelRc.bottom;
// TODO (FIX) : currently, AA path is broken/offset and doesn't return the correct pixel
switch (type)
{
case PEEK_Z:
{
if (s_MSAASamples > 1)
u32 z;
if (!s_efbCacheValid[0][cacheRectIdx])
{
// Resolve our rectangle.
FramebufferManager::GetEFBDepthTexture(efbPixelRc);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
if (s_MSAASamples > 1)
{
// Resolve our rectangle.
FramebufferManager::GetEFBDepthTexture(efbPixelRc);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
}
u32* depthMap = new u32[targetPixelRcWidth * targetPixelRcHeight];
glReadPixels(targetPixelRc.left, targetPixelRc.bottom, targetPixelRcWidth, targetPixelRcHeight,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, depthMap);
GL_REPORT_ERRORD();
UpdateEFBCache(type, cacheRectIdx, efbPixelRc, targetPixelRc, depthMap);
delete[] depthMap;
}
// Sample from the center of the target region.
int srcX = (targetPixelRc.left + targetPixelRc.right) / 2;
int srcY = (targetPixelRc.top + targetPixelRc.bottom) / 2;
u32 z = 0;
glReadPixels(srcX, srcY, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, &z);
GL_REPORT_ERRORD();
u32 xRect = x % EFB_CACHE_RECT_SIZE;
u32 yRect = y % EFB_CACHE_RECT_SIZE;
z = s_efbCache[0][cacheRectIdx][yRect * EFB_CACHE_RECT_SIZE + xRect];
// Scale the 32-bit value returned by glReadPixels to a 24-bit
// value (GC uses a 24-bit Z-buffer).
@ -769,21 +771,31 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
// determine if we're aiming at an enemy (0x80 / 0x88) or not (0x70)
// Wind Waker is also using it for the pictograph to determine the color of each pixel
if (s_MSAASamples > 1)
u32 color;
if (!s_efbCacheValid[1][cacheRectIdx])
{
// Resolve our rectangle.
FramebufferManager::GetEFBColorTexture(efbPixelRc);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
if (s_MSAASamples > 1)
{
// Resolve our rectangle.
FramebufferManager::GetEFBColorTexture(efbPixelRc);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, FramebufferManager::GetResolvedFramebuffer());
}
u32* colorMap = new u32[targetPixelRcWidth * targetPixelRcHeight];
glReadPixels(targetPixelRc.left, targetPixelRc.bottom, targetPixelRcWidth, targetPixelRcHeight,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, colorMap);
GL_REPORT_ERRORD();
UpdateEFBCache(type, cacheRectIdx, efbPixelRc, targetPixelRc, colorMap);
delete[] colorMap;
}
// Sample from the center of the target region.
int srcX = (targetPixelRc.left + targetPixelRc.right) / 2;
int srcY = (targetPixelRc.top + targetPixelRc.bottom) / 2;
// Read back pixel in BGRA format, then byteswap to get GameCube's ARGB Format.
u32 color = 0;
glReadPixels(srcX, srcY, 1, 1, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &color);
GL_REPORT_ERRORD();
u32 xRect = x % EFB_CACHE_RECT_SIZE;
u32 yRect = y % EFB_CACHE_RECT_SIZE;
color = s_efbCache[1][cacheRectIdx][yRect * EFB_CACHE_RECT_SIZE + xRect];
// check what to do with the alpha channel (GX_PokeAlphaRead)
PixelEngine::UPEAlphaReadReg alpha_read_mode;
@ -865,64 +877,35 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
{
ResetAPIState();
GLenum ColorMask = GL_FALSE, AlphaMask = GL_FALSE;
if (colorEnable) ColorMask = GL_TRUE;
if (alphaEnable) AlphaMask = GL_TRUE;
glColorMask(ColorMask, ColorMask, ColorMask, AlphaMask);
// color
GLboolean const
color_mask = colorEnable ? GL_TRUE : GL_FALSE,
alpha_mask = alphaEnable ? GL_TRUE : GL_FALSE;
glColorMask(color_mask, color_mask, color_mask, alpha_mask);
if (zEnable)
{
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_ALWAYS);
}
else
{
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDepthFunc(GL_NEVER);
}
glClearColor(
float((color >> 16) & 0xFF) / 255.0f,
float((color >> 8) & 0xFF) / 255.0f,
float((color >> 0) & 0xFF) / 255.0f,
float((color >> 24) & 0xFF) / 255.0f);
// Update viewport for clearing the picture
TargetRectangle targetRc = ConvertEFBRectangle(rc);
glViewport(targetRc.left, targetRc.bottom, targetRc.GetWidth(), targetRc.GetHeight());
glDepthRange(0.0, (float)(z & 0xFFFFFF) / float(0xFFFFFF));
// depth
glDepthMask(zEnable ? GL_TRUE : GL_FALSE);
GLfloat vtx1[] = {
-1, -1, 1,
-1, 1, 1,
1, 1, 1,
1, -1, 1
};
GLfloat col1[] = { // This looks terrible
(float)((color >> 16) & 0xFF) / 255.0f,
(float)((color >> 8) & 0xFF) / 255.0f,
(float)(color & 0xFF) / 255.0f,
(float)((color >> 24) & 0xFF) / 255.0f,
glClearDepth(float(z & 0xFFFFFF) / float(0xFFFFFF));
(float)((color >> 16) & 0xFF) / 255.0f,
(float)((color >> 8) & 0xFF) / 255.0f,
(float)(color & 0xFF) / 255.0f,
(float)((color >> 24) & 0xFF) / 255.0f,
// Update rect for clearing the picture
glEnable(GL_SCISSOR_TEST);
(float)((color >> 16) & 0xFF) / 255.0f,
(float)((color >> 8) & 0xFF) / 255.0f,
(float)(color & 0xFF) / 255.0f,
(float)((color >> 24) & 0xFF) / 255.0f,
TargetRectangle const targetRc = ConvertEFBRectangle(rc);
glScissor(targetRc.left, targetRc.bottom, targetRc.GetWidth(), targetRc.GetHeight());
(float)((color >> 16) & 0xFF) / 255.0f,
(float)((color >> 8) & 0xFF) / 255.0f,
(float)(color & 0xFF) / 255.0f,
(float)((color >> 24) & 0xFF) / 255.0f
};
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); // Only need this to not overwrite the GL_COLOR_ARRAY state
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_FLOAT, 0 ,col1);
glVertexPointer(3, GL_FLOAT, 0, vtx1);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glPopClientAttrib();
// glColorMask/glDepthMask/glScissor affect glClear (glViewport does not)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
RestoreAPIState();
ClearEFBCache();
}
void Renderer::ReinterpretPixelData(unsigned int convtype)
@ -1009,16 +992,17 @@ void Renderer::SetBlendMode(bool forceUpdate)
// This function has the final picture. We adjust the aspect ratio here.
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma)
{
static u8 *data = NULL;
static int w = 0, h = 0;
if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight)
{
if (g_ActiveConfig.bDumpFrames && data)
#ifdef _WIN32
AVIDump::AddFrame((char *) data);
#elif defined HAVE_LIBAV
AVIDump::AddFrame(data, w, h);
#endif
if (g_ActiveConfig.bDumpFrames && frame_data)
{
#ifdef _WIN32
AVIDump::AddFrame(frame_data);
#elif defined HAVE_LIBAV
AVIDump::AddFrame((u8*)frame_data, w, h);
#endif
}
Core::Callback_VideoCopiedToXFB(false);
return;
}
@ -1031,12 +1015,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
{
if (g_ActiveConfig.bDumpFrames && data)
#ifdef _WIN32
AVIDump::AddFrame((char *) data);
#elif defined HAVE_LIBAV
AVIDump::AddFrame(data, w, h);
#endif
if (g_ActiveConfig.bDumpFrames && frame_data)
{
#ifdef _WIN32
AVIDump::AddFrame(frame_data);
#elif defined HAVE_LIBAV
AVIDump::AddFrame((u8*)frame_data, w, h);
#endif
}
Core::Callback_VideoCopiedToXFB(false);
return;
}
@ -1145,11 +1131,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
1, 1, 1,
1, -1, 1
};
GLfloat top = (GLfloat)targetRc.top;
GLfloat right = (GLfloat)targetRc.right;
GLfloat bottom = (GLfloat)targetRc.bottom;
GLfloat left = (GLfloat)targetRc.left;
GLfloat tex1[] = { // For TEXTURE0
targetRc.left, targetRc.bottom,
targetRc.left, targetRc.top,
targetRc.right, targetRc.top,
targetRc.right, targetRc.bottom
left, bottom,
left, top,
right, top,
right, bottom
};
glClientActiveTexture(GL_TEXTURE0);
@ -1187,26 +1178,26 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if (g_ActiveConfig.bDumpFrames)
{
std::lock_guard<std::mutex> lk(s_criticalScreenshot);
if (!data || w != dst_rect.GetWidth() ||
if (!frame_data || w != dst_rect.GetWidth() ||
h != dst_rect.GetHeight())
{
if (data) delete[] data;
if (frame_data) delete[] frame_data;
w = dst_rect.GetWidth();
h = dst_rect.GetHeight();
data = new u8[3 * w * h];
frame_data = new char[3 * w * h];
}
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data);
glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data);
if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0)
{
if (!s_bLastFrameDumped)
if (!bLastFrameDumped)
{
#ifdef _WIN32
s_bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), w, h);
bAVIDumping = AVIDump::Start(EmuWindow::GetParentWnd(), w, h);
#else
s_bAVIDumping = AVIDump::Start(w, h);
bAVIDumping = AVIDump::Start(w, h);
#endif
if (!s_bAVIDumping)
if (!bAVIDumping)
OSD::AddMessage("AVIDump Start failed", 2000);
else
{
@ -1215,36 +1206,36 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), w, h).c_str(), 2000);
}
}
if (s_bAVIDumping)
if (bAVIDumping)
{
#ifdef _WIN32
AVIDump::AddFrame((char *) data);
AVIDump::AddFrame(frame_data);
#else
FlipImageData(data, w, h);
AVIDump::AddFrame(data, w, h);
FlipImageData((u8*)frame_data, w, h);
AVIDump::AddFrame((u8*)frame_data, w, h);
#endif
}
s_bLastFrameDumped = true;
bLastFrameDumped = true;
}
else
NOTICE_LOG(VIDEO, "Error reading framebuffer");
}
else
{
if (s_bLastFrameDumped && s_bAVIDumping)
if (bLastFrameDumped && bAVIDumping)
{
if (data)
if (frame_data)
{
delete[] data;
data = NULL;
delete[] frame_data;
frame_data = NULL;
w = h = 0;
}
AVIDump::Stop();
s_bAVIDumping = false;
bAVIDumping = false;
OSD::AddMessage("Stop dumping frames", 2000);
}
s_bLastFrameDumped = false;
bLastFrameDumped = false;
}
#else
if (g_ActiveConfig.bDumpFrames)
@ -1253,16 +1244,16 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
std::string movie_file_name;
w = dst_rect.GetWidth();
h = dst_rect.GetHeight();
data = new u8[3 * w * h];
frame_data = new char[3 * w * h];
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data);
glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data);
if (GL_REPORT_ERROR() == GL_NO_ERROR)
{
if (!s_bLastFrameDumped)
if (!bLastFrameDumped)
{
movie_file_name = File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump.raw";
f_pFrameDump.Open(movie_file_name, "wb");
if (!f_pFrameDump)
pFrameDump.Open(movie_file_name, "wb");
if (!pFrameDump)
OSD::AddMessage("Error opening framedump.raw for writing.", 2000);
else
{
@ -1271,22 +1262,22 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
OSD::AddMessage(msg, 2000);
}
}
if (f_pFrameDump)
if (pFrameDump)
{
FlipImageData(data, w, h);
f_pFrameDump.WriteBytes(data, w * 3 * h);
f_pFrameDump.Flush();
FlipImageData((u8*)frame_data, w, h);
pFrameDump.WriteBytes(frame_data, w * 3 * h);
pFrameDump.Flush();
}
s_bLastFrameDumped = true;
bLastFrameDumped = true;
}
delete[] data;
delete[] frame_data;
}
else
{
if (s_bLastFrameDumped)
f_pFrameDump.Close();
s_bLastFrameDumped = false;
if (bLastFrameDumped)
pFrameDump.Close();
bLastFrameDumped = false;
}
#endif
@ -1339,20 +1330,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
}
}
// Place messages on the picture, then copy it to the screen
// ---------------------------------------------------------------------
// Count FPS.
// -------------
static int fpscount = 0;
static unsigned long lasttime = 0;
if (Common::Timer::GetTimeMs() - lasttime >= 1000)
{
lasttime = Common::Timer::GetTimeMs();
s_fps = fpscount;
fpscount = 0;
}
if (XFBWrited)
++fpscount;
s_fps = UpdateFPSCounter();
// ---------------------------------------------------------------------
GL_REPORT_ERRORD();
@ -1406,15 +1385,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
GL_REPORT_ERRORD();
g_Config.iSaveTargetId = 0;
// reload textures if these settings changed
if (g_Config.bSafeTextureCache != g_ActiveConfig.bSafeTextureCache ||
g_Config.bUseNativeMips != g_ActiveConfig.bUseNativeMips)
TextureCache::Invalidate(false);
if (g_Config.bCopyEFBToTexture != g_ActiveConfig.bCopyEFBToTexture)
TextureCache::ClearRenderTargets();
UpdateActiveConfig();
TextureCache::OnConfigChanged(g_ActiveConfig);
// For testing zbuffer targets.
// Renderer::SetZBufferRender();
@ -1422,6 +1394,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
// GetTargetWidth(), GetTargetHeight());
Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB));
XFBWrited = false;
// Invalidate EFB cache
ClearEFBCache();
}
// ALWAYS call RestoreAPIState for each ResetAPIState call you're doing
@ -1437,9 +1412,6 @@ void Renderer::ResetAPIState()
glDisable(GL_BLEND);
glDepthMask(GL_FALSE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
// make sure to disable wireframe when drawing the clear quad
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
void Renderer::RestoreAPIState()
@ -1447,14 +1419,13 @@ void Renderer::RestoreAPIState()
// Gets us back into a more game-like state.
glEnable(GL_SCISSOR_TEST);
SetGenerationMode();
SetScissorRect();
BPFunctions::SetScissor();
SetColorMask();
SetDepthMode();
SetBlendMode(true);
VertexShaderManager::SetViewportChanged();
if (g_ActiveConfig.bWireFrame)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glPolygonMode(GL_FRONT_AND_BACK, g_ActiveConfig.bWireFrame ? GL_LINE : GL_FILL);
VertexShaderCache::SetCurrentShader(0);
PixelShaderCache::SetCurrentShader(0);

View file

@ -7,6 +7,8 @@
namespace OGL
{
void ClearEFBCache();
class Renderer : public ::Renderer
{
public:
@ -15,7 +17,7 @@ public:
void SetColorMask();
void SetBlendMode(bool forceUpdate);
bool SetScissorRect();
void SetScissorRect(const TargetRectangle& rc);
void SetGenerationMode();
void SetDepthMode();
void SetLogicOpMode();
@ -57,6 +59,9 @@ public:
void SetVSConstant4fv(unsigned int const_number, const float *f);
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f);
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
private:
void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const u32* data);
};
}

View file

@ -39,6 +39,7 @@
#include "Globals.h"
#include "Hash.h"
#include "HiresTextures.h"
#include "HW/Memmap.h"
#include "ImageWrite.h"
#include "MemoryUtil.h"
#include "PixelShaderCache.h"
@ -75,11 +76,13 @@ static const GLint c_WrapSettings[4] = {
GL_REPEAT,
};
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height)
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level)
{
int width = std::max(virtual_width >> level, 1);
int height = std::max(virtual_height >> level, 1);
std::vector<u32> data(width * height);
glBindTexture(textarget, tex);
glGetTexImage(textarget, 0, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]);
glGetTexImage(textarget, level, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]);
const GLenum err = GL_REPORT_ERROR();
if (GL_NO_ERROR != err)
@ -118,13 +121,13 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage)
SetTextureParameters(tm0, tm1);
}
bool TextureCache::TCacheEntry::Save(const char filename[])
bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
{
// TODO: make ogl dump PNGs
std::string tga_filename(filename);
tga_filename.replace(tga_filename.size() - 3, 3, "tga");
return SaveTexture(tga_filename.c_str(), GL_TEXTURE_2D, texture, realW, realH);
return SaveTexture(tga_filename.c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, level);
}
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
@ -278,7 +281,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
GL_REPORT_ERRORD();
if (false == isDynamic || g_ActiveConfig.bCopyEFBToTexture)
if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture)
{
if (s_TempFramebuffer == 0)
glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
@ -294,7 +297,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
glEnable(GL_TEXTURE_RECTANGLE_ARB);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
glViewport(0, 0, virtualW, virtualH);
glViewport(0, 0, virtual_width, virtual_height);
PixelShaderCache::SetCurrentShader((srcFormat == PIXELFMT_Z24) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram());
PixelShaderManager::SetColorMatrix(colmat); // set transformation
@ -329,7 +332,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
if (false == g_ActiveConfig.bCopyEFBToTexture)
{
hash = TextureConverter::EncodeToRamFromTexture(
int encoded_size = TextureConverter::EncodeToRamFromTexture(
addr,
read_texture,
srcFormat == PIXELFMT_Z24,
@ -337,6 +340,17 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
dstFormat,
scaleByHalf,
srcRect);
u8* dst = Memory::GetPointer(addr);
u64 hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples);
// Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date
if (!g_ActiveConfig.bEFBCopyCacheEnable)
TextureCache::MakeRangeDynamic(addr,encoded_size);
else if (!TextureCache::Find(addr, hash))
TextureCache::MakeRangeDynamic(addr,encoded_size);
this->hash = hash;
}
FramebufferManager::SetFramebuffer(0);
@ -349,7 +363,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
{
static int count = 0;
SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
count++).c_str(), GL_TEXTURE_2D, texture, realW, realH);
count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0);
}
}

View file

@ -62,7 +62,7 @@ private:
const float *colmat);
void Bind(unsigned int stage);
bool Save(const char filename[]);
bool Save(const char filename[], unsigned int level);
private:
void SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1);
@ -76,7 +76,7 @@ private:
TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h);
};
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height);
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level);
}

View file

@ -261,78 +261,7 @@ void EncodeToRamUsingShader(FRAGMENTSHADER& shader, GLuint srcTexture, const Tar
}
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
{
u32 format = copyfmt;
if (bFromZBuffer)
{
format |= _GX_TF_ZTF;
if (copyfmt == 11)
format = GX_TF_Z16;
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
format |= _GX_TF_CTF;
}
else
if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt))
format |= _GX_TF_CTF;
FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format);
if (texconv_shader.glprogid == 0)
return;
u8 *dest_ptr = Memory::GetPointer(address);
GLuint source_texture = bFromZBuffer ? FramebufferManager::ResolveAndGetDepthTarget(source) : FramebufferManager::ResolveAndGetRenderTarget(source);
int width = (source.right - source.left) >> bScaleByHalf;
int height = (source.bottom - source.top) >> bScaleByHalf;
int size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, format);
// Invalidate any existing texture covering this memory range.
// TODO - don't delete the texture if it already exists, just replace the contents.
TextureCache::InvalidateRange(address, size_in_bytes);
u16 blkW = TexDecoder_GetBlockWidthInTexels(format) - 1;
u16 blkH = TexDecoder_GetBlockHeightInTexels(format) - 1;
u16 samples = TextureConversionShader::GetEncodedSampleCount(format);
// only copy on cache line boundaries
// extra pixels are copied but not displayed in the resulting texture
s32 expandedWidth = (width + blkW) & (~blkW);
s32 expandedHeight = (height + blkH) & (~blkH);
float sampleStride = bScaleByHalf ? 2.f : 1.f;
TextureConversionShader::SetShaderParameters(
(float)expandedWidth,
(float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this?
(float)Renderer::EFBToScaledX(source.left),
(float)Renderer::EFBToScaledY(EFB_HEIGHT - source.top - expandedHeight),
Renderer::EFBToScaledXf(sampleStride),
Renderer::EFBToScaledYf(sampleStride));
TargetRectangle scaledSource;
scaledSource.top = 0;
scaledSource.bottom = expandedHeight;
scaledSource.left = 0;
scaledSource.right = expandedWidth / samples;
int cacheBytes = 32;
if ((format & 0x0f) == 6)
cacheBytes = 64;
int readStride = (expandedWidth * cacheBytes) / TexDecoder_GetBlockWidthInTexels(format);
g_renderer->ResetAPIState();
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0);
FramebufferManager::SetFramebuffer(0);
VertexShaderManager::SetViewportChanged();
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
TextureCache::DisableStage(0);
g_renderer->RestoreAPIState();
GL_REPORT_ERRORD();
}
u64 EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source)
{
u32 format = copyfmt;
@ -390,19 +319,8 @@ u64 EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer,
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource,
dest_ptr, expandedWidth / samples, expandedHeight, readStride,
true, bScaleByHalf > 0 && !bFromZBuffer);
return size_in_bytes; // TODO: D3D11 is calculating this value differently!
u64 hash = GetHash64(dest_ptr, size_in_bytes,
g_ActiveConfig.iSafeTextureCache_ColorSamples);
if (g_ActiveConfig.bEFBCopyCacheEnable)
{
// If the texture in RAM is already in the texture cache,
// do not copy it again as it has not changed.
if (TextureCache::Find(address, hash))
return hash;
}
TextureCache::MakeRangeDynamic(address,size_in_bytes);
return hash;
}
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* destAddr, int dstWidth, int dstHeight)

View file

@ -32,15 +32,13 @@ namespace TextureConverter
void Init();
void Shutdown();
void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt,
u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
u8* destAddr, int dstWidth, int dstHeight);
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
u64 EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
// returns size of the encoded data (in bytes)
int EncodeToRamFromTexture(u32 address, GLuint source_texture, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source);
}

View file

@ -69,6 +69,16 @@ VertexManager::VertexManager()
GL_REPORT_ERRORD();
}
void VertexManager::CreateDeviceObjects()
{
}
void VertexManager::DestroyDeviceObjects()
{
}
void VertexManager::Draw()
{
if (IndexGenerator::GetNumTriangles() > 0)
@ -154,22 +164,14 @@ void VertexManager::vFlush()
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
tex.texTlut[i&3].tlut_format,
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8) && g_ActiveConfig.bUseNativeMips,
(tex.texMode1[i&3].max_lod >> 4));
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
tex.texMode1[i&3].max_lod >> 4,
tex.texImage1[i&3].image_type);
if (tentry)
{
// 0s are probably for no manual wrapping needed.
PixelShaderManager::SetTexDims(i, tentry->realW, tentry->realH, 0, 0);
if (g_ActiveConfig.iLog & CONF_SAVETEXTURES)
{
// save the textures
char strfile[255];
sprintf(strfile, "%stex%.3d_%d.tga",
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_Config.iSaveTargetId, i);
tentry->Save(strfile);
}
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0);
}
else
ERROR_LOG(VIDEO, "error loading texture");
@ -268,6 +270,8 @@ void VertexManager::vFlush()
#endif
g_Config.iSaveTargetId++;
ClearEFBCache();
GL_REPORT_ERRORD();
}

View file

@ -33,7 +33,8 @@ public:
VertexManager();
NativeVertexFormat* CreateNativeVertexFormat();
void CreateDeviceObjects();
void DestroyDeviceObjects();
private:
void Draw();
// temp

View file

@ -41,7 +41,9 @@ VertexShaderCache::VSCache VertexShaderCache::vshaders;
GLuint VertexShaderCache::CurrentShader;
bool VertexShaderCache::ShaderEnabled;
static VERTEXSHADER *pShaderLast = NULL;
VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry = NULL;
VERTEXSHADERUID VertexShaderCache::last_uid;
static int s_nMaxVertexInstructions;
@ -50,7 +52,7 @@ void VertexShaderCache::Init()
glEnable(GL_VERTEX_PROGRAM_ARB);
ShaderEnabled = true;
CurrentShader = 0;
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
last_entry = NULL;
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions);
if (strstr((const char*)glGetString(GL_VENDOR), "Humper") != NULL) s_nMaxVertexInstructions = 4096;
@ -74,31 +76,34 @@ VERTEXSHADER* VertexShaderCache::SetShader(u32 components)
{
VERTEXSHADERUID uid;
GetVertexShaderId(&uid, components);
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
if (last_entry)
{
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
return pShaderLast;
if (uid == last_uid)
{
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
ValidateVertexShaderIDs(API_OPENGL, vshaders[uid].safe_uid, vshaders[uid].shader.strprog, components);
return &last_entry->shader;
}
}
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
last_uid = uid;
VSCache::iterator iter = vshaders.find(uid);
if (iter != vshaders.end())
{
iter->second.frameCount = frameCount;
VSCacheEntry &entry = iter->second;
if (&entry.shader != pShaderLast) {
pShaderLast = &entry.shader;
}
last_entry = &entry;
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
return pShaderLast;
ValidateVertexShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, components);
return &last_entry->shader;
}
// Make an entry in the table
VSCacheEntry& entry = vshaders[uid];
entry.frameCount = frameCount;
pShaderLast = &entry.shader;
last_entry = &entry;
const char *code = GenerateVertexShaderCode(components, API_OPENGL);
GetSafeVertexShaderId(&entry.safe_uid, components);
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
@ -118,7 +123,7 @@ VERTEXSHADER* VertexShaderCache::SetShader(u32 components)
INCSTAT(stats.numVertexShadersCreated);
SETSTAT(stats.numVertexShadersAlive, vshaders.size());
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
return pShaderLast;
return &last_entry->shader;
}
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
@ -182,9 +187,8 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr
cgDestroyProgram(tempprog);
#endif
#if defined(_DEBUG) || defined(DEBUGFAST)
vs.strprog = pstrprogram;
#endif
if (g_ActiveConfig.bEnableShaderDebugging)
vs.strprog = pstrprogram;
return true;
}

View file

@ -32,9 +32,7 @@ struct VERTEXSHADER
VERTEXSHADER() : glprogid(0) {}
GLuint glprogid; // opengl program id
#if defined(_DEBUG) || defined(DEBUGFAST)
std::string strprog;
#endif
};
class VertexShaderCache
@ -42,8 +40,8 @@ class VertexShaderCache
struct VSCacheEntry
{
VERTEXSHADER shader;
int frameCount;
VSCacheEntry() : frameCount(0) {}
VERTEXSHADERUIDSAFE safe_uid;
VSCacheEntry() {}
void Destroy() {
// printf("Destroying vs %i\n", shader.glprogid);
glDeleteProgramsARB(1, &shader.glprogid);
@ -55,6 +53,9 @@ class VertexShaderCache
static VSCache vshaders;
static VSCacheEntry* last_entry;
static VERTEXSHADERUID last_uid;
static GLuint CurrentShader;
static bool ShaderEnabled;

View file

@ -155,6 +155,7 @@ void VideoBackend::ShowConfig(void *_hParent)
bool VideoBackend::Initialize(void *&window_handle)
{
InitializeShared();
InitBackendInfo();
frameCount = 0;
@ -234,6 +235,7 @@ void VideoBackend::Shutdown()
OpcodeDecoder_Shutdown();
delete g_renderer;
g_renderer = NULL;
g_texture_cache = NULL;
}
OpenGL_Shutdown();
}

View file

@ -46,13 +46,12 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
<ConfigurationType>StaticLibrary</ConfigurationType>
@ -116,7 +115,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -127,7 +126,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -138,7 +137,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -151,7 +150,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -164,12 +163,12 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\Core\Common\Src;..\..\Core\Core\Src;..\..\Core\VideoCommon\Src;..\..\Core\DolphinWX\Src;..\..\..\Externals\GLew\include;..\..\..\Externals\wxWidgets3;..\..\..\Externals\wxWidgets3\Include;..\..\..\Externals;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
@ -234,22 +233,12 @@
<ClInclude Include="Src\XFMemLoader.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Externals\wxWidgets\build\msw\wx_adv.vcxproj">
<Project>{0e231fb1-f3c9-4724-accb-de8bcb3c089e}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\Externals\wxWidgets\build\msw\wx_base.vcxproj">
<Project>{1c8436c9-dbaf-42be-83bc-cf3ec9175abe}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\Externals\wxWidgets\build\msw\wx_core.vcxproj">
<Project>{11f55366-12ec-4c44-a8cb-1d4e315d61ed}</Project>
</ProjectReference>
<ProjectReference Include="..\..\Core\VideoCommon\VideoCommon.vcxproj">
<Project>{3e5c4e02-1ba9-4776-bdbe-e3f91ffa34cf}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
<None Include="Src\SConscript" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View file

@ -56,7 +56,6 @@
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
<None Include="Src\SConscript" />
</ItemGroup>
<ItemGroup>
<Filter Include="Win32">

View file

@ -1,35 +0,0 @@
# -*- python -*-
Import('env')
import os
import sys
files = [
'Src/BPMemLoader.cpp',
'Src/CPMemLoader.cpp',
'Src/Clipper.cpp',
'Src/DebugUtil.cpp',
'Src/EfbCopy.cpp',
'Src/EfbInterface.cpp',
'Src/HwRasterizer.cpp',
'Src/OpcodeDecoder.cpp',
'Src/Rasterizer.cpp',
'Src/SWCommandProcessor.cpp',
'Src/SWPixelEngine.cpp',
'Src/SWRenderer.cpp',
'Src/SWStatistics.cpp',
'Src/SWVertexLoader.cpp',
'Src/SWVideoConfig.cpp',
'Src/SWmain.cpp',
'Src/SetupUnit.cpp',
'Src/Tev.cpp',
'Src/TextureEncoder.cpp',
'Src/TextureSampler.cpp',
'Src/TransformUnit.cpp',
'Src/XFMemLoader.cpp',
]
if not env['nowx']:
files += ['Src/VideoConfigDialog.cpp']
env['LIBS'] += env.StaticLibrary('videosoftware', files)

View file

@ -101,14 +101,14 @@ void SWBPWritten(int address, int newvalue)
// TODO - figure out a cleaner way.
if (Core::g_CoreStartupParameter.bWii)
ptr = Memory::GetPointer(bpmem.tlutXferSrc << 5);
ptr = Memory::GetPointer(bpmem.tmem_config.tlut_src << 5);
else
ptr = Memory::GetPointer((bpmem.tlutXferSrc & 0xFFFFF) << 5);
ptr = Memory::GetPointer((bpmem.tmem_config.tlut_src & 0xFFFFF) << 5);
if (ptr)
memcpy_gc(texMem + tlutTMemAddr, ptr, tlutXferCount);
else
PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tlutXferSrc, bpmem.tlutXferSrc << 5, (bpmem.tlutXferSrc & 0xFFFFF)<< 5);
PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tmem_config.tlut_src, bpmem.tmem_config.tlut_src << 5, (bpmem.tmem_config.tlut_src & 0xFFFFF)<< 5);
break;
}

View file

@ -64,7 +64,12 @@ RasterBlock rasterBlock;
void Init()
{
tev.Init();
tev.Init();
// Set initial z reference plane in the unlikely case that zfreeze is enabled when drawing the first primitive.
// TODO: This is just a guess!
ZSlope.dfdx = ZSlope.dfdy = 0.f;
ZSlope.f0 = 1.f;
}
inline int iround(float x)
@ -364,7 +369,8 @@ void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVer
float w[3] = { 1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w, 1.0f / v2->projectedPosition.w };
InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31);
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
if (!bpmem.genMode.zfreeze)
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
for(unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
{

View file

@ -45,6 +45,7 @@ namespace SW
static volatile bool fifoStateRun = false;
static volatile bool emuRunningState = false;
static std::mutex m_csSWVidOccupied;
std::string VideoSoftware::GetName()
@ -91,6 +92,24 @@ bool VideoSoftware::Initialize(void *&window_handle)
void VideoSoftware::DoState(PointerWrap&)
{
// NYI
}
void VideoSoftware::PauseAndLock(bool doLock, bool unpauseOnUnlock)
{
if (doLock)
{
EmuStateChange(EMUSTATE_CHANGE_PAUSE);
if (!Core::IsGPUThread())
m_csSWVidOccupied.lock();
}
else
{
if (unpauseOnUnlock)
EmuStateChange(EMUSTATE_CHANGE_PLAY);
if (!Core::IsGPUThread())
m_csSWVidOccupied.unlock();
}
}
void VideoSoftware::RunLoop(bool enable)
@ -167,6 +186,7 @@ bool VideoSoftware::Video_Screenshot(const char *_szFilename)
// -------------------------------
void VideoSoftware::Video_EnterLoop()
{
std::lock_guard<std::mutex> lk(m_csSWVidOccupied);
fifoStateRun = true;
while (fifoStateRun)
@ -181,7 +201,9 @@ void VideoSoftware::Video_EnterLoop()
while (!emuRunningState && fifoStateRun)
{
g_video_backend->PeekMessages();
m_csSWVidOccupied.unlock();
Common::SleepCurrentThread(1);
m_csSWVidOccupied.lock();
}
}
}
@ -215,6 +237,12 @@ bool VideoSoftware::Video_IsPossibleWaitingSetDrawDone(void)
return false;
}
bool VideoSoftware::Video_IsHiWatermarkActive(void)
{
return false;
}
void VideoSoftware::Video_AbortFrame(void)
{
}

View file

@ -16,7 +16,6 @@ class VideoSoftware : public VideoBackend
void EmuStateChange(EMUSTATE_CHANGE newState);
void DoState(PointerWrap &p);
void RunLoop(bool enable);
void ShowConfig(void* parent);
@ -36,7 +35,7 @@ class VideoSoftware : public VideoBackend
void Video_SetRendering(bool bEnabled);
void Video_GatherPipeBursted();
bool Video_IsHiWatermarkActive();
bool Video_IsPossibleWaitingSetDrawDone();
void Video_AbortFrame();
@ -48,6 +47,9 @@ class VideoSoftware : public VideoBackend
void UpdateFPSDisplay(const char*);
unsigned int PeekMessages();
void PauseAndLock(bool doLock, bool unpauseOnUnlock=true);
void DoState(PointerWrap &p);
};
}