ppsspp/GPU/Common/ShaderId.h

235 lines
6.0 KiB
C
Raw Normal View History

#pragma once
2017-02-08 16:35:41 +00:00
#include <string>
2017-02-24 19:50:27 +00:00
#include <cstring>
2017-02-08 16:35:41 +00:00
#include <cstdint>
#include "Common/Common.h"
// TODO: There will be additional bits, indicating that groups of these will be
// sent to the shader and processed there. This will cut down the number of shaders ("ubershader approach")
// This is probably only really worth doing for lighting and bones.
enum VShaderBit : uint8_t {
VS_BIT_LMODE = 0,
VS_BIT_IS_THROUGH = 1,
VS_BIT_ENABLE_FOG = 2,
VS_BIT_HAS_COLOR = 3,
VS_BIT_DO_TEXTURE = 4,
VS_BIT_VERTEX_RANGE_CULLING = 5,
// 6 is free,
// 7 is free.
VS_BIT_USE_HW_TRANSFORM = 8,
VS_BIT_HAS_NORMAL = 9, // conditioned on hw transform
VS_BIT_NORM_REVERSE = 10,
VS_BIT_HAS_TEXCOORD = 11,
VS_BIT_HAS_COLOR_TESS = 12, // 1 bit
VS_BIT_HAS_TEXCOORD_TESS = 13, // 1 bit
VS_BIT_NORM_REVERSE_TESS = 14, // 1 bit
VS_BIT_HAS_NORMAL_TESS = 15, // 1 bit
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
VS_BIT_BONES = 22, // 3 should be enough, not 8
// 25 - 29 are free.
VS_BIT_ENABLE_BONES = 30,
// 31 is free.
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
VS_BIT_MATERIAL_UPDATE = 48, // 3 bits
VS_BIT_SPLINE = 51, // 1 bit
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,
VS_BIT_WEIGHT_FMTSCALE = 57, // only two bits
// 59 - 61 are free.
VS_BIT_FLATSHADE = 62, // 1 bit
VS_BIT_BEZIER = 63, // 1 bit
// No more free
};
static inline VShaderBit operator +(VShaderBit bit, int i) {
return VShaderBit((int)bit + i);
}
// Local
enum FShaderBit : uint8_t {
FS_BIT_CLEARMODE = 0,
FS_BIT_DO_TEXTURE = 1,
FS_BIT_TEXFUNC = 2, // 3 bits
FS_BIT_TEXALPHA = 5,
FS_BIT_SHADER_DEPAL = 6,
FS_BIT_SHADER_TEX_CLAMP = 7,
FS_BIT_CLAMP_S = 8,
FS_BIT_CLAMP_T = 9,
FS_BIT_TEXTURE_AT_OFFSET = 10,
FS_BIT_LMODE = 11,
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,
FS_BIT_ENABLE_FOG = 21,
FS_BIT_DO_TEXTURE_PROJ = 22,
FS_BIT_COLOR_DOUBLE = 23,
FS_BIT_STENCIL_TO_ALPHA = 24, // 2 bits
FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE = 26, // 4 bits (ReplaceAlphaType)
FS_BIT_REPLACE_LOGIC_OP_TYPE = 30, // 2 bits
FS_BIT_REPLACE_BLEND = 32, // 3 bits (ReplaceBlendType)
FS_BIT_BLENDEQ = 35, // 3 bits
FS_BIT_BLENDFUNC_A = 38, // 4 bits
FS_BIT_BLENDFUNC_B = 42, // 4 bits
FS_BIT_FLATSHADE = 46,
FS_BIT_BGRA_TEXTURE = 47,
FS_BIT_TEST_DISCARD_TO_ZERO = 48,
FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL = 49,
FS_BIT_COLOR_WRITEMASK = 50,
};
static inline FShaderBit operator +(FShaderBit bit, int i) {
return FShaderBit((int)bit + i);
}
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;
}
}
2017-02-08 16:35:41 +00:00
uint32_t d[2];
bool operator < (const ShaderID &other) const {
2017-02-08 16:35:41 +00:00
for (size_t i = 0; i < sizeof(d) / sizeof(uint32_t); i++) {
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 16:35:41 +00:00
for (size_t i = 0; i < sizeof(d) / sizeof(uint32_t); i++) {
if (d[i] != other.d[i])
return false;
}
return true;
}
bool operator != (const ShaderID &other) const {
return !(*this == other);
}
uint32_t Word(int word) const {
return d[word];
}
void ToString(std::string *dest) const {
dest->resize(sizeof(d));
memcpy(&(*dest)[0], d, sizeof(d));
}
void FromString(std::string src) {
memcpy(d, &(src)[0], sizeof(d));
}
protected:
bool Bit(int bit) const {
return (d[bit >> 5] >> (bit & 31)) & 1;
}
// Does not handle crossing 32-bit boundaries. count must be 30 or smaller.
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);
} else {
d[bit >> 5] &= ~(1 << (bit & 31));
}
}
void SetBits(int bit, int count, int value) {
2020-10-30 09:22:51 +00: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));
}
};
struct VShaderID : ShaderID {
VShaderID() : ShaderID() {
}
explicit VShaderID(ShaderID &src) {
memcpy(d, src.d, sizeof(d));
}
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);
}
};
struct FShaderID : ShaderID {
FShaderID() : ShaderID() {
}
explicit FShaderID(ShaderID &src) {
memcpy(d, src.d, sizeof(d));
}
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);
}
};
namespace Draw {
class Bugs;
}
void ComputeVertexShaderID(VShaderID *id, uint32_t vertexType, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat);
// Generates a compact string that describes the shader. Useful in a list to get an overview
// of the current flora of shaders.
std::string VertexShaderDesc(const VShaderID &id);
void ComputeFragmentShaderID(FShaderID *id, const Draw::Bugs &bugs);
std::string FragmentShaderDesc(const FShaderID &id);