2016-12-29 16:31:51 +00:00
|
|
|
// Copyright 2016 Dolphin Emulator Project
|
2021-07-05 01:22:19 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2016-12-29 16:31:51 +00:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "Common/BitField.h"
|
2023-01-28 02:13:49 +00:00
|
|
|
#include "Common/CommonTypes.h"
|
2016-12-29 16:31:51 +00:00
|
|
|
|
2023-01-28 02:13:49 +00:00
|
|
|
struct BPMemory;
|
2016-12-29 16:31:51 +00:00
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
enum class AbstractTextureFormat : u32;
|
|
|
|
|
2023-01-28 02:13:49 +00:00
|
|
|
enum class CompareMode : u32;
|
|
|
|
enum class CullMode : u32;
|
|
|
|
enum class DstBlendFactor : u32;
|
|
|
|
enum class FilterMode : u32;
|
|
|
|
enum class LODType : u32;
|
|
|
|
enum class LogicOp : u32;
|
|
|
|
enum class PixelFormat : u32;
|
|
|
|
enum class SrcBlendFactor : u32;
|
|
|
|
enum class WrapMode : u32;
|
|
|
|
|
2017-04-30 08:07:57 +00:00
|
|
|
enum class PrimitiveType : u32
|
|
|
|
{
|
|
|
|
Points,
|
|
|
|
Lines,
|
|
|
|
Triangles,
|
|
|
|
TriangleStrip,
|
|
|
|
};
|
|
|
|
|
|
|
|
union RasterizationState
|
|
|
|
{
|
|
|
|
void Generate(const BPMemory& bp, PrimitiveType primitive_type);
|
|
|
|
|
2021-10-07 00:36:15 +00:00
|
|
|
RasterizationState() = default;
|
|
|
|
RasterizationState(const RasterizationState&) = default;
|
|
|
|
RasterizationState& operator=(const RasterizationState& rhs)
|
|
|
|
{
|
|
|
|
hex = rhs.hex;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
RasterizationState(RasterizationState&&) = default;
|
|
|
|
RasterizationState& operator=(RasterizationState&& rhs)
|
|
|
|
{
|
|
|
|
hex = rhs.hex;
|
|
|
|
return *this;
|
|
|
|
}
|
2017-09-09 08:30:15 +00:00
|
|
|
|
|
|
|
bool operator==(const RasterizationState& rhs) const { return hex == rhs.hex; }
|
2021-10-07 00:36:15 +00:00
|
|
|
bool operator!=(const RasterizationState& rhs) const { return !operator==(rhs); }
|
2017-09-09 08:30:15 +00:00
|
|
|
bool operator<(const RasterizationState& rhs) const { return hex < rhs.hex; }
|
2021-10-07 00:36:15 +00:00
|
|
|
|
2021-02-11 02:11:31 +00:00
|
|
|
BitField<0, 2, CullMode> cullmode;
|
2017-04-30 08:07:57 +00:00
|
|
|
BitField<3, 2, PrimitiveType> primitive;
|
|
|
|
|
2023-02-16 03:18:39 +00:00
|
|
|
u32 hex = 0;
|
2017-04-30 08:07:57 +00:00
|
|
|
};
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
union FramebufferState
|
|
|
|
{
|
2021-10-07 00:36:15 +00:00
|
|
|
FramebufferState() = default;
|
|
|
|
FramebufferState(const FramebufferState&) = default;
|
|
|
|
FramebufferState& operator=(const FramebufferState& rhs)
|
|
|
|
{
|
|
|
|
hex = rhs.hex;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
FramebufferState(FramebufferState&&) = default;
|
|
|
|
FramebufferState& operator=(FramebufferState&& rhs)
|
|
|
|
{
|
|
|
|
hex = rhs.hex;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const FramebufferState& rhs) const { return hex == rhs.hex; }
|
|
|
|
bool operator!=(const FramebufferState& rhs) const { return !operator==(rhs); }
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
BitField<0, 8, AbstractTextureFormat> color_texture_format;
|
|
|
|
BitField<8, 8, AbstractTextureFormat> depth_texture_format;
|
|
|
|
BitField<16, 8, u32> samples;
|
|
|
|
BitField<24, 1, u32> per_sample_shading;
|
|
|
|
|
2023-05-29 01:59:02 +00:00
|
|
|
// Note: all additional color attachments
|
|
|
|
// have the same format as `color_texture_format`
|
|
|
|
// TODO: in the future improve this so every attachment
|
|
|
|
// can specify its own format
|
|
|
|
BitField<25, 3, u32> additional_color_attachment_count;
|
|
|
|
|
2023-02-16 03:18:39 +00:00
|
|
|
u32 hex = 0;
|
2019-02-15 01:59:50 +00:00
|
|
|
};
|
|
|
|
|
2017-04-30 05:54:45 +00:00
|
|
|
union DepthState
|
|
|
|
{
|
|
|
|
void Generate(const BPMemory& bp);
|
|
|
|
|
2021-10-07 00:36:15 +00:00
|
|
|
DepthState() = default;
|
|
|
|
DepthState(const DepthState&) = default;
|
|
|
|
DepthState& operator=(const DepthState& rhs)
|
|
|
|
{
|
|
|
|
hex = rhs.hex;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
DepthState(DepthState&&) = default;
|
|
|
|
DepthState& operator=(DepthState&& rhs)
|
|
|
|
{
|
|
|
|
hex = rhs.hex;
|
|
|
|
return *this;
|
|
|
|
}
|
2017-09-09 08:30:15 +00:00
|
|
|
|
|
|
|
bool operator==(const DepthState& rhs) const { return hex == rhs.hex; }
|
2021-10-07 00:36:15 +00:00
|
|
|
bool operator!=(const DepthState& rhs) const { return !operator==(rhs); }
|
2017-09-09 08:30:15 +00:00
|
|
|
bool operator<(const DepthState& rhs) const { return hex < rhs.hex; }
|
2021-10-07 00:36:15 +00:00
|
|
|
|
2017-04-30 05:54:45 +00:00
|
|
|
BitField<0, 1, u32> testenable;
|
|
|
|
BitField<1, 1, u32> updateenable;
|
2021-02-11 02:11:31 +00:00
|
|
|
BitField<2, 3, CompareMode> func;
|
2017-04-30 05:54:45 +00:00
|
|
|
|
2023-02-16 03:18:39 +00:00
|
|
|
u32 hex = 0;
|
2017-04-30 05:54:45 +00:00
|
|
|
};
|
|
|
|
|
2016-12-29 16:31:51 +00:00
|
|
|
union BlendingState
|
|
|
|
{
|
|
|
|
void Generate(const BPMemory& bp);
|
|
|
|
|
2019-08-02 09:20:36 +00:00
|
|
|
// HACK: Replaces logical operations with blend operations.
|
|
|
|
// Will not be bit-correct, and in some cases not even remotely in the same ballpark.
|
|
|
|
void ApproximateLogicOpWithBlending();
|
2022-07-13 08:56:33 +00:00
|
|
|
bool LogicOpApproximationIsExact();
|
|
|
|
bool LogicOpApproximationWantsShaderHelp();
|
2019-08-02 09:20:36 +00:00
|
|
|
|
2021-10-07 00:36:15 +00:00
|
|
|
BlendingState() = default;
|
|
|
|
BlendingState(const BlendingState&) = default;
|
|
|
|
BlendingState& operator=(const BlendingState& rhs)
|
|
|
|
{
|
|
|
|
hex = rhs.hex;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
BlendingState(BlendingState&&) = default;
|
|
|
|
BlendingState& operator=(BlendingState&& rhs)
|
|
|
|
{
|
|
|
|
hex = rhs.hex;
|
|
|
|
return *this;
|
|
|
|
}
|
2017-09-09 08:30:15 +00:00
|
|
|
|
|
|
|
bool operator==(const BlendingState& rhs) const { return hex == rhs.hex; }
|
2021-10-07 00:36:15 +00:00
|
|
|
bool operator!=(const BlendingState& rhs) const { return !operator==(rhs); }
|
2017-09-09 08:30:15 +00:00
|
|
|
bool operator<(const BlendingState& rhs) const { return hex < rhs.hex; }
|
2021-10-07 00:36:15 +00:00
|
|
|
|
2016-12-29 16:31:51 +00:00
|
|
|
BitField<0, 1, u32> blendenable;
|
|
|
|
BitField<1, 1, u32> logicopenable;
|
2017-04-18 11:45:03 +00:00
|
|
|
BitField<3, 1, u32> colorupdate;
|
|
|
|
BitField<4, 1, u32> alphaupdate;
|
|
|
|
BitField<5, 1, u32> subtract;
|
|
|
|
BitField<6, 1, u32> subtractAlpha;
|
|
|
|
BitField<7, 1, u32> usedualsrc;
|
2021-02-11 02:11:31 +00:00
|
|
|
BitField<8, 3, DstBlendFactor> dstfactor;
|
|
|
|
BitField<11, 3, SrcBlendFactor> srcfactor;
|
|
|
|
BitField<14, 3, DstBlendFactor> dstfactoralpha;
|
|
|
|
BitField<17, 3, SrcBlendFactor> srcfactoralpha;
|
|
|
|
BitField<20, 4, LogicOp> logicmode;
|
2016-12-29 16:31:51 +00:00
|
|
|
|
2022-06-12 02:03:09 +00:00
|
|
|
bool RequiresDualSrc() const;
|
|
|
|
|
2023-02-16 03:18:39 +00:00
|
|
|
u32 hex = 0;
|
2016-12-29 16:31:51 +00:00
|
|
|
};
|
2017-09-08 14:10:40 +00:00
|
|
|
|
2021-08-09 04:11:50 +00:00
|
|
|
struct SamplerState
|
2017-09-09 08:30:15 +00:00
|
|
|
{
|
|
|
|
void Generate(const BPMemory& bp, u32 index);
|
|
|
|
|
2021-10-07 00:36:15 +00:00
|
|
|
SamplerState() = default;
|
|
|
|
SamplerState(const SamplerState&) = default;
|
|
|
|
SamplerState& operator=(const SamplerState& rhs)
|
|
|
|
{
|
2021-08-09 04:11:50 +00:00
|
|
|
tm0.hex = rhs.tm0.hex;
|
|
|
|
tm1.hex = rhs.tm1.hex;
|
2021-10-07 00:36:15 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
SamplerState(SamplerState&&) = default;
|
|
|
|
SamplerState& operator=(SamplerState&& rhs)
|
|
|
|
{
|
|
|
|
tm0.hex = rhs.tm0.hex;
|
|
|
|
tm1.hex = rhs.tm1.hex;
|
|
|
|
return *this;
|
|
|
|
}
|
2017-09-09 08:30:15 +00:00
|
|
|
|
2021-08-09 04:11:50 +00:00
|
|
|
bool operator==(const SamplerState& rhs) const { return Hex() == rhs.Hex(); }
|
2021-10-07 00:36:15 +00:00
|
|
|
bool operator!=(const SamplerState& rhs) const { return !operator==(rhs); }
|
2021-08-09 04:11:50 +00:00
|
|
|
bool operator<(const SamplerState& rhs) const { return Hex() < rhs.Hex(); }
|
|
|
|
|
|
|
|
constexpr u64 Hex() const { return tm0.hex | (static_cast<u64>(tm1.hex) << 32); }
|
|
|
|
|
|
|
|
// Based on BPMemory TexMode0/TexMode1, but with slightly higher precision and some
|
|
|
|
// simplifications
|
|
|
|
union TM0
|
|
|
|
{
|
|
|
|
// BP's mipmap_filter can be None, but that is represented here by setting min_lod and max_lod
|
|
|
|
// to 0
|
|
|
|
BitField<0, 1, FilterMode> min_filter;
|
|
|
|
BitField<1, 1, FilterMode> mag_filter;
|
|
|
|
BitField<2, 1, FilterMode> mipmap_filter;
|
|
|
|
// Guaranteed to be valid values (i.e. not 3)
|
|
|
|
BitField<3, 2, WrapMode> wrap_u;
|
|
|
|
BitField<5, 2, WrapMode> wrap_v;
|
|
|
|
BitField<7, 1, LODType> diag_lod;
|
|
|
|
BitField<8, 16, s32> lod_bias; // multiplied by 256, higher precision than normal
|
|
|
|
BitField<24, 1, bool, u32> lod_clamp; // TODO: This isn't currently implemented
|
|
|
|
BitField<25, 1, bool, u32> anisotropic_filtering; // TODO: This doesn't use the BP one yet
|
2023-02-16 03:18:39 +00:00
|
|
|
u32 hex = 0;
|
2021-08-09 04:11:50 +00:00
|
|
|
};
|
|
|
|
union TM1
|
|
|
|
{
|
|
|
|
// Min is guaranteed to be less than or equal to max
|
|
|
|
BitField<0, 8, u32> min_lod; // multiplied by 16
|
|
|
|
BitField<8, 8, u32> max_lod; // multiplied by 16
|
2023-02-16 03:18:39 +00:00
|
|
|
u32 hex = 0;
|
2021-08-09 04:11:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
TM0 tm0;
|
|
|
|
TM1 tm1;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
2024-01-31 17:40:08 +00:00
|
|
|
struct std::hash<SamplerState>
|
2021-08-09 04:11:50 +00:00
|
|
|
{
|
2024-01-31 17:40:08 +00:00
|
|
|
std::size_t operator()(const SamplerState& state) const noexcept
|
2021-08-09 04:11:50 +00:00
|
|
|
{
|
|
|
|
return std::hash<u64>{}(state.Hex());
|
|
|
|
}
|
2017-09-09 08:30:15 +00:00
|
|
|
};
|
|
|
|
|
2017-09-08 14:10:40 +00:00
|
|
|
namespace RenderState
|
|
|
|
{
|
2019-01-19 13:54:35 +00:00
|
|
|
RasterizationState GetInvalidRasterizationState();
|
2019-02-15 01:59:50 +00:00
|
|
|
RasterizationState GetNoCullRasterizationState(PrimitiveType primitive);
|
|
|
|
RasterizationState GetCullBackFaceRasterizationState(PrimitiveType primitive);
|
2019-01-19 13:54:35 +00:00
|
|
|
DepthState GetInvalidDepthState();
|
2019-02-15 01:59:50 +00:00
|
|
|
DepthState GetNoDepthTestingDepthState();
|
|
|
|
DepthState GetAlwaysWriteDepthState();
|
2019-01-19 13:54:35 +00:00
|
|
|
BlendingState GetInvalidBlendingState();
|
2017-09-08 14:10:40 +00:00
|
|
|
BlendingState GetNoBlendingBlendState();
|
2019-02-15 01:59:50 +00:00
|
|
|
BlendingState GetNoColorWriteBlendState();
|
2019-01-19 13:54:35 +00:00
|
|
|
SamplerState GetInvalidSamplerState();
|
2017-09-09 08:30:15 +00:00
|
|
|
SamplerState GetPointSamplerState();
|
|
|
|
SamplerState GetLinearSamplerState();
|
2019-02-15 01:59:50 +00:00
|
|
|
FramebufferState GetColorFramebufferState(AbstractTextureFormat format);
|
|
|
|
FramebufferState GetRGBA8FramebufferState();
|
|
|
|
} // namespace RenderState
|