2015-10-24 23:24:06 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
2017-02-08 17:35:41 +01:00
|
|
|
#include <string>
|
2017-02-24 20:50:27 +01:00
|
|
|
#include <cstring>
|
2017-02-08 17:35:41 +01:00
|
|
|
#include <cstdint>
|
2020-09-29 12:44:47 +02:00
|
|
|
|
2022-01-30 15:49:02 -08:00
|
|
|
#include "Common/CommonFuncs.h"
|
2015-10-24 23:24:06 +02:00
|
|
|
|
2023-01-09 12:21:33 +01:00
|
|
|
// VS_BIT_LIGHT_UBERSHADER indicates that some groups of these will be
|
|
|
|
|
// sent to the shader and processed there. This cuts down the number of shaders ("ubershader approach").
|
2019-02-16 06:54:56 -08:00
|
|
|
enum VShaderBit : uint8_t {
|
2015-10-24 23:24:06 +02:00
|
|
|
VS_BIT_LMODE = 0,
|
|
|
|
|
VS_BIT_IS_THROUGH = 1,
|
2023-01-10 15:27:05 +01:00
|
|
|
// bit 2 is free.
|
2015-10-24 23:24:06 +02:00
|
|
|
VS_BIT_HAS_COLOR = 3,
|
2023-01-10 15:27:05 +01:00
|
|
|
// bit 4 is free.
|
2020-12-13 16:04:16 +01:00
|
|
|
VS_BIT_VERTEX_RANGE_CULLING = 5,
|
2022-10-22 17:34:23 +02:00
|
|
|
VS_BIT_SIMPLE_STEREO = 6,
|
2017-12-02 08:52:21 -08:00
|
|
|
// 7 is free.
|
2015-10-24 23:24:06 +02:00
|
|
|
VS_BIT_USE_HW_TRANSFORM = 8,
|
|
|
|
|
VS_BIT_HAS_NORMAL = 9, // conditioned on hw transform
|
|
|
|
|
VS_BIT_NORM_REVERSE = 10,
|
2017-01-07 01:21:17 +09:00
|
|
|
VS_BIT_HAS_TEXCOORD = 11,
|
|
|
|
|
VS_BIT_HAS_COLOR_TESS = 12, // 1 bit
|
|
|
|
|
VS_BIT_HAS_TEXCOORD_TESS = 13, // 1 bit
|
2017-12-02 08:52:21 -08:00
|
|
|
VS_BIT_NORM_REVERSE_TESS = 14, // 1 bit
|
2018-07-18 00:52:20 +09:00
|
|
|
VS_BIT_HAS_NORMAL_TESS = 15, // 1 bit
|
2015-10-24 23:24:06 +02:00
|
|
|
VS_BIT_UVGEN_MODE = 16,
|
|
|
|
|
VS_BIT_UVPROJ_MODE = 18, // 2, can overlap with LS0
|
|
|
|
|
VS_BIT_LS0 = 18, // 2
|
|
|
|
|
VS_BIT_LS1 = 20, // 2
|
2018-04-10 12:22:02 +02:00
|
|
|
VS_BIT_BONES = 22, // 3 should be enough, not 8
|
|
|
|
|
// 25 - 29 are free.
|
|
|
|
|
VS_BIT_ENABLE_BONES = 30,
|
2022-09-25 13:59:52 +02:00
|
|
|
|
|
|
|
|
// If this is set along with LIGHTING_ENABLE, all other lighting bits below
|
|
|
|
|
// are passed to the shader directly instead.
|
|
|
|
|
VS_BIT_LIGHT_UBERSHADER = 31,
|
|
|
|
|
|
2015-10-24 23:24:06 +02:00
|
|
|
VS_BIT_LIGHT0_COMP = 32, // 2 bits
|
|
|
|
|
VS_BIT_LIGHT0_TYPE = 34, // 2 bits
|
|
|
|
|
VS_BIT_LIGHT1_COMP = 36, // 2 bits
|
|
|
|
|
VS_BIT_LIGHT1_TYPE = 38, // 2 bits
|
|
|
|
|
VS_BIT_LIGHT2_COMP = 40, // 2 bits
|
|
|
|
|
VS_BIT_LIGHT2_TYPE = 42, // 2 bits
|
|
|
|
|
VS_BIT_LIGHT3_COMP = 44, // 2 bits
|
|
|
|
|
VS_BIT_LIGHT3_TYPE = 46, // 2 bits
|
2017-01-07 01:21:17 +09:00
|
|
|
VS_BIT_MATERIAL_UPDATE = 48, // 3 bits
|
|
|
|
|
VS_BIT_SPLINE = 51, // 1 bit
|
2015-10-24 23:24:06 +02:00
|
|
|
VS_BIT_LIGHT0_ENABLE = 52,
|
|
|
|
|
VS_BIT_LIGHT1_ENABLE = 53,
|
|
|
|
|
VS_BIT_LIGHT2_ENABLE = 54,
|
|
|
|
|
VS_BIT_LIGHT3_ENABLE = 55,
|
|
|
|
|
VS_BIT_LIGHTING_ENABLE = 56,
|
2018-04-10 11:22:58 +02:00
|
|
|
VS_BIT_WEIGHT_FMTSCALE = 57, // only two bits
|
|
|
|
|
// 59 - 61 are free.
|
2017-01-07 01:21:17 +09:00
|
|
|
VS_BIT_FLATSHADE = 62, // 1 bit
|
|
|
|
|
VS_BIT_BEZIER = 63, // 1 bit
|
|
|
|
|
// No more free
|
2015-10-24 23:24:06 +02:00
|
|
|
};
|
|
|
|
|
|
2019-02-16 06:54:56 -08:00
|
|
|
static inline VShaderBit operator +(VShaderBit bit, int i) {
|
|
|
|
|
return VShaderBit((int)bit + i);
|
|
|
|
|
}
|
2015-10-24 23:24:06 +02:00
|
|
|
|
|
|
|
|
// Local
|
2019-02-16 06:54:56 -08:00
|
|
|
enum FShaderBit : uint8_t {
|
2015-10-24 23:24:06 +02:00
|
|
|
FS_BIT_CLEARMODE = 0,
|
|
|
|
|
FS_BIT_DO_TEXTURE = 1,
|
|
|
|
|
FS_BIT_TEXFUNC = 2, // 3 bits
|
2023-05-10 16:14:33 +02:00
|
|
|
FS_BIT_DOUBLE_COLOR = 5, // Not used with FS_BIT_UBERSHADER
|
2022-09-11 14:14:18 +02:00
|
|
|
FS_BIT_3D_TEXTURE = 6,
|
2015-10-24 23:24:06 +02:00
|
|
|
FS_BIT_SHADER_TEX_CLAMP = 7,
|
|
|
|
|
FS_BIT_CLAMP_S = 8,
|
|
|
|
|
FS_BIT_CLAMP_T = 9,
|
2023-05-10 16:14:33 +02:00
|
|
|
FS_BIT_TEXALPHA = 10, // Not used with FS_BIT_UBERSHADER
|
2023-05-09 17:50:43 +02:00
|
|
|
FS_BIT_LMODE = 11,
|
2015-10-24 23:24:06 +02:00
|
|
|
FS_BIT_ALPHA_TEST = 12,
|
|
|
|
|
FS_BIT_ALPHA_TEST_FUNC = 13, // 3 bits
|
|
|
|
|
FS_BIT_ALPHA_AGAINST_ZERO = 16,
|
|
|
|
|
FS_BIT_COLOR_TEST = 17,
|
|
|
|
|
FS_BIT_COLOR_TEST_FUNC = 18, // 2 bits
|
|
|
|
|
FS_BIT_COLOR_AGAINST_ZERO = 20,
|
2023-05-10 16:14:33 +02:00
|
|
|
FS_BIT_ENABLE_FOG = 21, // Not used with FS_BIT_UBERSHADER
|
|
|
|
|
FS_BIT_DO_TEXTURE_PROJ = 22,
|
|
|
|
|
// 1 free bit
|
2015-10-24 23:24:06 +02:00
|
|
|
FS_BIT_STENCIL_TO_ALPHA = 24, // 2 bits
|
2020-11-06 20:08:57 +01:00
|
|
|
FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE = 26, // 4 bits (ReplaceAlphaType)
|
2022-09-03 23:28:03 +02:00
|
|
|
FS_BIT_SIMULATE_LOGIC_OP_TYPE = 30, // 2 bits
|
2020-11-06 20:08:57 +01:00
|
|
|
FS_BIT_REPLACE_BLEND = 32, // 3 bits (ReplaceBlendType)
|
2015-10-24 23:24:06 +02:00
|
|
|
FS_BIT_BLENDEQ = 35, // 3 bits
|
|
|
|
|
FS_BIT_BLENDFUNC_A = 38, // 4 bits
|
2017-12-02 08:52:21 -08:00
|
|
|
FS_BIT_BLENDFUNC_B = 42, // 4 bits
|
2023-05-10 16:14:33 +02:00
|
|
|
FS_BIT_FLATSHADE = 46,
|
2015-10-25 00:34:23 +02:00
|
|
|
FS_BIT_BGRA_TEXTURE = 47,
|
2018-07-27 20:04:36 -07:00
|
|
|
FS_BIT_TEST_DISCARD_TO_ZERO = 48,
|
2018-12-23 12:19:34 -08:00
|
|
|
FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL = 49,
|
2020-11-08 23:17:06 +01:00
|
|
|
FS_BIT_COLOR_WRITEMASK = 50,
|
2022-09-11 14:14:18 +02:00
|
|
|
FS_BIT_REPLACE_LOGIC_OP = 51, // 4 bits. GE_LOGIC_COPY means no-op/off.
|
|
|
|
|
FS_BIT_SHADER_DEPAL_MODE = 55, // 2 bits (ShaderDepalMode)
|
2023-05-10 16:14:33 +02:00
|
|
|
FS_BIT_SAMPLE_ARRAY_TEXTURE = 57, // For multiview, framebuffers are array textures and we need to sample the two layers correctly.
|
|
|
|
|
FS_BIT_STEREO = 58,
|
|
|
|
|
FS_BIT_USE_FRAMEBUFFER_FETCH = 59,
|
|
|
|
|
FS_BIT_UBERSHADER = 60,
|
2015-10-24 23:24:06 +02:00
|
|
|
};
|
|
|
|
|
|
2019-02-16 06:54:56 -08:00
|
|
|
static inline FShaderBit operator +(FShaderBit bit, int i) {
|
|
|
|
|
return FShaderBit((int)bit + i);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-01 20:01:23 -07:00
|
|
|
// Some of these bits are straight from FShaderBit, since they essentially enable attributes directly.
|
|
|
|
|
enum GShaderBit : uint8_t {
|
|
|
|
|
GS_BIT_ENABLED = 0, // If not set, we don't use a geo shader.
|
|
|
|
|
GS_BIT_DO_TEXTURE = 1, // presence of texcoords
|
2023-05-09 17:50:43 +02:00
|
|
|
GS_BIT_LMODE = 2,
|
|
|
|
|
GS_BIT_CURVE = 3, // curve, which means don't do range culling.
|
2022-10-01 20:01:23 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static inline GShaderBit operator +(GShaderBit bit, int i) {
|
|
|
|
|
return GShaderBit((int)bit + i);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-24 23:24:06 +02:00
|
|
|
struct ShaderID {
|
|
|
|
|
ShaderID() {
|
|
|
|
|
clear();
|
|
|
|
|
}
|
|
|
|
|
void clear() {
|
|
|
|
|
for (size_t i = 0; i < ARRAY_SIZE(d); i++) {
|
|
|
|
|
d[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void set_invalid() {
|
|
|
|
|
for (size_t i = 0; i < ARRAY_SIZE(d); i++) {
|
|
|
|
|
d[i] = 0xFFFFFFFF;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-01 12:12:46 -07:00
|
|
|
bool is_invalid() const {
|
|
|
|
|
for (size_t i = 0; i < ARRAY_SIZE(d); i++) {
|
|
|
|
|
if (d[i] != 0xFFFFFFFF)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2015-10-24 23:24:06 +02:00
|
|
|
|
2017-02-08 17:35:41 +01:00
|
|
|
uint32_t d[2];
|
2015-10-24 23:24:06 +02:00
|
|
|
bool operator < (const ShaderID &other) const {
|
2017-02-08 17:35:41 +01:00
|
|
|
for (size_t i = 0; i < sizeof(d) / sizeof(uint32_t); i++) {
|
2015-10-24 23:24:06 +02:00
|
|
|
if (d[i] < other.d[i])
|
|
|
|
|
return true;
|
|
|
|
|
if (d[i] > other.d[i])
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
bool operator == (const ShaderID &other) const {
|
2017-02-08 17:35:41 +01:00
|
|
|
for (size_t i = 0; i < sizeof(d) / sizeof(uint32_t); i++) {
|
2015-10-24 23:24:06 +02:00
|
|
|
if (d[i] != other.d[i])
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2017-04-03 16:45:58 +02:00
|
|
|
bool operator != (const ShaderID &other) const {
|
|
|
|
|
return !(*this == other);
|
|
|
|
|
}
|
2019-02-16 06:54:56 -08:00
|
|
|
|
|
|
|
|
uint32_t Word(int word) const {
|
|
|
|
|
return d[word];
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-18 18:05:20 +01:00
|
|
|
// Note: This is a binary copy to string-as-bytes, not a human-readable representation.
|
2019-02-16 06:54:56 -08:00
|
|
|
void ToString(std::string *dest) const {
|
|
|
|
|
dest->resize(sizeof(d));
|
|
|
|
|
memcpy(&(*dest)[0], d, sizeof(d));
|
|
|
|
|
}
|
2022-12-18 18:05:20 +01:00
|
|
|
// Note: This is a binary copy from string-as-bytes, not a human-readable representation.
|
2019-02-16 06:54:56 -08:00
|
|
|
void FromString(std::string src) {
|
|
|
|
|
memcpy(d, &(src)[0], sizeof(d));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
2015-10-24 23:24:06 +02:00
|
|
|
bool Bit(int bit) const {
|
|
|
|
|
return (d[bit >> 5] >> (bit & 31)) & 1;
|
|
|
|
|
}
|
2017-08-15 14:21:38 +02:00
|
|
|
// Does not handle crossing 32-bit boundaries. count must be 30 or smaller.
|
2015-10-24 23:24:06 +02:00
|
|
|
int Bits(int bit, int count) const {
|
|
|
|
|
const int mask = (1 << count) - 1;
|
|
|
|
|
return (d[bit >> 5] >> (bit & 31)) & mask;
|
|
|
|
|
}
|
|
|
|
|
void SetBit(int bit, bool value = true) {
|
|
|
|
|
if (value) {
|
|
|
|
|
d[bit >> 5] |= 1 << (bit & 31);
|
2020-10-21 23:09:34 +02:00
|
|
|
} else {
|
|
|
|
|
d[bit >> 5] &= ~(1 << (bit & 31));
|
2015-10-24 23:24:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void SetBits(int bit, int count, int value) {
|
2020-10-30 10:22:51 +01:00
|
|
|
const int mask = (1 << count) - 1;
|
|
|
|
|
const int shifted_mask = mask << (bit & 31);
|
|
|
|
|
d[bit >> 5] = (d[bit >> 5] & ~shifted_mask) | ((value & mask) << (bit & 31));
|
2015-10-24 23:24:06 +02:00
|
|
|
}
|
2015-10-24 23:49:05 +02:00
|
|
|
};
|
|
|
|
|
|
2017-12-02 09:07:27 -08:00
|
|
|
struct VShaderID : ShaderID {
|
|
|
|
|
VShaderID() : ShaderID() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
explicit VShaderID(ShaderID &src) {
|
|
|
|
|
memcpy(d, src.d, sizeof(d));
|
|
|
|
|
}
|
2019-02-16 06:54:56 -08:00
|
|
|
|
|
|
|
|
bool Bit(VShaderBit bit) const {
|
|
|
|
|
return ShaderID::Bit((int)bit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Bits(VShaderBit bit, int count) const {
|
|
|
|
|
return ShaderID::Bits((int)bit, count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetBit(VShaderBit bit, bool value = true) {
|
|
|
|
|
ShaderID::SetBit((int)bit, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetBits(VShaderBit bit, int count, int value) {
|
|
|
|
|
ShaderID::SetBits((int)bit, count, value);
|
|
|
|
|
}
|
2017-12-02 09:07:27 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct FShaderID : ShaderID {
|
|
|
|
|
FShaderID() : ShaderID() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
explicit FShaderID(ShaderID &src) {
|
|
|
|
|
memcpy(d, src.d, sizeof(d));
|
|
|
|
|
}
|
2019-02-16 06:54:56 -08:00
|
|
|
|
|
|
|
|
bool Bit(FShaderBit bit) const {
|
|
|
|
|
return ShaderID::Bit((int)bit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Bits(FShaderBit bit, int count) const {
|
|
|
|
|
return ShaderID::Bits((int)bit, count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetBit(FShaderBit bit, bool value = true) {
|
|
|
|
|
ShaderID::SetBit((int)bit, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetBits(FShaderBit bit, int count, int value) {
|
|
|
|
|
ShaderID::SetBits((int)bit, count, value);
|
|
|
|
|
}
|
2017-12-02 09:07:27 -08:00
|
|
|
};
|
|
|
|
|
|
2022-10-01 20:01:23 -07:00
|
|
|
struct GShaderID : ShaderID {
|
|
|
|
|
GShaderID() : ShaderID() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
explicit GShaderID(ShaderID &src) {
|
|
|
|
|
memcpy(d, src.d, sizeof(d));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Bit(GShaderBit bit) const {
|
|
|
|
|
return ShaderID::Bit((int)bit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Bits(GShaderBit bit, int count) const {
|
|
|
|
|
return ShaderID::Bits((int)bit, count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetBit(GShaderBit bit, bool value = true) {
|
|
|
|
|
ShaderID::SetBit((int)bit, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetBits(GShaderBit bit, int count, int value) {
|
|
|
|
|
ShaderID::SetBits((int)bit, count, value);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-12-23 12:19:34 -08:00
|
|
|
namespace Draw {
|
|
|
|
|
class Bugs;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-14 22:48:17 +01:00
|
|
|
class VertexDecoder;
|
|
|
|
|
|
|
|
|
|
void ComputeVertexShaderID(VShaderID *id, VertexDecoder *vertexDecoder, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode);
|
2015-10-24 23:49:05 +02:00
|
|
|
// Generates a compact string that describes the shader. Useful in a list to get an overview
|
|
|
|
|
// of the current flora of shaders.
|
2019-02-16 06:54:56 -08:00
|
|
|
std::string VertexShaderDesc(const VShaderID &id);
|
2015-10-24 23:49:05 +02:00
|
|
|
|
2022-09-02 22:07:42 +02:00
|
|
|
struct ComputedPipelineState;
|
|
|
|
|
void ComputeFragmentShaderID(FShaderID *id, const ComputedPipelineState &pipelineState, const Draw::Bugs &bugs);
|
2019-02-16 06:54:56 -08:00
|
|
|
std::string FragmentShaderDesc(const FShaderID &id);
|
2022-10-01 20:01:23 -07:00
|
|
|
|
|
|
|
|
void ComputeGeometryShaderID(GShaderID *id, const Draw::Bugs &bugs, int prim);
|
|
|
|
|
std::string GeometryShaderDesc(const GShaderID &id);
|
2022-10-13 22:35:23 +02:00
|
|
|
|
|
|
|
|
// For sanity checking.
|
|
|
|
|
bool FragmentIdNeedsFramebufferRead(const FShaderID &id);
|