Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
WIP - rendering N views at once, instead of 1 or 2
  • Loading branch information
kevinw committed May 26, 2020
1 parent 6870697 commit aa75629
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 9 deletions.
6 changes: 6 additions & 0 deletions Source/Core/Core/Config/GraphicsSettings.cpp
Expand Up @@ -130,6 +130,12 @@ const Info<bool> GFX_STEREO_EFB_MONO_DEPTH{{System::GFX, "Stereoscopy", "StereoE
false};
const Info<int> GFX_STEREO_DEPTH_PERCENTAGE{{System::GFX, "Stereoscopy", "StereoDepthPercentage"},
100};
const Info<int> GFX_STEREO_QUILT_VIEWS_WIDE{{System::GFX, "Stereoscopy", "StereoQuiltViewsWide"},
4};
const Info<int> GFX_STEREO_QUILT_VIEWS_TALL{{System::GFX, "Stereoscopy", "StereoQuiltViewsTall"},
4};
const Info<int> GFX_STEREO_MULTIVIEW_LAYERS_COUNT{{System::GFX, "Stereoscopy", "StereoMultiviewLayersCount"},
16};

// Graphics.Hacks

Expand Down
3 changes: 3 additions & 0 deletions Source/Core/Core/Config/GraphicsSettings.h
Expand Up @@ -101,6 +101,9 @@ extern const Info<bool> GFX_STEREO_SWAP_EYES;
extern const Info<int> GFX_STEREO_CONVERGENCE;
extern const Info<bool> GFX_STEREO_EFB_MONO_DEPTH;
extern const Info<int> GFX_STEREO_DEPTH_PERCENTAGE;
extern const Info<int> GFX_STEREO_QUILT_VIEWS_WIDE;
extern const Info<int> GFX_STEREO_QUILT_VIEWS_TALL;
extern const Info<int> GFX_STEREO_MULTIVIEW_LAYERS_COUNT;

// Stereoscopy pseudo-limits for consistent behavior between enhancements tab and hotkeys.
static constexpr int GFX_STEREO_DEPTH_MAXIMUM = 100;
Expand Down
13 changes: 12 additions & 1 deletion Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp
Expand Up @@ -19,6 +19,7 @@
#include "DolphinQt/Config/Graphics/GraphicsChoice.h"
#include "DolphinQt/Config/Graphics/GraphicsSlider.h"
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
#include "DolphinQt/Config/Graphics/GraphicsInteger.h"
#include "DolphinQt/Config/Graphics/PostProcessingConfigWindow.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/Settings.h"
Expand Down Expand Up @@ -120,12 +121,16 @@ void EnhancementsWidget::CreateWidgets()
stereoscopy_box->setLayout(stereoscopy_layout);

m_3d_mode = new GraphicsChoice({tr("Off"), tr("Side-by-Side"), tr("Top-and-Bottom"),
tr("Anaglyph"), tr("HDMI 3D"), tr("Passive")},
tr("Anaglyph"), tr("HDMI 3D"), tr("Passive"),
tr("Quilt"), tr("Multiview Layers")},
Config::GFX_STEREO_MODE);
m_3d_depth = new GraphicsSlider(0, Config::GFX_STEREO_DEPTH_MAXIMUM, Config::GFX_STEREO_DEPTH);
m_3d_convergence = new GraphicsSlider(0, Config::GFX_STEREO_CONVERGENCE_MAXIMUM,
Config::GFX_STEREO_CONVERGENCE, 100);
m_3d_swap_eyes = new GraphicsBool(tr("Swap Eyes"), Config::GFX_STEREO_SWAP_EYES);
m_quilt_views_wide = new GraphicsInteger(2, 5, Config::GFX_STEREO_QUILT_VIEWS_WIDE);
m_quilt_views_tall = new GraphicsInteger(2, 9, Config::GFX_STEREO_QUILT_VIEWS_TALL);
m_multiview_layers_count = new GraphicsInteger(1, 45, Config::GFX_STEREO_MULTIVIEW_LAYERS_COUNT);

stereoscopy_layout->addWidget(new QLabel(tr("Stereoscopic 3D Mode:")), 0, 0);
stereoscopy_layout->addWidget(m_3d_mode, 0, 1);
Expand All @@ -134,6 +139,12 @@ void EnhancementsWidget::CreateWidgets()
stereoscopy_layout->addWidget(new QLabel(tr("Convergence:")), 2, 0);
stereoscopy_layout->addWidget(m_3d_convergence, 2, 1);
stereoscopy_layout->addWidget(m_3d_swap_eyes, 3, 0);
stereoscopy_layout->addWidget(new QLabel(tr("Quilt Num Views Wide:")), 4, 0);
stereoscopy_layout->addWidget(m_quilt_views_wide, 4, 1);
stereoscopy_layout->addWidget(new QLabel(tr("Quilt Num Views Tall:")), 5, 0);
stereoscopy_layout->addWidget(m_quilt_views_tall, 5, 1);
stereoscopy_layout->addWidget(new QLabel(tr("Multiview Layers Count:")), 6, 0);
stereoscopy_layout->addWidget(m_multiview_layers_count, 6, 1);

main_layout->addWidget(enhancements_box);
main_layout->addWidget(stereoscopy_box);
Expand Down
4 changes: 4 additions & 0 deletions Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h
Expand Up @@ -11,6 +11,7 @@ class QCheckBox;
class QComboBox;
class QPushButton;
class QSlider;
class QSpinBox;

class EnhancementsWidget final : public GraphicsWidget
{
Expand Down Expand Up @@ -48,6 +49,9 @@ class EnhancementsWidget final : public GraphicsWidget
QSlider* m_3d_depth;
QSlider* m_3d_convergence;
QCheckBox* m_3d_swap_eyes;
QSpinBox* m_quilt_views_wide;
QSpinBox* m_quilt_views_tall;
QSpinBox* m_multiview_layers_count;

int m_msaa_modes;
bool m_block_save;
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoCommon/FramebufferManager.cpp
Expand Up @@ -136,7 +136,7 @@ AbstractTextureFormat FramebufferManager::GetEFBDepthCopyFormat()

static u32 CalculateEFBLayers()
{
return (g_ActiveConfig.stereo_mode != StereoMode::Off) ? 2 : 1;
return g_ActiveConfig.GetNumStereoLayers();
}

TextureConfig FramebufferManager::GetEFBColorTextureConfig()
Expand Down
13 changes: 8 additions & 5 deletions Source/Core/VideoCommon/GeometryShaderGen.cpp
Expand Up @@ -7,6 +7,7 @@
#include <cmath>

#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "VideoCommon/DriverDetails.h"
#include "VideoCommon/LightingShaderGen.h"
#include "VideoCommon/VideoCommon.h"
Expand Down Expand Up @@ -51,6 +52,8 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
const bool msaa = host_config.msaa;
const bool ssaa = host_config.ssaa;
const bool stereo = host_config.stereo;
const uint16_t stereo_num_views = host_config.stereo_num_views;
INFO_LOG(HOST_GPU, "in geo shader gen: stereo_num_views %d", stereo_num_views);
const PrimitiveType primitive_type = static_cast<PrimitiveType>(uid_data->primitive_type);
const unsigned primitive_type_index = static_cast<unsigned>(uid_data->primitive_type);
const unsigned vertex_in = std::min(static_cast<unsigned>(primitive_type_index) + 1, 3u);
Expand All @@ -65,15 +68,15 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
if (host_config.backend_gs_instancing)
{
out.Write("layout(%s, invocations = %d) in;\n", primitives_ogl[primitive_type_index],
stereo ? 2 : 1);
stereo ? stereo_num_views : 1);
out.Write("layout(%s_strip, max_vertices = %d) out;\n", wireframe ? "line" : "triangle",
vertex_out);
}
else
{
out.Write("layout(%s) in;\n", primitives_ogl[primitive_type_index]);
out.Write("layout(%s_strip, max_vertices = %d) out;\n", wireframe ? "line" : "triangle",
stereo ? vertex_out * 2 : vertex_out);
stereo ? vertex_out * stereo_num_views : vertex_out);
}
}

Expand Down Expand Up @@ -127,14 +130,14 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h

if (host_config.backend_gs_instancing)
{
out.Write("[maxvertexcount(%d)]\n[instance(%d)]\n", vertex_out, stereo ? 2 : 1);
out.Write("[maxvertexcount(%d)]\n[instance(%d)]\n", vertex_out, stereo ? stereo_num_views : 1);
out.Write("void main(%s VS_OUTPUT o[%d], inout %sStream<VertexData> output, in uint "
"InstanceID : SV_GSInstanceID)\n{\n",
primitives_d3d[primitive_type_index], vertex_in, wireframe ? "Line" : "Triangle");
}
else
{
out.Write("[maxvertexcount(%d)]\n", stereo ? vertex_out * 2 : vertex_out);
out.Write("[maxvertexcount(%d)]\n", stereo ? vertex_out * stereo_num_views : vertex_out);
out.Write("void main(%s VS_OUTPUT o[%d], inout %sStream<VertexData> output)\n{\n",
primitives_d3d[primitive_type_index], vertex_in, wireframe ? "Line" : "Triangle");
}
Expand Down Expand Up @@ -198,7 +201,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
if (host_config.backend_gs_instancing)
out.Write("\tint eye = InstanceID;\n");
else
out.Write("\tfor (int eye = 0; eye < 2; ++eye) {\n");
out.Write("\tfor (int eye = 0; eye < %d; ++eye) {\n", stereo_num_views);
}

if (wireframe)
Expand Down
68 changes: 68 additions & 0 deletions Source/Core/VideoCommon/RenderBase.cpp
Expand Up @@ -21,6 +21,7 @@
#include <mutex>
#include <string>
#include <tuple>
#include <vector>

#include <fmt/format.h>
#include <imgui.h>
Expand Down Expand Up @@ -337,6 +338,65 @@ bool Renderer::CalculateTargetSize()
return false;
}

void Renderer::ConvertStereoRectangles(const MathUtil::Rectangle<int>& rc, std::vector<MathUtil::Rectangle<int>>& stereo_rects) const {

if (g_ActiveConfig.stereo_mode == StereoMode::Quilt ||
g_ActiveConfig.stereo_mode == StereoMode::MultiviewLayers)
{
auto numViews = g_ActiveConfig.GetNumStereoLayers();

int w = (float)(rc.right - rc.left) / (float)(numViews);
for (u32 i = 0; i < numViews; ++i)
{
MathUtil::Rectangle<int> stereo_rect;
stereo_rect.left = rc.left + i * w;
stereo_rect.right = rc.left + i * w + w;
stereo_rect.top = rc.top;
stereo_rect.bottom = rc.bottom;
stereo_rects.push_back(stereo_rect);
}

return;
}

// Resize target to half its original size
auto draw_rc = rc;
if (g_ActiveConfig.stereo_mode == StereoMode::TAB)
{
// The height may be negative due to flipped rectangles
int height = rc.bottom - rc.top;
draw_rc.top += height / 4;
draw_rc.bottom -= height / 4;
}
else
{
int width = rc.right - rc.left;
draw_rc.left += width / 4;
draw_rc.right -= width / 4;
}

// Create two target rectangle offset to the sides of the backbuffer
auto left_rc = draw_rc;
auto right_rc = draw_rc;
if (g_ActiveConfig.stereo_mode == StereoMode::TAB)
{
left_rc.top -= m_backbuffer_height / 4;
left_rc.bottom -= m_backbuffer_height / 4;
right_rc.top += m_backbuffer_height / 4;
right_rc.bottom += m_backbuffer_height / 4;
}
else
{
left_rc.left -= m_backbuffer_width / 4;
left_rc.right -= m_backbuffer_width / 4;
right_rc.left += m_backbuffer_width / 4;
right_rc.right += m_backbuffer_width / 4;
}

stereo_rects.push_back(left_rc);
stereo_rects.push_back(right_rc);
}

std::tuple<MathUtil::Rectangle<int>, MathUtil::Rectangle<int>>
Renderer::ConvertStereoRectangle(const MathUtil::Rectangle<int>& rc) const
{
Expand Down Expand Up @@ -1348,6 +1408,14 @@ void Renderer::RenderXFBToScreen(const MathUtil::Rectangle<int>& target_rc,
m_post_processor->BlitFromTexture(left_rc, source_rc, source_texture, 0);
m_post_processor->BlitFromTexture(right_rc, source_rc, source_texture, 1);
}
else if (g_ActiveConfig.GetNumStereoLayers() > 1) {
std::vector<MathUtil::Rectangle<int>> stereo_rects;
ConvertStereoRectangles(target_rc, stereo_rects);

for (auto i = 0; i < stereo_rects.size(); ++i) {
m_post_processor->BlitFromTexture(stereo_rects[i], source_rc, source_texture, i);
}
}
else
{
m_post_processor->BlitFromTexture(target_rc, source_rc, source_texture, 0);
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/VideoCommon/RenderBase.h
Expand Up @@ -188,6 +188,8 @@ class Renderer
std::tuple<MathUtil::Rectangle<int>, MathUtil::Rectangle<int>>
ConvertStereoRectangle(const MathUtil::Rectangle<int>& rc) const;

void ConvertStereoRectangles(const MathUtil::Rectangle<int>& rc, std::vector<MathUtil::Rectangle<int>>& stereo_rects) const;

unsigned int GetEFBScale() const;

// Use this to upscale native EFB coordinates to IDEAL internal resolution
Expand Down
1 change: 1 addition & 0 deletions Source/Core/VideoCommon/ShaderGenCommon.cpp
Expand Up @@ -16,6 +16,7 @@ ShaderHostConfig ShaderHostConfig::GetCurrent()
bits.ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA &&
g_ActiveConfig.backend_info.bSupportsSSAA;
bits.stereo = g_ActiveConfig.stereo_mode != StereoMode::Off;
bits.stereo_num_views = g_ActiveConfig.GetNumStereoLayers();
bits.wireframe = g_ActiveConfig.bWireFrame;
bits.per_pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
bits.vertex_rounding = g_ActiveConfig.UseVertexRounding();
Expand Down
3 changes: 2 additions & 1 deletion Source/Core/VideoCommon/ShaderGenCommon.h
Expand Up @@ -183,7 +183,8 @@ union ShaderHostConfig
u32 backend_shader_framebuffer_fetch : 1;
u32 backend_logic_op : 1;
u32 backend_palette_conversion : 1;
u32 pad : 9;
u32 stereo_num_views : 6;
u32 pad : 3;
};

static ShaderHostConfig GetCurrent();
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/VideoCommon/VideoConfig.cpp
Expand Up @@ -142,6 +142,9 @@ void VideoConfig::Refresh()
iStereoConvergence = Config::Get(Config::GFX_STEREO_CONVERGENCE);
bStereoEFBMonoDepth = Config::Get(Config::GFX_STEREO_EFB_MONO_DEPTH);
iStereoDepthPercentage = Config::Get(Config::GFX_STEREO_DEPTH_PERCENTAGE);
iQuiltViewsWide = Config::Get(Config::GFX_STEREO_QUILT_VIEWS_WIDE);
iQuiltViewsTall = Config::Get(Config::GFX_STEREO_QUILT_VIEWS_TALL);
iMultiviewLayersCount = Config::Get(Config::GFX_STEREO_MULTIVIEW_LAYERS_COUNT);

bEFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE);
bEFBAccessDeferInvalidation = Config::Get(Config::GFX_HACK_EFB_DEFER_INVALIDATION);
Expand Down
19 changes: 18 additions & 1 deletion Source/Core/VideoCommon/VideoConfig.h
Expand Up @@ -40,7 +40,9 @@ enum class StereoMode : int
TAB,
Anaglyph,
QuadBuffer,
Passive
Passive,
Quilt,
MultiviewLayers
};

enum class ShaderCompilationMode : int
Expand Down Expand Up @@ -148,6 +150,9 @@ struct VideoConfig final
int iStereoDepth;
int iStereoConvergence;
int iStereoConvergencePercentage;
int iMultiviewLayersCount;
int iQuiltViewsWide;
int iQuiltViewsTall;
bool bStereoSwapEyes;
bool bStereoEFBMonoDepth;
int iStereoDepthPercentage;
Expand Down Expand Up @@ -248,6 +253,18 @@ struct VideoConfig final
bool UsingUberShaders() const;
u32 GetShaderCompilerThreads() const;
u32 GetShaderPrecompilerThreads() const;
u32 GetNumStereoLayers() const {
switch (stereo_mode) {
case StereoMode::Off:
return 1;
case StereoMode::Quilt:
return iQuiltViewsWide * iQuiltViewsTall;
case StereoMode::MultiviewLayers:
return iMultiviewLayersCount;
default:
return 2;
}
}
};

extern VideoConfig g_Config;
Expand Down

0 comments on commit aa75629

Please sign in to comment.