mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
VideoBackends: Move SamplerState to common
This commit is contained in:
@ -22,7 +22,7 @@ bool geometry_shader_uid_data::IsPassthrough() const
|
||||
{
|
||||
const bool stereo = g_ActiveConfig.iStereoMode > 0;
|
||||
const bool wireframe = g_ActiveConfig.bWireFrame;
|
||||
return primitive_type >= PrimitiveType::Triangles && !stereo && !wireframe;
|
||||
return primitive_type >= static_cast<u32>(PrimitiveType::Triangles) && !stereo && !wireframe;
|
||||
}
|
||||
|
||||
GeometryShaderUid GetGeometryShaderUid(PrimitiveType primitive_type)
|
||||
@ -31,7 +31,7 @@ GeometryShaderUid GetGeometryShaderUid(PrimitiveType primitive_type)
|
||||
geometry_shader_uid_data* uid_data = out.GetUidData<geometry_shader_uid_data>();
|
||||
memset(uid_data, 0, sizeof(geometry_shader_uid_data));
|
||||
|
||||
uid_data->primitive_type = primitive_type;
|
||||
uid_data->primitive_type = static_cast<u32>(primitive_type);
|
||||
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
|
||||
|
||||
return out;
|
||||
@ -56,9 +56,10 @@ 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 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);
|
||||
unsigned vertex_out = uid_data->primitive_type == PrimitiveType::TriangleStrip ? 3 : 4;
|
||||
unsigned vertex_out = primitive_type == PrimitiveType::TriangleStrip ? 3 : 4;
|
||||
|
||||
if (wireframe)
|
||||
vertex_out++;
|
||||
@ -146,7 +147,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
|
||||
out.Write("\tVertexData ps;\n");
|
||||
}
|
||||
|
||||
if (uid_data->primitive_type == PrimitiveType::Lines)
|
||||
if (primitive_type == PrimitiveType::Lines)
|
||||
{
|
||||
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
||||
{
|
||||
@ -177,7 +178,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
|
||||
"\t\toffset = float2(0, -" I_LINEPTPARAMS ".z / " I_LINEPTPARAMS ".y);\n"
|
||||
"\t}\n");
|
||||
}
|
||||
else if (uid_data->primitive_type == PrimitiveType::Points)
|
||||
else if (primitive_type == PrimitiveType::Points)
|
||||
{
|
||||
if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan)
|
||||
{
|
||||
@ -247,7 +248,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
|
||||
out.Write("\tf.pos.x += hoffset * (f.pos.w - " I_STEREOPARAMS ".z);\n");
|
||||
}
|
||||
|
||||
if (uid_data->primitive_type == PrimitiveType::Lines)
|
||||
if (primitive_type == PrimitiveType::Lines)
|
||||
{
|
||||
out.Write("\tVS_OUTPUT l = f;\n"
|
||||
"\tVS_OUTPUT r = f;\n");
|
||||
@ -268,7 +269,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const ShaderHostConfig& h
|
||||
EmitVertex(out, host_config, uid_data, "l", ApiType, wireframe, pixel_lighting, true);
|
||||
EmitVertex(out, host_config, uid_data, "r", ApiType, wireframe, pixel_lighting);
|
||||
}
|
||||
else if (uid_data->primitive_type == PrimitiveType::Points)
|
||||
else if (primitive_type == PrimitiveType::Points)
|
||||
{
|
||||
out.Write("\tVS_OUTPUT ll = f;\n"
|
||||
"\tVS_OUTPUT lr = f;\n"
|
||||
@ -376,7 +377,7 @@ void EnumerateGeometryShaderUids(const std::function<void(const GeometryShaderUi
|
||||
for (PrimitiveType primitive : primitive_lut)
|
||||
{
|
||||
auto* guid = uid.GetUidData<geometry_shader_uid_data>();
|
||||
guid->primitive_type = primitive;
|
||||
guid->primitive_type = static_cast<u32>(primitive);
|
||||
|
||||
for (u32 texgens = 0; texgens <= 8; texgens++)
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ struct geometry_shader_uid_data
|
||||
bool IsPassthrough() const;
|
||||
|
||||
u32 numTexGens : 4;
|
||||
PrimitiveType primitive_type : 2;
|
||||
u32 primitive_type : 2;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
virtual void SetScissorRect(const EFBRectangle& rc) {}
|
||||
virtual void SetRasterizationState(const RasterizationState& state) {}
|
||||
virtual void SetDepthState(const DepthState& state) {}
|
||||
virtual void SetSamplerState(int stage, int texindex, bool custom_tex) {}
|
||||
virtual void SetSamplerState(u32 index, const SamplerState& state) {}
|
||||
virtual void SetInterlacingMode() {}
|
||||
virtual void SetViewport() {}
|
||||
virtual void SetFullscreen(bool enable_fullscreen) {}
|
||||
|
@ -3,6 +3,9 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "VideoCommon/RenderState.h"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include "VideoCommon/SamplerCommon.h"
|
||||
|
||||
void RasterizationState::Generate(const BPMemory& bp, PrimitiveType primitive_type)
|
||||
{
|
||||
@ -14,6 +17,12 @@ void RasterizationState::Generate(const BPMemory& bp, PrimitiveType primitive_ty
|
||||
cullmode = GenMode::CULL_NONE;
|
||||
}
|
||||
|
||||
RasterizationState& RasterizationState::operator=(const RasterizationState& rhs)
|
||||
{
|
||||
hex = rhs.hex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void DepthState::Generate(const BPMemory& bp)
|
||||
{
|
||||
testenable = bp.zmode.testenable.Value();
|
||||
@ -21,6 +30,12 @@ void DepthState::Generate(const BPMemory& bp)
|
||||
func = bp.zmode.func.Value();
|
||||
}
|
||||
|
||||
DepthState& DepthState::operator=(const DepthState& rhs)
|
||||
{
|
||||
hex = rhs.hex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// If the framebuffer format has no alpha channel, it is assumed to
|
||||
// ONE on blending. As the backends may emulate this framebuffer
|
||||
// configuration with an alpha channel, we just drop all references
|
||||
@ -145,6 +160,43 @@ void BlendingState::Generate(const BPMemory& bp)
|
||||
}
|
||||
}
|
||||
|
||||
BlendingState& BlendingState::operator=(const BlendingState& rhs)
|
||||
{
|
||||
hex = rhs.hex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SamplerState::Generate(const BPMemory& bp, u32 index)
|
||||
{
|
||||
const FourTexUnits& tex = bpmem.tex[index / 4];
|
||||
const TexMode0& tm0 = tex.texMode0[index % 4];
|
||||
const TexMode1& tm1 = tex.texMode1[index % 4];
|
||||
|
||||
// GX can configure the mip filter to none. However, D3D and Vulkan can't express this in their
|
||||
// sampler states. Therefore, we set the min/max LOD to zero if this option is used.
|
||||
min_filter = (tm0.min_filter & 4) != 0 ? Filter::Linear : Filter::Point;
|
||||
mipmap_filter = (tm0.min_filter & 3) == TexMode0::TEXF_LINEAR ? Filter::Linear : Filter::Point;
|
||||
mag_filter = tm0.mag_filter != 0 ? Filter::Linear : Filter::Point;
|
||||
|
||||
// If mipmaps are disabled, clamp min/max lod
|
||||
max_lod = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? tm1.max_lod : 0;
|
||||
min_lod = std::min(max_lod.Value(), tm1.min_lod);
|
||||
lod_bias = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? tm0.lod_bias : 0;
|
||||
|
||||
// Address modes
|
||||
static constexpr std::array<AddressMode, 4> address_modes = {
|
||||
{AddressMode::Clamp, AddressMode::Repeat, AddressMode::MirroredRepeat, AddressMode::Repeat}};
|
||||
wrap_u = address_modes[tm0.wrap_s];
|
||||
wrap_v = address_modes[tm0.wrap_t];
|
||||
anisotropic_filtering = 0;
|
||||
}
|
||||
|
||||
SamplerState& SamplerState::operator=(const SamplerState& rhs)
|
||||
{
|
||||
hex = rhs.hex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
namespace RenderState
|
||||
{
|
||||
RasterizationState GetNoCullRasterizationState()
|
||||
@ -177,4 +229,34 @@ BlendingState GetNoBlendingBlendState()
|
||||
state.alphaupdate = true;
|
||||
return state;
|
||||
}
|
||||
|
||||
SamplerState GetPointSamplerState()
|
||||
{
|
||||
SamplerState state = {};
|
||||
state.min_filter = SamplerState::Filter::Point;
|
||||
state.mag_filter = SamplerState::Filter::Point;
|
||||
state.mipmap_filter = SamplerState::Filter::Point;
|
||||
state.wrap_u = SamplerState::AddressMode::Clamp;
|
||||
state.wrap_v = SamplerState::AddressMode::Clamp;
|
||||
state.min_lod = 0;
|
||||
state.max_lod = 255;
|
||||
state.lod_bias = 0;
|
||||
state.anisotropic_filtering = false;
|
||||
return state;
|
||||
}
|
||||
|
||||
SamplerState GetLinearSamplerState()
|
||||
{
|
||||
SamplerState state = {};
|
||||
state.min_filter = SamplerState::Filter::Linear;
|
||||
state.mag_filter = SamplerState::Filter::Linear;
|
||||
state.mipmap_filter = SamplerState::Filter::Linear;
|
||||
state.wrap_u = SamplerState::AddressMode::Clamp;
|
||||
state.wrap_v = SamplerState::AddressMode::Clamp;
|
||||
state.min_lod = 0;
|
||||
state.max_lod = 255;
|
||||
state.lod_bias = 0;
|
||||
state.anisotropic_filtering = false;
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,11 @@ union RasterizationState
|
||||
{
|
||||
void Generate(const BPMemory& bp, PrimitiveType primitive_type);
|
||||
|
||||
RasterizationState& operator=(const RasterizationState& rhs);
|
||||
|
||||
bool operator==(const RasterizationState& rhs) const { return hex == rhs.hex; }
|
||||
bool operator!=(const RasterizationState& rhs) const { return hex != rhs.hex; }
|
||||
bool operator<(const RasterizationState& rhs) const { return hex < rhs.hex; }
|
||||
BitField<0, 2, GenMode::CullMode> cullmode;
|
||||
BitField<3, 2, PrimitiveType> primitive;
|
||||
|
||||
@ -31,6 +36,11 @@ union DepthState
|
||||
{
|
||||
void Generate(const BPMemory& bp);
|
||||
|
||||
DepthState& operator=(const DepthState& rhs);
|
||||
|
||||
bool operator==(const DepthState& rhs) const { return hex == rhs.hex; }
|
||||
bool operator!=(const DepthState& rhs) const { return hex != rhs.hex; }
|
||||
bool operator<(const DepthState& rhs) const { return hex < rhs.hex; }
|
||||
BitField<0, 1, u32> testenable;
|
||||
BitField<1, 1, u32> updateenable;
|
||||
BitField<2, 3, ZMode::CompareMode> func;
|
||||
@ -42,6 +52,11 @@ union BlendingState
|
||||
{
|
||||
void Generate(const BPMemory& bp);
|
||||
|
||||
BlendingState& operator=(const BlendingState& rhs);
|
||||
|
||||
bool operator==(const BlendingState& rhs) const { return hex == rhs.hex; }
|
||||
bool operator!=(const BlendingState& rhs) const { return hex != rhs.hex; }
|
||||
bool operator<(const BlendingState& rhs) const { return hex < rhs.hex; }
|
||||
BitField<0, 1, u32> blendenable;
|
||||
BitField<1, 1, u32> logicopenable;
|
||||
BitField<2, 1, u32> dstalpha;
|
||||
@ -59,9 +74,46 @@ union BlendingState
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union SamplerState
|
||||
{
|
||||
enum class Filter : u32
|
||||
{
|
||||
Point,
|
||||
Linear
|
||||
};
|
||||
|
||||
enum class AddressMode : u32
|
||||
{
|
||||
Clamp,
|
||||
Repeat,
|
||||
MirroredRepeat
|
||||
};
|
||||
|
||||
void Generate(const BPMemory& bp, u32 index);
|
||||
|
||||
SamplerState& operator=(const SamplerState& rhs);
|
||||
|
||||
bool operator==(const SamplerState& rhs) const { return hex == rhs.hex; }
|
||||
bool operator!=(const SamplerState& rhs) const { return hex != rhs.hex; }
|
||||
bool operator<(const SamplerState& rhs) const { return hex < rhs.hex; }
|
||||
BitField<0, 1, Filter> min_filter;
|
||||
BitField<1, 1, Filter> mag_filter;
|
||||
BitField<2, 1, Filter> mipmap_filter;
|
||||
BitField<3, 2, AddressMode> wrap_u;
|
||||
BitField<5, 2, AddressMode> wrap_v;
|
||||
BitField<7, 8, u32> min_lod; // multiplied by 16
|
||||
BitField<15, 8, u32> max_lod; // multiplied by 16
|
||||
BitField<23, 8, s32> lod_bias; // multiplied by 32
|
||||
BitField<31, 1, u32> anisotropic_filtering;
|
||||
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
namespace RenderState
|
||||
{
|
||||
RasterizationState GetNoCullRasterizationState();
|
||||
DepthState GetNoDepthTestingDepthStencilState();
|
||||
BlendingState GetNoBlendingBlendState();
|
||||
SamplerState GetPointSamplerState();
|
||||
SamplerState GetLinearSamplerState();
|
||||
}
|
||||
|
@ -24,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"
|
||||
@ -208,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)
|
||||
@ -276,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
|
||||
|
Reference in New Issue
Block a user