D3D11: Implement zcomploc for hardware supporting D3D 11.0.

This commit is contained in:
NeoBrainX 2013-07-22 14:38:09 +02:00 committed by degasus
parent 805009abca
commit eed36cbf78
6 changed files with 47 additions and 12 deletions

View File

@ -805,6 +805,7 @@ union PE_CONTROL
u32 unused : 17; u32 unused : 17;
u32 rid : 8; u32 rid : 8;
}; };
u32 hex; u32 hex;
}; };
@ -1005,6 +1006,9 @@ struct BPMemory
TevKSel tevksel[8];//0xf6,0xf7,f8,f9,fa,fb,fc,fd TevKSel tevksel[8];//0xf6,0xf7,f8,f9,fa,fb,fc,fd
u32 bpMask; //0xFE u32 bpMask; //0xFE
u32 unknown18; //ff u32 unknown18; //ff
bool UseEarlyDepthTest() const { return zcontrol.early_ztest && zmode.testenable; }
bool UseLateDepthTest() const { return !zcontrol.early_ztest && zmode.testenable; }
}; };
#pragma pack() #pragma pack()

View File

@ -258,8 +258,8 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api
unsigned int numStages = bpmem.genMode.numtevstages + 1; unsigned int numStages = bpmem.genMode.numtevstages + 1;
unsigned int numTexgen = bpmem.genMode.numtexgens; unsigned int numTexgen = bpmem.genMode.numtexgens;
const bool forced_early_z = g_ActiveConfig.backend_info.bSupportsEarlyZ && bpmem.zcontrol.early_ztest && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED); const bool forced_early_z = g_ActiveConfig.backend_info.bSupportsEarlyZ && bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED);
const bool per_pixel_depth = (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.early_ztest && bpmem.zmode.testenable) || (!g_ActiveConfig.bFastDepthCalc && !forced_early_z); const bool per_pixel_depth = (bpmem.ztex2.op != ZTEXTURE_DISABLE && bpmem.UseLateDepthTest()) || (!g_ActiveConfig.bFastDepthCalc && !forced_early_z);
out.Write("//Pixel Shader for TEV stages\n"); out.Write("//Pixel Shader for TEV stages\n");
out.Write("//%i TEV stages, %i texgens, %i IND stages\n", out.Write("//%i TEV stages, %i texgens, %i IND stages\n",
@ -372,11 +372,30 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api
// It just allows it, but it seems that all drivers do. // It just allows it, but it seems that all drivers do.
out.Write("layout(early_fragment_tests) in;\n"); out.Write("layout(early_fragment_tests) in;\n");
} }
else if (bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED))
{
static bool warn_once = true;
if (warn_once)
WARN_LOG(VIDEO, "Early z test enabled but not possible to emulate with current configuration. Make sure to use the D3D11 or OpenGL backend and enable fast depth calculations. If this message still shows up your hardware isn't able to emulate the feature properly (a GPU which supports D3D 11.0 / OGL 4.2 is required).");
warn_once = false;
}
out.Write("void main()\n{\n"); out.Write("void main()\n{\n");
} }
else else
{ {
if (forced_early_z)
{
out.Write("[earlydepthstencil]\n");
}
else if (bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED))
{
static bool warn_once = true;
if (warn_once)
WARN_LOG(VIDEO, "Early z test enabled but not possible to emulate with current configuration. Make sure to use the D3D11 or OpenGL backend and enable fast depth calculations. If this message still shows up your hardware isn't able to emulate the feature properly (a GPU which supports D3D 11.0 / OGL 4.2 is required).");
warn_once = false;
}
out.Write("void main(\n"); out.Write("void main(\n");
if(ApiType != API_D3D11) if(ApiType != API_D3D11)
{ {
@ -630,11 +649,11 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api
uid_data.per_pixel_depth = per_pixel_depth; uid_data.per_pixel_depth = per_pixel_depth;
uid_data.forced_early_z = forced_early_z; uid_data.forced_early_z = forced_early_z;
uid_data.fast_depth_calc = g_ActiveConfig.bFastDepthCalc; uid_data.fast_depth_calc = g_ActiveConfig.bFastDepthCalc;
uid_data.early_ztest = bpmem.zcontrol.early_ztest; uid_data.early_ztest = bpmem.UseEarlyDepthTest();
uid_data.fog_fsel = bpmem.fog.c_proj_fsel.fsel; uid_data.fog_fsel = bpmem.fog.c_proj_fsel.fsel;
// Note: z-textures are not written to depth buffer if early depth test is used // Note: z-textures are not written to depth buffer if early depth test is used
if (per_pixel_depth && bpmem.zcontrol.early_ztest) if (per_pixel_depth && bpmem.UseEarlyDepthTest())
out.Write("depth = zCoord;\n"); out.Write("depth = zCoord;\n");
// Note: depth texture output is only written to depth buffer if late depth test is used // Note: depth texture output is only written to depth buffer if late depth test is used
@ -652,7 +671,7 @@ static void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE Api
out.Write("zCoord = zCoord * (16777216.0f/16777215.0f);\n"); out.Write("zCoord = zCoord * (16777216.0f/16777215.0f);\n");
} }
if (per_pixel_depth && !bpmem.zcontrol.early_ztest) if (per_pixel_depth && bpmem.UseLateDepthTest())
out.Write("depth = zCoord;\n"); out.Write("depth = zCoord;\n");
if (dstAlphaMode == DSTALPHA_ALPHA_PASS) if (dstAlphaMode == DSTALPHA_ALPHA_PASS)
@ -1189,7 +1208,7 @@ static void WriteAlphaTest(T& out, pixel_shader_uid_data& uid_data, API_TYPE Api
// OpenGL 4.2 has a flag which allows the driver to still update the depth buffer // OpenGL 4.2 has a flag which allows the driver to still update the depth buffer
// if alpha test fails. The driver doesn't have to, but I assume they all do because // if alpha test fails. The driver doesn't have to, but I assume they all do because
// it's the much faster code path for the GPU. // it's the much faster code path for the GPU.
uid_data.alpha_test_use_zcomploc_hack = bpmem.zcontrol.early_ztest && bpmem.zmode.updateenable && !g_ActiveConfig.backend_info.bSupportsEarlyZ; uid_data.alpha_test_use_zcomploc_hack = bpmem.UseEarlyDepthTest() && bpmem.zmode.updateenable && !g_ActiveConfig.backend_info.bSupportsEarlyZ;
if (!uid_data.alpha_test_use_zcomploc_hack) if (!uid_data.alpha_test_use_zcomploc_hack)
{ {
out.Write("\t\tdiscard;\n"); out.Write("\t\tdiscard;\n");

View File

@ -245,6 +245,13 @@ std::vector<DXGI_SAMPLE_DESC> EnumAAModes(IDXGIAdapter* adapter)
return aa_modes; return aa_modes;
} }
D3D_FEATURE_LEVEL GetFeatureLevel(IDXGIAdapter* adapter)
{
D3D_FEATURE_LEVEL feat_level = D3D_FEATURE_LEVEL_9_1;
PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, D3D11_CREATE_DEVICE_SINGLETHREADED, supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, NULL, &feat_level, NULL);
return feat_level;
}
DXGI_SAMPLE_DESC GetAAMode(int index) DXGI_SAMPLE_DESC GetAAMode(int index)
{ {
return aa_modes[index]; return aa_modes[index];

View File

@ -31,6 +31,7 @@ void UnloadD3D();
void UnloadD3DX(); void UnloadD3DX();
void UnloadD3DCompiler(); void UnloadD3DCompiler();
D3D_FEATURE_LEVEL GetFeatureLevel(IDXGIAdapter* adapter);
std::vector<DXGI_SAMPLE_DESC> EnumAAModes(IDXGIAdapter* adapter); std::vector<DXGI_SAMPLE_DESC> EnumAAModes(IDXGIAdapter* adapter);
DXGI_SAMPLE_DESC GetAAMode(int index); DXGI_SAMPLE_DESC GetAAMode(int index);

View File

@ -90,7 +90,6 @@ void InitBackendInfo()
g_Config.backend_info.bSupportsFormatReinterpretation = true; g_Config.backend_info.bSupportsFormatReinterpretation = true;
g_Config.backend_info.bSupportsPixelLighting = true; g_Config.backend_info.bSupportsPixelLighting = true;
g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsPrimitiveRestart = true;
g_Config.backend_info.bSupportsEarlyZ = false;
IDXGIFactory* factory; IDXGIFactory* factory;
IDXGIAdapter* ad; IDXGIAdapter* ad;
@ -103,11 +102,13 @@ void InitBackendInfo()
g_Config.backend_info.AAModes.clear(); g_Config.backend_info.AAModes.clear();
while (factory->EnumAdapters((UINT)g_Config.backend_info.Adapters.size(), &ad) != DXGI_ERROR_NOT_FOUND) while (factory->EnumAdapters((UINT)g_Config.backend_info.Adapters.size(), &ad) != DXGI_ERROR_NOT_FOUND)
{ {
const size_t adapter_index = g_Config.backend_info.Adapters.size();
DXGI_ADAPTER_DESC desc; DXGI_ADAPTER_DESC desc;
ad->GetDesc(&desc); ad->GetDesc(&desc);
// TODO: These don't get updated on adapter change, yet // TODO: These don't get updated on adapter change, yet
if (g_Config.backend_info.Adapters.size() == g_Config.iAdapter) if (adapter_index == g_Config.iAdapter)
{ {
char buf[32]; char buf[32];
std::vector<DXGI_SAMPLE_DESC> modes; std::vector<DXGI_SAMPLE_DESC> modes;
@ -119,6 +120,9 @@ void InitBackendInfo()
else sprintf_s(buf, 32, _trans("%d samples"), modes[i].Count); else sprintf_s(buf, 32, _trans("%d samples"), modes[i].Count);
g_Config.backend_info.AAModes.push_back(buf); g_Config.backend_info.AAModes.push_back(buf);
} }
// Requires the earlydepthstencil attribute (only available in shader model 5)
g_Config.backend_info.bSupportsEarlyZ = (DX11::D3D::GetFeatureLevel(ad) == D3D_FEATURE_LEVEL_11_0);
} }
g_Config.backend_info.Adapters.push_back(UTF16ToUTF8(desc.Description)); g_Config.backend_info.Adapters.push_back(UTF16ToUTF8(desc.Description));

View File

@ -135,7 +135,7 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
if (z < 0 || z > 0x00ffffff) if (z < 0 || z > 0x00ffffff)
return; return;
if (bpmem.zcontrol.early_ztest && bpmem.zmode.testenable && g_SWVideoConfig.bZComploc) if (bpmem.UseEarlyDepthTest() && g_SWVideoConfig.bZComploc)
{ {
// TODO: Test if perf regs are incremented even if test is disabled // TODO: Test if perf regs are incremented even if test is disabled
SWPixelEngine::pereg.IncZInputQuadCount(true); SWPixelEngine::pereg.IncZInputQuadCount(true);