1
0
forked from mirrors/0ad

Uses vertex streams to get attribute locations reducing duplication in XML.

Also adds missing streams.

This was SVN commit r26792.
This commit is contained in:
vladislavbelov
2022-04-15 18:13:33 +00:00
parent 37645670c1
commit eaac0b0dbe
33 changed files with 270 additions and 325 deletions
+2 -3
View File
@@ -297,7 +297,7 @@ void InstancingModelRenderer::UpdateModelData(CModel* UNUSED(model), CModelRData
// Setup one rendering pass.
void InstancingModelRenderer::BeginPass(int streamflags)
{
ENSURE(streamflags == (streamflags & (STREAM_POS|STREAM_NORMAL|STREAM_UV0|STREAM_UV1)));
ENSURE(streamflags == (streamflags & (STREAM_POS|STREAM_NORMAL|STREAM_UV0|STREAM_UV1|STREAM_UV2|STREAM_UV3|STREAM_UV4)));
}
// Cleanup rendering pass.
@@ -345,8 +345,7 @@ void InstancingModelRenderer::PrepareModelDef(
GL_FALSE, stride, base + m->imodeldef->m_Tangent.offset);
}
// The last UV set is STREAM_UV3
for (size_t uv = 0; uv < 4; ++uv)
for (size_t uv = 0; uv < 2; ++uv)
if (streamflags & (STREAM_UV0 << uv))
{
if (def.GetNumUVsPerVertex() >= uv + 1)
+85 -65
View File
@@ -100,41 +100,47 @@ GLenum GLTypeFromFormat(const Renderer::Backend::Format format)
return type;
}
int ParseAttribSemantics(Renderer::Backend::GL::CDevice* device, const CStr& str)
int GetAttributeLocationFromStream(Renderer::Backend::GL::CDevice* device, const int stream)
{
// Old mapping makes sense only if we have an old/low-end hardware. Else we
// need to use sequential numbering to fix #3054. We use presence of
// compute shaders as a check that the hardware has universal CUs.
if (device->GetCapabilities().computeShaders)
{
if (str == "gl_Vertex") return 0;
if (str == "gl_Normal") return 1;
if (str == "gl_Color") return 2;
if (str == "gl_MultiTexCoord0") return 3;
if (str == "gl_MultiTexCoord1") return 4;
if (str == "gl_MultiTexCoord2") return 5;
if (str == "gl_MultiTexCoord3") return 6;
if (str == "gl_MultiTexCoord4") return 7;
if (str == "gl_MultiTexCoord5") return 8;
if (str == "gl_MultiTexCoord6") return 9;
if (str == "gl_MultiTexCoord7") return 10;
switch (stream)
{
case STREAM_POS: return 0;
case STREAM_NORMAL: return 1;
case STREAM_COLOR: return 2;
case STREAM_UV0: return 3;
case STREAM_UV1: return 4;
case STREAM_UV2: return 5;
case STREAM_UV3: return 6;
case STREAM_UV4: return 7;
case STREAM_UV5: return 8;
case STREAM_UV6: return 9;
case STREAM_UV7: return 10;
}
}
else
{
// Map known semantics onto the attribute locations documented by NVIDIA:
// https://download.nvidia.com/developer/Papers/2005/OpenGL_2.0/NVIDIA_OpenGL_2.0_Support.pdf
// https://developer.download.nvidia.com/opengl/glsl/glsl_release_notes.pdf
if (str == "gl_Vertex") return 0;
if (str == "gl_Normal") return 2;
if (str == "gl_Color") return 3;
if (str == "gl_MultiTexCoord0") return 8;
if (str == "gl_MultiTexCoord1") return 9;
if (str == "gl_MultiTexCoord2") return 10;
if (str == "gl_MultiTexCoord3") return 11;
if (str == "gl_MultiTexCoord4") return 12;
if (str == "gl_MultiTexCoord5") return 13;
if (str == "gl_MultiTexCoord6") return 14;
if (str == "gl_MultiTexCoord7") return 15;
switch (stream)
{
case STREAM_POS: return 0;
case STREAM_NORMAL: return 2;
case STREAM_COLOR: return 3;
case STREAM_UV0: return 8;
case STREAM_UV1: return 9;
case STREAM_UV2: return 10;
case STREAM_UV3: return 11;
case STREAM_UV4: return 12;
case STREAM_UV5: return 13;
case STREAM_UV6: return 14;
case STREAM_UV7: return 15;
}
}
debug_warn("Invalid attribute semantics");
@@ -815,6 +821,7 @@ public:
const GLint size = GLSizeFromFormat(format);
const GLenum type = GLTypeFromFormat(format);
glVertexAttribPointer(it->second, size, type, normalized, stride, pointer);
m_ValidStreams |= STREAM_UV0 << (it->second - (m_Device->GetCapabilities().computeShaders ? 3 : 8));
}
}
@@ -875,17 +882,16 @@ std::unique_ptr<CShaderProgram> CShaderProgram::Create(CDevice* device, const CS
// Define all the elements and attributes used in the XML file
#define EL(x) int el_##x = XeroFile.GetElementID(#x)
#define AT(x) int at_##x = XeroFile.GetAttributeID(#x)
EL(attrib);
EL(define);
EL(fragment);
EL(stream);
EL(uniform);
EL(vertex);
AT(attribute);
AT(file);
AT(if);
AT(loc);
AT(name);
AT(semantics);
AT(type);
AT(value);
#undef AT
@@ -904,72 +910,86 @@ std::unique_ptr<CShaderProgram> CShaderProgram::Create(CDevice* device, const CS
std::map<CStrIntern, int> vertexAttribs;
int streamFlags = 0;
XERO_ITER_EL(root, Child)
XERO_ITER_EL(root, child)
{
if (Child.GetNodeName() == el_define)
if (child.GetNodeName() == el_define)
{
defines.Add(CStrIntern(Child.GetAttributes().GetNamedItem(at_name)), CStrIntern(Child.GetAttributes().GetNamedItem(at_value)));
defines.Add(CStrIntern(child.GetAttributes().GetNamedItem(at_name)), CStrIntern(child.GetAttributes().GetNamedItem(at_value)));
}
else if (Child.GetNodeName() == el_vertex)
else if (child.GetNodeName() == el_vertex)
{
vertexFile = L"shaders/" + Child.GetAttributes().GetNamedItem(at_file).FromUTF8();
vertexFile = L"shaders/" + child.GetAttributes().GetNamedItem(at_file).FromUTF8();
XERO_ITER_EL(Child, Param)
XERO_ITER_EL(child, param)
{
XMBAttributeList Attrs = Param.GetAttributes();
XMBAttributeList attributes = param.GetAttributes();
CStr cond = Attrs.GetNamedItem(at_if);
CStr cond = attributes.GetNamedItem(at_if);
if (!cond.empty() && !preprocessor.TestConditional(cond))
continue;
if (Param.GetNodeName() == el_uniform)
if (param.GetNodeName() == el_uniform)
{
vertexUniforms[CStrIntern(Attrs.GetNamedItem(at_name))] = Attrs.GetNamedItem(at_loc).ToInt();
vertexUniforms[CStrIntern(attributes.GetNamedItem(at_name))] = attributes.GetNamedItem(at_loc).ToInt();
}
else if (Param.GetNodeName() == el_stream)
else if (param.GetNodeName() == el_stream)
{
CStr StreamName = Attrs.GetNamedItem(at_name);
if (StreamName == "pos")
streamFlags |= STREAM_POS;
else if (StreamName == "normal")
streamFlags |= STREAM_NORMAL;
else if (StreamName == "color")
streamFlags |= STREAM_COLOR;
else if (StreamName == "uv0")
streamFlags |= STREAM_UV0;
else if (StreamName == "uv1")
streamFlags |= STREAM_UV1;
else if (StreamName == "uv2")
streamFlags |= STREAM_UV2;
else if (StreamName == "uv3")
streamFlags |= STREAM_UV3;
}
else if (Param.GetNodeName() == el_attrib)
{
const int attribLoc = ParseAttribSemantics(device, Attrs.GetNamedItem(at_semantics));
vertexAttribs[CStrIntern(Attrs.GetNamedItem(at_name))] = attribLoc;
const CStr streamName = attributes.GetNamedItem(at_name);
const CStr attributeName = attributes.GetNamedItem(at_attribute);
if (attributeName.empty())
LOGERROR("Empty attribute name in vertex shader description '%s'", vertexFile.string8().c_str());
int stream = 0;
if (streamName == "pos")
stream = STREAM_POS;
else if (streamName == "normal")
stream = STREAM_NORMAL;
else if (streamName == "color")
stream = STREAM_COLOR;
else if (streamName == "uv0")
stream = STREAM_UV0;
else if (streamName == "uv1")
stream = STREAM_UV1;
else if (streamName == "uv2")
stream = STREAM_UV2;
else if (streamName == "uv3")
stream = STREAM_UV3;
else if (streamName == "uv4")
stream = STREAM_UV4;
else if (streamName == "uv5")
stream = STREAM_UV5;
else if (streamName == "uv6")
stream = STREAM_UV6;
else if (streamName == "uv7")
stream = STREAM_UV7;
else
LOGERROR("Unknown stream '%s' in vertex shader description '%s'", streamName.c_str(), vertexFile.string8().c_str());
const int attributeLocation = GetAttributeLocationFromStream(device, stream);
vertexAttribs[CStrIntern(attributeName)] = attributeLocation;
streamFlags |= stream;
}
}
}
else if (Child.GetNodeName() == el_fragment)
else if (child.GetNodeName() == el_fragment)
{
fragmentFile = L"shaders/" + Child.GetAttributes().GetNamedItem(at_file).FromUTF8();
fragmentFile = L"shaders/" + child.GetAttributes().GetNamedItem(at_file).FromUTF8();
XERO_ITER_EL(Child, Param)
XERO_ITER_EL(child, param)
{
XMBAttributeList Attrs = Param.GetAttributes();
XMBAttributeList attributes = param.GetAttributes();
CStr cond = Attrs.GetNamedItem(at_if);
CStr cond = attributes.GetNamedItem(at_if);
if (!cond.empty() && !preprocessor.TestConditional(cond))
continue;
if (Param.GetNodeName() == el_uniform)
if (param.GetNodeName() == el_uniform)
{
// A somewhat incomplete listing, missing "shadow" and "rect" versions
// which are interpreted as 2D (NB: our shadowmaps may change
// type based on user config).
GLenum type = GL_TEXTURE_2D;
CStr t = Attrs.GetNamedItem(at_type);
const CStr t = attributes.GetNamedItem(at_type);
if (t == "sampler1D")
#if CONFIG2_GLES
debug_warn(L"sampler1D not implemented on GLES");
@@ -987,8 +1007,8 @@ std::unique_ptr<CShaderProgram> CShaderProgram::Create(CDevice* device, const CS
else if (t == "samplerCube")
type = GL_TEXTURE_CUBE_MAP;
fragmentUniforms[CStrIntern(Attrs.GetNamedItem(at_name))] =
std::make_pair(Attrs.GetNamedItem(at_loc).ToInt(), type);
fragmentUniforms[CStrIntern(attributes.GetNamedItem(at_name))] =
std::make_pair(attributes.GetNamedItem(at_loc).ToInt(), type);
}
}
}
+5 -1
View File
@@ -43,7 +43,11 @@ enum
STREAM_UV0 = (1 << 3),
STREAM_UV1 = (1 << 4),
STREAM_UV2 = (1 << 5),
STREAM_UV3 = (1 << 6)
STREAM_UV3 = (1 << 6),
STREAM_UV4 = (1 << 7),
STREAM_UV5 = (1 << 8),
STREAM_UV6 = (1 << 9),
STREAM_UV7 = (1 << 10),
};
namespace Renderer