Merge pull request #11801 from unknownbrackets/shaderid

GPU: Better typesafety for shader bits
This commit is contained in:
Henrik Rydgård 2019-02-16 16:40:41 +01:00 committed by GitHub
commit 8e0f3c9ea2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 24 deletions

View File

@ -11,7 +11,7 @@
#include "GPU/Common/ShaderId.h"
#include "GPU/Common/VertexDecoderCommon.h"
std::string VertexShaderDesc(const ShaderID &id) {
std::string VertexShaderDesc(const VShaderID &id) {
std::stringstream desc;
desc << StringFromFormat("%08x:%08x ", id.d[1], id.d[0]);
if (id.Bit(VS_BIT_IS_THROUGH)) desc << "THR ";
@ -60,7 +60,7 @@ std::string VertexShaderDesc(const ShaderID &id) {
return desc.str();
}
void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform) {
void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform) {
bool isModeThrough = (vertType & GE_VTYPE_THROUGH) != 0;
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
bool doTextureTransform = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
@ -81,7 +81,7 @@ void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform)
bool enableFog = gstate.isFogEnabled() && !isModeThrough && !gstate.isModeClear();
bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled() && !isModeThrough;
ShaderID id;
VShaderID id;
id.SetBit(VS_BIT_LMODE, lmode);
id.SetBit(VS_BIT_IS_THROUGH, isModeThrough);
id.SetBit(VS_BIT_ENABLE_FOG, enableFog);
@ -160,7 +160,7 @@ static bool MatrixNeedsProjection(const float m[12]) {
return m[2] != 0.0f || m[5] != 0.0f || m[8] != 0.0f || m[11] != 1.0f;
}
std::string FragmentShaderDesc(const ShaderID &id) {
std::string FragmentShaderDesc(const FShaderID &id) {
std::stringstream desc;
desc << StringFromFormat("%08x:%08x ", id.d[1], id.d[0]);
if (id.Bit(FS_BIT_CLEARMODE)) desc << "Clear ";
@ -226,8 +226,8 @@ std::string FragmentShaderDesc(const ShaderID &id) {
// Here we must take all the bits of the gstate that determine what the fragment shader will
// look like, and concatenate them together into an ID.
void ComputeFragmentShaderID(ShaderID *id_out, const Draw::Bugs &bugs) {
ShaderID id;
void ComputeFragmentShaderID(FShaderID *id_out, const Draw::Bugs &bugs) {
FShaderID id;
if (gstate.isModeClear()) {
// We only need one clear shader, so let's ignore the rest of the bits.
id.SetBit(FS_BIT_CLEARMODE);

View File

@ -8,7 +8,7 @@
// 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 {
enum VShaderBit : uint8_t {
VS_BIT_LMODE = 0,
VS_BIT_IS_THROUGH = 1,
VS_BIT_ENABLE_FOG = 2,
@ -55,9 +55,12 @@ enum {
// No more free
};
static inline VShaderBit operator +(VShaderBit bit, int i) {
return VShaderBit((int)bit + i);
}
// Local
enum {
enum FShaderBit : uint8_t {
FS_BIT_CLEARMODE = 0,
FS_BIT_DO_TEXTURE = 1,
FS_BIT_TEXFUNC = 2, // 3 bits
@ -91,6 +94,10 @@ enum {
// 50+ are free.
};
static inline FShaderBit operator +(FShaderBit bit, int i) {
return FShaderBit((int)bit + i);
}
struct ShaderID {
ShaderID() {
clear();
@ -126,6 +133,20 @@ struct ShaderID {
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;
}
@ -134,9 +155,6 @@ struct ShaderID {
const int mask = (1 << count) - 1;
return (d[bit >> 5] >> (bit & 31)) & mask;
}
uint32_t Word(int word) const {
return d[word];
}
void SetBit(int bit, bool value = true) {
if (value) {
d[bit >> 5] |= 1 << (bit & 31);
@ -148,14 +166,6 @@ struct ShaderID {
d[bit >> 5] |= (value & mask) << (bit & 31);
}
}
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));
}
};
struct VShaderID : ShaderID {
@ -165,6 +175,22 @@ struct 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 {
@ -174,6 +200,22 @@ struct 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 {
@ -181,10 +223,10 @@ class Bugs;
}
void ComputeVertexShaderID(ShaderID *id, uint32_t vertexType, bool useHWTransform);
void ComputeVertexShaderID(VShaderID *id, uint32_t vertexType, bool useHWTransform);
// 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 ShaderID &id);
std::string VertexShaderDesc(const VShaderID &id);
void ComputeFragmentShaderID(ShaderID *id, const Draw::Bugs &bugs);
std::string FragmentShaderDesc(const ShaderID &id);
void ComputeFragmentShaderID(FShaderID *id, const Draw::Bugs &bugs);
std::string FragmentShaderDesc(const FShaderID &id);

View File

@ -762,7 +762,7 @@ std::string Shader::GetShaderString(DebugShaderStringType type, ShaderID id) con
case SHADER_STRING_SOURCE_CODE:
return source_;
case SHADER_STRING_SHORT_DESC:
return isFragment_ ? FragmentShaderDesc(id) : VertexShaderDesc(id);
return isFragment_ ? FragmentShaderDesc(FShaderID(id)) : VertexShaderDesc(VShaderID(id));
default:
return "N/A";
}