mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 16:19:28 +01:00
Merge pull request #3513 from phire/make_hdkr_happy
Get shadergen ready for Multithreadded generation of shaders.
This commit is contained in:
commit
ee9e3432cb
@ -26,7 +26,6 @@ namespace DX11
|
||||
GeometryShaderCache::GSCache GeometryShaderCache::GeometryShaders;
|
||||
const GeometryShaderCache::GSCacheEntry* GeometryShaderCache::last_entry;
|
||||
GeometryShaderUid GeometryShaderCache::last_uid;
|
||||
UidChecker<GeometryShaderUid, ShaderCode> GeometryShaderCache::geometry_uid_checker;
|
||||
const GeometryShaderCache::GSCacheEntry GeometryShaderCache::pass_entry;
|
||||
|
||||
ID3D11GeometryShader* ClearGeometryShader = nullptr;
|
||||
@ -165,9 +164,6 @@ void GeometryShaderCache::Init()
|
||||
GeometryShaderCacheInserter inserter;
|
||||
g_gs_disk_cache.OpenAndRead(cache_filename, inserter);
|
||||
|
||||
if (g_Config.bEnableShaderDebugging)
|
||||
Clear();
|
||||
|
||||
last_entry = nullptr;
|
||||
}
|
||||
|
||||
@ -177,7 +173,6 @@ void GeometryShaderCache::Clear()
|
||||
for (auto& iter : GeometryShaders)
|
||||
iter.second.Destroy();
|
||||
GeometryShaders.clear();
|
||||
geometry_uid_checker.Invalidate();
|
||||
|
||||
last_entry = nullptr;
|
||||
}
|
||||
@ -196,12 +191,7 @@ void GeometryShaderCache::Shutdown()
|
||||
|
||||
bool GeometryShaderCache::SetShader(u32 primitive_type)
|
||||
{
|
||||
GeometryShaderUid uid = GetGeometryShaderUid(primitive_type, API_D3D);
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
ShaderCode code = GenerateGeometryShaderCode(primitive_type, API_D3D);
|
||||
geometry_uid_checker.AddToIndexAndCheck(code, uid, "Geometry", "g");
|
||||
}
|
||||
GeometryShaderUid uid = GetGeometryShaderUid(primitive_type);
|
||||
|
||||
// Check if the shader is already set
|
||||
if (last_entry)
|
||||
@ -235,7 +225,7 @@ bool GeometryShaderCache::SetShader(u32 primitive_type)
|
||||
}
|
||||
|
||||
// Need to compile a new shader
|
||||
ShaderCode code = GenerateGeometryShaderCode(primitive_type, API_D3D);
|
||||
ShaderCode code = GenerateGeometryShaderCode(API_D3D, uid.GetUidData());
|
||||
|
||||
D3DBlob* pbytecode;
|
||||
if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode))
|
||||
@ -250,11 +240,6 @@ bool GeometryShaderCache::SetShader(u32 primitive_type)
|
||||
bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
|
||||
pbytecode->Release();
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging && success)
|
||||
{
|
||||
GeometryShaders[uid].code = code.GetBuffer();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -32,8 +32,6 @@ private:
|
||||
{
|
||||
ID3D11GeometryShader* shader;
|
||||
|
||||
std::string code;
|
||||
|
||||
GSCacheEntry() : shader(nullptr) {}
|
||||
void Destroy() { SAFE_RELEASE(shader); }
|
||||
};
|
||||
@ -44,8 +42,6 @@ private:
|
||||
static const GSCacheEntry* last_entry;
|
||||
static GeometryShaderUid last_uid;
|
||||
static const GSCacheEntry pass_entry;
|
||||
|
||||
static UidChecker<GeometryShaderUid, ShaderCode> geometry_uid_checker;
|
||||
};
|
||||
|
||||
} // namespace DX11
|
||||
|
@ -26,7 +26,6 @@ namespace DX11
|
||||
PixelShaderCache::PSCache PixelShaderCache::PixelShaders;
|
||||
const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry;
|
||||
PixelShaderUid PixelShaderCache::last_uid;
|
||||
UidChecker<PixelShaderUid, ShaderCode> PixelShaderCache::pixel_uid_checker;
|
||||
|
||||
LinearDiskCache<PixelShaderUid, u8> g_ps_disk_cache;
|
||||
|
||||
@ -505,9 +504,6 @@ void PixelShaderCache::Init()
|
||||
PixelShaderCacheInserter inserter;
|
||||
g_ps_disk_cache.OpenAndRead(cache_filename, inserter);
|
||||
|
||||
if (g_Config.bEnableShaderDebugging)
|
||||
Clear();
|
||||
|
||||
last_entry = nullptr;
|
||||
}
|
||||
|
||||
@ -517,7 +513,6 @@ void PixelShaderCache::Clear()
|
||||
for (auto& iter : PixelShaders)
|
||||
iter.second.Destroy();
|
||||
PixelShaders.clear();
|
||||
pixel_uid_checker.Invalidate();
|
||||
|
||||
last_entry = nullptr;
|
||||
}
|
||||
@ -556,12 +551,7 @@ void PixelShaderCache::Shutdown()
|
||||
|
||||
bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode)
|
||||
{
|
||||
PixelShaderUid uid = GetPixelShaderUid(dstAlphaMode, API_D3D);
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
ShaderCode code = GeneratePixelShaderCode(dstAlphaMode, API_D3D);
|
||||
pixel_uid_checker.AddToIndexAndCheck(code, uid, "Pixel", "p");
|
||||
}
|
||||
PixelShaderUid uid = GetPixelShaderUid(dstAlphaMode);
|
||||
|
||||
// Check if the shader is already set
|
||||
if (last_entry)
|
||||
@ -588,7 +578,7 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode)
|
||||
}
|
||||
|
||||
// Need to compile a new shader
|
||||
ShaderCode code = GeneratePixelShaderCode(dstAlphaMode, API_D3D);
|
||||
ShaderCode code = GeneratePixelShaderCode(dstAlphaMode, API_D3D, uid.GetUidData());
|
||||
|
||||
D3DBlob* pbytecode;
|
||||
if (!D3D::CompilePixelShader(code.GetBuffer(), &pbytecode))
|
||||
@ -603,11 +593,6 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode)
|
||||
bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
|
||||
pbytecode->Release();
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging && success)
|
||||
{
|
||||
PixelShaders[uid].code = code.GetBuffer();
|
||||
}
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
return success;
|
||||
}
|
||||
|
@ -42,8 +42,6 @@ private:
|
||||
{
|
||||
ID3D11PixelShader* shader;
|
||||
|
||||
std::string code;
|
||||
|
||||
PSCacheEntry() : shader(nullptr) {}
|
||||
void Destroy() { SAFE_RELEASE(shader); }
|
||||
};
|
||||
@ -53,8 +51,6 @@ private:
|
||||
static PSCache PixelShaders;
|
||||
static const PSCacheEntry* last_entry;
|
||||
static PixelShaderUid last_uid;
|
||||
|
||||
static UidChecker<PixelShaderUid, ShaderCode> pixel_uid_checker;
|
||||
};
|
||||
|
||||
} // namespace DX11
|
||||
|
@ -24,7 +24,6 @@ namespace DX11
|
||||
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
||||
const VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry;
|
||||
VertexShaderUid VertexShaderCache::last_uid;
|
||||
UidChecker<VertexShaderUid, ShaderCode> VertexShaderCache::vertex_uid_checker;
|
||||
|
||||
static ID3D11VertexShader* SimpleVertexShader = nullptr;
|
||||
static ID3D11VertexShader* ClearVertexShader = nullptr;
|
||||
@ -166,9 +165,6 @@ void VertexShaderCache::Init()
|
||||
VertexShaderCacheInserter inserter;
|
||||
g_vs_disk_cache.OpenAndRead(cache_filename, inserter);
|
||||
|
||||
if (g_Config.bEnableShaderDebugging)
|
||||
Clear();
|
||||
|
||||
last_entry = nullptr;
|
||||
}
|
||||
|
||||
@ -177,7 +173,6 @@ void VertexShaderCache::Clear()
|
||||
for (auto& iter : vshaders)
|
||||
iter.second.Destroy();
|
||||
vshaders.clear();
|
||||
vertex_uid_checker.Invalidate();
|
||||
|
||||
last_entry = nullptr;
|
||||
}
|
||||
@ -199,12 +194,7 @@ void VertexShaderCache::Shutdown()
|
||||
|
||||
bool VertexShaderCache::SetShader()
|
||||
{
|
||||
VertexShaderUid uid = GetVertexShaderUid(API_D3D);
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
ShaderCode code = GenerateVertexShaderCode(API_D3D);
|
||||
vertex_uid_checker.AddToIndexAndCheck(code, uid, "Vertex", "v");
|
||||
}
|
||||
VertexShaderUid uid = GetVertexShaderUid();
|
||||
|
||||
if (last_entry)
|
||||
{
|
||||
@ -227,7 +217,7 @@ bool VertexShaderCache::SetShader()
|
||||
return (entry.shader != nullptr);
|
||||
}
|
||||
|
||||
ShaderCode code = GenerateVertexShaderCode(API_D3D);
|
||||
ShaderCode code = GenerateVertexShaderCode(API_D3D, uid.GetUidData());
|
||||
|
||||
D3DBlob* pbytecode = nullptr;
|
||||
D3D::CompileVertexShader(code.GetBuffer(), &pbytecode);
|
||||
@ -242,11 +232,6 @@ bool VertexShaderCache::SetShader()
|
||||
bool success = InsertByteCode(uid, pbytecode);
|
||||
pbytecode->Release();
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging && success)
|
||||
{
|
||||
vshaders[uid].code = code.GetBuffer();
|
||||
}
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
|
||||
return success;
|
||||
}
|
||||
|
@ -38,8 +38,6 @@ private:
|
||||
ID3D11VertexShader* shader;
|
||||
D3DBlob* bytecode; // needed to initialize the input layout
|
||||
|
||||
std::string code;
|
||||
|
||||
VSCacheEntry() : shader(nullptr), bytecode(nullptr) {}
|
||||
void SetByteCode(D3DBlob* blob)
|
||||
{
|
||||
@ -58,8 +56,6 @@ private:
|
||||
static VSCache vshaders;
|
||||
static const VSCacheEntry* last_entry;
|
||||
static VertexShaderUid last_uid;
|
||||
|
||||
static UidChecker<VertexShaderUid, ShaderCode> vertex_uid_checker;
|
||||
};
|
||||
|
||||
} // namespace DX11
|
||||
|
@ -30,22 +30,10 @@ VsBytecodeCache s_vs_bytecode_cache;
|
||||
// Used to keep track of blobs to release at Shutdown time.
|
||||
static std::vector<ID3DBlob*> s_shader_blob_list;
|
||||
|
||||
// Only used for shader debugging..
|
||||
using GsHlslCache = std::map<GeometryShaderUid, std::string>;
|
||||
using PsHlslCache = std::map<PixelShaderUid, std::string>;
|
||||
using VsHlslCache = std::map<VertexShaderUid, std::string>;
|
||||
static GsHlslCache s_gs_hlsl_cache;
|
||||
static PsHlslCache s_ps_hlsl_cache;
|
||||
static VsHlslCache s_vs_hlsl_cache;
|
||||
|
||||
static LinearDiskCache<GeometryShaderUid, u8> s_gs_disk_cache;
|
||||
static LinearDiskCache<PixelShaderUid, u8> s_ps_disk_cache;
|
||||
static LinearDiskCache<VertexShaderUid, u8> s_vs_disk_cache;
|
||||
|
||||
static UidChecker<GeometryShaderUid, ShaderCode> s_geometry_uid_checker;
|
||||
static UidChecker<PixelShaderUid, ShaderCode> s_pixel_uid_checker;
|
||||
static UidChecker<VertexShaderUid, ShaderCode> s_vertex_uid_checker;
|
||||
|
||||
static D3D12_SHADER_BYTECODE s_last_geometry_shader_bytecode;
|
||||
static D3D12_SHADER_BYTECODE s_last_pixel_shader_bytecode;
|
||||
static D3D12_SHADER_BYTECODE s_last_vertex_shader_bytecode;
|
||||
@ -104,10 +92,6 @@ void ShaderCache::Init()
|
||||
ShaderCacheInserter<VertexShaderUid, VsBytecodeCache, &s_vs_bytecode_cache> vs_inserter;
|
||||
s_vs_disk_cache.OpenAndRead(vs_cache_filename, vs_inserter);
|
||||
|
||||
// Clear out cache when debugging shaders to ensure stale ones don't stick around..
|
||||
if (g_Config.bEnableShaderDebugging)
|
||||
Clear();
|
||||
|
||||
SETSTAT(stats.numPixelShadersAlive, static_cast<int>(s_ps_bytecode_cache.size()));
|
||||
SETSTAT(stats.numPixelShadersCreated, static_cast<int>(s_ps_bytecode_cache.size()));
|
||||
SETSTAT(stats.numVertexShadersAlive, static_cast<int>(s_vs_bytecode_cache.size()));
|
||||
@ -145,26 +129,15 @@ void ShaderCache::Shutdown()
|
||||
s_ps_disk_cache.Close();
|
||||
s_vs_disk_cache.Sync();
|
||||
s_vs_disk_cache.Close();
|
||||
|
||||
if (g_Config.bEnableShaderDebugging)
|
||||
{
|
||||
s_gs_hlsl_cache.clear();
|
||||
s_ps_hlsl_cache.clear();
|
||||
s_vs_hlsl_cache.clear();
|
||||
}
|
||||
|
||||
s_geometry_uid_checker.Invalidate();
|
||||
s_pixel_uid_checker.Invalidate();
|
||||
s_vertex_uid_checker.Invalidate();
|
||||
}
|
||||
|
||||
void ShaderCache::LoadAndSetActiveShaders(DSTALPHA_MODE ps_dst_alpha_mode, u32 gs_primitive_type)
|
||||
{
|
||||
SetCurrentPrimitiveTopology(gs_primitive_type);
|
||||
|
||||
GeometryShaderUid gs_uid = GetGeometryShaderUid(gs_primitive_type, API_D3D);
|
||||
PixelShaderUid ps_uid = GetPixelShaderUid(ps_dst_alpha_mode, API_D3D);
|
||||
VertexShaderUid vs_uid = GetVertexShaderUid(API_D3D);
|
||||
GeometryShaderUid gs_uid = GetGeometryShaderUid(gs_primitive_type);
|
||||
PixelShaderUid ps_uid = GetPixelShaderUid(ps_dst_alpha_mode);
|
||||
VertexShaderUid vs_uid = GetVertexShaderUid();
|
||||
|
||||
bool gs_changed = gs_uid != s_last_geometry_shader_uid;
|
||||
bool ps_changed = ps_uid != s_last_pixel_shader_uid;
|
||||
@ -217,12 +190,6 @@ void ShaderCache::HandleGSUIDChange(GeometryShaderUid gs_uid, u32 gs_primitive_t
|
||||
{
|
||||
s_last_geometry_shader_uid = gs_uid;
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
ShaderCode code = GenerateGeometryShaderCode(gs_primitive_type, API_D3D);
|
||||
s_geometry_uid_checker.AddToIndexAndCheck(code, gs_uid, "Geometry", "g");
|
||||
}
|
||||
|
||||
if (gs_uid.GetUidData()->IsPassthrough())
|
||||
{
|
||||
s_last_geometry_shader_bytecode = {};
|
||||
@ -236,7 +203,7 @@ void ShaderCache::HandleGSUIDChange(GeometryShaderUid gs_uid, u32 gs_primitive_t
|
||||
}
|
||||
else
|
||||
{
|
||||
ShaderCode gs_code = GenerateGeometryShaderCode(gs_primitive_type, API_D3D);
|
||||
ShaderCode gs_code = GenerateGeometryShaderCode(API_D3D, gs_uid.GetUidData());
|
||||
ID3DBlob* gs_bytecode = nullptr;
|
||||
|
||||
if (!D3D::CompileGeometryShader(gs_code.GetBuffer(), &gs_bytecode))
|
||||
@ -248,11 +215,6 @@ void ShaderCache::HandleGSUIDChange(GeometryShaderUid gs_uid, u32 gs_primitive_t
|
||||
s_last_geometry_shader_bytecode = InsertByteCode(gs_uid, &s_gs_bytecode_cache, gs_bytecode);
|
||||
s_gs_disk_cache.Append(gs_uid, reinterpret_cast<u8*>(gs_bytecode->GetBufferPointer()),
|
||||
static_cast<u32>(gs_bytecode->GetBufferSize()));
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
s_gs_hlsl_cache[gs_uid] = gs_code.GetBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,12 +222,6 @@ void ShaderCache::HandlePSUIDChange(PixelShaderUid ps_uid, DSTALPHA_MODE ps_dst_
|
||||
{
|
||||
s_last_pixel_shader_uid = ps_uid;
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
ShaderCode code = GeneratePixelShaderCode(ps_dst_alpha_mode, API_D3D);
|
||||
s_pixel_uid_checker.AddToIndexAndCheck(code, ps_uid, "Pixel", "p");
|
||||
}
|
||||
|
||||
auto ps_iterator = s_ps_bytecode_cache.find(ps_uid);
|
||||
if (ps_iterator != s_ps_bytecode_cache.end())
|
||||
{
|
||||
@ -274,7 +230,7 @@ void ShaderCache::HandlePSUIDChange(PixelShaderUid ps_uid, DSTALPHA_MODE ps_dst_
|
||||
}
|
||||
else
|
||||
{
|
||||
ShaderCode ps_code = GeneratePixelShaderCode(ps_dst_alpha_mode, API_D3D);
|
||||
ShaderCode ps_code = GeneratePixelShaderCode(ps_dst_alpha_mode, API_D3D, ps_uid.GetUidData());
|
||||
ID3DBlob* ps_bytecode = nullptr;
|
||||
|
||||
if (!D3D::CompilePixelShader(ps_code.GetBuffer(), &ps_bytecode))
|
||||
@ -289,11 +245,6 @@ void ShaderCache::HandlePSUIDChange(PixelShaderUid ps_uid, DSTALPHA_MODE ps_dst_
|
||||
|
||||
SETSTAT(stats.numPixelShadersAlive, static_cast<int>(s_ps_bytecode_cache.size()));
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
s_ps_hlsl_cache[ps_uid] = ps_code.GetBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,12 +252,6 @@ void ShaderCache::HandleVSUIDChange(VertexShaderUid vs_uid)
|
||||
{
|
||||
s_last_vertex_shader_uid = vs_uid;
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
ShaderCode code = GenerateVertexShaderCode(API_D3D);
|
||||
s_vertex_uid_checker.AddToIndexAndCheck(code, vs_uid, "Vertex", "v");
|
||||
}
|
||||
|
||||
auto vs_iterator = s_vs_bytecode_cache.find(vs_uid);
|
||||
if (vs_iterator != s_vs_bytecode_cache.end())
|
||||
{
|
||||
@ -315,7 +260,7 @@ void ShaderCache::HandleVSUIDChange(VertexShaderUid vs_uid)
|
||||
}
|
||||
else
|
||||
{
|
||||
ShaderCode vs_code = GenerateVertexShaderCode(API_D3D);
|
||||
ShaderCode vs_code = GenerateVertexShaderCode(API_D3D, vs_uid.GetUidData());
|
||||
ID3DBlob* vs_bytecode = nullptr;
|
||||
|
||||
if (!D3D::CompileVertexShader(vs_code.GetBuffer(), &vs_bytecode))
|
||||
@ -330,11 +275,6 @@ void ShaderCache::HandleVSUIDChange(VertexShaderUid vs_uid)
|
||||
|
||||
SETSTAT(stats.numVertexShadersAlive, static_cast<int>(s_vs_bytecode_cache.size()));
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
s_vs_hlsl_cache[vs_uid] = vs_code.GetBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ bool ShaderCache<Uid>::SetShader(DSTALPHA_MODE dst_alpha_mode, u32 primitive_typ
|
||||
}
|
||||
|
||||
// Need to compile a new shader
|
||||
ShaderCode code = GenerateCode(dst_alpha_mode, primitive_type, API_OPENGL);
|
||||
ShaderCode code = GenerateCode(dst_alpha_mode, API_OPENGL, uid);
|
||||
m_shaders.emplace(uid, code.GetBuffer());
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
|
@ -26,14 +26,12 @@ public:
|
||||
|
||||
protected:
|
||||
virtual Uid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, API_TYPE api_type) = 0;
|
||||
virtual ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
|
||||
API_TYPE api_type) = 0;
|
||||
virtual ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, API_TYPE api_type, Uid uid) = 0;
|
||||
|
||||
private:
|
||||
std::map<Uid, std::string> m_shaders;
|
||||
const std::string* m_last_entry = nullptr;
|
||||
Uid m_last_uid;
|
||||
UidChecker<Uid, ShaderCode> m_uid_checker;
|
||||
};
|
||||
|
||||
class VertexShaderCache : public ShaderCache<VertexShaderUid>
|
||||
@ -45,12 +43,12 @@ protected:
|
||||
VertexShaderUid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
|
||||
API_TYPE api_type) override
|
||||
{
|
||||
return GetVertexShaderUid(api_type);
|
||||
return GetVertexShaderUid();
|
||||
}
|
||||
ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
|
||||
API_TYPE api_type) override
|
||||
ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, API_TYPE api_type,
|
||||
VertexShaderUid uid) override
|
||||
{
|
||||
return GenerateVertexShaderCode(api_type);
|
||||
return GenerateVertexShaderCode(api_type, uid.GetUidData());
|
||||
}
|
||||
};
|
||||
|
||||
@ -63,12 +61,12 @@ protected:
|
||||
GeometryShaderUid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
|
||||
API_TYPE api_type) override
|
||||
{
|
||||
return GetGeometryShaderUid(primitive_type, api_type);
|
||||
return GetGeometryShaderUid(primitive_type);
|
||||
}
|
||||
ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
|
||||
API_TYPE api_type) override
|
||||
ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, API_TYPE api_type,
|
||||
GeometryShaderUid uid) override
|
||||
{
|
||||
return GenerateGeometryShaderCode(primitive_type, api_type);
|
||||
return GenerateGeometryShaderCode(api_type, uid.GetUidData());
|
||||
}
|
||||
};
|
||||
|
||||
@ -81,12 +79,12 @@ protected:
|
||||
PixelShaderUid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
|
||||
API_TYPE api_type) override
|
||||
{
|
||||
return GetPixelShaderUid(dst_alpha_mode, api_type);
|
||||
return GetPixelShaderUid(dst_alpha_mode);
|
||||
}
|
||||
ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
|
||||
API_TYPE api_type) override
|
||||
ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, API_TYPE api_type,
|
||||
PixelShaderUid uid) override
|
||||
{
|
||||
return GeneratePixelShaderCode(dst_alpha_mode, api_type);
|
||||
return GeneratePixelShaderCode(dst_alpha_mode, api_type, uid.GetUidData());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -36,9 +36,6 @@ static GLuint CurrentProgram = 0;
|
||||
ProgramShaderCache::PCache ProgramShaderCache::pshaders;
|
||||
ProgramShaderCache::PCacheEntry* ProgramShaderCache::last_entry;
|
||||
SHADERUID ProgramShaderCache::last_uid;
|
||||
UidChecker<PixelShaderUid, ShaderCode> ProgramShaderCache::pixel_uid_checker;
|
||||
UidChecker<VertexShaderUid, ShaderCode> ProgramShaderCache::vertex_uid_checker;
|
||||
UidChecker<GeometryShaderUid, ShaderCode> ProgramShaderCache::geometry_uid_checker;
|
||||
|
||||
static std::string s_glsl_header = "";
|
||||
|
||||
@ -209,19 +206,12 @@ SHADER* ProgramShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 primitive_
|
||||
last_entry = &newentry;
|
||||
newentry.in_cache = 0;
|
||||
|
||||
ShaderCode vcode = GenerateVertexShaderCode(API_OPENGL);
|
||||
ShaderCode pcode = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL);
|
||||
ShaderCode vcode = GenerateVertexShaderCode(API_OPENGL, uid.vuid.GetUidData());
|
||||
ShaderCode pcode = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, uid.puid.GetUidData());
|
||||
ShaderCode gcode;
|
||||
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders &&
|
||||
!uid.guid.GetUidData()->IsPassthrough())
|
||||
gcode = GenerateGeometryShaderCode(primitive_type, API_OPENGL);
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
newentry.shader.strvprog = vcode.GetBuffer();
|
||||
newentry.shader.strpprog = pcode.GetBuffer();
|
||||
newentry.shader.strgprog = gcode.GetBuffer();
|
||||
}
|
||||
gcode = GenerateGeometryShaderCode(API_OPENGL, uid.guid.GetUidData());
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS)
|
||||
@ -397,21 +387,9 @@ GLuint ProgramShaderCache::CompileSingleShader(GLuint type, const std::string& c
|
||||
|
||||
void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 primitive_type)
|
||||
{
|
||||
uid->puid = GetPixelShaderUid(dstAlphaMode, API_OPENGL);
|
||||
uid->vuid = GetVertexShaderUid(API_OPENGL);
|
||||
uid->guid = GetGeometryShaderUid(primitive_type, API_OPENGL);
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
ShaderCode pcode = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL);
|
||||
pixel_uid_checker.AddToIndexAndCheck(pcode, uid->puid, "Pixel", "p");
|
||||
|
||||
ShaderCode vcode = GenerateVertexShaderCode(API_OPENGL);
|
||||
vertex_uid_checker.AddToIndexAndCheck(vcode, uid->vuid, "Vertex", "v");
|
||||
|
||||
ShaderCode gcode = GenerateGeometryShaderCode(primitive_type, API_OPENGL);
|
||||
geometry_uid_checker.AddToIndexAndCheck(gcode, uid->guid, "Geometry", "g");
|
||||
}
|
||||
uid->puid = GetPixelShaderUid(dstAlphaMode);
|
||||
uid->vuid = GetVertexShaderUid();
|
||||
uid->guid = GetGeometryShaderUid(primitive_type);
|
||||
}
|
||||
|
||||
ProgramShaderCache::PCacheEntry ProgramShaderCache::GetShaderProgram()
|
||||
@ -436,7 +414,7 @@ void ProgramShaderCache::Init()
|
||||
s_buffer = StreamBuffer::Create(GL_UNIFORM_BUFFER, UBO_LENGTH);
|
||||
|
||||
// Read our shader cache, only if supported
|
||||
if (g_ogl_config.bSupportsGLSLCache && !g_Config.bEnableShaderDebugging)
|
||||
if (g_ogl_config.bSupportsGLSLCache)
|
||||
{
|
||||
GLint Supported;
|
||||
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &Supported);
|
||||
@ -470,7 +448,7 @@ void ProgramShaderCache::Init()
|
||||
void ProgramShaderCache::Shutdown()
|
||||
{
|
||||
// store all shaders in cache on disk
|
||||
if (g_ogl_config.bSupportsGLSLCache && !g_Config.bEnableShaderDebugging)
|
||||
if (g_ogl_config.bSupportsGLSLCache)
|
||||
{
|
||||
for (auto& entry : pshaders)
|
||||
{
|
||||
@ -516,9 +494,6 @@ void ProgramShaderCache::Shutdown()
|
||||
}
|
||||
pshaders.clear();
|
||||
|
||||
pixel_uid_checker.Invalidate();
|
||||
vertex_uid_checker.Invalidate();
|
||||
|
||||
s_buffer.reset();
|
||||
}
|
||||
|
||||
|
@ -88,10 +88,6 @@ private:
|
||||
static PCacheEntry* last_entry;
|
||||
static SHADERUID last_uid;
|
||||
|
||||
static UidChecker<PixelShaderUid, ShaderCode> pixel_uid_checker;
|
||||
static UidChecker<VertexShaderUid, ShaderCode> vertex_uid_checker;
|
||||
static UidChecker<GeometryShaderUid, ShaderCode> geometry_uid_checker;
|
||||
|
||||
static u32 s_ubo_buffer_size;
|
||||
static s32 s_ubo_align;
|
||||
};
|
||||
|
@ -20,43 +20,55 @@ static void EmitVertex(T& out, const char* vertex, API_TYPE ApiType, bool first_
|
||||
template <class T>
|
||||
static void EndPrimitive(T& out, API_TYPE ApiType);
|
||||
|
||||
template <class T>
|
||||
static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
GeometryShaderUid GetGeometryShaderUid(u32 primitive_type)
|
||||
{
|
||||
T out;
|
||||
// Non-uid template parameters will write to the dummy data (=> gets optimized out)
|
||||
geometry_shader_uid_data dummy_data;
|
||||
geometry_shader_uid_data* uid_data = out.template GetUidData<geometry_shader_uid_data>();
|
||||
if (uid_data != nullptr)
|
||||
memset(uid_data, 0, sizeof(*uid_data));
|
||||
else
|
||||
uid_data = &dummy_data;
|
||||
ShaderUid<geometry_shader_uid_data> out;
|
||||
geometry_shader_uid_data* uid_data = out.GetUidData<geometry_shader_uid_data>();
|
||||
memset(uid_data, 0, sizeof(geometry_shader_uid_data));
|
||||
|
||||
uid_data->primitive_type = primitive_type;
|
||||
const unsigned int vertex_in = primitive_type + 1;
|
||||
unsigned int vertex_out = primitive_type == PRIMITIVE_TRIANGLES ? 3 : 4;
|
||||
|
||||
uid_data->wireframe = g_ActiveConfig.bWireFrame;
|
||||
if (g_ActiveConfig.bWireFrame)
|
||||
uid_data->msaa = g_ActiveConfig.iMultisamples > 1;
|
||||
uid_data->ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA;
|
||||
uid_data->stereo = g_ActiveConfig.iStereoMode > 0;
|
||||
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
|
||||
uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data,
|
||||
const char* vertex, API_TYPE ApiType, bool first_vertex = false);
|
||||
static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data,
|
||||
API_TYPE ApiType);
|
||||
|
||||
ShaderCode GenerateGeometryShaderCode(API_TYPE ApiType, const geometry_shader_uid_data* uid_data)
|
||||
{
|
||||
ShaderCode out;
|
||||
// Non-uid template parameters will write to the dummy data (=> gets optimized out)
|
||||
|
||||
const unsigned int vertex_in = uid_data->primitive_type + 1;
|
||||
unsigned int vertex_out = uid_data->primitive_type == PRIMITIVE_TRIANGLES ? 3 : 4;
|
||||
|
||||
if (uid_data->wireframe)
|
||||
vertex_out++;
|
||||
|
||||
uid_data->stereo = g_ActiveConfig.iStereoMode > 0;
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
// Insert layout parameters
|
||||
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
||||
{
|
||||
out.Write("layout(%s, invocations = %d) in;\n", primitives_ogl[primitive_type],
|
||||
g_ActiveConfig.iStereoMode > 0 ? 2 : 1);
|
||||
out.Write("layout(%s, invocations = %d) in;\n", primitives_ogl[uid_data->primitive_type],
|
||||
uid_data->stereo ? 2 : 1);
|
||||
out.Write("layout(%s_strip, max_vertices = %d) out;\n",
|
||||
g_ActiveConfig.bWireFrame ? "line" : "triangle", vertex_out);
|
||||
uid_data->wireframe ? "line" : "triangle", vertex_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("layout(%s) in;\n", primitives_ogl[primitive_type]);
|
||||
out.Write("layout(%s) in;\n", primitives_ogl[uid_data->primitive_type]);
|
||||
out.Write("layout(%s_strip, max_vertices = %d) out;\n",
|
||||
g_ActiveConfig.bWireFrame ? "line" : "triangle",
|
||||
g_ActiveConfig.iStereoMode > 0 ? vertex_out * 2 : vertex_out);
|
||||
uid_data->wireframe ? "line" : "triangle",
|
||||
uid_data->stereo ? vertex_out * 2 : vertex_out);
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,11 +85,9 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
"\tint4 " I_TEXOFFSET ";\n"
|
||||
"};\n");
|
||||
|
||||
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
|
||||
uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
|
||||
|
||||
out.Write("struct VS_OUTPUT {\n");
|
||||
GenerateVSOutputMembers<T>(out, ApiType, "");
|
||||
GenerateVSOutputMembers<ShaderCode>(out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting,
|
||||
"");
|
||||
out.Write("};\n");
|
||||
|
||||
if (ApiType == API_OPENGL)
|
||||
@ -86,13 +96,17 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
out.Write("#define InstanceID gl_InvocationID\n");
|
||||
|
||||
out.Write("in VertexData {\n");
|
||||
GenerateVSOutputMembers<T>(out, ApiType, GetInterpolationQualifier(true, true));
|
||||
GenerateVSOutputMembers<ShaderCode>(
|
||||
out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting,
|
||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, true));
|
||||
out.Write("} vs[%d];\n", vertex_in);
|
||||
|
||||
out.Write("out VertexData {\n");
|
||||
GenerateVSOutputMembers<T>(out, ApiType, GetInterpolationQualifier(true, false));
|
||||
GenerateVSOutputMembers<ShaderCode>(
|
||||
out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting,
|
||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, false, true));
|
||||
|
||||
if (g_ActiveConfig.iStereoMode > 0)
|
||||
if (uid_data->stereo)
|
||||
out.Write("\tflat int layer;\n");
|
||||
|
||||
out.Write("} ps;\n");
|
||||
@ -104,39 +118,37 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
out.Write("struct VertexData {\n");
|
||||
out.Write("\tVS_OUTPUT o;\n");
|
||||
|
||||
if (g_ActiveConfig.iStereoMode > 0)
|
||||
if (uid_data->stereo)
|
||||
out.Write("\tuint layer : SV_RenderTargetArrayIndex;\n");
|
||||
|
||||
out.Write("};\n");
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
||||
{
|
||||
out.Write("[maxvertexcount(%d)]\n[instance(%d)]\n", vertex_out,
|
||||
g_ActiveConfig.iStereoMode > 0 ? 2 : 1);
|
||||
out.Write("[maxvertexcount(%d)]\n[instance(%d)]\n", vertex_out, uid_data->stereo ? 2 : 1);
|
||||
out.Write("void main(%s VS_OUTPUT o[%d], inout %sStream<VertexData> output, in uint "
|
||||
"InstanceID : SV_GSInstanceID)\n{\n",
|
||||
primitives_d3d[primitive_type], vertex_in,
|
||||
g_ActiveConfig.bWireFrame ? "Line" : "Triangle");
|
||||
primitives_d3d[uid_data->primitive_type], vertex_in,
|
||||
uid_data->wireframe ? "Line" : "Triangle");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("[maxvertexcount(%d)]\n",
|
||||
g_ActiveConfig.iStereoMode > 0 ? vertex_out * 2 : vertex_out);
|
||||
out.Write("[maxvertexcount(%d)]\n", uid_data->stereo ? vertex_out * 2 : vertex_out);
|
||||
out.Write("void main(%s VS_OUTPUT o[%d], inout %sStream<VertexData> output)\n{\n",
|
||||
primitives_d3d[primitive_type], vertex_in,
|
||||
g_ActiveConfig.bWireFrame ? "Line" : "Triangle");
|
||||
primitives_d3d[uid_data->primitive_type], vertex_in,
|
||||
uid_data->wireframe ? "Line" : "Triangle");
|
||||
}
|
||||
|
||||
out.Write("\tVertexData ps;\n");
|
||||
}
|
||||
|
||||
if (primitive_type == PRIMITIVE_LINES)
|
||||
if (uid_data->primitive_type == PRIMITIVE_LINES)
|
||||
{
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
out.Write("\tVS_OUTPUT start, end;\n");
|
||||
AssignVSOutputMembers(out, "start", "vs[0]");
|
||||
AssignVSOutputMembers(out, "end", "vs[1]");
|
||||
AssignVSOutputMembers(out, "start", "vs[0]", uid_data->numTexGens, uid_data->pixel_lighting);
|
||||
AssignVSOutputMembers(out, "end", "vs[1]", uid_data->numTexGens, uid_data->pixel_lighting);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -161,16 +173,16 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
"\t\toffset = float2(0, -" I_LINEPTPARAMS ".z / " I_LINEPTPARAMS ".y);\n"
|
||||
"\t}\n");
|
||||
}
|
||||
else if (primitive_type == PRIMITIVE_POINTS)
|
||||
else if (uid_data->primitive_type == PRIMITIVE_POINTS)
|
||||
{
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
out.Write("\tVS_OUTPUT center;\n");
|
||||
AssignVSOutputMembers(out, "center", "vs[0]");
|
||||
AssignVSOutputMembers(out, "center", "vs[0]", uid_data->numTexGens, uid_data->pixel_lighting);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("\tVS_OUTPUT center = o[0];\n");
|
||||
out.Write("\tVS_OUTPUT center = o[0];\n", uid_data->numTexGens, uid_data->pixel_lighting);
|
||||
}
|
||||
|
||||
// Offset from center to upper right vertex
|
||||
@ -179,7 +191,7 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
".x, -" I_LINEPTPARAMS ".w / " I_LINEPTPARAMS ".y) * center.pos.w;\n");
|
||||
}
|
||||
|
||||
if (g_ActiveConfig.iStereoMode > 0)
|
||||
if (uid_data->stereo)
|
||||
{
|
||||
// If the GPU supports invocation we don't need a for loop and can simply use the
|
||||
// invocation identifier to determine which layer we're rendering.
|
||||
@ -189,7 +201,7 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
out.Write("\tfor (int eye = 0; eye < 2; ++eye) {\n");
|
||||
}
|
||||
|
||||
if (g_ActiveConfig.bWireFrame)
|
||||
if (uid_data->wireframe)
|
||||
out.Write("\tVS_OUTPUT first;\n");
|
||||
|
||||
out.Write("\tfor (int i = 0; i < %d; ++i) {\n", vertex_in);
|
||||
@ -197,14 +209,14 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
out.Write("\tVS_OUTPUT f;\n");
|
||||
AssignVSOutputMembers(out, "f", "vs[i]");
|
||||
AssignVSOutputMembers(out, "f", "vs[i]", uid_data->numTexGens, uid_data->pixel_lighting);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("\tVS_OUTPUT f = o[i];\n");
|
||||
}
|
||||
|
||||
if (g_ActiveConfig.iStereoMode > 0)
|
||||
if (uid_data->stereo)
|
||||
{
|
||||
// Select the output layer
|
||||
out.Write("\tps.layer = eye;\n");
|
||||
@ -221,7 +233,7 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
out.Write("\tf.pos.x += " I_STEREOPARAMS "[eye] * (f.pos.w - " I_STEREOPARAMS "[2]);\n");
|
||||
}
|
||||
|
||||
if (primitive_type == PRIMITIVE_LINES)
|
||||
if (uid_data->primitive_type == PRIMITIVE_LINES)
|
||||
{
|
||||
out.Write("\tVS_OUTPUT l = f;\n"
|
||||
"\tVS_OUTPUT r = f;\n");
|
||||
@ -232,17 +244,17 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
out.Write("\tif (" I_TEXOFFSET "[2] != 0) {\n");
|
||||
out.Write("\tfloat texOffset = 1.0 / float(" I_TEXOFFSET "[2]);\n");
|
||||
|
||||
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
|
||||
for (unsigned int i = 0; i < uid_data->numTexGens; ++i)
|
||||
{
|
||||
out.Write("\tif (((" I_TEXOFFSET "[0] >> %d) & 0x1) != 0)\n", i);
|
||||
out.Write("\t\tr.tex%d.x += texOffset;\n", i);
|
||||
}
|
||||
out.Write("\t}\n");
|
||||
|
||||
EmitVertex<T>(out, "l", ApiType, true);
|
||||
EmitVertex<T>(out, "r", ApiType);
|
||||
EmitVertex(out, uid_data, "l", ApiType, true);
|
||||
EmitVertex(out, uid_data, "r", ApiType);
|
||||
}
|
||||
else if (primitive_type == PRIMITIVE_POINTS)
|
||||
else if (uid_data->primitive_type == PRIMITIVE_POINTS)
|
||||
{
|
||||
out.Write("\tVS_OUTPUT ll = f;\n"
|
||||
"\tVS_OUTPUT lr = f;\n"
|
||||
@ -258,7 +270,7 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
out.Write("\tfloat2 texOffset = float2(1.0 / float(" I_TEXOFFSET
|
||||
"[3]), 1.0 / float(" I_TEXOFFSET "[3]));\n");
|
||||
|
||||
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
|
||||
for (unsigned int i = 0; i < uid_data->numTexGens; ++i)
|
||||
{
|
||||
out.Write("\tif (((" I_TEXOFFSET "[1] >> %d) & 0x1) != 0) {\n", i);
|
||||
out.Write("\t\tll.tex%d.xy += float2(0,1) * texOffset;\n", i);
|
||||
@ -268,21 +280,21 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
}
|
||||
out.Write("\t}\n");
|
||||
|
||||
EmitVertex<T>(out, "ll", ApiType, true);
|
||||
EmitVertex<T>(out, "lr", ApiType);
|
||||
EmitVertex<T>(out, "ul", ApiType);
|
||||
EmitVertex<T>(out, "ur", ApiType);
|
||||
EmitVertex(out, uid_data, "ll", ApiType, true);
|
||||
EmitVertex(out, uid_data, "lr", ApiType);
|
||||
EmitVertex(out, uid_data, "ul", ApiType);
|
||||
EmitVertex(out, uid_data, "ur", ApiType);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitVertex<T>(out, "f", ApiType, true);
|
||||
EmitVertex(out, uid_data, "f", ApiType, true);
|
||||
}
|
||||
|
||||
out.Write("\t}\n");
|
||||
|
||||
EndPrimitive<T>(out, ApiType);
|
||||
EndPrimitive(out, uid_data, ApiType);
|
||||
|
||||
if (g_ActiveConfig.iStereoMode > 0 && !g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
||||
if (uid_data->stereo && !g_ActiveConfig.backend_info.bSupportsGSInstancing)
|
||||
out.Write("\t}\n");
|
||||
|
||||
out.Write("}\n");
|
||||
@ -290,16 +302,16 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void EmitVertex(T& out, const char* vertex, API_TYPE ApiType, bool first_vertex)
|
||||
static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data,
|
||||
const char* vertex, API_TYPE ApiType, bool first_vertex)
|
||||
{
|
||||
if (g_ActiveConfig.bWireFrame && first_vertex)
|
||||
if (uid_data->wireframe && first_vertex)
|
||||
out.Write("\tif (i == 0) first = %s;\n", vertex);
|
||||
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
out.Write("\tgl_Position = %s.pos;\n", vertex);
|
||||
AssignVSOutputMembers(out, "ps", vertex);
|
||||
AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, uid_data->pixel_lighting);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -311,24 +323,15 @@ static void EmitVertex(T& out, const char* vertex, API_TYPE ApiType, bool first_
|
||||
else
|
||||
out.Write("\toutput.Append(ps);\n");
|
||||
}
|
||||
template <class T>
|
||||
static void EndPrimitive(T& out, API_TYPE ApiType)
|
||||
|
||||
static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data,
|
||||
API_TYPE ApiType)
|
||||
{
|
||||
if (g_ActiveConfig.bWireFrame)
|
||||
EmitVertex<T>(out, "first", ApiType);
|
||||
if (uid_data->wireframe)
|
||||
EmitVertex(out, uid_data, "first", ApiType);
|
||||
|
||||
if (ApiType == API_OPENGL)
|
||||
out.Write("\tEndPrimitive();\n");
|
||||
else
|
||||
out.Write("\toutput.RestartStrip();\n");
|
||||
}
|
||||
|
||||
GeometryShaderUid GetGeometryShaderUid(u32 primitive_type, API_TYPE ApiType)
|
||||
{
|
||||
return GenerateGeometryShader<GeometryShaderUid>(primitive_type, ApiType);
|
||||
}
|
||||
|
||||
ShaderCode GenerateGeometryShaderCode(u32 primitive_type, API_TYPE ApiType)
|
||||
{
|
||||
return GenerateGeometryShader<ShaderCode>(primitive_type, ApiType);
|
||||
}
|
||||
|
@ -23,11 +23,13 @@ struct geometry_shader_uid_data
|
||||
u32 pixel_lighting : 1;
|
||||
u32 primitive_type : 2;
|
||||
u32 wireframe : 1;
|
||||
u32 msaa : 1;
|
||||
u32 ssaa : 1;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
typedef ShaderUid<geometry_shader_uid_data> GeometryShaderUid;
|
||||
|
||||
ShaderCode GenerateGeometryShaderCode(u32 primitive_type, API_TYPE ApiType);
|
||||
GeometryShaderUid GetGeometryShaderUid(u32 primitive_type, API_TYPE ApiType);
|
||||
ShaderCode GenerateGeometryShaderCode(API_TYPE ApiType, const geometry_shader_uid_data* uid_data);
|
||||
GeometryShaderUid GetGeometryShaderUid(u32 primitive_type);
|
||||
|
@ -46,19 +46,16 @@ static const char s_lighting_struct[] = "struct Light {\n"
|
||||
"\tfloat4 dir;\n"
|
||||
"};\n";
|
||||
|
||||
template <class T>
|
||||
static void GenerateLightShader(T& object, LightingUidData& uid_data, int index, int litchan_index,
|
||||
int coloralpha)
|
||||
static void GenerateLightShader(ShaderCode& object, const LightingUidData& uid_data, int index,
|
||||
int litchan_index, bool alpha)
|
||||
{
|
||||
const LitChannel& chan =
|
||||
(litchan_index > 1) ? xfmem.alpha[litchan_index - 2] : xfmem.color[litchan_index];
|
||||
const char* swizzle = (coloralpha == 1) ? "xyz" : (coloralpha == 2) ? "w" : "xyzw";
|
||||
const char* swizzle_components = (coloralpha == 1) ? "3" : (coloralpha == 2) ? "" : "4";
|
||||
const char* swizzle = alpha ? "a" : "rgb";
|
||||
const char* swizzle_components = (alpha) ? "" : "3";
|
||||
|
||||
uid_data.attnfunc |= chan.attnfunc << (2 * litchan_index);
|
||||
uid_data.diffusefunc |= chan.diffusefunc << (2 * litchan_index);
|
||||
int attnfunc = (uid_data.attnfunc >> (2 * litchan_index)) & 0x3;
|
||||
int diffusefunc = (uid_data.diffusefunc >> (2 * litchan_index)) & 0x3;
|
||||
|
||||
switch (chan.attnfunc)
|
||||
switch (attnfunc)
|
||||
{
|
||||
case LIGHTATTN_NONE:
|
||||
case LIGHTATTN_DIR:
|
||||
@ -73,8 +70,7 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
|
||||
LIGHT_DIR_PARAMS(index));
|
||||
object.Write("cosAttn = " LIGHT_COSATT ".xyz;\n", LIGHT_COSATT_PARAMS(index));
|
||||
object.Write("distAttn = %s(" LIGHT_DISTATT ".xyz);\n",
|
||||
(chan.diffusefunc == LIGHTDIF_NONE) ? "" : "normalize",
|
||||
LIGHT_DISTATT_PARAMS(index));
|
||||
(diffusefunc == LIGHTDIF_NONE) ? "" : "normalize", LIGHT_DISTATT_PARAMS(index));
|
||||
object.Write("attn = max(0.0f, dot(cosAttn, float3(1.0, attn, attn*attn))) / dot(distAttn, "
|
||||
"float3(1.0, attn, attn*attn));\n");
|
||||
break;
|
||||
@ -91,11 +87,9 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
|
||||
LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index),
|
||||
LIGHT_DISTATT_PARAMS(index));
|
||||
break;
|
||||
default:
|
||||
_assert_(0);
|
||||
}
|
||||
|
||||
switch (chan.diffusefunc)
|
||||
switch (diffusefunc)
|
||||
{
|
||||
case LIGHTDIF_NONE:
|
||||
object.Write("lacc.%s += int%s(round(attn * float%s(" LIGHT_COL ")));\n", swizzle,
|
||||
@ -104,7 +98,7 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
|
||||
case LIGHTDIF_SIGN:
|
||||
case LIGHTDIF_CLAMP:
|
||||
object.Write("lacc.%s += int%s(round(attn * %sdot(ldir, _norm0)) * float%s(" LIGHT_COL ")));\n",
|
||||
swizzle, swizzle_components, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0," : "(",
|
||||
swizzle, swizzle_components, diffusefunc != LIGHTDIF_SIGN ? "max(0.0," : "(",
|
||||
swizzle_components, LIGHT_COL_PARAMS(index, swizzle));
|
||||
break;
|
||||
default:
|
||||
@ -119,19 +113,15 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
|
||||
// materials name is I_MATERIALS in vs and I_PMATERIALS in ps
|
||||
// inColorName is color in vs and colors_ in ps
|
||||
// dest is o.colors_ in vs and colors_ in ps
|
||||
template <class T>
|
||||
static void GenerateLightingShader(T& object, LightingUidData& uid_data, int components,
|
||||
const char* inColorName, const char* dest)
|
||||
static void GenerateLightingShaderCode(ShaderCode& object, const LightingUidData& uid_data,
|
||||
int components, const char* inColorName, const char* dest)
|
||||
{
|
||||
for (unsigned int j = 0; j < xfmem.numChan.numColorChans; j++)
|
||||
{
|
||||
const LitChannel& color = xfmem.color[j];
|
||||
const LitChannel& alpha = xfmem.alpha[j];
|
||||
|
||||
object.Write("{\n");
|
||||
|
||||
uid_data.matsource |= xfmem.color[j].matsource << j;
|
||||
if (color.matsource) // from vertex
|
||||
bool colormatsource = !!(uid_data.matsource & (1 << j));
|
||||
if (colormatsource) // from vertex
|
||||
{
|
||||
if (components & (VB_HAS_COL0 << j))
|
||||
object.Write("int4 mat = int4(round(%s%d * 255.0));\n", inColorName, j);
|
||||
@ -145,11 +135,9 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
|
||||
object.Write("int4 mat = %s[%d];\n", I_MATERIALS, j + 2);
|
||||
}
|
||||
|
||||
uid_data.enablelighting |= xfmem.color[j].enablelighting << j;
|
||||
if (color.enablelighting)
|
||||
if (uid_data.enablelighting & (1 << j))
|
||||
{
|
||||
uid_data.ambsource |= xfmem.color[j].ambsource << j;
|
||||
if (color.ambsource) // from vertex
|
||||
if (uid_data.ambsource & (1 << j)) // from vertex
|
||||
{
|
||||
if (components & (VB_HAS_COL0 << j))
|
||||
object.Write("lacc = int4(round(%s%d * 255.0));\n", inColorName, j);
|
||||
@ -158,7 +146,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
|
||||
else
|
||||
// TODO: this isn't verified. Here we want to read the ambient from the vertex,
|
||||
// but the vertex itself has no color. So we don't know which value to read.
|
||||
// Returing 1.0 is the same as disabled lightning, so this could be fine
|
||||
// Returning 1.0 is the same as disabled lightning, so this could be fine
|
||||
object.Write("lacc = int4(255, 255, 255, 255);\n");
|
||||
}
|
||||
else // from color
|
||||
@ -172,10 +160,10 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
|
||||
}
|
||||
|
||||
// check if alpha is different
|
||||
uid_data.matsource |= xfmem.alpha[j].matsource << (j + 2);
|
||||
if (alpha.matsource != color.matsource)
|
||||
bool alphamatsource = !!(uid_data.matsource & (1 << (j + 2)));
|
||||
if (alphamatsource != colormatsource)
|
||||
{
|
||||
if (alpha.matsource) // from vertex
|
||||
if (alphamatsource) // from vertex
|
||||
{
|
||||
if (components & (VB_HAS_COL0 << j))
|
||||
object.Write("mat.w = int(round(%s%d.w * 255.0));\n", inColorName, j);
|
||||
@ -190,11 +178,9 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
|
||||
}
|
||||
}
|
||||
|
||||
uid_data.enablelighting |= xfmem.alpha[j].enablelighting << (j + 2);
|
||||
if (alpha.enablelighting)
|
||||
if (uid_data.enablelighting & (1 << (j + 2)))
|
||||
{
|
||||
uid_data.ambsource |= xfmem.alpha[j].ambsource << (j + 2);
|
||||
if (alpha.ambsource) // from vertex
|
||||
if (uid_data.ambsource & (1 << (j + 2))) // from vertex
|
||||
{
|
||||
if (components & (VB_HAS_COL0 << j))
|
||||
object.Write("lacc.w = int(round(%s%d.w * 255.0));\n", inColorName, j);
|
||||
@ -214,56 +200,46 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
|
||||
object.Write("lacc.w = 255;\n");
|
||||
}
|
||||
|
||||
if (color.enablelighting && alpha.enablelighting)
|
||||
{
|
||||
// both have lighting, test if they use the same lights
|
||||
int mask = 0;
|
||||
uid_data.attnfunc |= color.attnfunc << (2 * j);
|
||||
uid_data.attnfunc |= alpha.attnfunc << (2 * (j + 2));
|
||||
uid_data.diffusefunc |= color.diffusefunc << (2 * j);
|
||||
uid_data.diffusefunc |= alpha.diffusefunc << (2 * (j + 2));
|
||||
uid_data.light_mask |= color.GetFullLightMask() << (8 * j);
|
||||
uid_data.light_mask |= alpha.GetFullLightMask() << (8 * (j + 2));
|
||||
if (color.lightparams == alpha.lightparams)
|
||||
{
|
||||
mask = color.GetFullLightMask() & alpha.GetFullLightMask();
|
||||
if (mask)
|
||||
if (uid_data.enablelighting & (1 << j)) // Color lights
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
if (uid_data.light_mask & (1 << (i + 8 * j)))
|
||||
GenerateLightShader(object, uid_data, i, j, false);
|
||||
}
|
||||
if (uid_data.enablelighting & (1 << (j + 2))) // Alpha lights
|
||||
{
|
||||
if (mask & (1 << i))
|
||||
{
|
||||
GenerateLightShader<T>(object, uid_data, i, j, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no shared lights
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (!(mask & (1 << i)) && (color.GetFullLightMask() & (1 << i)))
|
||||
GenerateLightShader<T>(object, uid_data, i, j, 1);
|
||||
if (!(mask & (1 << i)) && (alpha.GetFullLightMask() & (1 << i)))
|
||||
GenerateLightShader<T>(object, uid_data, i, j + 2, 2);
|
||||
}
|
||||
}
|
||||
else if (color.enablelighting || alpha.enablelighting)
|
||||
{
|
||||
// lights are disabled on one channel so process only the active ones
|
||||
const LitChannel& workingchannel = color.enablelighting ? color : alpha;
|
||||
const int lit_index = color.enablelighting ? j : (j + 2);
|
||||
int coloralpha = color.enablelighting ? 1 : 2;
|
||||
|
||||
uid_data.light_mask |= workingchannel.GetFullLightMask() << (8 * lit_index);
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (workingchannel.GetFullLightMask() & (1 << i))
|
||||
GenerateLightShader<T>(object, uid_data, i, lit_index, coloralpha);
|
||||
}
|
||||
if (uid_data.light_mask & (1 << (i + 8 * (j + 2))))
|
||||
GenerateLightShader(object, uid_data, i, j + 2, true);
|
||||
}
|
||||
object.Write("lacc = clamp(lacc, 0, 255);\n");
|
||||
object.Write("%s%d = float4((mat * (lacc + (lacc >> 7))) >> 8) / 255.0;\n", dest, j);
|
||||
object.Write("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void GetLightingShaderUid(LightingUidData& uid_data)
|
||||
{
|
||||
for (unsigned int j = 0; j < xfmem.numChan.numColorChans; j++)
|
||||
{
|
||||
uid_data.matsource |= xfmem.color[j].matsource << j;
|
||||
uid_data.matsource |= xfmem.alpha[j].matsource << (j + 2);
|
||||
uid_data.enablelighting |= xfmem.color[j].enablelighting << j;
|
||||
uid_data.enablelighting |= xfmem.alpha[j].enablelighting << (j + 2);
|
||||
|
||||
if (uid_data.enablelighting & (1 << j)) // Color lights
|
||||
{
|
||||
uid_data.ambsource |= xfmem.color[j].ambsource << j;
|
||||
uid_data.attnfunc |= xfmem.color[j].attnfunc << (2 * j);
|
||||
uid_data.diffusefunc |= xfmem.color[j].diffusefunc << (2 * j);
|
||||
uid_data.light_mask |= xfmem.color[j].GetFullLightMask() << (8 * j);
|
||||
}
|
||||
if (uid_data.enablelighting & (1 << (j + 2))) // Alpha lights
|
||||
{
|
||||
uid_data.ambsource |= xfmem.alpha[j].ambsource << (j + 2);
|
||||
uid_data.attnfunc |= xfmem.alpha[j].attnfunc << (2 * (j + 2));
|
||||
uid_data.diffusefunc |= xfmem.alpha[j].diffusefunc << (2 * (j + 2));
|
||||
uid_data.light_mask |= xfmem.alpha[j].GetFullLightMask() << (8 * (j + 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ enum
|
||||
VB_HAS_NRM2 = (1 << 12),
|
||||
VB_HAS_NRMALL = (7 << 10),
|
||||
|
||||
VB_COL_SHIFT = 13,
|
||||
VB_HAS_COL0 = (1 << 13),
|
||||
VB_HAS_COL1 = (1 << 14),
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,12 +24,11 @@ struct pixel_shader_uid_data
|
||||
|
||||
u32 num_values; // TODO: Shouldn't be a u32
|
||||
u32 NumValues() const { return num_values; }
|
||||
u32 components : 23;
|
||||
u32 components : 2;
|
||||
u32 dstAlphaMode : 2;
|
||||
u32 Pretest : 2;
|
||||
u32 nIndirectStagesUsed : 4;
|
||||
u32 stereo : 1;
|
||||
|
||||
u32 genMode_numtexgens : 4;
|
||||
u32 genMode_numtevstages : 4;
|
||||
u32 genMode_numindstages : 3;
|
||||
@ -38,20 +37,21 @@ struct pixel_shader_uid_data
|
||||
u32 alpha_test_logic : 2;
|
||||
u32 alpha_test_use_zcomploc_hack : 1;
|
||||
u32 fog_proj : 1;
|
||||
|
||||
u32 fog_fsel : 3;
|
||||
u32 fog_RangeBaseEnabled : 1;
|
||||
u32 ztex_op : 2;
|
||||
u32 fast_depth_calc : 1;
|
||||
u32 per_pixel_depth : 1;
|
||||
u32 per_pixel_lighting : 1;
|
||||
u32 forced_early_z : 1;
|
||||
u32 early_ztest : 1;
|
||||
u32 late_ztest : 1;
|
||||
u32 bounding_box : 1;
|
||||
|
||||
// TODO: 29 bits of padding is a waste. Can we free up some bits elseware?
|
||||
u32 zfreeze : 1;
|
||||
u32 msaa : 1;
|
||||
u32 ssaa : 1;
|
||||
u32 pad : 29;
|
||||
u32 pad : 16;
|
||||
|
||||
u32 texMtxInfo_n_projection : 8; // 8x1 bit
|
||||
u32 tevindref_bi0 : 3;
|
||||
@ -63,7 +63,7 @@ struct pixel_shader_uid_data
|
||||
u32 tevindref_bi4 : 3;
|
||||
u32 tevindref_bc4 : 3;
|
||||
|
||||
inline void SetTevindrefValues(int index, u32 texcoord, u32 texmap)
|
||||
void SetTevindrefValues(int index, u32 texcoord, u32 texmap)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
@ -86,31 +86,54 @@ struct pixel_shader_uid_data
|
||||
tevindref_bi4 = texmap;
|
||||
}
|
||||
}
|
||||
inline void SetTevindrefTexmap(int index, u32 texmap)
|
||||
|
||||
u32 GetTevindirefCoord(int index) const
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
tevindref_bi0 = texmap;
|
||||
return tevindref_bc0;
|
||||
}
|
||||
else if (index == 1)
|
||||
{
|
||||
tevindref_bi1 = texmap;
|
||||
return tevindref_bc1;
|
||||
}
|
||||
else if (index == 2)
|
||||
{
|
||||
tevindref_bi2 = texmap;
|
||||
return tevindref_bc3;
|
||||
}
|
||||
else if (index == 3)
|
||||
{
|
||||
tevindref_bi4 = texmap;
|
||||
return tevindref_bc4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 GetTevindirefMap(int index) const
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
return tevindref_bi0;
|
||||
}
|
||||
else if (index == 1)
|
||||
{
|
||||
return tevindref_bi1;
|
||||
}
|
||||
else if (index == 2)
|
||||
{
|
||||
return tevindref_bi2;
|
||||
}
|
||||
else if (index == 3)
|
||||
{
|
||||
return tevindref_bi4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct
|
||||
{
|
||||
// TODO: Can save a lot space by removing the padding bits
|
||||
u32 cc : 24;
|
||||
u32 ac : 24;
|
||||
u32 ac : 24; // tswap and rswap are left blank (encoded into the tevksel fields below)
|
||||
|
||||
u32 tevorders_texmap : 3;
|
||||
u32 tevorders_texcoord : 3;
|
||||
@ -136,13 +159,12 @@ struct pixel_shader_uid_data
|
||||
u32 pad3 : 14;
|
||||
} stagehash[16];
|
||||
|
||||
// TODO: I think we're fine without an enablePixelLighting field, should probably double check,
|
||||
// though..
|
||||
LightingUidData lighting;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
typedef ShaderUid<pixel_shader_uid_data> PixelShaderUid;
|
||||
|
||||
ShaderCode GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType);
|
||||
PixelShaderUid GetPixelShaderUid(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType);
|
||||
ShaderCode GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType,
|
||||
const pixel_shader_uid_data* uid_data);
|
||||
PixelShaderUid GetPixelShaderUid(DSTALPHA_MODE dstAlphaMode);
|
||||
|
@ -154,74 +154,6 @@ public:
|
||||
private:
|
||||
std::vector<bool> constant_usage; // TODO: Is vector<bool> appropriate here?
|
||||
};
|
||||
/**
|
||||
* Checks if there has been
|
||||
*/
|
||||
template <class UidT, class CodeT>
|
||||
class UidChecker
|
||||
{
|
||||
public:
|
||||
void Invalidate()
|
||||
{
|
||||
m_shaders.clear();
|
||||
m_uids.clear();
|
||||
}
|
||||
|
||||
void AddToIndexAndCheck(CodeT& new_code, const UidT& new_uid, const char* shader_type,
|
||||
const char* dump_prefix)
|
||||
{
|
||||
bool uid_is_indexed = std::find(m_uids.begin(), m_uids.end(), new_uid) != m_uids.end();
|
||||
if (!uid_is_indexed)
|
||||
{
|
||||
m_uids.push_back(new_uid);
|
||||
m_shaders[new_uid] = new_code.GetBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
// uid is already in the index => check if there's a shader with the same uid but different
|
||||
// code
|
||||
auto& old_code = m_shaders[new_uid];
|
||||
if (old_code != new_code.GetBuffer())
|
||||
{
|
||||
static int num_failures = 0;
|
||||
|
||||
std::string temp =
|
||||
StringFromFormat("%s%ssuid_mismatch_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(),
|
||||
dump_prefix, ++num_failures);
|
||||
|
||||
// TODO: Should also dump uids
|
||||
std::ofstream file;
|
||||
OpenFStream(file, temp, std::ios_base::out);
|
||||
file << "Old shader code:\n" << old_code;
|
||||
file << "\n\nNew shader code:\n" << new_code.GetBuffer();
|
||||
file << "\n\nShader uid:\n";
|
||||
for (unsigned int i = 0; i < new_uid.GetUidDataSize(); ++i)
|
||||
{
|
||||
u8 value = new_uid.GetUidDataRaw()[i];
|
||||
if ((i % 4) == 0)
|
||||
{
|
||||
auto last_value =
|
||||
(i + 3 < new_uid.GetUidDataSize() - 1) ? i + 3 : new_uid.GetUidDataSize();
|
||||
file << std::setfill(' ') << std::dec;
|
||||
file << "Values " << std::setw(2) << i << " - " << last_value << ": ";
|
||||
}
|
||||
|
||||
file << std::setw(2) << std::setfill('0') << std::hex << value << std::setw(1);
|
||||
if ((i % 4) < 3)
|
||||
file << ' ';
|
||||
else
|
||||
file << std::endl;
|
||||
}
|
||||
|
||||
ERROR_LOG(VIDEO, "%s shader uid mismatch! See %s for details", shader_type, temp.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<UidT, std::string> m_shaders;
|
||||
std::vector<UidT> m_uids;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline void DefineOutputMember(T& object, API_TYPE api_type, const char* qualifier,
|
||||
@ -245,40 +177,41 @@ inline void DefineOutputMember(T& object, API_TYPE api_type, const char* qualifi
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void GenerateVSOutputMembers(T& object, API_TYPE api_type, const char* qualifier)
|
||||
inline void GenerateVSOutputMembers(T& object, API_TYPE api_type, u32 texgens,
|
||||
bool per_pixel_lighting, const char* qualifier)
|
||||
{
|
||||
DefineOutputMember(object, api_type, qualifier, "float4", "pos", -1, "POSITION");
|
||||
DefineOutputMember(object, api_type, qualifier, "float4", "colors_", 0, "COLOR", 0);
|
||||
DefineOutputMember(object, api_type, qualifier, "float4", "colors_", 1, "COLOR", 1);
|
||||
|
||||
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
|
||||
for (unsigned int i = 0; i < texgens; ++i)
|
||||
DefineOutputMember(object, api_type, qualifier, "float3", "tex", i, "TEXCOORD", i);
|
||||
|
||||
DefineOutputMember(object, api_type, qualifier, "float4", "clipPos", -1, "TEXCOORD",
|
||||
xfmem.numTexGen.numTexGens);
|
||||
DefineOutputMember(object, api_type, qualifier, "float4", "clipPos", -1, "TEXCOORD", texgens);
|
||||
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
if (per_pixel_lighting)
|
||||
{
|
||||
DefineOutputMember(object, api_type, qualifier, "float3", "Normal", -1, "TEXCOORD",
|
||||
xfmem.numTexGen.numTexGens + 1);
|
||||
texgens + 1);
|
||||
DefineOutputMember(object, api_type, qualifier, "float3", "WorldPos", -1, "TEXCOORD",
|
||||
xfmem.numTexGen.numTexGens + 2);
|
||||
texgens + 2);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void AssignVSOutputMembers(T& object, const char* a, const char* b)
|
||||
inline void AssignVSOutputMembers(T& object, const char* a, const char* b, u32 texgens,
|
||||
bool per_pixel_lighting)
|
||||
{
|
||||
object.Write("\t%s.pos = %s.pos;\n", a, b);
|
||||
object.Write("\t%s.colors_0 = %s.colors_0;\n", a, b);
|
||||
object.Write("\t%s.colors_1 = %s.colors_1;\n", a, b);
|
||||
|
||||
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
|
||||
for (unsigned int i = 0; i < texgens; ++i)
|
||||
object.Write("\t%s.tex%d = %s.tex%d;\n", a, i, b, i);
|
||||
|
||||
object.Write("\t%s.clipPos = %s.clipPos;\n", a, b);
|
||||
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
if (per_pixel_lighting)
|
||||
{
|
||||
object.Write("\t%s.Normal = %s.Normal;\n", a, b);
|
||||
object.Write("\t%s.WorldPos = %s.WorldPos;\n", a, b);
|
||||
@ -293,23 +226,24 @@ inline void AssignVSOutputMembers(T& object, const char* a, const char* b)
|
||||
// As a workaround, we interpolate at the centroid of the coveraged pixel, which
|
||||
// is always inside the primitive.
|
||||
// Without MSAA, this flag is defined to have no effect.
|
||||
inline const char* GetInterpolationQualifier(bool in_glsl_interface_block = false, bool in = false)
|
||||
inline const char* GetInterpolationQualifier(bool msaa, bool ssaa,
|
||||
bool in_glsl_interface_block = false, bool in = false)
|
||||
{
|
||||
if (g_ActiveConfig.iMultisamples <= 1)
|
||||
if (!msaa)
|
||||
return "";
|
||||
|
||||
// Without GL_ARB_shading_language_420pack support, the interpolation qualifier must be
|
||||
// "centroid in" and not "centroid", even within an interface block.
|
||||
if (in_glsl_interface_block && !g_ActiveConfig.backend_info.bSupportsBindingLayout)
|
||||
{
|
||||
if (!g_ActiveConfig.bSSAA)
|
||||
if (!ssaa)
|
||||
return in ? "centroid in" : "centroid out";
|
||||
else
|
||||
return in ? "sample in" : "sample out";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!g_ActiveConfig.bSSAA)
|
||||
if (!ssaa)
|
||||
return "centroid";
|
||||
else
|
||||
return "sample";
|
||||
|
@ -14,22 +14,73 @@
|
||||
#include "VideoCommon/VertexShaderGen.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
template <class T>
|
||||
static T GenerateVertexShader(API_TYPE api_type)
|
||||
VertexShaderUid GetVertexShaderUid()
|
||||
{
|
||||
T out;
|
||||
const u32 components = VertexLoaderManager::g_current_components;
|
||||
// Non-uid template parameters will write to the dummy data (=> gets optimized out)
|
||||
vertex_shader_uid_data dummy_data;
|
||||
vertex_shader_uid_data* uid_data = out.template GetUidData<vertex_shader_uid_data>();
|
||||
if (uid_data != nullptr)
|
||||
VertexShaderUid out;
|
||||
vertex_shader_uid_data* uid_data = out.GetUidData<vertex_shader_uid_data>();
|
||||
memset(uid_data, 0, sizeof(*uid_data));
|
||||
else
|
||||
uid_data = &dummy_data;
|
||||
|
||||
_assert_(bpmem.genMode.numtexgens == xfmem.numTexGen.numTexGens);
|
||||
_assert_(bpmem.genMode.numcolchans == xfmem.numChan.numColorChans);
|
||||
|
||||
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
|
||||
uid_data->components = VertexLoaderManager::g_current_components;
|
||||
uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
|
||||
uid_data->msaa = g_ActiveConfig.iMultisamples > 1;
|
||||
uid_data->ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA;
|
||||
uid_data->numColorChans = xfmem.numChan.numColorChans;
|
||||
|
||||
GetLightingShaderUid(uid_data->lighting);
|
||||
|
||||
// transform texcoords
|
||||
for (unsigned int i = 0; i < uid_data->numTexGens; ++i)
|
||||
{
|
||||
auto& texinfo = uid_data->texMtxInfo[i];
|
||||
|
||||
texinfo.sourcerow = xfmem.texMtxInfo[i].sourcerow;
|
||||
texinfo.texgentype = xfmem.texMtxInfo[i].texgentype;
|
||||
texinfo.inputform = xfmem.texMtxInfo[i].inputform;
|
||||
|
||||
// first transformation
|
||||
switch (texinfo.texgentype)
|
||||
{
|
||||
case XF_TEXGEN_EMBOSS_MAP: // calculate tex coords into bump map
|
||||
if (uid_data->components & (VB_HAS_NRM1 | VB_HAS_NRM2))
|
||||
{
|
||||
// transform the light dir into tangent space
|
||||
texinfo.embosslightshift = xfmem.texMtxInfo[i].embosslightshift;
|
||||
texinfo.embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift;
|
||||
}
|
||||
else
|
||||
{
|
||||
texinfo.embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift;
|
||||
}
|
||||
break;
|
||||
case XF_TEXGEN_COLOR_STRGBC0:
|
||||
case XF_TEXGEN_COLOR_STRGBC1:
|
||||
break;
|
||||
case XF_TEXGEN_REGULAR:
|
||||
default:
|
||||
uid_data->texMtxInfo_n_projection |= xfmem.texMtxInfo[i].projection << i;
|
||||
break;
|
||||
}
|
||||
|
||||
uid_data->dualTexTrans_enabled = xfmem.dualTexTrans.enabled;
|
||||
// CHECKME: does this only work for regular tex gen types?
|
||||
if (uid_data->dualTexTrans_enabled && texinfo.texgentype == XF_TEXGEN_REGULAR)
|
||||
{
|
||||
auto& postInfo = uid_data->postMtxInfo[i];
|
||||
postInfo.index = xfmem.postMtxInfo[i].index;
|
||||
postInfo.normalize = xfmem.postMtxInfo[i].normalize;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
ShaderCode GenerateVertexShaderCode(API_TYPE api_type, const vertex_shader_uid_data* uid_data)
|
||||
{
|
||||
ShaderCode out;
|
||||
out.Write("%s", s_lighting_struct);
|
||||
|
||||
// uniforms
|
||||
@ -42,34 +93,30 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
out.Write("};\n");
|
||||
|
||||
out.Write("struct VS_OUTPUT {\n");
|
||||
GenerateVSOutputMembers<T>(out, api_type, "");
|
||||
GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, uid_data->pixel_lighting, "");
|
||||
out.Write("};\n");
|
||||
|
||||
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
|
||||
uid_data->components = components;
|
||||
uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
|
||||
|
||||
if (api_type == API_OPENGL)
|
||||
{
|
||||
out.Write("in float4 rawpos; // ATTR%d,\n", SHADER_POSITION_ATTRIB);
|
||||
if (components & VB_HAS_POSMTXIDX)
|
||||
if (uid_data->components & VB_HAS_POSMTXIDX)
|
||||
out.Write("in int posmtx; // ATTR%d,\n", SHADER_POSMTX_ATTRIB);
|
||||
if (components & VB_HAS_NRM0)
|
||||
if (uid_data->components & VB_HAS_NRM0)
|
||||
out.Write("in float3 rawnorm0; // ATTR%d,\n", SHADER_NORM0_ATTRIB);
|
||||
if (components & VB_HAS_NRM1)
|
||||
if (uid_data->components & VB_HAS_NRM1)
|
||||
out.Write("in float3 rawnorm1; // ATTR%d,\n", SHADER_NORM1_ATTRIB);
|
||||
if (components & VB_HAS_NRM2)
|
||||
if (uid_data->components & VB_HAS_NRM2)
|
||||
out.Write("in float3 rawnorm2; // ATTR%d,\n", SHADER_NORM2_ATTRIB);
|
||||
|
||||
if (components & VB_HAS_COL0)
|
||||
if (uid_data->components & VB_HAS_COL0)
|
||||
out.Write("in float4 color0; // ATTR%d,\n", SHADER_COLOR0_ATTRIB);
|
||||
if (components & VB_HAS_COL1)
|
||||
if (uid_data->components & VB_HAS_COL1)
|
||||
out.Write("in float4 color1; // ATTR%d,\n", SHADER_COLOR1_ATTRIB);
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0 << i));
|
||||
if ((components & (VB_HAS_UV0 << i)) || hastexmtx)
|
||||
u32 hastexmtx = (uid_data->components & (VB_HAS_TEXMTXIDX0 << i));
|
||||
if ((uid_data->components & (VB_HAS_UV0 << i)) || hastexmtx)
|
||||
out.Write("in float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i,
|
||||
SHADER_TEXTURE0_ATTRIB + i);
|
||||
}
|
||||
@ -77,7 +124,9 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders)
|
||||
{
|
||||
out.Write("out VertexData {\n");
|
||||
GenerateVSOutputMembers<T>(out, api_type, GetInterpolationQualifier(true, false));
|
||||
GenerateVSOutputMembers(
|
||||
out, api_type, uid_data->numTexGens, uid_data->pixel_lighting,
|
||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, false, true));
|
||||
out.Write("} vs;\n");
|
||||
}
|
||||
else
|
||||
@ -85,19 +134,25 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
// Let's set up attributes
|
||||
for (u32 i = 0; i < 8; ++i)
|
||||
{
|
||||
if (i < xfmem.numTexGen.numTexGens)
|
||||
if (i < uid_data->numTexGens)
|
||||
{
|
||||
out.Write("%s out float3 uv%u;\n", GetInterpolationQualifier(), i);
|
||||
out.Write("%s out float3 uv%u;\n",
|
||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa), i);
|
||||
}
|
||||
}
|
||||
out.Write("%s out float4 clipPos;\n", GetInterpolationQualifier());
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
out.Write("%s out float4 clipPos;\n",
|
||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
||||
if (uid_data->pixel_lighting)
|
||||
{
|
||||
out.Write("%s out float3 Normal;\n", GetInterpolationQualifier());
|
||||
out.Write("%s out float3 WorldPos;\n", GetInterpolationQualifier());
|
||||
out.Write("%s out float3 Normal;\n",
|
||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
||||
out.Write("%s out float3 WorldPos;\n",
|
||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
||||
}
|
||||
out.Write("%s out float4 colors_0;\n", GetInterpolationQualifier());
|
||||
out.Write("%s out float4 colors_1;\n", GetInterpolationQualifier());
|
||||
out.Write("%s out float4 colors_0;\n",
|
||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
||||
out.Write("%s out float4 colors_1;\n",
|
||||
GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa));
|
||||
}
|
||||
|
||||
out.Write("void main()\n{\n");
|
||||
@ -107,23 +162,23 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
out.Write("VS_OUTPUT main(\n");
|
||||
|
||||
// inputs
|
||||
if (components & VB_HAS_NRM0)
|
||||
if (uid_data->components & VB_HAS_NRM0)
|
||||
out.Write(" float3 rawnorm0 : NORMAL0,\n");
|
||||
if (components & VB_HAS_NRM1)
|
||||
if (uid_data->components & VB_HAS_NRM1)
|
||||
out.Write(" float3 rawnorm1 : NORMAL1,\n");
|
||||
if (components & VB_HAS_NRM2)
|
||||
if (uid_data->components & VB_HAS_NRM2)
|
||||
out.Write(" float3 rawnorm2 : NORMAL2,\n");
|
||||
if (components & VB_HAS_COL0)
|
||||
if (uid_data->components & VB_HAS_COL0)
|
||||
out.Write(" float4 color0 : COLOR0,\n");
|
||||
if (components & VB_HAS_COL1)
|
||||
if (uid_data->components & VB_HAS_COL1)
|
||||
out.Write(" float4 color1 : COLOR1,\n");
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0 << i));
|
||||
if ((components & (VB_HAS_UV0 << i)) || hastexmtx)
|
||||
u32 hastexmtx = (uid_data->components & (VB_HAS_TEXMTXIDX0 << i));
|
||||
if ((uid_data->components & (VB_HAS_UV0 << i)) || hastexmtx)
|
||||
out.Write(" float%d tex%d : TEXCOORD%d,\n", hastexmtx ? 3 : 2, i, i);
|
||||
}
|
||||
if (components & VB_HAS_POSMTXIDX)
|
||||
if (uid_data->components & VB_HAS_POSMTXIDX)
|
||||
out.Write(" int posmtx : BLENDINDICES,\n");
|
||||
out.Write(" float4 rawpos : POSITION) {\n");
|
||||
}
|
||||
@ -131,26 +186,26 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
out.Write("VS_OUTPUT o;\n");
|
||||
|
||||
// transforms
|
||||
if (components & VB_HAS_POSMTXIDX)
|
||||
if (uid_data->components & VB_HAS_POSMTXIDX)
|
||||
{
|
||||
out.Write("float4 pos = float4(dot(" I_TRANSFORMMATRICES
|
||||
"[posmtx], rawpos), dot(" I_TRANSFORMMATRICES
|
||||
"[posmtx+1], rawpos), dot(" I_TRANSFORMMATRICES "[posmtx+2], rawpos), 1);\n");
|
||||
|
||||
if (components & VB_HAS_NRMALL)
|
||||
if (uid_data->components & VB_HAS_NRMALL)
|
||||
{
|
||||
out.Write("int normidx = posmtx & 31;\n");
|
||||
out.Write("float3 N0 = " I_NORMALMATRICES "[normidx].xyz, N1 = " I_NORMALMATRICES
|
||||
"[normidx+1].xyz, N2 = " I_NORMALMATRICES "[normidx+2].xyz;\n");
|
||||
}
|
||||
|
||||
if (components & VB_HAS_NRM0)
|
||||
if (uid_data->components & VB_HAS_NRM0)
|
||||
out.Write("float3 _norm0 = normalize(float3(dot(N0, rawnorm0), dot(N1, rawnorm0), dot(N2, "
|
||||
"rawnorm0)));\n");
|
||||
if (components & VB_HAS_NRM1)
|
||||
if (uid_data->components & VB_HAS_NRM1)
|
||||
out.Write(
|
||||
"float3 _norm1 = float3(dot(N0, rawnorm1), dot(N1, rawnorm1), dot(N2, rawnorm1));\n");
|
||||
if (components & VB_HAS_NRM2)
|
||||
if (uid_data->components & VB_HAS_NRM2)
|
||||
out.Write(
|
||||
"float3 _norm2 = float3(dot(N0, rawnorm2), dot(N1, rawnorm2), dot(N2, rawnorm2));\n");
|
||||
}
|
||||
@ -158,21 +213,21 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
{
|
||||
out.Write("float4 pos = float4(dot(" I_POSNORMALMATRIX "[0], rawpos), dot(" I_POSNORMALMATRIX
|
||||
"[1], rawpos), dot(" I_POSNORMALMATRIX "[2], rawpos), 1.0);\n");
|
||||
if (components & VB_HAS_NRM0)
|
||||
if (uid_data->components & VB_HAS_NRM0)
|
||||
out.Write("float3 _norm0 = normalize(float3(dot(" I_POSNORMALMATRIX
|
||||
"[3].xyz, rawnorm0), dot(" I_POSNORMALMATRIX
|
||||
"[4].xyz, rawnorm0), dot(" I_POSNORMALMATRIX "[5].xyz, rawnorm0)));\n");
|
||||
if (components & VB_HAS_NRM1)
|
||||
if (uid_data->components & VB_HAS_NRM1)
|
||||
out.Write("float3 _norm1 = float3(dot(" I_POSNORMALMATRIX
|
||||
"[3].xyz, rawnorm1), dot(" I_POSNORMALMATRIX
|
||||
"[4].xyz, rawnorm1), dot(" I_POSNORMALMATRIX "[5].xyz, rawnorm1));\n");
|
||||
if (components & VB_HAS_NRM2)
|
||||
if (uid_data->components & VB_HAS_NRM2)
|
||||
out.Write("float3 _norm2 = float3(dot(" I_POSNORMALMATRIX
|
||||
"[3].xyz, rawnorm2), dot(" I_POSNORMALMATRIX
|
||||
"[4].xyz, rawnorm2), dot(" I_POSNORMALMATRIX "[5].xyz, rawnorm2));\n");
|
||||
}
|
||||
|
||||
if (!(components & VB_HAS_NRM0))
|
||||
if (!(uid_data->components & VB_HAS_NRM0))
|
||||
out.Write("float3 _norm0 = float3(0.0, 0.0, 0.0);\n");
|
||||
|
||||
out.Write("o.pos = float4(dot(" I_PROJECTION "[0], pos), dot(" I_PROJECTION
|
||||
@ -182,20 +237,19 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
"float3 ldir, h, cosAttn, distAttn;\n"
|
||||
"float dist, dist2, attn;\n");
|
||||
|
||||
uid_data->numColorChans = xfmem.numChan.numColorChans;
|
||||
if (xfmem.numChan.numColorChans == 0)
|
||||
if (uid_data->numColorChans == 0)
|
||||
{
|
||||
if (components & VB_HAS_COL0)
|
||||
if (uid_data->components & VB_HAS_COL0)
|
||||
out.Write("o.colors_0 = color0;\n");
|
||||
else
|
||||
out.Write("o.colors_0 = float4(1.0, 1.0, 1.0, 1.0);\n");
|
||||
}
|
||||
|
||||
GenerateLightingShader<T>(out, uid_data->lighting, components, "color", "o.colors_");
|
||||
GenerateLightingShaderCode(out, uid_data->lighting, uid_data->components, "color", "o.colors_");
|
||||
|
||||
if (xfmem.numChan.numColorChans < 2)
|
||||
if (uid_data->numColorChans < 2)
|
||||
{
|
||||
if (components & VB_HAS_COL1)
|
||||
if (uid_data->components & VB_HAS_COL1)
|
||||
out.Write("o.colors_1 = color1;\n");
|
||||
else
|
||||
out.Write("o.colors_1 = o.colors_0;\n");
|
||||
@ -203,20 +257,19 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
|
||||
// transform texcoords
|
||||
out.Write("float4 coord = float4(0.0, 0.0, 1.0, 1.0);\n");
|
||||
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
|
||||
for (unsigned int i = 0; i < uid_data->numTexGens; ++i)
|
||||
{
|
||||
TexMtxInfo& texinfo = xfmem.texMtxInfo[i];
|
||||
auto& texinfo = uid_data->texMtxInfo[i];
|
||||
|
||||
out.Write("{\n");
|
||||
out.Write("coord = float4(0.0, 0.0, 1.0, 1.0);\n");
|
||||
uid_data->texMtxInfo[i].sourcerow = xfmem.texMtxInfo[i].sourcerow;
|
||||
switch (texinfo.sourcerow)
|
||||
{
|
||||
case XF_SRCGEOM_INROW:
|
||||
out.Write("coord.xyz = rawpos.xyz;\n");
|
||||
break;
|
||||
case XF_SRCNORMAL_INROW:
|
||||
if (components & VB_HAS_NRM0)
|
||||
if (uid_data->components & VB_HAS_NRM0)
|
||||
{
|
||||
out.Write("coord.xyz = rawnorm0.xyz;\n");
|
||||
}
|
||||
@ -226,40 +279,37 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
texinfo.texgentype == XF_TEXGEN_COLOR_STRGBC1);
|
||||
break;
|
||||
case XF_SRCBINORMAL_T_INROW:
|
||||
if (components & VB_HAS_NRM1)
|
||||
if (uid_data->components & VB_HAS_NRM1)
|
||||
{
|
||||
out.Write("coord.xyz = rawnorm1.xyz;\n");
|
||||
}
|
||||
break;
|
||||
case XF_SRCBINORMAL_B_INROW:
|
||||
if (components & VB_HAS_NRM2)
|
||||
if (uid_data->components & VB_HAS_NRM2)
|
||||
{
|
||||
out.Write("coord.xyz = rawnorm2.xyz;\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_assert_(texinfo.sourcerow <= XF_SRCTEX7_INROW);
|
||||
if (components & (VB_HAS_UV0 << (texinfo.sourcerow - XF_SRCTEX0_INROW)))
|
||||
if (uid_data->components & (VB_HAS_UV0 << (texinfo.sourcerow - XF_SRCTEX0_INROW)))
|
||||
out.Write("coord = float4(tex%d.x, tex%d.y, 1.0, 1.0);\n",
|
||||
texinfo.sourcerow - XF_SRCTEX0_INROW, texinfo.sourcerow - XF_SRCTEX0_INROW);
|
||||
break;
|
||||
}
|
||||
// Input form of AB11 sets z element to 1.0
|
||||
uid_data->texMtxInfo[i].inputform = xfmem.texMtxInfo[i].inputform;
|
||||
|
||||
if (texinfo.inputform == XF_TEXINPUT_AB11)
|
||||
out.Write("coord.z = 1.0;\n");
|
||||
|
||||
// first transformation
|
||||
uid_data->texMtxInfo[i].texgentype = xfmem.texMtxInfo[i].texgentype;
|
||||
switch (texinfo.texgentype)
|
||||
{
|
||||
case XF_TEXGEN_EMBOSS_MAP: // calculate tex coords into bump map
|
||||
|
||||
if (components & (VB_HAS_NRM1 | VB_HAS_NRM2))
|
||||
if (uid_data->components & (VB_HAS_NRM1 | VB_HAS_NRM2))
|
||||
{
|
||||
// transform the light dir into tangent space
|
||||
uid_data->texMtxInfo[i].embosslightshift = xfmem.texMtxInfo[i].embosslightshift;
|
||||
uid_data->texMtxInfo[i].embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift;
|
||||
out.Write("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n",
|
||||
LIGHT_POS_PARAMS(texinfo.embosslightshift));
|
||||
out.Write(
|
||||
@ -271,7 +321,6 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
// The following assert was triggered in House of the Dead Overkill and Star Wars Rogue
|
||||
// Squadron 2
|
||||
//_assert_(0); // should have normals
|
||||
uid_data->texMtxInfo[i].embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift;
|
||||
out.Write("o.tex%d.xyz = o.tex%d.xyz;\n", i, texinfo.embosssourceshift);
|
||||
}
|
||||
|
||||
@ -284,11 +333,10 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
break;
|
||||
case XF_TEXGEN_REGULAR:
|
||||
default:
|
||||
uid_data->texMtxInfo_n_projection |= xfmem.texMtxInfo[i].projection << i;
|
||||
if (components & (VB_HAS_TEXMTXIDX0 << i))
|
||||
if (uid_data->components & (VB_HAS_TEXMTXIDX0 << i))
|
||||
{
|
||||
out.Write("int tmp = int(tex%d.z);\n", i);
|
||||
if (texinfo.projection == XF_TEXPROJ_STQ)
|
||||
if (((uid_data->texMtxInfo_n_projection >> i) & 1) == XF_TEXPROJ_STQ)
|
||||
out.Write("o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES
|
||||
"[tmp]), dot(coord, " I_TRANSFORMMATRICES
|
||||
"[tmp+1]), dot(coord, " I_TRANSFORMMATRICES "[tmp+2]));\n",
|
||||
@ -300,7 +348,7 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (texinfo.projection == XF_TEXPROJ_STQ)
|
||||
if (((uid_data->texMtxInfo_n_projection >> i) & 1) == XF_TEXPROJ_STQ)
|
||||
out.Write("o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES
|
||||
"[%d]), dot(coord, " I_TEXMATRICES "[%d]), dot(coord, " I_TEXMATRICES
|
||||
"[%d]));\n",
|
||||
@ -313,20 +361,16 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
break;
|
||||
}
|
||||
|
||||
uid_data->dualTexTrans_enabled = xfmem.dualTexTrans.enabled;
|
||||
// CHECKME: does this only work for regular tex gen types?
|
||||
if (xfmem.dualTexTrans.enabled && texinfo.texgentype == XF_TEXGEN_REGULAR)
|
||||
if (uid_data->dualTexTrans_enabled && texinfo.texgentype == XF_TEXGEN_REGULAR)
|
||||
{
|
||||
const PostMtxInfo& postInfo = xfmem.postMtxInfo[i];
|
||||
auto& postInfo = uid_data->postMtxInfo[i];
|
||||
|
||||
uid_data->postMtxInfo[i].index = xfmem.postMtxInfo[i].index;
|
||||
int postidx = postInfo.index;
|
||||
out.Write("float4 P0 = " I_POSTTRANSFORMMATRICES "[%d];\n"
|
||||
"float4 P1 = " I_POSTTRANSFORMMATRICES "[%d];\n"
|
||||
"float4 P2 = " I_POSTTRANSFORMMATRICES "[%d];\n",
|
||||
postidx & 0x3f, (postidx + 1) & 0x3f, (postidx + 2) & 0x3f);
|
||||
postInfo.index & 0x3f, (postInfo.index + 1) & 0x3f, (postInfo.index + 2) & 0x3f);
|
||||
|
||||
uid_data->postMtxInfo[i].normalize = xfmem.postMtxInfo[i].normalize;
|
||||
if (postInfo.normalize)
|
||||
out.Write("o.tex%d.xyz = normalize(o.tex%d.xyz);\n", i, i);
|
||||
|
||||
@ -342,15 +386,15 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
// clipPos/w needs to be done in pixel shader, not here
|
||||
out.Write("o.clipPos = o.pos;\n");
|
||||
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
if (uid_data->pixel_lighting)
|
||||
{
|
||||
out.Write("o.Normal = _norm0;\n");
|
||||
out.Write("o.WorldPos = pos.xyz;\n");
|
||||
|
||||
if (components & VB_HAS_COL0)
|
||||
if (uid_data->components & VB_HAS_COL0)
|
||||
out.Write("o.colors_0 = color0;\n");
|
||||
|
||||
if (components & VB_HAS_COL1)
|
||||
if (uid_data->components & VB_HAS_COL1)
|
||||
out.Write("o.colors_1 = color1;\n");
|
||||
}
|
||||
|
||||
@ -390,16 +434,16 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
{
|
||||
if (g_ActiveConfig.backend_info.bSupportsGeometryShaders)
|
||||
{
|
||||
AssignVSOutputMembers(out, "vs", "o");
|
||||
AssignVSOutputMembers(out, "vs", "o", uid_data->numTexGens, uid_data->pixel_lighting);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Pass interface blocks between shader stages even if geometry shaders
|
||||
// are not supported, however that will require at least OpenGL 3.2 support.
|
||||
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
|
||||
for (unsigned int i = 0; i < uid_data->numTexGens; ++i)
|
||||
out.Write("uv%d.xyz = o.tex%d;\n", i, i);
|
||||
out.Write("clipPos = o.clipPos;\n");
|
||||
if (g_ActiveConfig.bEnablePixelLighting)
|
||||
if (uid_data->pixel_lighting)
|
||||
{
|
||||
out.Write("Normal = o.Normal;\n");
|
||||
out.Write("WorldPos = o.WorldPos;\n");
|
||||
@ -418,13 +462,3 @@ static T GenerateVertexShader(API_TYPE api_type)
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
VertexShaderUid GetVertexShaderUid(API_TYPE api_type)
|
||||
{
|
||||
return GenerateVertexShader<VertexShaderUid>(api_type);
|
||||
}
|
||||
|
||||
ShaderCode GenerateVertexShaderCode(API_TYPE api_type)
|
||||
{
|
||||
return GenerateVertexShader<ShaderCode>(api_type);
|
||||
}
|
||||
|
@ -37,10 +37,13 @@ struct vertex_shader_uid_data
|
||||
u32 numColorChans : 2;
|
||||
u32 dualTexTrans_enabled : 1;
|
||||
u32 pixel_lighting : 1;
|
||||
u32 pad : 1;
|
||||
u32 msaa : 1;
|
||||
|
||||
u32 texMtxInfo_n_projection : 16; // Stored separately to guarantee that the texMtxInfo struct is
|
||||
// 8 bits wide
|
||||
u32 ssaa : 1;
|
||||
u32 pad : 15;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 inputform : 2;
|
||||
@ -63,5 +66,5 @@ struct vertex_shader_uid_data
|
||||
|
||||
typedef ShaderUid<vertex_shader_uid_data> VertexShaderUid;
|
||||
|
||||
VertexShaderUid GetVertexShaderUid(API_TYPE api_type);
|
||||
ShaderCode GenerateVertexShaderCode(API_TYPE api_type);
|
||||
VertexShaderUid GetVertexShaderUid();
|
||||
ShaderCode GenerateVertexShaderCode(API_TYPE api_type, const vertex_shader_uid_data* uid_data);
|
||||
|
@ -79,7 +79,6 @@ void VideoConfig::Load(const std::string& ini_file)
|
||||
settings->Get("TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0);
|
||||
settings->Get("WireFrame", &bWireFrame, 0);
|
||||
settings->Get("DisableFog", &bDisableFog, 0);
|
||||
settings->Get("EnableShaderDebugging", &bEnableShaderDebugging, false);
|
||||
settings->Get("BorderlessFullscreen", &bBorderlessFullscreen, false);
|
||||
|
||||
settings->Get("SWZComploc", &bZComploc, true);
|
||||
@ -120,18 +119,6 @@ void VideoConfig::Load(const std::string& ini_file)
|
||||
interface->Get("UsePanicHandlers", &bTmp, true);
|
||||
SetEnableAlert(bTmp);
|
||||
|
||||
// Shader Debugging causes a huge slowdown and it's easy to forget about it
|
||||
// since it's not exposed in the settings dialog. It's only used by
|
||||
// developers, so displaying an obnoxious message avoids some confusion and
|
||||
// is not too annoying/confusing for users.
|
||||
//
|
||||
// XXX(delroth): This is kind of a bad place to put this, but the current
|
||||
// VideoCommon is a mess and we don't have a central initialization
|
||||
// function to do these kind of checks. Instead, the init code is
|
||||
// triplicated for each video backend.
|
||||
if (bEnableShaderDebugging)
|
||||
OSD::AddMessage("Warning: Shader Debugging is enabled, performance will suffer heavily", 15000);
|
||||
|
||||
VerifyValidity();
|
||||
}
|
||||
|
||||
@ -299,7 +286,6 @@ void VideoConfig::Save(const std::string& ini_file)
|
||||
settings->Set("TexFmtOverlayCenter", bTexFmtOverlayCenter);
|
||||
settings->Set("Wireframe", bWireFrame);
|
||||
settings->Set("DisableFog", bDisableFog);
|
||||
settings->Set("EnableShaderDebugging", bEnableShaderDebugging);
|
||||
settings->Set("BorderlessFullscreen", bBorderlessFullscreen);
|
||||
|
||||
settings->Set("SWZComploc", bZComploc);
|
||||
|
@ -132,9 +132,6 @@ struct VideoConfig final
|
||||
// D3D only config, mostly to be merged into the above
|
||||
int iAdapter;
|
||||
|
||||
// Debugging
|
||||
bool bEnableShaderDebugging;
|
||||
|
||||
// VideoSW Debugging
|
||||
int drawStart;
|
||||
int drawEnd;
|
||||
|
Loading…
x
Reference in New Issue
Block a user