Move Zfreeze code out individual backends into videoCommon

Also:
 * Implement support for per-vertex PosMatrixIndex
 * Only update zslope constant once when zfreeze is activated.
 * Added a bunch of comments.
This commit is contained in:
Scott Mansell 2015-01-24 03:15:09 +13:00
parent daf760b202
commit 5510c86b81
10 changed files with 59 additions and 40 deletions

View File

@ -59,7 +59,7 @@ DXGI_FORMAT VarToD3D(VarType t, int size, bool integer)
void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl) void D3DVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
{ {
vertex_stride = _vtx_decl.stride; vtx_decl = _vtx_decl;
memset(m_elems, 0, sizeof(m_elems)); memset(m_elems, 0, sizeof(m_elems));
const AttributeFormat* format = &_vtx_decl.position; const AttributeFormat* format = &_vtx_decl.position;

View File

@ -181,13 +181,6 @@ void VertexManager::vFlush(bool useDstAlpha)
PrepareDrawBuffers(stride); PrepareDrawBuffers(stride);
if (!bpmem.genMode.zfreeze)
CalculateZSlope(stride);
// If cull mode is CULL_ALL, do not render these triangles
if (bpmem.genMode.cullmode == GenMode::CULL_ALL && current_primitive_type == PRIMITIVE_TRIANGLES)
return;
VertexLoaderManager::GetCurrentVertexFormat()->SetupVertexPointers(); VertexLoaderManager::GetCurrentVertexFormat()->SetupVertexPointers();
g_renderer->ApplyState(useDstAlpha); g_renderer->ApplyState(useDstAlpha);
@ -200,9 +193,6 @@ void VertexManager::ResetBuffer(u32 stride)
{ {
s_pCurBufferPointer = s_pBaseBufferPointer; s_pCurBufferPointer = s_pBaseBufferPointer;
IndexGenerator::Start(GetIndexBuffer()); IndexGenerator::Start(GetIndexBuffer());
if (bpmem.genMode.zfreeze)
PixelShaderManager::SetZSlope(ZSlope.dfdx, ZSlope.dfdy, ZSlope.f0);
} }
} // namespace } // namespace

View File

@ -58,7 +58,7 @@ static void SetPointer(u32 attrib, u32 stride, const AttributeFormat &format)
void GLVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl) void GLVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
{ {
this->vtx_decl = _vtx_decl; this->vtx_decl = _vtx_decl;
vertex_stride = vtx_decl.stride; u32 vertex_stride = _vtx_decl.stride;
// We will not allow vertex components causing uneven strides. // We will not allow vertex components causing uneven strides.
if (vertex_stride & 3) if (vertex_stride & 3)

View File

@ -89,9 +89,6 @@ void VertexManager::ResetBuffer(u32 stride)
buffer = s_indexBuffer->Map(MAXIBUFFERSIZE * sizeof(u16)); buffer = s_indexBuffer->Map(MAXIBUFFERSIZE * sizeof(u16));
IndexGenerator::Start((u16*)buffer.first); IndexGenerator::Start((u16*)buffer.first);
s_index_offset = buffer.second; s_index_offset = buffer.second;
if (bpmem.genMode.zfreeze)
PixelShaderManager::SetZSlope(ZSlope.dfdx, ZSlope.dfdy, ZSlope.f0);
} }
void VertexManager::Draw(u32 stride) void VertexManager::Draw(u32 stride)
@ -143,13 +140,6 @@ void VertexManager::vFlush(bool useDstAlpha)
PrepareDrawBuffers(stride); PrepareDrawBuffers(stride);
if (!bpmem.genMode.zfreeze)
CalculateZSlope(stride);
// If cull mode is CULL_ALL, do not render these triangles
if (bpmem.genMode.cullmode == GenMode::CULL_ALL && current_primitive_type == PRIMITIVE_TRIANGLES)
return;
// Makes sure we can actually do Dual source blending // Makes sure we can actually do Dual source blending
bool dualSourcePossible = g_ActiveConfig.backend_info.bSupportsDualSourceBlend; bool dualSourcePossible = g_ActiveConfig.backend_info.bSupportsDualSourceBlend;

View File

@ -13,8 +13,6 @@ namespace OGL
{ {
class GLVertexFormat : public NativeVertexFormat class GLVertexFormat : public NativeVertexFormat
{ {
PortableVertexDeclaration vtx_decl;
public: public:
GLVertexFormat(); GLVertexFormat();
~GLVertexFormat(); ~GLVertexFormat();

View File

@ -109,7 +109,8 @@ public:
virtual void Initialize(const PortableVertexDeclaration &vtx_decl) = 0; virtual void Initialize(const PortableVertexDeclaration &vtx_decl) = 0;
virtual void SetupVertexPointers() = 0; virtual void SetupVertexPointers() = 0;
u32 GetVertexStride() const { return vertex_stride; } u32 GetVertexStride() const { return vtx_decl.stride; }
PortableVertexDeclaration GetVertexDeclaration() const { return vtx_decl; }
// TODO: move this under private: // TODO: move this under private:
u32 m_components; // VB_HAS_X. Bitmask telling what vertex components are present. u32 m_components; // VB_HAS_X. Bitmask telling what vertex components are present.
@ -118,5 +119,5 @@ protected:
// Let subclasses construct. // Let subclasses construct.
NativeVertexFormat() {} NativeVertexFormat() {}
u32 vertex_stride; PortableVertexDeclaration vtx_decl;
}; };

View File

@ -12,6 +12,7 @@
#include "VideoCommon/RenderBase.h" #include "VideoCommon/RenderBase.h"
#include "VideoCommon/Statistics.h" #include "VideoCommon/Statistics.h"
#include "VideoCommon/TextureCacheBase.h" #include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VertexManagerBase.h" #include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VertexShaderManager.h" #include "VideoCommon/VertexShaderManager.h"
#include "VideoCommon/VideoConfig.h" #include "VideoCommon/VideoConfig.h"
@ -220,6 +221,30 @@ void VertexManager::Flush()
GeometryShaderManager::SetConstants(); GeometryShaderManager::SetConstants();
PixelShaderManager::SetConstants(); PixelShaderManager::SetConstants();
// Calculate ZSlope for zfreeze
if (!bpmem.genMode.zfreeze)
{
// Must be done after VertexShaderManager::SetConstants()
CalculateZSlope(VertexLoaderManager::GetCurrentVertexFormat());
}
else if (ZSlope.dirty) // or apply any dirty ZSlopes
{
PixelShaderManager::SetZSlope(ZSlope.dfdx, ZSlope.dfdy, ZSlope.f0);
ZSlope.dirty = false;
}
// If cull mode is CULL_ALL, we shouldn't render any triangles/quads (points and lines don't get culled)
// vertex loader has already converted any quads into triangles, so we just check for triangles.
// TODO: These culled primites need to get this far through the pipeline to be used as zfreeze refrence
// planes. But currently we apply excessive processing and store the vertices in buffers on the
// video card, which is a waste of bandwidth.
if (bpmem.genMode.cullmode == GenMode::CULL_ALL && current_primitive_type == PRIMITIVE_TRIANGLES)
{
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
IsFlushed = true;
return;
}
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass &&
bpmem.dstalpha.enable && bpmem.dstalpha.enable &&
bpmem.blendmode.alphaupdate && bpmem.blendmode.alphaupdate &&
@ -245,24 +270,34 @@ void VertexManager::DoState(PointerWrap& p)
g_vertex_manager->vDoState(p); g_vertex_manager->vDoState(p);
} }
void VertexManager::CalculateZSlope(u32 stride) void VertexManager::CalculateZSlope(NativeVertexFormat *format)
{ {
float vtx[9]; float vtx[9];
float out[12]; float out[12];
float viewOffset[2] = { xfmem.viewport.xOrig - bpmem.scissorOffset.x * 2, float viewOffset[2] = { xfmem.viewport.xOrig - bpmem.scissorOffset.x * 2,
xfmem.viewport.yOrig - bpmem.scissorOffset.y * 2}; xfmem.viewport.yOrig - bpmem.scissorOffset.y * 2};
// Global matrix ID.
u32 mtxIdx = g_main_cp_state.matrix_index_a.PosNormalMtxIdx;
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 // Lookup vertices of the last rendered triangle and software-transform them
// This allows us to determine the depth slope, which will be used if zfreeze // This allows us to determine the depth slope, which will be used if z--freeze
// is enabled in the following flush. // is enabled in the following flush.
for (unsigned int i = 0; i < 3; ++i) for (unsigned int i = 0; i < 3; ++i)
{ {
u8* vtx_ptr = s_pCurBufferPointer - stride * (3 - i); u8* vtx_ptr = s_pCurBufferPointer - vert_decl.stride * (3 - i);
vtx[0 + i * 3] = ((float*)vtx_ptr)[0]; vtx[0 + i * 3] = ((float*)(vtx_ptr + posOff))[0];
vtx[1 + i * 3] = ((float*)vtx_ptr)[1]; vtx[1 + i * 3] = ((float*)(vtx_ptr + posOff))[1];
vtx[2 + i * 3] = ((float*)vtx_ptr)[2]; vtx[2 + i * 3] = ((float*)(vtx_ptr + posOff))[2];
VertexShaderManager::TransformToClipSpace(&vtx[i * 3], &out[i * 4]); // 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 // Transform to Screenspace
float inv_w = 1.0f / out[3 + i * 4]; float inv_w = 1.0f / out[3 + i * 4];
@ -283,11 +318,12 @@ void VertexManager::CalculateZSlope(u32 stride)
float b = dx31 * DF21 + dx12 * DF31; float b = dx31 * DF21 + dx12 * DF31;
float c = -dx12 * dy31 - dx31 * -dy12; float c = -dx12 * dy31 - dx31 * -dy12;
// Stop divide by zero // Sometimes we process de-generate triangles. Stop any divide by zeros
if (c == 0) if (c == 0)
return; return;
ZSlope.dfdx = -a / c; ZSlope.dfdx = -a / c;
ZSlope.dfdy = -b / c; ZSlope.dfdy = -b / c;
ZSlope.f0 = out[2] - (out[0] * ZSlope.dfdx + out[1] * ZSlope.dfdy); ZSlope.f0 = out[2] - (out[0] * ZSlope.dfdx + out[1] * ZSlope.dfdy);
ZSlope.dirty = true;
} }

View File

@ -4,6 +4,7 @@
#include "Common/CommonFuncs.h" #include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "VideoCommon/DataReader.h" #include "VideoCommon/DataReader.h"
#include "VideoCommon/NativeVertexFormat.h"
class NativeVertexFormat; class NativeVertexFormat;
class PointerWrap; class PointerWrap;
@ -19,6 +20,7 @@ struct Slope
float dfdx; float dfdx;
float dfdy; float dfdy;
float f0; float f0;
bool dirty;
}; };
class VertexManager class VertexManager
@ -63,7 +65,7 @@ protected:
static u32 GetRemainingIndices(int primitive); static u32 GetRemainingIndices(int primitive);
static Slope ZSlope; static Slope ZSlope;
static void CalculateZSlope(u32 stride); static void CalculateZSlope(NativeVertexFormat *format);
private: private:
static bool IsFlushed; static bool IsFlushed;

View File

@ -690,10 +690,12 @@ void VertexShaderManager::ResetView()
bProjectionChanged = true; bProjectionChanged = true;
} }
void VertexShaderManager::TransformToClipSpace(const float* data, float *out) void VertexShaderManager::TransformToClipSpace(const float* data, float *out, u32 MtxIdx)
{ {
// Can we use constants.posnormalmatrix here instead? const float *world_matrix = (const float *)xfmem.posMatrices + (MtxIdx & 0x3f) * 4;
const float *world_matrix = (const float *)xfmem.posMatrices + g_main_cp_state.matrix_index_a.PosNormalMtxIdx * 4; // We use the projection matrix calculated by vertexShaderManager, because it
// includes any free look transformations.
// Make sure VertexManager::SetConstants() has been called first.
const float *proj_matrix = &g_fProjectionMatrix[0]; const float *proj_matrix = &g_fProjectionMatrix[0];
float t[3]; float t[3];

View File

@ -34,11 +34,11 @@ public:
static void RotateView(float x, float y); static void RotateView(float x, float y);
static void ResetView(); static void ResetView();
// data: 3 floats representing the X, Y and Z vertex model coordinates // data: 3 floats representing the X, Y and Z vertex model coordinates and the posmatrix index.
// out: 4 floats which will be initialized with the corresponding clip space coordinates // out: 4 floats which will be initialized with the corresponding clip space coordinates
// NOTE: g_fProjectionMatrix must be up to date when this is called // NOTE: g_fProjectionMatrix must be up to date when this is called
// (i.e. VertexShaderManager::SetConstants needs to be called before using this!) // (i.e. VertexShaderManager::SetConstants needs to be called before using this!)
static void TransformToClipSpace(const float* data, float *out); static void TransformToClipSpace(const float* data, float *out, u32 mtxIdx);
static VertexShaderConstants constants; static VertexShaderConstants constants;
static bool dirty; static bool dirty;