Merge pull request #3431 from stenzek/shadercache

ShaderGen: Remove virtual methods and string from ShaderGeneratorInterface.
This commit is contained in:
Mathew Maidment 2016-01-04 19:11:14 -05:00
commit 0509292f86
6 changed files with 35 additions and 32 deletions

View File

@ -7,6 +7,7 @@
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <type_traits>
#include "Common/Common.h" #include "Common/Common.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
@ -54,6 +55,15 @@ public:
{ {
using std::ios_base; using std::ios_base;
// Since we're reading/writing directly to the storage of K instances,
// K must be trivially copyable. TODO: Remove #if once GCC 5.0 is a
// minimum requirement.
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
static_assert(std::has_trivial_copy_constructor<K>::value, "K must be a trivially copyable type");
#else
static_assert(std::is_trivially_copyable<K>::value, "K must be a trivially copyable type");
#endif
// close any currently opened file // close any currently opened file
Close(); Close();
m_num_entries = 0; m_num_entries = 0;

View File

@ -25,10 +25,6 @@ public:
PixelShaderUid puid; PixelShaderUid puid;
GeometryShaderUid guid; GeometryShaderUid guid;
SHADERUID() {}
SHADERUID(const SHADERUID& r) : vuid(r.vuid), puid(r.puid), guid(r.guid) {}
bool operator <(const SHADERUID& r) const bool operator <(const SHADERUID& r) const
{ {
return std::tie(puid, vuid, guid) < return std::tie(puid, vuid, guid) <

View File

@ -34,7 +34,9 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType)
// Non-uid template parameters will write to the dummy data (=> gets optimized out) // Non-uid template parameters will write to the dummy data (=> gets optimized out)
geometry_shader_uid_data dummy_data; geometry_shader_uid_data dummy_data;
geometry_shader_uid_data* uid_data = out.template GetUidData<geometry_shader_uid_data>(); geometry_shader_uid_data* uid_data = out.template GetUidData<geometry_shader_uid_data>();
if (uid_data == nullptr) if (uid_data != nullptr)
memset(uid_data, 0, sizeof(*uid_data));
else
uid_data = &dummy_data; uid_data = &dummy_data;
uid_data->primitive_type = primitive_type; uid_data->primitive_type = primitive_type;

View File

@ -168,7 +168,9 @@ static T GeneratePixelShader(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType)
// Non-uid template parameters will write to the dummy data (=> gets optimized out) // Non-uid template parameters will write to the dummy data (=> gets optimized out)
pixel_shader_uid_data dummy_data; pixel_shader_uid_data dummy_data;
pixel_shader_uid_data* uid_data = out.template GetUidData<pixel_shader_uid_data>(); pixel_shader_uid_data* uid_data = out.template GetUidData<pixel_shader_uid_data>();
if (uid_data == nullptr) if (uid_data != nullptr)
memset(uid_data, 0, sizeof(*uid_data));
else
uid_data = &dummy_data; uid_data = &dummy_data;
unsigned int numStages = bpmem.genMode.numtevstages + 1; unsigned int numStages = bpmem.genMode.numtevstages + 1;

View File

@ -18,30 +18,23 @@
#include "VideoCommon/XFMemory.h" #include "VideoCommon/XFMemory.h"
/** /**
* Common interface for classes that need to go through the shader generation path (GenerateVertexShader, GeneratePixelShader) * Common interface for classes that need to go through the shader generation path (GenerateVertexShader, GenerateGeometryShader, GeneratePixelShader)
* In particular, this includes the shader code generator (ShaderCode). * In particular, this includes the shader code generator (ShaderCode).
* A different class (ShaderUid) can be used to uniquely identify each ShaderCode object. * A different class (ShaderUid) can be used to uniquely identify each ShaderCode object.
* More interesting things can be done with this, e.g. ShaderConstantProfile checks what shader constants are being used. This can be used to optimize buffer management. * More interesting things can be done with this, e.g. ShaderConstantProfile checks what shader constants are being used. This can be used to optimize buffer management.
* Each of the ShaderCode, ShaderUid and ShaderConstantProfile child classes only implement the subset of ShaderGeneratorInterface methods that are required for the specific tasks. * If the class does not use one or more of these methods (e.g. Uid class does not need code), the method will be defined as a no-op by the base class, and the call
* should be optimized out. The reason for this implementation is so that shader selection/generation can be done in two passes, with only a cache lookup being
* required if the shader has already been generated.
*/ */
class ShaderGeneratorInterface class ShaderGeneratorInterface
{ {
public: public:
virtual ~ShaderGeneratorInterface()
{
}
/*
* Returns a read pointer to the internal buffer.
*/
const std::string& GetBuffer() const { return m_buffer; }
/* /*
* Used when the shader generator would write a piece of ShaderCode. * Used when the shader generator would write a piece of ShaderCode.
* Can be used like printf. * Can be used like printf.
* @note In the ShaderCode implementation, this does indeed write the parameter string to an internal buffer. However, you're free to do whatever you like with the parameter. * @note In the ShaderCode implementation, this does indeed write the parameter string to an internal buffer. However, you're free to do whatever you like with the parameter.
*/ */
virtual void Write(const char*, ...) void Write(const char*, ...)
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((format(printf, 2, 3))) __attribute__((format(printf, 2, 3)))
#endif #endif
@ -51,7 +44,7 @@ public:
/* /*
* Tells us that a specific constant range (including last_index) is being used by the shader * Tells us that a specific constant range (including last_index) is being used by the shader
*/ */
virtual void SetConstantsUsed(unsigned int first_index, unsigned int last_index) {} void SetConstantsUsed(unsigned int first_index, unsigned int last_index) {}
/* /*
* Returns a pointer to an internally stored object of the uid_data type. * Returns a pointer to an internally stored object of the uid_data type.
@ -59,27 +52,19 @@ public:
*/ */
template<class uid_data> template<class uid_data>
uid_data* GetUidData() { return nullptr; } uid_data* GetUidData() { return nullptr; }
protected:
std::string m_buffer;
}; };
/** /*
* Shader UID class used to uniquely identify the ShaderCode output written in the shader generator. * Shader UID class used to uniquely identify the ShaderCode output written in the shader generator.
* uid_data can be any struct of parameters that uniquely identify each shader code output. * uid_data can be any struct of parameters that uniquely identify each shader code output.
* Unless performance is not an issue, uid_data should be tightly packed to reduce memory footprint. * Unless performance is not an issue, uid_data should be tightly packed to reduce memory footprint.
* Shader generators will write to specific uid_data fields; ShaderUid methods will only read raw u32 values from a union. * Shader generators will write to specific uid_data fields; ShaderUid methods will only read raw u32 values from a union.
* NOTE: Because LinearDiskCache reads and writes the storage associated with a ShaderUid instance, ShaderUid must be trivially copyable.
*/ */
template<class uid_data> template<class uid_data>
class ShaderUid : public ShaderGeneratorInterface class ShaderUid : public ShaderGeneratorInterface
{ {
public: public:
ShaderUid()
{
// TODO: Move to Shadergen => can be optimized out
memset(values, 0, sizeof(values));
}
bool operator == (const ShaderUid& obj) const bool operator == (const ShaderUid& obj) const
{ {
return memcmp(this->values, obj.values, data.NumValues() * sizeof(*values)) == 0; return memcmp(this->values, obj.values, data.NumValues() * sizeof(*values)) == 0;
@ -119,7 +104,9 @@ public:
m_buffer.reserve(16384); m_buffer.reserve(16384);
} }
void Write(const char* fmt, ...) override const std::string& GetBuffer() const { return m_buffer; }
void Write(const char* fmt, ...)
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((format(printf, 2, 3))) __attribute__((format(printf, 2, 3)))
#endif #endif
@ -129,6 +116,9 @@ public:
m_buffer += StringFromFormatV(fmt, arglist); m_buffer += StringFromFormatV(fmt, arglist);
va_end(arglist); va_end(arglist);
} }
protected:
std::string m_buffer;
}; };
/** /**
@ -139,7 +129,7 @@ class ShaderConstantProfile : public ShaderGeneratorInterface
public: public:
ShaderConstantProfile(int num_constants) { constant_usage.resize(num_constants); } ShaderConstantProfile(int num_constants) { constant_usage.resize(num_constants); }
void SetConstantsUsed(unsigned int first_index, unsigned int last_index) override void SetConstantsUsed(unsigned int first_index, unsigned int last_index)
{ {
for (unsigned int i = first_index; i < last_index + 1; ++i) for (unsigned int i = first_index; i < last_index + 1; ++i)
constant_usage[i] = true; constant_usage[i] = true;
@ -151,6 +141,7 @@ public:
return true; return true;
//return constant_usage[index]; //return constant_usage[index];
} }
private: private:
std::vector<bool> constant_usage; // TODO: Is vector<bool> appropriate here? std::vector<bool> constant_usage; // TODO: Is vector<bool> appropriate here?
}; };

View File

@ -19,7 +19,9 @@ static T GenerateVertexShader(API_TYPE api_type)
// Non-uid template parameters will write to the dummy data (=> gets optimized out) // Non-uid template parameters will write to the dummy data (=> gets optimized out)
vertex_shader_uid_data dummy_data; vertex_shader_uid_data dummy_data;
vertex_shader_uid_data* uid_data = out.template GetUidData<vertex_shader_uid_data>(); vertex_shader_uid_data* uid_data = out.template GetUidData<vertex_shader_uid_data>();
if (uid_data == nullptr) if (uid_data != nullptr)
memset(uid_data, 0, sizeof(*uid_data));
else
uid_data = &dummy_data; uid_data = &dummy_data;
_assert_(bpmem.genMode.numtexgens == xfmem.numTexGen.numTexGens); _assert_(bpmem.genMode.numtexgens == xfmem.numTexGen.numTexGens);