mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Merge pull request #1439 from Armada651/ogl-stereo-3d
OGL: Stereoscopic 3D Support
This commit is contained in:
@ -9,6 +9,7 @@ set(SRCS BoundingBox.cpp
|
||||
Fifo.cpp
|
||||
FPSCounter.cpp
|
||||
FramebufferManagerBase.cpp
|
||||
GeometryShaderGen.cpp
|
||||
HiresTextures.cpp
|
||||
ImageWrite.cpp
|
||||
IndexGenerator.cpp
|
||||
|
@ -43,5 +43,6 @@ struct VertexShaderConstants
|
||||
float4 normalmatrices[32];
|
||||
float4 posttransformmatrices[64];
|
||||
float4 depthparams;
|
||||
float4 stereoparams;
|
||||
};
|
||||
|
||||
|
@ -12,6 +12,8 @@ const XFBSourceBase* FramebufferManagerBase::m_overlappingXFBArray[MAX_VIRTUAL_X
|
||||
unsigned int FramebufferManagerBase::s_last_xfb_width = 1;
|
||||
unsigned int FramebufferManagerBase::s_last_xfb_height = 1;
|
||||
|
||||
unsigned int FramebufferManagerBase::m_EFBLayers = 1;
|
||||
|
||||
FramebufferManagerBase::FramebufferManagerBase()
|
||||
{
|
||||
m_realXFBSource = nullptr;
|
||||
|
@ -55,6 +55,8 @@ public:
|
||||
static int ScaleToVirtualXfbWidth(int x, unsigned int backbuffer_width);
|
||||
static int ScaleToVirtualXfbHeight(int y, unsigned int backbuffer_height);
|
||||
|
||||
static int GetEFBLayers() { return m_EFBLayers; }
|
||||
|
||||
protected:
|
||||
struct VirtualXFB
|
||||
{
|
||||
@ -70,6 +72,8 @@ protected:
|
||||
|
||||
typedef std::list<VirtualXFB> VirtualXFBListType;
|
||||
|
||||
static unsigned int m_EFBLayers;
|
||||
|
||||
private:
|
||||
virtual XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) = 0;
|
||||
// TODO: figure out why OGL is different for this guy
|
||||
|
134
Source/Core/VideoCommon/GeometryShaderGen.cpp
Normal file
134
Source/Core/VideoCommon/GeometryShaderGen.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cmath>
|
||||
#include <locale.h>
|
||||
#ifdef __APPLE__
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
#include "VideoCommon/GeometryShaderGen.h"
|
||||
#include "VideoCommon/LightingShaderGen.h"
|
||||
#include "VideoCommon/VertexShaderGen.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
static char text[16384];
|
||||
|
||||
template<class T>
|
||||
static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiType)
|
||||
{
|
||||
// Non-uid template parameters will write to the dummy data (=> gets optimized out)
|
||||
geometry_shader_uid_data dummy_data;
|
||||
geometry_shader_uid_data* uid_data = out.template GetUidData<geometry_shader_uid_data>();
|
||||
if (uid_data == nullptr)
|
||||
uid_data = &dummy_data;
|
||||
|
||||
out.SetBuffer(text);
|
||||
const bool is_writing_shadercode = (out.GetBuffer() != nullptr);
|
||||
#ifndef ANDROID
|
||||
locale_t locale;
|
||||
locale_t old_locale;
|
||||
if (is_writing_shadercode)
|
||||
{
|
||||
locale = newlocale(LC_NUMERIC_MASK, "C", nullptr); // New locale for compilation
|
||||
old_locale = uselocale(locale); // Apply the locale for this thread
|
||||
}
|
||||
#endif
|
||||
|
||||
if (is_writing_shadercode)
|
||||
text[sizeof(text) - 1] = 0x7C; // canary
|
||||
|
||||
out.Write("//Geometry Shader for 3D stereoscopy\n");
|
||||
|
||||
uid_data->stereo = g_ActiveConfig.iStereoMode > 0;
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
// Insert layout parameters
|
||||
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
||||
out.Write("layout(triangles, invocations = %d) in;\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1);
|
||||
else
|
||||
out.Write("layout(triangles) in;\n");
|
||||
out.Write("layout(triangle_strip, max_vertices = %d) out;\n", g_ActiveConfig.backend_info.bSupportsGSInstancing ? 3 : 6);
|
||||
}
|
||||
|
||||
out.Write("%s", s_lighting_struct);
|
||||
|
||||
// uniforms
|
||||
if (ApiType == API_OPENGL)
|
||||
out.Write("layout(std140%s) uniform VSBlock {\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 2" : "");
|
||||
else
|
||||
out.Write("cbuffer VSBlock {\n");
|
||||
out.Write(s_shader_uniforms);
|
||||
out.Write("};\n");
|
||||
|
||||
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
|
||||
uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
|
||||
|
||||
GenerateVSOutputStruct(out, ApiType);
|
||||
|
||||
out.Write("centroid in VS_OUTPUT o[3];\n");
|
||||
out.Write("centroid out VS_OUTPUT f;\n");
|
||||
|
||||
out.Write("flat out int layer;\n");
|
||||
|
||||
out.Write("void main()\n{\n");
|
||||
|
||||
// If the GPU supports invocation we don't need a for loop and can simply use the
|
||||
// invocation identifier to determine which layer we're rendering.
|
||||
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
||||
out.Write("\tint l = gl_InvocationID;\n");
|
||||
else
|
||||
out.Write("\tfor (int l = 0; l < %d; ++l) {\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1);
|
||||
|
||||
out.Write("\tfor (int i = 0; i < 3; ++i) {\n");
|
||||
out.Write("\t\tlayer = l;\n");
|
||||
out.Write("\t\tgl_Layer = l;\n");
|
||||
out.Write("\t\tf = o[i];\n");
|
||||
out.Write("\t\tfloat4 pos = o[i].pos;\n");
|
||||
|
||||
if (g_ActiveConfig.iStereoMode > 0)
|
||||
{
|
||||
// For stereoscopy add a small horizontal offset in Normalized Device Coordinates proportional
|
||||
// to the depth of the vertex. We retrieve the depth value from the w-component of the projected
|
||||
// vertex which contains the negated z-component of the original vertex.
|
||||
// For negative parallax (out-of-screen effects) we subtract a convergence value from
|
||||
// the depth value. This results in objects at a distance smaller than the convergence
|
||||
// distance to seemingly appear in front of the screen.
|
||||
// This formula is based on page 13 of the "Nvidia 3D Vision Automatic, Best Practices Guide"
|
||||
out.Write("\t\tf.clipPos.x = o[i].clipPos.x + " I_STEREOPARAMS"[l] * (o[i].clipPos.w - " I_STEREOPARAMS"[2]);\n");
|
||||
out.Write("\t\tpos.x = o[i].pos.x + " I_STEREOPARAMS"[l] * (o[i].pos.w - " I_STEREOPARAMS"[2]);\n");
|
||||
}
|
||||
|
||||
out.Write("\t\tf.pos.x = pos.x;\n");
|
||||
out.Write("\t\tgl_Position = pos;\n");
|
||||
out.Write("\t\tEmitVertex();\n");
|
||||
out.Write("\t}\n");
|
||||
out.Write("\tEndPrimitive();\n");
|
||||
|
||||
if (!g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
||||
out.Write("\t}\n");
|
||||
|
||||
out.Write("}\n");
|
||||
|
||||
if (is_writing_shadercode)
|
||||
{
|
||||
if (text[sizeof(text) - 1] != 0x7C)
|
||||
PanicAlert("GeometryShader generator - buffer too small, canary has been eaten!");
|
||||
|
||||
#ifndef ANDROID
|
||||
uselocale(old_locale); // restore locale
|
||||
freelocale(locale);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GetGeometryShaderUid(GeometryShaderUid& object, u32 components, API_TYPE ApiType)
|
||||
{
|
||||
GenerateGeometryShader<GeometryShaderUid>(object, components, ApiType);
|
||||
}
|
||||
|
||||
void GenerateGeometryShaderCode(ShaderCode& object, u32 components, API_TYPE ApiType)
|
||||
{
|
||||
GenerateGeometryShader<ShaderCode>(object, components, ApiType);
|
||||
}
|
26
Source/Core/VideoCommon/GeometryShaderGen.h
Normal file
26
Source/Core/VideoCommon/GeometryShaderGen.h
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VideoCommon/ShaderGenCommon.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
struct geometry_shader_uid_data
|
||||
{
|
||||
u32 NumValues() const { return sizeof(geometry_shader_uid_data); }
|
||||
|
||||
u32 stereo : 1;
|
||||
u32 numTexGens : 4;
|
||||
u32 pixel_lighting : 1;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
typedef ShaderUid<geometry_shader_uid_data> GeometryShaderUid;
|
||||
|
||||
void GenerateGeometryShaderCode(ShaderCode& object, u32 components, API_TYPE ApiType);
|
||||
void GetGeometryShaderUid(GeometryShaderUid& object, u32 components, API_TYPE ApiType);
|
@ -16,6 +16,7 @@
|
||||
#include "VideoCommon/LightingShaderGen.h"
|
||||
#include "VideoCommon/NativeVertexFormat.h"
|
||||
#include "VideoCommon/PixelShaderGen.h"
|
||||
#include "VideoCommon/VertexShaderGen.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
#include "VideoCommon/XFMemory.h" // for texture projection mode
|
||||
|
||||
@ -206,7 +207,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
|
||||
{
|
||||
// Declare samplers
|
||||
for (int i = 0; i < 8; ++i)
|
||||
out.Write("SAMPLER_BINDING(%d) uniform sampler2D samp%d;\n", i, i);
|
||||
out.Write("SAMPLER_BINDING(%d) uniform sampler2DArray samp%d;\n", i, i);
|
||||
}
|
||||
else // D3D
|
||||
{
|
||||
@ -253,17 +254,8 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
|
||||
{
|
||||
out.Write("cbuffer VSBlock : register(b1) {\n");
|
||||
}
|
||||
out.Write(
|
||||
"\tfloat4 " I_POSNORMALMATRIX"[6];\n"
|
||||
"\tfloat4 " I_PROJECTION"[4];\n"
|
||||
"\tint4 " I_MATERIALS"[4];\n"
|
||||
"\tLight " I_LIGHTS"[8];\n"
|
||||
"\tfloat4 " I_TEXMATRICES"[24];\n"
|
||||
"\tfloat4 " I_TRANSFORMMATRICES"[64];\n"
|
||||
"\tfloat4 " I_NORMALMATRICES"[32];\n"
|
||||
"\tfloat4 " I_POSTTRANSFORMMATRICES"[64];\n"
|
||||
"\tfloat4 " I_DEPTHPARAMS";\n"
|
||||
"};\n");
|
||||
out.Write(s_shader_uniforms);
|
||||
out.Write("};\n");
|
||||
}
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsBBox)
|
||||
@ -275,6 +267,8 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
|
||||
);
|
||||
}
|
||||
|
||||
GenerateVSOutputStruct(out, ApiType);
|
||||
|
||||
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.UseLateDepthTest()) || (!g_ActiveConfig.bFastDepthCalc && bpmem.zmode.testenable && !forced_early_z);
|
||||
|
||||
@ -325,22 +319,52 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
|
||||
// As a workaround, we interpolate at the centroid of the coveraged pixel, which
|
||||
// is always inside the primitive.
|
||||
// Without MSAA, this flag is defined to have no effect.
|
||||
out.Write("centroid in float4 colors_02;\n");
|
||||
out.Write("centroid in float4 colors_12;\n");
|
||||
|
||||
// compute window position if needed because binding semantic WPOS is not widely supported
|
||||
// Let's set up attributes
|
||||
for (unsigned int i = 0; i < numTexgen; ++i)
|
||||
uid_data->stereo = g_ActiveConfig.iStereoMode > 0;
|
||||
if (g_ActiveConfig.iStereoMode > 0)
|
||||
{
|
||||
out.Write("centroid in float3 uv%d;\n", i);
|
||||
out.Write("centroid in VS_OUTPUT f;\n");
|
||||
out.Write("flat in int layer;\n");
|
||||
}
|
||||
out.Write("centroid in float4 clipPos;\n");
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
else
|
||||
{
|
||||
out.Write("centroid in float4 Normal;\n");
|
||||
out.Write("centroid in float4 colors_02;\n");
|
||||
out.Write("centroid in float4 colors_12;\n");
|
||||
|
||||
// compute window position if needed because binding semantic WPOS is not widely supported
|
||||
// Let's set up attributes
|
||||
for (unsigned int i = 0; i < numTexgen; ++i)
|
||||
{
|
||||
out.Write("centroid in float3 uv%d;\n", i);
|
||||
}
|
||||
out.Write("centroid in float4 clipPos;\n");
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
{
|
||||
out.Write("centroid in float4 Normal;\n");
|
||||
}
|
||||
}
|
||||
|
||||
out.Write("void main()\n{\n");
|
||||
|
||||
if (g_ActiveConfig.iStereoMode > 0)
|
||||
{
|
||||
// compute window position if needed because binding semantic WPOS is not widely supported
|
||||
// Let's set up attributes
|
||||
for (unsigned int i = 0; i < numTexgen; ++i)
|
||||
{
|
||||
out.Write("\tfloat3 uv%d = f.tex%d;\n", i, i);
|
||||
}
|
||||
out.Write("\tfloat4 clipPos = f.clipPos;\n");
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
{
|
||||
out.Write("\tfloat4 Normal = f.Normal;\n");
|
||||
}
|
||||
}
|
||||
|
||||
// On Mali, global variables must be initialized as constants.
|
||||
// This is why we initialize these variables locally instead.
|
||||
out.Write("\tfloat4 colors_0 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "f.colors_0" : "colors_02");
|
||||
out.Write("\tfloat4 colors_1 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "f.colors_1" : "colors_12");
|
||||
|
||||
out.Write("\tfloat4 rawpos = gl_FragCoord;\n");
|
||||
}
|
||||
else // D3D
|
||||
@ -370,14 +394,6 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
|
||||
"\tint2 wrappedcoord=int2(0,0), tempcoord=int2(0,0);\n"
|
||||
"\tint4 tevin_a=int4(0,0,0,0),tevin_b=int4(0,0,0,0),tevin_c=int4(0,0,0,0),tevin_d=int4(0,0,0,0);\n\n"); // tev combiner inputs
|
||||
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
// On Mali, global variables must be initialized as constants.
|
||||
// This is why we initialize these variables locally instead.
|
||||
out.Write("\tfloat4 colors_0 = colors_02;\n");
|
||||
out.Write("\tfloat4 colors_1 = colors_12;\n");
|
||||
}
|
||||
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
{
|
||||
out.Write("\tfloat3 _norm0 = normalize(Normal.xyz);\n\n");
|
||||
@ -931,7 +947,7 @@ static inline void SampleTexture(T& out, const char *texcoords, const char *texs
|
||||
if (ApiType == API_D3D)
|
||||
out.Write("iround(255.0 * Tex%d.Sample(samp%d,%s.xy * " I_TEXDIMS"[%d].xy)).%s;\n", texmap,texmap, texcoords, texmap, texswap);
|
||||
else
|
||||
out.Write("iround(255.0 * texture(samp%d,%s.xy * " I_TEXDIMS"[%d].xy)).%s;\n", texmap, texcoords, texmap, texswap);
|
||||
out.Write("iround(255.0 * texture(samp%d, float3(%s.xy * " I_TEXDIMS"[%d].xy, %s))).%s;\n", texmap, texcoords, texmap, g_ActiveConfig.iStereoMode > 0 ? "layer" : "0.0", texswap);
|
||||
}
|
||||
|
||||
static const char *tevAlphaFuncsTable[] =
|
||||
|
@ -44,7 +44,7 @@ struct pixel_shader_uid_data
|
||||
u32 dstAlphaMode : 2;
|
||||
u32 Pretest : 2;
|
||||
u32 nIndirectStagesUsed : 4;
|
||||
u32 pad0 : 1;
|
||||
u32 stereo : 1;
|
||||
|
||||
u32 genMode_numtexgens : 4;
|
||||
u32 genMode_numtevstages : 4;
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
|
||||
// Should be implemented by the backends for backend specific code
|
||||
virtual void BlitFromTexture(TargetRectangle src, TargetRectangle dst,
|
||||
int src_texture, int src_width, int src_height) = 0;
|
||||
int src_texture, int src_width, int src_height, int layer = 0) = 0;
|
||||
virtual void ApplyShader() = 0;
|
||||
|
||||
protected:
|
||||
|
@ -240,6 +240,42 @@ bool Renderer::CalculateTargetSize(unsigned int framebuffer_width, unsigned int
|
||||
return false;
|
||||
}
|
||||
|
||||
void Renderer::ConvertStereoRectangle(const TargetRectangle& rc, TargetRectangle& leftRc, TargetRectangle& rightRc)
|
||||
{
|
||||
// Resize target to half its original size
|
||||
TargetRectangle drawRc = rc;
|
||||
if (g_ActiveConfig.iStereoMode == STEREO_TAB)
|
||||
{
|
||||
// The height may be negative due to flipped rectangles
|
||||
int height = rc.bottom - rc.top;
|
||||
drawRc.top += height / 4;
|
||||
drawRc.bottom -= height / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
int width = rc.right - rc.left;
|
||||
drawRc.left += width / 4;
|
||||
drawRc.right -= width / 4;
|
||||
}
|
||||
|
||||
// Create two target rectangle offset to the sides of the backbuffer
|
||||
leftRc = drawRc, rightRc = drawRc;
|
||||
if (g_ActiveConfig.iStereoMode == STEREO_TAB)
|
||||
{
|
||||
leftRc.top -= s_backbuffer_height / 4;
|
||||
leftRc.bottom -= s_backbuffer_height / 4;
|
||||
rightRc.top += s_backbuffer_height / 4;
|
||||
rightRc.bottom += s_backbuffer_height / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
leftRc.left -= s_backbuffer_width / 4;
|
||||
leftRc.right -= s_backbuffer_width / 4;
|
||||
rightRc.left += s_backbuffer_width / 4;
|
||||
rightRc.right += s_backbuffer_width / 4;
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetScreenshot(const std::string& filename)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(s_criticalScreenshot);
|
||||
|
@ -83,6 +83,8 @@ public:
|
||||
static const TargetRectangle& GetTargetRectangle() { return target_rc; }
|
||||
static void UpdateDrawRectangle(int backbuffer_width, int backbuffer_height);
|
||||
|
||||
// Use this to convert a single target rectangle to two stereo rectangles
|
||||
static void ConvertStereoRectangle(const TargetRectangle& rc, TargetRectangle& leftRc, TargetRectangle& rightRc);
|
||||
|
||||
// Use this to upscale native EFB coordinates to IDEAL internal resolution
|
||||
static int EFBToScaledX(int x);
|
||||
|
@ -239,3 +239,16 @@ private:
|
||||
#define I_NORMALMATRICES "cnmtx"
|
||||
#define I_POSTTRANSFORMMATRICES "cpostmtx"
|
||||
#define I_DEPTHPARAMS "cDepth" // farZ, zRange
|
||||
#define I_STEREOPARAMS "cstereo"
|
||||
|
||||
static const char s_shader_uniforms[] =
|
||||
"\tfloat4 " I_POSNORMALMATRIX"[6];\n"
|
||||
"\tfloat4 " I_PROJECTION"[4];\n"
|
||||
"\tint4 " I_MATERIALS"[4];\n"
|
||||
"\tLight " I_LIGHTS"[8];\n"
|
||||
"\tfloat4 " I_TEXMATRICES"[24];\n"
|
||||
"\tfloat4 " I_TRANSFORMMATRICES"[64];\n"
|
||||
"\tfloat4 " I_NORMALMATRICES"[32];\n"
|
||||
"\tfloat4 " I_POSTTRANSFORMMATRICES"[64];\n"
|
||||
"\tfloat4 " I_DEPTHPARAMS";\n"
|
||||
"\tfloat4 " I_STEREOPARAMS";\n";
|
||||
|
@ -115,6 +115,13 @@ void TextureCache::OnConfigChanged(VideoConfig& config)
|
||||
{
|
||||
g_texture_cache->ClearRenderTargets();
|
||||
}
|
||||
|
||||
if ((config.iStereoMode > 0) != backup_config.s_stereo_3d ||
|
||||
config.bStereoMonoEFBDepth != backup_config.s_mono_efb_depth)
|
||||
{
|
||||
g_texture_cache->DeleteShaders();
|
||||
g_texture_cache->CompileShaders();
|
||||
}
|
||||
}
|
||||
|
||||
backup_config.s_colorsamples = config.iSafeTextureCache_ColorSamples;
|
||||
@ -126,6 +133,8 @@ void TextureCache::OnConfigChanged(VideoConfig& config)
|
||||
backup_config.s_texfmt_overlay_center = config.bTexFmtOverlayCenter;
|
||||
backup_config.s_hires_textures = config.bHiresTextures;
|
||||
backup_config.s_copy_cache_enable = config.bEFBCopyCacheEnable;
|
||||
backup_config.s_stereo_3d = config.iStereoMode > 0;
|
||||
backup_config.s_mono_efb_depth = config.bStereoMonoEFBDepth;
|
||||
}
|
||||
|
||||
void TextureCache::Cleanup()
|
||||
@ -444,14 +453,15 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage,
|
||||
//
|
||||
// TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies?
|
||||
// TODO: Actually, it should be enough if the internal texture format matches...
|
||||
if ((entry->type == TCET_NORMAL &&
|
||||
if (((entry->type == TCET_NORMAL &&
|
||||
width == entry->virtual_width &&
|
||||
height == entry->virtual_height &&
|
||||
full_format == entry->format &&
|
||||
entry->num_mipmaps > maxlevel) ||
|
||||
(entry->type == TCET_EC_DYNAMIC &&
|
||||
entry->native_width == width &&
|
||||
entry->native_height == height))
|
||||
entry->native_height == height)) &&
|
||||
entry->num_layers == 1)
|
||||
{
|
||||
// reuse the texture
|
||||
}
|
||||
@ -519,6 +529,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage,
|
||||
// But that will currently make the above "existing entry" tests fail as "texLevels" is not calculated until after.
|
||||
// Currently, we might try to reuse a texture which appears to have more levels than actual, maybe..
|
||||
entry->num_mipmaps = maxlevel + 1;
|
||||
entry->num_layers = 1;
|
||||
entry->type = TCET_NORMAL;
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true);
|
||||
@ -529,7 +540,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage,
|
||||
entry->Load(width, height, expandedWidth, 0);
|
||||
}
|
||||
|
||||
entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps);
|
||||
entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps, entry->num_layers);
|
||||
entry->SetDimensions(nativeW, nativeH, width, height);
|
||||
entry->hash = tex_hash;
|
||||
|
||||
@ -886,12 +897,12 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
|
||||
TCacheEntryBase *entry = textures[dstAddr];
|
||||
if (entry)
|
||||
{
|
||||
if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h)
|
||||
if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h && entry->num_layers == FramebufferManagerBase::GetEFBLayers())
|
||||
{
|
||||
scaled_tex_w = tex_w;
|
||||
scaled_tex_h = tex_h;
|
||||
}
|
||||
else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h))
|
||||
else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h && entry->num_layers == FramebufferManagerBase::GetEFBLayers()))
|
||||
{
|
||||
if (entry->type == TCET_EC_VRAM)
|
||||
{
|
||||
@ -914,7 +925,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
|
||||
textures[dstAddr] = entry = AllocateRenderTarget(scaled_tex_w, scaled_tex_h);
|
||||
|
||||
// TODO: Using the wrong dstFormat, dumb...
|
||||
entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1);
|
||||
entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1, FramebufferManagerBase::GetEFBLayers());
|
||||
entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h);
|
||||
entry->SetHashes(TEXHASH_INVALID);
|
||||
entry->type = TCET_EC_VRAM;
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
enum TexCacheEntryType type;
|
||||
|
||||
unsigned int num_mipmaps;
|
||||
unsigned int num_layers;
|
||||
unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view
|
||||
unsigned int virtual_width, virtual_height; // Texture dimensions from OUR point of view - for hires textures or scaled EFB copies
|
||||
|
||||
@ -46,12 +47,13 @@ public:
|
||||
int frameCount;
|
||||
|
||||
|
||||
void SetGeneralParameters(u32 _addr, u32 _size, u32 _format, unsigned int _num_mipmaps)
|
||||
void SetGeneralParameters(u32 _addr, u32 _size, u32 _format, unsigned int _num_mipmaps, unsigned int _num_layers)
|
||||
{
|
||||
addr = _addr;
|
||||
size_in_bytes = _size;
|
||||
format = _format;
|
||||
num_mipmaps = _num_mipmaps;
|
||||
num_layers = _num_layers;
|
||||
}
|
||||
|
||||
void SetDimensions(unsigned int _native_width, unsigned int _native_height, unsigned int _virtual_width, unsigned int _virtual_height)
|
||||
@ -101,6 +103,9 @@ public:
|
||||
unsigned int expanded_width, unsigned int tex_levels, PC_TexFormat pcfmt) = 0;
|
||||
virtual TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) = 0;
|
||||
|
||||
virtual void CompileShaders() = 0; // currently only implemented by OGL
|
||||
virtual void DeleteShaders() = 0; // currently only implemented by OGL
|
||||
|
||||
static TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width, unsigned int height,
|
||||
int format, unsigned int tlutaddr, int tlutfmt, bool use_mipmaps, unsigned int maxlevel, bool from_tmem);
|
||||
static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, PEControl::PixelFormat srcFormat,
|
||||
@ -140,6 +145,8 @@ private:
|
||||
bool s_texfmt_overlay_center;
|
||||
bool s_hires_textures;
|
||||
bool s_copy_cache_enable;
|
||||
bool s_stereo_3d;
|
||||
bool s_mono_efb_depth;
|
||||
} backup_config;
|
||||
};
|
||||
|
||||
|
@ -70,7 +70,7 @@ static void WriteSwizzler(char*& p, u32 format, API_TYPE ApiType)
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
WRITE(p, "#define samp0 samp9\n");
|
||||
WRITE(p, "SAMPLER_BINDING(9) uniform sampler2D samp0;\n");
|
||||
WRITE(p, "SAMPLER_BINDING(9) uniform sampler2DArray samp0;\n");
|
||||
|
||||
WRITE(p, " out vec4 ocol0;\n");
|
||||
WRITE(p, "void main()\n");
|
||||
@ -120,7 +120,7 @@ static void WriteSwizzler(char*& p, u32 format, API_TYPE ApiType)
|
||||
|
||||
static void WriteSampleColor(char*& p, const char* colorComp, const char* dest, int xoffset, API_TYPE ApiType)
|
||||
{
|
||||
WRITE(p, " %s = texture(samp0, uv0 + float2(%d, 0) * sample_offset).%s;\n",
|
||||
WRITE(p, " %s = texture(samp0, float3(uv0 + float2(%d, 0) * sample_offset, 0.0)).%s;\n",
|
||||
dest, xoffset, colorComp
|
||||
);
|
||||
}
|
||||
|
@ -89,17 +89,8 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ
|
||||
out.Write("layout(std140%s) uniform VSBlock {\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 2" : "");
|
||||
else
|
||||
out.Write("cbuffer VSBlock {\n");
|
||||
out.Write(
|
||||
"\tfloat4 " I_POSNORMALMATRIX"[6];\n"
|
||||
"\tfloat4 " I_PROJECTION"[4];\n"
|
||||
"\tint4 " I_MATERIALS"[4];\n"
|
||||
"\tLight " I_LIGHTS"[8];\n"
|
||||
"\tfloat4 " I_TEXMATRICES"[24];\n"
|
||||
"\tfloat4 " I_TRANSFORMMATRICES"[64];\n"
|
||||
"\tfloat4 " I_NORMALMATRICES"[32];\n"
|
||||
"\tfloat4 " I_POSTTRANSFORMMATRICES"[64];\n"
|
||||
"\tfloat4 " I_DEPTHPARAMS";\n"
|
||||
"};\n");
|
||||
out.Write(s_shader_uniforms);
|
||||
out.Write("};\n");
|
||||
|
||||
GenerateVSOutputStruct(out, api_type);
|
||||
|
||||
@ -131,22 +122,33 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ
|
||||
out.Write("in float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i, SHADER_TEXTURE0_ATTRIB + i);
|
||||
}
|
||||
|
||||
// Let's set up attributes
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
uid_data->stereo = g_ActiveConfig.iStereoMode > 0;
|
||||
if (g_ActiveConfig.iStereoMode > 0)
|
||||
{
|
||||
if (i < xfmem.numTexGen.numTexGens)
|
||||
{
|
||||
out.Write("centroid out float3 uv%d;\n", i);
|
||||
}
|
||||
out.Write("centroid out VS_OUTPUT o;\n");
|
||||
}
|
||||
out.Write("centroid out float4 clipPos;\n");
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
out.Write("centroid out float4 Normal;\n");
|
||||
else
|
||||
{
|
||||
// Let's set up attributes
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
{
|
||||
if (i < xfmem.numTexGen.numTexGens)
|
||||
{
|
||||
out.Write("centroid out float3 uv%d;\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
out.Write("centroid out float4 colors_02;\n");
|
||||
out.Write("centroid out float4 colors_12;\n");
|
||||
out.Write("centroid out float4 clipPos;\n");
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
out.Write("centroid out float4 Normal;\n");
|
||||
out.Write("centroid out float4 colors_02;\n");
|
||||
out.Write("centroid out float4 colors_12;\n");
|
||||
}
|
||||
|
||||
out.Write("void main()\n{\n");
|
||||
|
||||
if (g_ActiveConfig.iStereoMode <= 0)
|
||||
out.Write("VS_OUTPUT o;\n");
|
||||
}
|
||||
else // D3D
|
||||
{
|
||||
@ -172,8 +174,9 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ
|
||||
if (components & VB_HAS_POSMTXIDX)
|
||||
out.Write(" int posmtx : BLENDINDICES,\n");
|
||||
out.Write(" float4 rawpos : POSITION) {\n");
|
||||
|
||||
out.Write("VS_OUTPUT o;\n");
|
||||
}
|
||||
out.Write("VS_OUTPUT o;\n");
|
||||
|
||||
// transforms
|
||||
if (components & VB_HAS_POSMTXIDX)
|
||||
@ -431,27 +434,32 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ
|
||||
|
||||
if (api_type == API_OPENGL)
|
||||
{
|
||||
// Bit ugly here
|
||||
// TODO: Make pretty
|
||||
// Will look better when we bind uniforms in GLSL 1.3
|
||||
// clipPos/w needs to be done in pixel shader, not here
|
||||
if (g_ActiveConfig.iStereoMode <= 0)
|
||||
{
|
||||
// Bit ugly here
|
||||
// TODO: Make pretty
|
||||
// Will look better when we bind uniforms in GLSL 1.3
|
||||
// clipPos/w needs to be done in pixel shader, not here
|
||||
|
||||
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
|
||||
out.Write(" uv%d.xyz = o.tex%d;\n", i, i);
|
||||
out.Write(" clipPos = o.clipPos;\n");
|
||||
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
|
||||
out.Write("uv%d.xyz = o.tex%d;\n", i, i);
|
||||
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
out.Write(" Normal = o.Normal;\n");
|
||||
out.Write("clipPos = o.clipPos;\n");
|
||||
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
out.Write("Normal = o.Normal;\n");
|
||||
|
||||
out.Write("colors_02 = o.colors_0;\n");
|
||||
out.Write("colors_12 = o.colors_1;\n");
|
||||
}
|
||||
|
||||
out.Write("colors_02 = o.colors_0;\n");
|
||||
out.Write("colors_12 = o.colors_1;\n");
|
||||
out.Write("gl_Position = o.pos;\n");
|
||||
out.Write("}\n");
|
||||
}
|
||||
else // D3D
|
||||
{
|
||||
out.Write("return o;\n}\n");
|
||||
out.Write("return o;\n");
|
||||
}
|
||||
out.Write("}\n");
|
||||
|
||||
if (is_writing_shadercode)
|
||||
{
|
||||
@ -475,7 +483,12 @@ void GenerateVertexShaderCode(VertexShaderCode& object, u32 components, API_TYPE
|
||||
GenerateVertexShader<VertexShaderCode>(object, components, api_type);
|
||||
}
|
||||
|
||||
void GenerateVSOutputStructForGS(ShaderCode& object, API_TYPE api_type)
|
||||
void GenerateVSOutputStruct(ShaderCode& object, API_TYPE api_type)
|
||||
{
|
||||
GenerateVSOutputStruct<ShaderCode>(object, api_type);
|
||||
}
|
||||
|
||||
void GenerateVSOutputStruct(ShaderGeneratorInterface& object, API_TYPE api_type)
|
||||
{
|
||||
// Ignore unknown types
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ struct vertex_shader_uid_data
|
||||
u32 numColorChans : 2;
|
||||
u32 dualTexTrans_enabled : 1;
|
||||
u32 pixel_lighting : 1;
|
||||
u32 pad0 : 1;
|
||||
u32 stereo : 1;
|
||||
|
||||
u32 texMtxInfo_n_projection : 16; // Stored separately to guarantee that the texMtxInfo struct is 8 bits wide
|
||||
struct {
|
||||
@ -64,4 +64,5 @@ typedef ShaderCode VertexShaderCode; // TODO: Obsolete..
|
||||
|
||||
void GetVertexShaderUid(VertexShaderUid& object, u32 components, API_TYPE api_type);
|
||||
void GenerateVertexShaderCode(VertexShaderCode& object, u32 components, API_TYPE api_type);
|
||||
void GenerateVSOutputStructForGS(ShaderCode& object, API_TYPE api_type);
|
||||
void GenerateVSOutputStruct(ShaderCode& object, API_TYPE api_type);
|
||||
void GenerateVSOutputStruct(ShaderGeneratorInterface& object, API_TYPE api_type);
|
||||
|
@ -489,7 +489,7 @@ void VertexShaderManager::SetConstants()
|
||||
|
||||
PRIM_LOG("Projection: %f %f %f %f %f %f\n", rawProjection[0], rawProjection[1], rawProjection[2], rawProjection[3], rawProjection[4], rawProjection[5]);
|
||||
|
||||
if ((g_ActiveConfig.bFreeLook || g_ActiveConfig.bAnaglyphStereo ) && xfmem.projection.type == GX_PERSPECTIVE)
|
||||
if (g_ActiveConfig.bFreeLook && xfmem.projection.type == GX_PERSPECTIVE)
|
||||
{
|
||||
Matrix44 mtxA;
|
||||
Matrix44 mtxB;
|
||||
@ -512,6 +512,19 @@ void VertexShaderManager::SetConstants()
|
||||
Matrix44::Multiply(s_viewportCorrection, projMtx, correctedMtx);
|
||||
memcpy(constants.projection, correctedMtx.data, 4*16);
|
||||
}
|
||||
|
||||
if (g_ActiveConfig.iStereoMode > 0 && xfmem.projection.type == GX_PERSPECTIVE)
|
||||
{
|
||||
float offset = (g_ActiveConfig.iStereoSeparation / 1000.0f) * (g_ActiveConfig.iStereoSeparationPercent / 100.0f);
|
||||
constants.stereoparams[0] = (g_ActiveConfig.bStereoSwapEyes) ? offset : -offset;
|
||||
constants.stereoparams[1] = (g_ActiveConfig.bStereoSwapEyes) ? -offset : offset;
|
||||
constants.stereoparams[2] = (g_ActiveConfig.iStereoConvergence / 10.0f) * (g_ActiveConfig.iStereoConvergencePercent / 100.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
constants.stereoparams[0] = constants.stereoparams[1] = 0;
|
||||
}
|
||||
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,7 @@
|
||||
<ClCompile Include="PostProcessing.cpp" />
|
||||
<ClCompile Include="RenderBase.cpp" />
|
||||
<ClCompile Include="Statistics.cpp" />
|
||||
<ClCompile Include="GeometryShaderGen.cpp" />
|
||||
<ClCompile Include="TextureCacheBase.cpp" />
|
||||
<ClCompile Include="TextureConversionShader.cpp" />
|
||||
<ClCompile Include="VertexLoader.cpp" />
|
||||
@ -110,6 +111,7 @@
|
||||
<ClInclude Include="RenderBase.h" />
|
||||
<ClInclude Include="ShaderGenCommon.h" />
|
||||
<ClInclude Include="Statistics.h" />
|
||||
<ClInclude Include="GeometryShaderGen.h" />
|
||||
<ClInclude Include="TextureCacheBase.h" />
|
||||
<ClInclude Include="TextureConversionShader.h" />
|
||||
<ClInclude Include="TextureDecoder.h" />
|
||||
|
@ -143,6 +143,9 @@
|
||||
<ClCompile Include="BoundingBox.cpp">
|
||||
<Filter>Util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeometryShaderGen.cpp">
|
||||
<Filter>Shader Generators</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CommandProcessor.h" />
|
||||
@ -275,6 +278,9 @@
|
||||
<ClInclude Include="BoundingBox.h">
|
||||
<Filter>Util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GeometryShaderGen.h">
|
||||
<Filter>Shader Generators</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
|
@ -38,6 +38,11 @@ VideoConfig::VideoConfig()
|
||||
backend_info.APIType = API_NONE;
|
||||
backend_info.bUseMinimalMipCount = false;
|
||||
backend_info.bSupportsExclusiveFullscreen = false;
|
||||
|
||||
// Game-specific stereoscopy settings
|
||||
bStereoMonoEFBDepth = false;
|
||||
iStereoSeparationPercent = 100;
|
||||
iStereoConvergencePercent = 100;
|
||||
}
|
||||
|
||||
void VideoConfig::Load(const std::string& ini_file)
|
||||
@ -66,9 +71,6 @@ void VideoConfig::Load(const std::string& ini_file)
|
||||
settings->Get("DumpEFBTarget", &bDumpEFBTarget, 0);
|
||||
settings->Get("FreeLook", &bFreeLook, 0);
|
||||
settings->Get("UseFFV1", &bUseFFV1, 0);
|
||||
settings->Get("AnaglyphStereo", &bAnaglyphStereo, false);
|
||||
settings->Get("AnaglyphStereoSeparation", &iAnaglyphStereoSeparation, 200);
|
||||
settings->Get("AnaglyphFocalAngle", &iAnaglyphFocalAngle, 0);
|
||||
settings->Get("EnablePixelLighting", &bEnablePixelLighting, 0);
|
||||
settings->Get("FastDepthCalc", &bFastDepthCalc, true);
|
||||
settings->Get("MSAA", &iMultisampleMode, 0);
|
||||
@ -85,6 +87,10 @@ void VideoConfig::Load(const std::string& ini_file)
|
||||
enhancements->Get("ForceFiltering", &bForceFiltering, 0);
|
||||
enhancements->Get("MaxAnisotropy", &iMaxAnisotropy, 0); // NOTE - this is x in (1 << x)
|
||||
enhancements->Get("PostProcessingShader", &sPostProcessingShader, "");
|
||||
enhancements->Get("StereoMode", &iStereoMode, 0);
|
||||
enhancements->Get("StereoSeparation", &iStereoSeparation, 20);
|
||||
enhancements->Get("StereoConvergence", &iStereoConvergence, 20);
|
||||
enhancements->Get("StereoSwapEyes", &bStereoSwapEyes, false);
|
||||
|
||||
IniFile::Section* hacks = iniFile.GetOrCreateSection("Hacks");
|
||||
hacks->Get("EFBAccessEnable", &bEFBAccessEnable, true);
|
||||
@ -140,9 +146,6 @@ void VideoConfig::GameIniLoad()
|
||||
CHECK_SETTING("Video_Settings", "UseRealXFB", bUseRealXFB);
|
||||
CHECK_SETTING("Video_Settings", "SafeTextureCacheColorSamples", iSafeTextureCache_ColorSamples);
|
||||
CHECK_SETTING("Video_Settings", "HiresTextures", bHiresTextures);
|
||||
CHECK_SETTING("Video_Settings", "AnaglyphStereo", bAnaglyphStereo);
|
||||
CHECK_SETTING("Video_Settings", "AnaglyphStereoSeparation", iAnaglyphStereoSeparation);
|
||||
CHECK_SETTING("Video_Settings", "AnaglyphFocalAngle", iAnaglyphFocalAngle);
|
||||
CHECK_SETTING("Video_Settings", "EnablePixelLighting", bEnablePixelLighting);
|
||||
CHECK_SETTING("Video_Settings", "FastDepthCalc", bFastDepthCalc);
|
||||
CHECK_SETTING("Video_Settings", "MSAA", iMultisampleMode);
|
||||
@ -179,6 +182,14 @@ void VideoConfig::GameIniLoad()
|
||||
CHECK_SETTING("Video_Enhancements", "ForceFiltering", bForceFiltering);
|
||||
CHECK_SETTING("Video_Enhancements", "MaxAnisotropy", iMaxAnisotropy); // NOTE - this is x in (1 << x)
|
||||
CHECK_SETTING("Video_Enhancements", "PostProcessingShader", sPostProcessingShader);
|
||||
CHECK_SETTING("Video_Enhancements", "StereoMode", iStereoMode);
|
||||
CHECK_SETTING("Video_Enhancements", "StereoSeparation", iStereoSeparation);
|
||||
CHECK_SETTING("Video_Enhancements", "StereoConvergence", iStereoConvergence);
|
||||
CHECK_SETTING("Video_Enhancements", "StereoSwapEyes", bStereoSwapEyes);
|
||||
|
||||
CHECK_SETTING("Video_Stereoscopy", "StereoMonoEFBDepth", bStereoMonoEFBDepth);
|
||||
CHECK_SETTING("Video_Stereoscopy", "StereoSeparationPercent", iStereoSeparationPercent);
|
||||
CHECK_SETTING("Video_Stereoscopy", "StereoConvergencePercent", iStereoConvergencePercent);
|
||||
|
||||
CHECK_SETTING("Video_Hacks", "EFBAccessEnable", bEFBAccessEnable);
|
||||
CHECK_SETTING("Video_Hacks", "EFBCopyEnable", bEFBCopyEnable);
|
||||
@ -203,6 +214,7 @@ void VideoConfig::VerifyValidity()
|
||||
// TODO: Check iMaxAnisotropy value
|
||||
if (iAdapter < 0 || iAdapter > ((int)backend_info.Adapters.size() - 1)) iAdapter = 0;
|
||||
if (iMultisampleMode < 0 || iMultisampleMode >= (int)backend_info.AAModes.size()) iMultisampleMode = 0;
|
||||
if (!backend_info.bSupportsStereoscopy) iStereoMode = 0;
|
||||
}
|
||||
|
||||
void VideoConfig::Save(const std::string& ini_file)
|
||||
@ -230,9 +242,6 @@ void VideoConfig::Save(const std::string& ini_file)
|
||||
settings->Set("DumpEFBTarget", bDumpEFBTarget);
|
||||
settings->Set("FreeLook", bFreeLook);
|
||||
settings->Set("UseFFV1", bUseFFV1);
|
||||
settings->Set("AnaglyphStereo", bAnaglyphStereo);
|
||||
settings->Set("AnaglyphStereoSeparation", iAnaglyphStereoSeparation);
|
||||
settings->Set("AnaglyphFocalAngle", iAnaglyphFocalAngle);
|
||||
settings->Set("EnablePixelLighting", bEnablePixelLighting);
|
||||
settings->Set("FastDepthCalc", bFastDepthCalc);
|
||||
settings->Set("ShowEFBCopyRegions", bShowEFBCopyRegions);
|
||||
@ -250,6 +259,10 @@ void VideoConfig::Save(const std::string& ini_file)
|
||||
enhancements->Set("ForceFiltering", bForceFiltering);
|
||||
enhancements->Set("MaxAnisotropy", iMaxAnisotropy);
|
||||
enhancements->Set("PostProcessingShader", sPostProcessingShader);
|
||||
enhancements->Set("StereoMode", iStereoMode);
|
||||
enhancements->Set("StereoSeparation", iStereoSeparation);
|
||||
enhancements->Set("StereoConvergence", iStereoConvergence);
|
||||
enhancements->Set("StereoSwapEyes", bStereoSwapEyes);
|
||||
|
||||
IniFile::Section* hacks = iniFile.GetOrCreateSection("Hacks");
|
||||
hacks->Set("EFBAccessEnable", bEFBAccessEnable);
|
||||
|
@ -44,6 +44,14 @@ enum EFBScale
|
||||
SCALE_4X,
|
||||
};
|
||||
|
||||
enum StereoMode
|
||||
{
|
||||
STEREO_OFF = 0,
|
||||
STEREO_SBS,
|
||||
STEREO_TAB,
|
||||
STEREO_ANAGLYPH
|
||||
};
|
||||
|
||||
// NEVER inherit from this class.
|
||||
struct VideoConfig final
|
||||
{
|
||||
@ -71,6 +79,10 @@ struct VideoConfig final
|
||||
bool bForceFiltering;
|
||||
int iMaxAnisotropy;
|
||||
std::string sPostProcessingShader;
|
||||
int iStereoMode;
|
||||
int iStereoSeparation;
|
||||
int iStereoConvergence;
|
||||
bool bStereoSwapEyes;
|
||||
|
||||
// Information
|
||||
bool bShowFPS;
|
||||
@ -92,9 +104,6 @@ struct VideoConfig final
|
||||
bool bDumpEFBTarget;
|
||||
bool bUseFFV1;
|
||||
bool bFreeLook;
|
||||
bool bAnaglyphStereo;
|
||||
int iAnaglyphStereoSeparation;
|
||||
int iAnaglyphFocalAngle;
|
||||
bool bBorderlessFullscreen;
|
||||
|
||||
// Hacks
|
||||
@ -115,6 +124,11 @@ struct VideoConfig final
|
||||
int iLog; // CONF_ bits
|
||||
int iSaveTargetId; // TODO: Should be dropped
|
||||
|
||||
// Stereoscopy
|
||||
bool bStereoMonoEFBDepth;
|
||||
int iStereoSeparationPercent;
|
||||
int iStereoConvergencePercent;
|
||||
|
||||
// D3D only config, mostly to be merged into the above
|
||||
int iAdapter;
|
||||
|
||||
@ -136,9 +150,11 @@ struct VideoConfig final
|
||||
bool bSupportsDualSourceBlend;
|
||||
bool bSupportsPrimitiveRestart;
|
||||
bool bSupportsOversizedViewports;
|
||||
bool bSupportsStereoscopy;
|
||||
bool bSupportsEarlyZ; // needed by PixelShaderGen, so must stay in VideoCommon
|
||||
bool bSupportsBindingLayout; // Needed by ShaderGen, so must stay in VideoCommon
|
||||
bool bSupportsBBox;
|
||||
bool bSupportsGSInstancing; // Needed by GeometryShaderGen, so must stay in VideoCommon
|
||||
} backend_info;
|
||||
|
||||
// Utility
|
||||
|
Reference in New Issue
Block a user