summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/VertexManagerBase.cpp
diff options
context:
space:
mode:
authorMarkus Wick <degasus@users.noreply.github.com>2017-09-11 13:28:09 +0200
committerGitHub <noreply@github.com>2017-09-11 13:28:09 +0200
commit002e01d0ede3bd0eeebebc09f8f6a813ebc8d444 (patch)
tree5fb17c3d07988499767c51908b49dac2d8d9c881 /Source/Core/VideoCommon/VertexManagerBase.cpp
parent9d169449a7898cefab29a5e033f82560cfcdef5e (diff)
parent24ddea04ce3c843dd1de3d34d775e9a49d195225 (diff)
Merge pull request #5343 from stenzek/videocommon-states
Move depth, rasterization and sampler states to VideoCommon
Diffstat (limited to 'Source/Core/VideoCommon/VertexManagerBase.cpp')
-rw-r--r--Source/Core/VideoCommon/VertexManagerBase.cpp100
1 files changed, 87 insertions, 13 deletions
diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp
index 7807cdb98c..9138b0db09 100644
--- a/Source/Core/VideoCommon/VertexManagerBase.cpp
+++ b/Source/Core/VideoCommon/VertexManagerBase.cpp
@@ -4,6 +4,7 @@
#include "VideoCommon/VertexManagerBase.h"
+#include <array>
#include <cmath>
#include <memory>
@@ -23,6 +24,7 @@
#include "VideoCommon/PerfQueryBase.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/RenderBase.h"
+#include "VideoCommon/SamplerCommon.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VertexShaderManager.h"
@@ -32,15 +34,28 @@
std::unique_ptr<VertexManagerBase> g_vertex_manager;
-static const PrimitiveType primitive_from_gx[8] = {
- PRIMITIVE_TRIANGLES, // GX_DRAW_QUADS
- PRIMITIVE_TRIANGLES, // GX_DRAW_QUADS_2
- PRIMITIVE_TRIANGLES, // GX_DRAW_TRIANGLES
- PRIMITIVE_TRIANGLES, // GX_DRAW_TRIANGLE_STRIP
- PRIMITIVE_TRIANGLES, // GX_DRAW_TRIANGLE_FAN
- PRIMITIVE_LINES, // GX_DRAW_LINES
- PRIMITIVE_LINES, // GX_DRAW_LINE_STRIP
- PRIMITIVE_POINTS, // GX_DRAW_POINTS
+// GX primitive -> RenderState primitive, no primitive restart
+constexpr std::array<PrimitiveType, 8> primitive_from_gx = {
+ PrimitiveType::Triangles, // GX_DRAW_QUADS
+ PrimitiveType::Triangles, // GX_DRAW_QUADS_2
+ PrimitiveType::Triangles, // GX_DRAW_TRIANGLES
+ PrimitiveType::Triangles, // GX_DRAW_TRIANGLE_STRIP
+ PrimitiveType::Triangles, // GX_DRAW_TRIANGLE_FAN
+ PrimitiveType::Lines, // GX_DRAW_LINES
+ PrimitiveType::Lines, // GX_DRAW_LINE_STRIP
+ PrimitiveType::Points, // GX_DRAW_POINTS
+};
+
+// GX primitive -> RenderState primitive, using primitive restart
+constexpr std::array<PrimitiveType, 8> primitive_from_gx_pr = {
+ PrimitiveType::TriangleStrip, // GX_DRAW_QUADS
+ PrimitiveType::TriangleStrip, // GX_DRAW_QUADS_2
+ PrimitiveType::TriangleStrip, // GX_DRAW_TRIANGLES
+ PrimitiveType::TriangleStrip, // GX_DRAW_TRIANGLE_STRIP
+ PrimitiveType::TriangleStrip, // GX_DRAW_TRIANGLE_FAN
+ PrimitiveType::Lines, // GX_DRAW_LINES
+ PrimitiveType::Lines, // GX_DRAW_LINE_STRIP
+ PrimitiveType::Points, // GX_DRAW_POINTS
};
// Due to the BT.601 standard which the GameCube is based on being a compromise
@@ -80,9 +95,19 @@ DataReader VertexManagerBase::PrepareForAdditionalData(int primitive, u32 count,
u32 const needed_vertex_bytes = count * stride + 4;
// We can't merge different kinds of primitives, so we have to flush here
- if (m_current_primitive_type != primitive_from_gx[primitive])
+ PrimitiveType new_primitive_type = g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ?
+ primitive_from_gx_pr[primitive] :
+ primitive_from_gx[primitive];
+ if (m_current_primitive_type != new_primitive_type)
+ {
Flush();
- m_current_primitive_type = primitive_from_gx[primitive];
+
+ // Have to update the rasterization state for point/line cull modes.
+ RasterizationState raster_state = {};
+ raster_state.Generate(bpmem, new_primitive_type);
+ g_renderer->SetRasterizationState(raster_state);
+ m_current_primitive_type = new_primitive_type;
+ }
// Check for size in buffer, if the buffer gets full, call Flush()
if (!m_is_flushed &&
@@ -184,6 +209,52 @@ std::pair<size_t, size_t> VertexManagerBase::ResetFlushAspectRatioCount()
return val;
}
+static void SetSamplerState(u32 index, bool custom_tex)
+{
+ const FourTexUnits& tex = bpmem.tex[index / 4];
+ const TexMode0& tm0 = tex.texMode0[index % 4];
+
+ SamplerState state = {};
+ state.Generate(bpmem, index);
+
+ // Force texture filtering config option.
+ if (g_ActiveConfig.bForceFiltering)
+ {
+ state.min_filter = SamplerState::Filter::Linear;
+ state.mag_filter = SamplerState::Filter::Linear;
+ state.mipmap_filter = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ?
+ SamplerState::Filter::Linear :
+ SamplerState::Filter::Point;
+ }
+
+ // Custom textures may have a greater number of mips
+ if (custom_tex)
+ state.max_lod = 255;
+
+ // Anisotropic filtering option.
+ if (g_ActiveConfig.iMaxAnisotropy != 0 && !SamplerCommon::IsBpTexMode0PointFiltering(tm0))
+ {
+ // https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt
+ // For predictable results on all hardware/drivers, only use one of:
+ // GL_LINEAR + GL_LINEAR (No Mipmaps [Bilinear])
+ // GL_LINEAR + GL_LINEAR_MIPMAP_LINEAR (w/ Mipmaps [Trilinear])
+ // Letting the game set other combinations will have varying arbitrary results;
+ // possibly being interpreted as equal to bilinear/trilinear, implicitly
+ // disabling anisotropy, or changing the anisotropic algorithm employed.
+ state.min_filter = SamplerState::Filter::Linear;
+ state.mag_filter = SamplerState::Filter::Linear;
+ if (SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0))
+ state.mipmap_filter = SamplerState::Filter::Linear;
+ state.anisotropic_filtering = 1;
+ }
+ else
+ {
+ state.anisotropic_filtering = 0;
+ }
+
+ g_renderer->SetSamplerState(index, state);
+}
+
void VertexManagerBase::Flush()
{
if (m_is_flushed)
@@ -252,7 +323,7 @@ void VertexManagerBase::Flush()
if (tentry)
{
- g_renderer->SetSamplerState(i & 3, i >> 2, tentry->is_custom_tex);
+ SetSamplerState(i, tentry->is_custom_tex);
PixelShaderManager::SetTexDims(i, tentry->native_width, tentry->native_height);
}
else
@@ -332,8 +403,11 @@ void VertexManagerBase::CalculateZSlope(NativeVertexFormat* format)
float viewOffset[2] = {xfmem.viewport.xOrig - bpmem.scissorOffset.x * 2,
xfmem.viewport.yOrig - bpmem.scissorOffset.y * 2};
- if (m_current_primitive_type != PRIMITIVE_TRIANGLES)
+ if (m_current_primitive_type != PrimitiveType::Triangles &&
+ m_current_primitive_type != PrimitiveType::TriangleStrip)
+ {
return;
+ }
// Global matrix ID.
u32 mtxIdx = g_main_cp_state.matrix_index_a.PosNormalMtxIdx;