Permalink
Browse files

Merge pull request #10231 from unknownbrackets/shader-ids

Fix hashmap grow bug and add shader id typesafety
  • Loading branch information...
hrydgard committed Dec 2, 2017
2 parents 341611e + 9c52155 commit 7f858cc49727d48c112c1d61b7a3447fdc52d784
@@ -5,6 +5,7 @@
#include "ext/xxhash.h"
#include "Common/CommonFuncs.h"
#include "Common/Log.h"
// Whatever random value.
const uint32_t hashmapSeed = 0x23B58532;
@@ -50,8 +51,9 @@ class DenseHashMap {
else if (state[p] == BucketState::FREE)
return NullValue;
p = (p + 1) & mask; // If the state is REMOVED, we just keep on walking.
if (p == pos)
Crash();
if (p == pos) {
_assert_msg_(SYSTEM, false, "DenseHashMap: Hit full on Get()");
}
}
return NullValue;
}
@@ -68,7 +70,8 @@ class DenseHashMap {
while (true) {
if (state[p] == BucketState::TAKEN) {
if (KeyEquals(key, map[p].key)) {
Crash(); // Bad! We already got this one. Let's avoid this case.
// Bad! We already got this one. Let's avoid this case.
_assert_msg_(SYSTEM, false, "DenseHashMap: Duplicate key inserted");
return false;
}
// continue looking....
@@ -79,7 +82,7 @@ class DenseHashMap {
p = (p + 1) & mask;
if (p == pos) {
// FULL! Error. Should not happen thanks to Grow().
Crash();
_assert_msg_(SYSTEM, false, "DenseHashMap: Hit full on Insert()");
}
}
if (state[p] == BucketState::REMOVED) {
@@ -107,7 +110,7 @@ class DenseHashMap {
p = (p + 1) & mask;
if (p == pos) {
// FULL! Error. Should not happen.
Crash();
_assert_msg_(SYSTEM, false, "DenseHashMap: Hit full on Remove()");
}
}
return false;
@@ -147,6 +150,11 @@ class DenseHashMap {
// This is extremely non-atomic and will need synchronization.
std::vector<Pair> old = std::move(map);
std::vector<BucketState> oldState = std::move(state);
// Can't assume move will clear, it just may clear.
map.clear();
state.clear();
int oldCount = count_;
capacity_ *= factor;
map.resize(capacity_);
state.resize(capacity_);
@@ -157,6 +165,7 @@ class DenseHashMap {
Insert(old[i].key, old[i].value);
}
}
_assert_msg_(SYSTEM, oldCount == count_, "DenseHashMap: count should not change in Grow()");
}
struct Pair {
Key key;
@@ -191,8 +200,9 @@ class PrehashMap {
else if (state[p] == BucketState::FREE)
return NullValue;
p = (p + 1) & mask; // If the state is REMOVED, we just keep on walking.
if (p == pos)
Crash();
if (p == pos) {
_assert_msg_(SYSTEM, false, "PrehashMap: Hit full on Get()");
}
}
return NullValue;
}
@@ -217,7 +227,7 @@ class PrehashMap {
p = (p + 1) & mask;
if (p == pos) {
// FULL! Error. Should not happen thanks to Grow().
Crash();
_assert_msg_(SYSTEM, false, "PrehashMap: Hit full on Insert()");
}
}
if (state[p] == BucketState::REMOVED) {
@@ -244,7 +254,7 @@ class PrehashMap {
}
p = (p + 1) & mask;
if (p == pos) {
Crash();
_assert_msg_(SYSTEM, false, "PrehashMap: Hit full on Remove()");
}
}
return false;
@@ -285,6 +295,11 @@ class PrehashMap {
// This is extremely non-atomic and will need synchronization.
std::vector<Pair> old = std::move(map);
std::vector<BucketState> oldState = std::move(state);
// Can't assume move will clear, it just may clear.
map.clear();
state.clear();
int oldCount = count_;
capacity_ *= factor;
map.resize(capacity_);
state.resize(capacity_);
@@ -295,6 +310,7 @@ class PrehashMap {
Insert(old[i].hash, old[i].value);
}
}
_assert_msg_(SYSTEM, oldCount == count_, "PrehashMap: count should not change in Grow()");
}
struct Pair {
uint32_t hash;
@@ -1323,7 +1323,7 @@ void ConvertStencilFuncState(GenericStencilFuncState &state) {
return;
// The PSP's mask is reversed (bits not to write.)
state.writeMask = (~(gstate.pmska >> 0)) & 0xFF;
state.writeMask = (~gstate.pmska) & 0xFF;
state.sFail = gstate.getStencilOpSFail();
state.zFail = gstate.getStencilOpZFail();
@@ -14,20 +14,25 @@ enum {
VS_BIT_ENABLE_FOG = 2,
VS_BIT_HAS_COLOR = 3,
VS_BIT_DO_TEXTURE = 4,
// 5 is free.
VS_BIT_DO_TEXTURE_TRANSFORM = 6,
// 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 1 free after
VS_BIT_NORM_REVERSE_TESS = 14, // 1 bit
// 15 is free.
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
@@ -43,7 +48,8 @@ enum {
VS_BIT_LIGHT2_ENABLE = 54,
VS_BIT_LIGHT3_ENABLE = 55,
VS_BIT_LIGHTING_ENABLE = 56,
VS_BIT_WEIGHT_FMTSCALE = 57, // only two bits, 1 free after
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
@@ -56,6 +62,7 @@ enum {
FS_BIT_DO_TEXTURE = 1,
FS_BIT_TEXFUNC = 2, // 3 bits
FS_BIT_TEXALPHA = 5,
// 6 is free.
FS_BIT_SHADER_TEX_CLAMP = 7,
FS_BIT_CLAMP_S = 8,
FS_BIT_CLAMP_T = 9,
@@ -76,9 +83,10 @@ enum {
FS_BIT_REPLACE_BLEND = 32, // 3 bits
FS_BIT_BLENDEQ = 35, // 3 bits
FS_BIT_BLENDFUNC_A = 38, // 4 bits
FS_BIT_BLENDFUNC_B = 42,
FS_BIT_BLENDFUNC_B = 42, // 4 bits
FS_BIT_FLATSHADE = 46,
FS_BIT_BGRA_TEXTURE = 47,
// 48+ are free.
};
struct ShaderID {
@@ -148,6 +156,24 @@ struct ShaderID {
}
};
struct VShaderID : ShaderID {
VShaderID() : ShaderID() {
}
explicit VShaderID(ShaderID &src) {
memcpy(d, src.d, sizeof(d));
}
};
struct FShaderID : ShaderID {
FShaderID() : ShaderID() {
}
explicit FShaderID(ShaderID &src) {
memcpy(d, src.d, sizeof(d));
}
};
bool CanUseHardwareTransform(int prim);
void ComputeVertexShaderID(ShaderID *id, uint32_t vertexType, bool useHWTransform);
@@ -19,6 +19,6 @@
#include "GPU/D3D11/FragmentShaderGeneratorD3D11.h"
#include "GPU/Directx9/PixelShaderGeneratorDX9.h"
void GenerateFragmentShaderD3D11(const ShaderID &id, char *buffer, ShaderLanguage lang) {
void GenerateFragmentShaderD3D11(const FShaderID &id, char *buffer, ShaderLanguage lang) {
DX9::GenerateFragmentShaderHLSL(id, buffer, lang);
}
@@ -19,4 +19,4 @@
#include "GPU/Common/ShaderId.h"
void GenerateFragmentShaderD3D11(const ShaderID &id, char *buffer, ShaderLanguage lang);
void GenerateFragmentShaderD3D11(const FShaderID &id, char *buffer, ShaderLanguage lang);
@@ -38,7 +38,7 @@
#include "GPU/D3D11/VertexShaderGeneratorD3D11.h"
#include "GPU/D3D11/D3D11Util.h"
D3D11FragmentShader::D3D11FragmentShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, ShaderID id, const char *code, bool useHWTransform)
D3D11FragmentShader::D3D11FragmentShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, FShaderID id, const char *code, bool useHWTransform)
: device_(device), id_(id), failed_(false), useHWTransform_(useHWTransform), module_(0) {
source_ = code;
@@ -63,7 +63,7 @@ std::string D3D11FragmentShader::GetShaderString(DebugShaderStringType type) con
}
}
D3D11VertexShader::D3D11VertexShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, ShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting)
D3D11VertexShader::D3D11VertexShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, VShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting)
: device_(device), id_(id), failed_(false), useHWTransform_(useHWTransform), module_(nullptr), usesLighting_(usesLighting) {
source_ = code;
@@ -178,8 +178,8 @@ void ShaderManagerD3D11::BindUniforms() {
}
void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform) {
ShaderID VSID;
ShaderID FSID;
VShaderID VSID;
FShaderID FSID;
if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
@@ -268,7 +268,7 @@ std::string ShaderManagerD3D11::DebugGetShaderString(std::string id, DebugShader
switch (type) {
case SHADER_TYPE_VERTEX:
{
auto iter = vsCache_.find(shaderId);
auto iter = vsCache_.find(VShaderID(shaderId));
if (iter == vsCache_.end()) {
return "";
}
@@ -277,7 +277,7 @@ std::string ShaderManagerD3D11::DebugGetShaderString(std::string id, DebugShader
case SHADER_TYPE_FRAGMENT:
{
auto iter = fsCache_.find(shaderId);
auto iter = fsCache_.find(FShaderID(shaderId));
if (iter == fsCache_.end()) {
return "";
}
@@ -31,7 +31,7 @@ class D3D11PushBuffer;
class D3D11FragmentShader {
public:
D3D11FragmentShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, ShaderID id, const char *code, bool useHWTransform);
D3D11FragmentShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, FShaderID id, const char *code, bool useHWTransform);
~D3D11FragmentShader();
const std::string &source() const { return source_; }
@@ -49,12 +49,12 @@ class D3D11FragmentShader {
std::string source_;
bool failed_;
bool useHWTransform_;
ShaderID id_;
FShaderID id_;
};
class D3D11VertexShader {
public:
D3D11VertexShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, ShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting);
D3D11VertexShader(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel, VShaderID id, const char *code, int vertType, bool useHWTransform, bool usesLighting);
~D3D11VertexShader();
const std::string &source() const { return source_; }
@@ -81,7 +81,7 @@ class D3D11VertexShader {
bool failed_;
bool useHWTransform_;
bool usesLighting_;
ShaderID id_;
VShaderID id_;
};
class D3D11PushBuffer;
@@ -123,10 +123,10 @@ class ShaderManagerD3D11 : public ShaderManagerCommon {
ID3D11DeviceContext *context_;
D3D_FEATURE_LEVEL featureLevel_;
typedef std::map<ShaderID, D3D11FragmentShader *> FSCache;
typedef std::map<FShaderID, D3D11FragmentShader *> FSCache;
FSCache fsCache_;
typedef std::map<ShaderID, D3D11VertexShader *> VSCache;
typedef std::map<VShaderID, D3D11VertexShader *> VSCache;
VSCache vsCache_;
char *codeBuffer_;
@@ -144,6 +144,6 @@ class ShaderManagerD3D11 : public ShaderManagerCommon {
D3D11FragmentShader *lastFShader_;
D3D11VertexShader *lastVShader_;
ShaderID lastFSID_;
ShaderID lastVSID_;
};
FShaderID lastFSID_;
VShaderID lastVSID_;
};
@@ -19,7 +19,7 @@
#include "GPU/D3D11/VertexShaderGeneratorD3D11.h"
#include "GPU/Directx9/VertexShaderGeneratorDX9.h"
void GenerateVertexShaderD3D11(const ShaderID &id, char *buffer, bool *usesLighting, ShaderLanguage lang) {
void GenerateVertexShaderD3D11(const VShaderID &id, char *buffer, bool *usesLighting, ShaderLanguage lang) {
*usesLighting = true;
DX9::GenerateVertexShaderHLSL(id, buffer, lang);
}
@@ -19,4 +19,4 @@
#include "GPU/Common/ShaderId.h"
void GenerateVertexShaderD3D11(const ShaderID &id, char *buffer, bool *usesLighting, ShaderLanguage lang);
void GenerateVertexShaderD3D11(const VShaderID &id, char *buffer, bool *usesLighting, ShaderLanguage lang);
@@ -33,7 +33,7 @@ namespace DX9 {
// Missing: Z depth range
// Also, logic ops etc, of course, as they are not supported in DX9.
bool GenerateFragmentShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage lang) {
bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguage lang) {
char *p = buffer;
bool lmode = id.Bit(FS_BIT_LMODE);
@@ -22,7 +22,7 @@
namespace DX9 {
bool GenerateFragmentShaderHLSL(const ShaderID &id, char *buffer, ShaderLanguage lang = HLSL_DX9);
bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguage lang = HLSL_DX9);
#define CONST_PS_TEXENV 0
#define CONST_PS_ALPHACOLORREF 1
Oops, something went wrong.

0 comments on commit 7f858cc

Please sign in to comment.