diff options
| author | Tony Wasserka <neobrainx@gmail.com> | 2015-01-24 13:29:57 +0100 |
|---|---|---|
| committer | Tony Wasserka <neobrainx@gmail.com> | 2015-01-24 13:29:57 +0100 |
| commit | 43036af944e706ac38821561c2f3333a500e63f6 (patch) | |
| tree | 6c5b23ed4707d9af477143774dd86f9f9b9fe7be /Source/Core/VideoCommon/VertexManagerBase.cpp | |
| parent | 4e9497cdb85ecbd088ca06fb501496aa0c8240a7 (diff) | |
| parent | 14baf038e70a598a6af1ce71719bb557425941f9 (diff) | |
Merge pull request #1812 from phire/real_zfreeze
Add proper zfreeze support.
Diffstat (limited to 'Source/Core/VideoCommon/VertexManagerBase.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/VertexManagerBase.cpp | 150 |
1 files changed, 119 insertions, 31 deletions
diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index 38cfd19630..0c5ccdd10d 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -12,6 +12,7 @@ #include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/TextureCacheBase.h" +#include "VideoCommon/VertexLoaderManager.h" #include "VideoCommon/VertexManagerBase.h" #include "VideoCommon/VertexShaderManager.h" #include "VideoCommon/VideoConfig.h" @@ -25,7 +26,10 @@ u8 *VertexManager::s_pEndBufferPointer; PrimitiveType VertexManager::current_primitive_type; +Slope VertexManager::ZSlope; + bool VertexManager::IsFlushed; +bool VertexManager::CullAll; static const PrimitiveType primitive_from_gx[8] = { PRIMITIVE_TRIANGLES, // GX_DRAW_QUADS @@ -41,6 +45,7 @@ static const PrimitiveType primitive_from_gx[8] = { VertexManager::VertexManager() { IsFlushed = true; + CullAll = false; } VertexManager::~VertexManager() @@ -52,7 +57,7 @@ u32 VertexManager::GetRemainingSize() return (u32)(s_pEndBufferPointer - s_pCurBufferPointer); } -DataReader VertexManager::PrepareForAdditionalData(int primitive, u32 count, u32 stride) +DataReader VertexManager::PrepareForAdditionalData(int primitive, u32 count, u32 stride, bool cullall) { // The SSE vertex loader can write up to 4 bytes past the end u32 const needed_vertex_bytes = count * stride + 4; @@ -78,6 +83,8 @@ DataReader VertexManager::PrepareForAdditionalData(int primitive, u32 count, u32 "Increase MAXVBUFFERSIZE or we need primitive breaking after all."); } + CullAll = cullall; + // need to alloc new buffer if (IsFlushed) { @@ -189,45 +196,66 @@ void VertexManager::Flush() (int)bpmem.genMode.numtexgens, (u32)bpmem.dstalpha.enable, (bpmem.alpha_test.hex>>16)&0xff); #endif - BitSet32 usedtextures; - for (u32 i = 0; i < bpmem.genMode.numtevstages + 1u; ++i) - if (bpmem.tevorders[i / 2].getEnable(i & 1)) - usedtextures[bpmem.tevorders[i/2].getTexMap(i & 1)] = true; - - if (bpmem.genMode.numindstages > 0) - for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1u; ++i) - if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) - usedtextures[bpmem.tevindref.getTexMap(bpmem.tevind[i].bt)] = true; - - for (unsigned int i : usedtextures) + // If the primitave is marked CullAll. All we need to do is update the vertex constants and calculate the zfreeze refrence slope + if (!CullAll) { - g_renderer->SetSamplerState(i & 3, i >> 2); - const TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i); + BitSet32 usedtextures; + for (u32 i = 0; i < bpmem.genMode.numtevstages + 1u; ++i) + if (bpmem.tevorders[i / 2].getEnable(i & 1)) + usedtextures[bpmem.tevorders[i/2].getTexMap(i & 1)] = true; - if (tentry) + if (bpmem.genMode.numindstages > 0) + for (unsigned int i = 0; i < bpmem.genMode.numtevstages + 1u; ++i) + if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) + usedtextures[bpmem.tevindref.getTexMap(bpmem.tevind[i].bt)] = true; + + for (unsigned int i : usedtextures) { - // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); + g_renderer->SetSamplerState(i & 3, i >> 2); + const TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i); + + if (tentry) + { + // 0s are probably for no manual wrapping needed. + PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height, 0, 0); + } + else + ERROR_LOG(VIDEO, "error loading texture"); } - else - ERROR_LOG(VIDEO, "error loading texture"); } - // set global constants + // set global vertex constants VertexShaderManager::SetConstants(); - GeometryShaderManager::SetConstants(); - PixelShaderManager::SetConstants(); - bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && - bpmem.dstalpha.enable && - bpmem.blendmode.alphaupdate && - bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24; + // Calculate ZSlope for zfreeze + if (!bpmem.genMode.zfreeze) + { + // Must be done after VertexShaderManager::SetConstants() + CalculateZSlope(VertexLoaderManager::GetCurrentVertexFormat()); + } + else if (ZSlope.dirty && !CullAll) // or apply any dirty ZSlopes + { + PixelShaderManager::SetZSlope(ZSlope.dfdx, ZSlope.dfdy, ZSlope.f0); + ZSlope.dirty = false; + } - if (PerfQueryBase::ShouldEmulate()) - g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); - g_vertex_manager->vFlush(useDstAlpha); - if (PerfQueryBase::ShouldEmulate()) - g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); + if (!CullAll) + { + // set the rest of the global constants + GeometryShaderManager::SetConstants(); + PixelShaderManager::SetConstants(); + + bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && + bpmem.dstalpha.enable && + bpmem.blendmode.alphaupdate && + bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24; + + if (PerfQueryBase::ShouldEmulate()) + g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); + g_vertex_manager->vFlush(useDstAlpha); + if (PerfQueryBase::ShouldEmulate()) + g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); + } GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true); @@ -235,9 +263,69 @@ void VertexManager::Flush() ERROR_LOG(VIDEO, "xf.numtexgens (%d) does not match bp.numtexgens (%d). Error in command stream.", xfmem.numTexGen.numTexGens, bpmem.genMode.numtexgens.Value()); IsFlushed = true; + CullAll = false; } void VertexManager::DoState(PointerWrap& p) { + p.Do(ZSlope); g_vertex_manager->vDoState(p); } + +void VertexManager::CalculateZSlope(NativeVertexFormat *format) +{ + float vtx[9]; + float out[12]; + float viewOffset[2] = { xfmem.viewport.xOrig - bpmem.scissorOffset.x * 2, + xfmem.viewport.yOrig - bpmem.scissorOffset.y * 2}; + + // Global matrix ID. + u32 mtxIdx = g_main_cp_state.matrix_index_a.PosNormalMtxIdx; + const PortableVertexDeclaration vert_decl = format->GetVertexDeclaration(); + size_t posOff = vert_decl.position.offset; + size_t mtxOff = vert_decl.posmtx.offset; + + // Lookup vertices of the last rendered triangle and software-transform them + // This allows us to determine the depth slope, which will be used if z--freeze + // is enabled in the following flush. + for (unsigned int i = 0; i < 3; ++i) + { + u8* vtx_ptr = s_pCurBufferPointer - vert_decl.stride * (3 - i); + vtx[0 + i * 3] = ((float*)(vtx_ptr + posOff))[0]; + vtx[1 + i * 3] = ((float*)(vtx_ptr + posOff))[1]; + vtx[2 + i * 3] = ((float*)(vtx_ptr + posOff))[2]; + + // If this vertex format has per-vertex position matrix IDs, look it up. + if(vert_decl.posmtx.enable) + mtxIdx = *((u32*)(vtx_ptr + mtxOff)); + + VertexShaderManager::TransformToClipSpace(&vtx[i * 3], &out[i * 4], mtxIdx); + + // Transform to Screenspace + float inv_w = 1.0f / out[3 + i * 4]; + + out[0 + i * 4] = out[0 + i * 4] * inv_w * xfmem.viewport.wd + viewOffset[0]; + out[1 + i * 4] = out[1 + i * 4] * inv_w * xfmem.viewport.ht + viewOffset[1]; + out[2 + i * 4] = out[2 + i * 4] * inv_w * xfmem.viewport.zRange + xfmem.viewport.farZ; + } + + float dx31 = out[8] - out[0]; + float dx12 = out[0] - out[4]; + float dy12 = out[1] - out[5]; + float dy31 = out[9] - out[1]; + + float DF31 = out[10] - out[2]; + float DF21 = out[6] - out[2]; + float a = DF31 * -dy12 - DF21 * dy31; + float b = dx31 * DF21 + dx12 * DF31; + float c = -dx12 * dy31 - dx31 * -dy12; + + // Sometimes we process de-generate triangles. Stop any divide by zeros + if (c == 0) + return; + + ZSlope.dfdx = -a / c; + ZSlope.dfdy = -b / c; + ZSlope.f0 = out[2] - (out[0] * ZSlope.dfdx + out[1] * ZSlope.dfdy); + ZSlope.dirty = true; +} |
