Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix missing max vertices in geometry shaders
  • Loading branch information
kevinw committed May 26, 2020
1 parent aa75629 commit 272c74f
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 48 deletions.
10 changes: 5 additions & 5 deletions Source/Core/VideoCommon/FramebufferShaderGen.cpp
Expand Up @@ -238,7 +238,7 @@ std::string GenerateScreenQuadVertexShader()
return ss.str();
}

std::string GeneratePassthroughGeometryShader(u32 num_tex, u32 num_colors)
std::string GeneratePassthroughGeometryShader(u32 num_tex, u32 num_colors, u32 num_layers)
{
std::ostringstream ss;
if (GetAPIType() == APIType::D3D)
Expand All @@ -262,10 +262,10 @@ std::string GeneratePassthroughGeometryShader(u32 num_tex, u32 num_colors)
" uint slice : SV_RenderTargetArrayIndex;\n"
"};\n\n";

ss << "[maxvertexcount(6)]\n"
ss << "[maxvertexcount(" << (3 * num_layers) << ")]\n"
"void main(triangle VS_OUTPUT vso[3], inout TriangleStream<GS_OUTPUT> output)\n"
"{\n"
" for (uint slice = 0; slice < 2u; slice++)\n"
" for (uint slice = 0; slice < " << num_layers << "u; slice++)\n"
" {\n"
" for (int i = 0; i < 3; i++)\n"
" {\n"
Expand All @@ -285,7 +285,7 @@ std::string GeneratePassthroughGeometryShader(u32 num_tex, u32 num_colors)
else if (GetAPIType() == APIType::OpenGL || GetAPIType() == APIType::Vulkan)
{
ss << "layout(triangles) in;\n"
"layout(triangle_strip, max_vertices = 6) out;\n";
"layout(triangle_strip, max_vertices = " << (3 * num_layers) << ") out;\n";
if (num_tex > 0 || num_colors > 0)
{
ss << "VARYING_LOCATION(0) in VertexData {\n";
Expand All @@ -305,7 +305,7 @@ std::string GeneratePassthroughGeometryShader(u32 num_tex, u32 num_colors)
ss << "\n"
"void main()\n"
"{\n"
" for (int j = 0; j < 2; j++)\n"
" for (int j = 0; j < " << num_layers << "; j++)\n"
" {\n"
" gl_Layer = j;\n";

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoCommon/FramebufferShaderGen.h
Expand Up @@ -13,7 +13,7 @@ enum class TextureFormat;
namespace FramebufferShaderGen
{
std::string GenerateScreenQuadVertexShader();
std::string GeneratePassthroughGeometryShader(u32 num_tex, u32 num_colors);
std::string GeneratePassthroughGeometryShader(u32 num_tex, u32 num_colors, u32 num_layers);
std::string GenerateTextureCopyVertexShader();
std::string GenerateTextureCopyPixelShader();
std::string GenerateResolveDepthPixelShader(u32 samples);
Expand Down
99 changes: 60 additions & 39 deletions Source/Core/VideoCommon/RenderBase.cpp
Expand Up @@ -340,61 +340,82 @@ bool Renderer::CalculateTargetSize()

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)
if (g_ActiveConfig.stereo_mode == StereoMode::Quilt)
{
int w = (float)abs(rc.right - rc.left) / (float)g_ActiveConfig.iQuiltViewsWide;
int h = (float)abs(rc.top - rc.bottom) / (float)g_ActiveConfig.iQuiltViewsTall;

// TODO: do we need to maintain the sign of the differences here?

for (int y = 0; y < g_ActiveConfig.iQuiltViewsTall; ++y)
{
for (int x = 0; x < g_ActiveConfig.iQuiltViewsWide; ++x)
{
MathUtil::Rectangle<int> stereo_rect;
stereo_rect.left = rc.left + x * w;
stereo_rect.right = stereo_rect.left + w;
stereo_rect.top = rc.top + y * h;
stereo_rect.bottom = stereo_rect.top + h;
stereo_rects.push_back(stereo_rect);
}
}
}
else if (g_ActiveConfig.stereo_mode == StereoMode::MultiviewLayers)
{
// TODO: this is just laying them out in a series horizontally, which isn't
// actually useful...
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.right = rc.left + i * w + w;
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;
}
// 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;
}
// 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);
stereo_rects.push_back(left_rc);
stereo_rects.push_back(right_rc);
}
}

std::tuple<MathUtil::Rectangle<int>, MathUtil::Rectangle<int>>
Expand Down Expand Up @@ -1030,7 +1051,7 @@ bool Renderer::RecompileImGuiPipeline()
if (UseGeometryShaderForUI())
{
geometry_shader = CreateShaderFromSource(
ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(1, 1));
ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(1, 1, g_ActiveConfig.GetNumStereoLayers()));
if (!geometry_shader)
{
PanicAlert("Failed to compile imgui geometry shader");
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/VideoCommon/ShaderCache.cpp
Expand Up @@ -1214,9 +1214,9 @@ bool ShaderCache::CompileSharedPipelines()
if (UseGeometryShaderForEFBCopies())
{
m_texcoord_geometry_shader = g_renderer->CreateShaderFromSource(
ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(1, 0));
ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(1, 0, g_ActiveConfig.GetNumStereoLayers()));
m_color_geometry_shader = g_renderer->CreateShaderFromSource(
ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(0, 1));
ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(0, 1, g_ActiveConfig.GetNumStereoLayers()));
if (!m_texcoord_geometry_shader || !m_color_geometry_shader)
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoCommon/TextureConfig.h
Expand Up @@ -81,7 +81,7 @@ struct hash<TextureConfig>
result_type operator()(const argument_type& c) const noexcept
{
const u64 id = static_cast<u64>(c.flags) << 58 | static_cast<u64>(c.format) << 50 |
static_cast<u64>(c.layers) << 48 | static_cast<u64>(c.levels) << 32 |
static_cast<u64>(c.layers) << 48 | static_cast<u64>(c.levels) << 32 | // TODO: layers can occupy more than 2 bits now
static_cast<u64>(c.height) << 16 | static_cast<u64>(c.width);
return std::hash<u64>{}(id);
}
Expand Down

0 comments on commit 272c74f

Please sign in to comment.