VertexLoaderManager: Add methods to generate "uber" vertex formats
These vertex formats enable all attributes. Inactive attributes are set to offset=0, and the smallest type possible. This "optimization" stops the NV compiler from generating variants of vertex shaders.
This commit is contained in:
parent
f48ef65bec
commit
38c48ff72e
|
@ -133,6 +133,75 @@ void MarkAllDirty()
|
|||
g_preprocess_cp_state.attr_dirty = BitSet32::AllTrue(8);
|
||||
}
|
||||
|
||||
NativeVertexFormat* GetOrCreateMatchingFormat(const PortableVertexDeclaration& decl)
|
||||
{
|
||||
auto iter = s_native_vertex_map.find(decl);
|
||||
if (iter == s_native_vertex_map.end())
|
||||
{
|
||||
std::unique_ptr<NativeVertexFormat> fmt = g_vertex_manager->CreateNativeVertexFormat(decl);
|
||||
auto ipair = s_native_vertex_map.emplace(decl, std::move(fmt));
|
||||
iter = ipair.first;
|
||||
}
|
||||
|
||||
return iter->second.get();
|
||||
}
|
||||
|
||||
NativeVertexFormat* GetUberVertexFormat(const PortableVertexDeclaration& decl)
|
||||
{
|
||||
// The padding in the structs can cause the memcmp() in the map to create duplicates.
|
||||
// Avoid this by initializing the padding to zero.
|
||||
PortableVertexDeclaration new_decl;
|
||||
std::memset(&new_decl, 0, sizeof(new_decl));
|
||||
new_decl.stride = decl.stride;
|
||||
|
||||
auto MakeDummyAttribute = [](AttributeFormat& attr, VarType type, int components, bool integer) {
|
||||
attr.type = type;
|
||||
attr.components = components;
|
||||
attr.offset = 0;
|
||||
attr.enable = true;
|
||||
attr.integer = integer;
|
||||
};
|
||||
auto CopyAttribute = [](AttributeFormat& attr, const AttributeFormat& src) {
|
||||
attr.type = src.type;
|
||||
attr.components = src.components;
|
||||
attr.offset = src.offset;
|
||||
attr.enable = src.enable;
|
||||
attr.integer = src.integer;
|
||||
};
|
||||
|
||||
if (decl.position.enable)
|
||||
CopyAttribute(new_decl.position, decl.position);
|
||||
else
|
||||
MakeDummyAttribute(new_decl.position, VAR_FLOAT, 1, false);
|
||||
for (size_t i = 0; i < ArraySize(new_decl.normals); i++)
|
||||
{
|
||||
if (decl.normals[i].enable)
|
||||
CopyAttribute(new_decl.normals[i], decl.normals[i]);
|
||||
else
|
||||
MakeDummyAttribute(new_decl.normals[i], VAR_FLOAT, 1, false);
|
||||
}
|
||||
for (size_t i = 0; i < ArraySize(new_decl.colors); i++)
|
||||
{
|
||||
if (decl.colors[i].enable)
|
||||
CopyAttribute(new_decl.colors[i], decl.colors[i]);
|
||||
else
|
||||
MakeDummyAttribute(new_decl.colors[i], VAR_UNSIGNED_BYTE, 4, false);
|
||||
}
|
||||
for (size_t i = 0; i < ArraySize(new_decl.texcoords); i++)
|
||||
{
|
||||
if (decl.texcoords[i].enable)
|
||||
CopyAttribute(new_decl.texcoords[i], decl.texcoords[i]);
|
||||
else
|
||||
MakeDummyAttribute(new_decl.texcoords[i], VAR_FLOAT, 1, false);
|
||||
}
|
||||
if (decl.posmtx.enable)
|
||||
CopyAttribute(new_decl.posmtx, decl.posmtx);
|
||||
else
|
||||
MakeDummyAttribute(new_decl.posmtx, VAR_UNSIGNED_BYTE, 1, true);
|
||||
|
||||
return GetOrCreateMatchingFormat(new_decl);
|
||||
}
|
||||
|
||||
static VertexLoaderBase* RefreshLoader(int vtx_attr_group, bool preprocess = false)
|
||||
{
|
||||
CPState* state = preprocess ? &g_preprocess_cp_state : &g_main_cp_state;
|
||||
|
|
|
@ -26,6 +26,16 @@ void MarkAllDirty();
|
|||
|
||||
NativeVertexFormatMap* GetNativeVertexFormatMap();
|
||||
|
||||
// Creates or obtains a pointer to a VertexFormat representing decl.
|
||||
// If this results in a VertexFormat being created, if the game later uses a matching vertex
|
||||
// declaration, the one that was previously created will be used.
|
||||
NativeVertexFormat* GetOrCreateMatchingFormat(const PortableVertexDeclaration& decl);
|
||||
|
||||
// For vertex ubershaders, all attributes need to be present, even when the vertex
|
||||
// format does not contain them. This function returns a vertex format with dummy
|
||||
// offsets set to the unused attributes.
|
||||
NativeVertexFormat* GetUberVertexFormat(const PortableVertexDeclaration& decl);
|
||||
|
||||
// Returns -1 if buf_size is insufficient, else the amount of bytes consumed
|
||||
int RunVertices(int vtx_attr_group, int primitive, int count, DataReader src, bool is_preprocess);
|
||||
|
||||
|
|
Loading…
Reference in New Issue