D3D: Add geometry shader stereoscopy support.

This commit is contained in:
Jules Blok 2014-11-02 23:40:52 +01:00
parent d5ebdf7a97
commit 9253bb7d96
10 changed files with 112 additions and 73 deletions

View File

@ -57,7 +57,7 @@ FramebufferManager::FramebufferManager()
D3D11_TEXTURE2D_DESC texdesc; D3D11_TEXTURE2D_DESC texdesc;
HRESULT hr; HRESULT hr;
m_efb.slices = 1; m_efb.slices = (g_ActiveConfig.iStereoMode > 0) ? 2 : 1;
// EFB color texture - primary render target // EFB color texture - primary render target
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality); texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality);

View File

@ -173,7 +173,7 @@ bool LineGeometryShader::SetShader(u32 components, float lineWidth,
static char buffer[16384]; static char buffer[16384];
ShaderCode code; ShaderCode code;
code.SetBuffer(buffer); code.SetBuffer(buffer);
GenerateVSOutputStruct(code, API_D3D); GenerateVSOutputStruct<ShaderCode>(code, API_D3D);
code.Write("\n%s", LINE_GS_COMMON); code.Write("\n%s", LINE_GS_COMMON);
std::stringstream numTexCoordsStream; std::stringstream numTexCoordsStream;

View File

@ -167,7 +167,7 @@ bool PointGeometryShader::SetShader(u32 components, float pointSize,
static char buffer[16384]; static char buffer[16384];
ShaderCode code; ShaderCode code;
code.SetBuffer(buffer); code.SetBuffer(buffer);
GenerateVSOutputStruct(code, API_D3D); GenerateVSOutputStruct<ShaderCode>(code, API_D3D);
code.Write("\n%s", POINT_GS_COMMON); code.Write("\n%s", POINT_GS_COMMON);
std::stringstream numTexCoordsStream; std::stringstream numTexCoordsStream;

View File

@ -214,10 +214,20 @@ void VertexManager::vFlush(bool useDstAlpha)
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
return; return;
} }
if (g_ActiveConfig.iStereoMode > 0)
{
if (!GeometryShaderCache::SetShader(components))
{
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR, true, { printf("Fail to set pixel shader\n"); });
}
}
if (g_ActiveConfig.backend_info.bSupportsBBox && BoundingBox::active) if (g_ActiveConfig.backend_info.bSupportsBBox && BoundingBox::active)
{ {
D3D::context->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, 2, 1, &BBox::GetUAV(), nullptr); D3D::context->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, 2, 1, &BBox::GetUAV(), nullptr);
} }
u32 stride = VertexLoaderManager::GetCurrentVertexFormat()->GetVertexStride(); u32 stride = VertexLoaderManager::GetCurrentVertexFormat()->GetVertexStride();
PrepareDrawBuffers(stride); PrepareDrawBuffers(stride);

View File

@ -79,7 +79,8 @@ void InitBackendInfo()
g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsDualSourceBlend = true;
g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsPrimitiveRestart = true;
g_Config.backend_info.bSupportsOversizedViewports = false; g_Config.backend_info.bSupportsOversizedViewports = false;
g_Config.backend_info.bSupportsStereoscopy = false; // TODO: not implemented g_Config.backend_info.bSupportsStereoscopy = true;
g_Config.backend_info.bSupportsGSInstancing = false;
IDXGIFactory* factory; IDXGIFactory* factory;
IDXGIAdapter* ad; IDXGIAdapter* ad;

View File

@ -52,14 +52,25 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy
uid_data->numTexGens = xfmem.numTexGen.numTexGens; uid_data->numTexGens = xfmem.numTexGen.numTexGens;
uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting; uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
GenerateVSOutputStruct(out, ApiType); GenerateVSOutputStruct<T>(out, ApiType);
GenerateGSOutputStruct<T>(out, ApiType);
out.Write("centroid in VS_OUTPUT o[3];\n"); if (ApiType == API_OPENGL)
out.Write("centroid out VS_OUTPUT f;\n"); {
out.Write("centroid in VS_OUTPUT o[3];\n");
out.Write("centroid out GS_OUTPUT gs;\n");
out.Write("flat out int layer;\n"); out.Write("void main()\n{\n");
}
else // D3D
{
out.Write("[maxvertexcount(6)]\n");
out.Write("void main(triangle VS_OUTPUT o[3], inout TriangleStream<GS_OUTPUT> Output)\n{\n");
out.Write("void main()\n{\n"); out.Write("\tGS_OUTPUT gs;\n");
}
out.Write("\tVS_OUTPUT f;\n");
// If the GPU supports invocation we don't need a for loop and can simply use the // 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. // invocation identifier to determine which layer we're rendering.
@ -70,7 +81,10 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy
out.Write("\tfor (int i = 0; i < 3; ++i) {\n"); out.Write("\tfor (int i = 0; i < 3; ++i) {\n");
out.Write("\t\tgs.layer = l;\n"); out.Write("\t\tgs.layer = l;\n");
out.Write("\t\tgl_Layer = l;\n");
if (ApiType == API_OPENGL)
out.Write("\t\tgl_Layer = l;\n");
out.Write("\t\tf = o[i];\n"); out.Write("\t\tf = o[i];\n");
out.Write("\t\tfloat4 pos = o[i].pos;\n"); out.Write("\t\tfloat4 pos = o[i].pos;\n");
@ -88,10 +102,23 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy
} }
out.Write("\t\tf.pos.x = pos.x;\n"); out.Write("\t\tf.pos.x = pos.x;\n");
out.Write("\t\tgl_Position = pos;\n");
out.Write("\t\tEmitVertex();\n"); if (ApiType == API_OPENGL)
out.Write("\t\tgl_Position = pos;\n");
out.Write("\t\tgs.vs = f;\n");
if (ApiType == API_OPENGL)
out.Write("\t\tEmitVertex();\n");
else
out.Write("\t\tOutput.Append(gs);\n");
out.Write("\t}\n"); out.Write("\t}\n");
out.Write("\tEndPrimitive();\n");
if (ApiType == API_OPENGL)
out.Write("\tEndPrimitive();\n");
else
out.Write("\t\tOutput.RestartStrip();\n");
if (!g_ActiveConfig.backend_info.bSupportsGSInstancing) if (!g_ActiveConfig.backend_info.bSupportsGSInstancing)
out.Write("\t}\n"); out.Write("\t}\n");

View File

@ -264,7 +264,8 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
} }
} }
GenerateVSOutputStruct(out, ApiType); GenerateVSOutputStruct<T>(out, ApiType);
GenerateGSOutputStruct<T>(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 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); const bool per_pixel_depth = (bpmem.ztex2.op != ZTEXTURE_DISABLE && bpmem.UseLateDepthTest()) || (!g_ActiveConfig.bFastDepthCalc && bpmem.zmode.testenable && !forced_early_z);
@ -319,8 +320,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
uid_data->stereo = g_ActiveConfig.iStereoMode > 0; uid_data->stereo = g_ActiveConfig.iStereoMode > 0;
if (g_ActiveConfig.iStereoMode > 0) if (g_ActiveConfig.iStereoMode > 0)
{ {
out.Write("centroid in VS_OUTPUT f;\n"); out.Write("centroid in GS_OUTPUT gs;\n");
out.Write("flat in int layer;\n");
} }
else else
{ {
@ -348,19 +348,19 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
// Let's set up attributes // Let's set up attributes
for (unsigned int i = 0; i < numTexgen; ++i) for (unsigned int i = 0; i < numTexgen; ++i)
{ {
out.Write("\tfloat3 uv%d = f.tex%d;\n", i, i); out.Write("\tfloat3 uv%d = gs.vs.tex%d;\n", i, i);
} }
out.Write("\tfloat4 clipPos = f.clipPos;\n"); out.Write("\tfloat4 clipPos = gs.vs.clipPos;\n");
if (g_ActiveConfig.bEnablePixelLighting) if (g_ActiveConfig.bEnablePixelLighting)
{ {
out.Write("\tfloat4 Normal = f.Normal;\n"); out.Write("\tfloat4 Normal = gs.vs.Normal;\n");
} }
} }
// On Mali, global variables must be initialized as constants. // On Mali, global variables must be initialized as constants.
// This is why we initialize these variables locally instead. // 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_0 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "gs.vs.colors_0" : "colors_02");
out.Write("\tfloat4 colors_1 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "f.colors_1" : "colors_12"); out.Write("\tfloat4 colors_1 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "gs.vs.colors_1" : "colors_12");
out.Write("\tfloat4 rawpos = gl_FragCoord;\n"); out.Write("\tfloat4 rawpos = gl_FragCoord;\n");
} }
@ -940,7 +940,7 @@ static inline void SampleTexture(T& out, const char *texcoords, const char *texs
if (ApiType == API_D3D) 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); out.Write("iround(255.0 * Tex%d.Sample(samp%d,%s.xy * " I_TEXDIMS"[%d].xy)).%s;\n", texmap,texmap, texcoords, texmap, texswap);
else else
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); 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 ? "gs.layer" : "0.0", texswap);
} }
static const char *tevAlphaFuncsTable[] = static const char *tevAlphaFuncsTable[] =

View File

@ -14,6 +14,8 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/StringUtil.h" #include "Common/StringUtil.h"
#include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
#include "VideoCommon/XFMemory.h"
/** /**
* Common interface for classes that need to go through the shader generation path (GenerateVertexShader, GeneratePixelShader) * Common interface for classes that need to go through the shader generation path (GenerateVertexShader, GeneratePixelShader)
@ -218,6 +220,55 @@ private:
std::vector<UidT> m_uids; std::vector<UidT> m_uids;
}; };
template<class T>
static void DefineOutputStructMember(T& object, API_TYPE api_type, const char* type, const char* name, int var_index, const char* semantic = "", int semantic_index = -1)
{
object.Write(" %s %s", type, name);
if (var_index != -1)
object.Write("%d", var_index);
if (api_type == API_D3D && strlen(semantic) > 0)
{
if (semantic_index != -1)
object.Write(" : %s%d", semantic, semantic_index);
else
object.Write(" : %s", semantic);
}
object.Write(";\n");
}
template<class T>
static inline void GenerateVSOutputStruct(T& object, API_TYPE api_type)
{
object.Write("struct VS_OUTPUT {\n");
DefineOutputStructMember(object, api_type, "float4", "pos", -1, "POSITION");
DefineOutputStructMember(object, api_type, "float4", "colors_", 0, "COLOR", 0);
DefineOutputStructMember(object, api_type, "float4", "colors_", 1, "COLOR", 1);
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
DefineOutputStructMember(object, api_type, "float3", "tex", i, "TEXCOORD", i);
DefineOutputStructMember(object, api_type, "float4", "clipPos", -1, "TEXCOORD", xfmem.numTexGen.numTexGens);
if (g_ActiveConfig.bEnablePixelLighting)
DefineOutputStructMember(object, api_type, "float4", "Normal", -1, "TEXCOORD", xfmem.numTexGen.numTexGens + 1);
object.Write("};\n");
}
template<class T>
static inline void GenerateGSOutputStruct(T& object, API_TYPE api_type)
{
object.Write("struct GS_OUTPUT {\n");
DefineOutputStructMember(object, api_type, "VS_OUTPUT", "vs", -1, "");
DefineOutputStructMember(object, api_type, (api_type == API_OPENGL) ? "flat int" : "uint", "layer", -1, "SV_RenderTargetArrayIndex");
object.Write("};\n");
}
// Constant variable names // Constant variable names
#define I_COLORS "color" #define I_COLORS "color"
#define I_KCOLORS "k" #define I_KCOLORS "k"

View File

@ -14,43 +14,6 @@
static char text[16768]; static char text[16768];
template<class T>
static void DefineVSOutputStructMember(T& object, API_TYPE api_type, const char* type, const char* name, int var_index, const char* semantic, int semantic_index = -1)
{
object.Write(" %s %s", type, name);
if (var_index != -1)
object.Write("%d", var_index);
if (api_type == API_OPENGL)
object.Write(";\n");
else // D3D
{
if (semantic_index != -1)
object.Write(" : %s%d;\n", semantic, semantic_index);
else
object.Write(" : %s;\n", semantic);
}
}
template<class T>
static inline void GenerateVSOutputStruct(T& object, API_TYPE api_type)
{
object.Write("struct VS_OUTPUT {\n");
DefineVSOutputStructMember(object, api_type, "float4", "pos", -1, "POSITION");
DefineVSOutputStructMember(object, api_type, "float4", "colors_", 0, "COLOR", 0);
DefineVSOutputStructMember(object, api_type, "float4", "colors_", 1, "COLOR", 1);
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
DefineVSOutputStructMember(object, api_type, "float3", "tex", i, "TEXCOORD", i);
DefineVSOutputStructMember(object, api_type, "float4", "clipPos", -1, "TEXCOORD", xfmem.numTexGen.numTexGens);
if (g_ActiveConfig.bEnablePixelLighting)
DefineVSOutputStructMember(object, api_type, "float4", "Normal", -1, "TEXCOORD", xfmem.numTexGen.numTexGens + 1);
object.Write("};\n");
}
template<class T> template<class T>
static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_type) static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
{ {
@ -79,7 +42,7 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ
out.Write(s_shader_uniforms); out.Write(s_shader_uniforms);
out.Write("};\n"); out.Write("};\n");
GenerateVSOutputStruct(out, api_type); GenerateVSOutputStruct<T>(out, api_type);
uid_data->numTexGens = xfmem.numTexGen.numTexGens; uid_data->numTexGens = xfmem.numTexGen.numTexGens;
uid_data->components = components; uid_data->components = components;
@ -464,13 +427,3 @@ void GenerateVertexShaderCode(VertexShaderCode& object, u32 components, API_TYPE
{ {
GenerateVertexShader<VertexShaderCode>(object, components, api_type); GenerateVertexShader<VertexShaderCode>(object, components, 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
}

View File

@ -7,7 +7,6 @@
#include "VideoCommon/LightingShaderGen.h" #include "VideoCommon/LightingShaderGen.h"
#include "VideoCommon/ShaderGenCommon.h" #include "VideoCommon/ShaderGenCommon.h"
#include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoCommon.h"
#include "VideoCommon/XFMemory.h"
// TODO should be reordered // TODO should be reordered
#define SHADER_POSITION_ATTRIB 0 #define SHADER_POSITION_ATTRIB 0
@ -64,5 +63,3 @@ typedef ShaderCode VertexShaderCode; // TODO: Obsolete..
void GetVertexShaderUid(VertexShaderUid& object, u32 components, API_TYPE api_type); void GetVertexShaderUid(VertexShaderUid& object, u32 components, API_TYPE api_type);
void GenerateVertexShaderCode(VertexShaderCode& object, u32 components, API_TYPE api_type); void GenerateVertexShaderCode(VertexShaderCode& object, u32 components, API_TYPE api_type);
void GenerateVSOutputStruct(ShaderCode& object, API_TYPE api_type);
void GenerateVSOutputStruct(ShaderGeneratorInterface& object, API_TYPE api_type);