|
|
@@ -113,6 +113,47 @@ static ANKI_USE_RESULT Error computeShaderVariableDataType(
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+//==============================================================================
|
|
|
+static CString toString(ShaderVariableDataType in)
|
|
|
+{
|
|
|
+ CString out;
|
|
|
+
|
|
|
+ switch(in)
|
|
|
+ {
|
|
|
+ case ShaderVariableDataType::FLOAT:
|
|
|
+ out = "float";
|
|
|
+ break;
|
|
|
+ case ShaderVariableDataType::VEC2:
|
|
|
+ out = "vec2";
|
|
|
+ break;
|
|
|
+ case ShaderVariableDataType::VEC3:
|
|
|
+ out = "vec3";
|
|
|
+ break;
|
|
|
+ case ShaderVariableDataType::VEC4:
|
|
|
+ out = "vec4";
|
|
|
+ break;
|
|
|
+ case ShaderVariableDataType::MAT4:
|
|
|
+ out = "mat4";
|
|
|
+ break;
|
|
|
+ case ShaderVariableDataType::MAT3:
|
|
|
+ out = "mat3";
|
|
|
+ break;
|
|
|
+ case ShaderVariableDataType::SAMPLER_2D:
|
|
|
+ out = "sampler2D";
|
|
|
+ break;
|
|
|
+ case ShaderVariableDataType::SAMPLER_2D_ARRAY:
|
|
|
+ out = "sampler2DArray";
|
|
|
+ break;
|
|
|
+ case ShaderVariableDataType::SAMPLER_CUBE:
|
|
|
+ out = "samplerCube";
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ANKI_ASSERT(0);
|
|
|
+ };
|
|
|
+
|
|
|
+ return out;
|
|
|
+}
|
|
|
+
|
|
|
//==============================================================================
|
|
|
static ANKI_USE_RESULT Error computeBuiltin(const CString& name,
|
|
|
BuiltinMaterialVariableId& out)
|
|
|
@@ -158,6 +199,42 @@ static ANKI_USE_RESULT Error computeBuiltin(const CString& name,
|
|
|
return ErrorCode::NONE;
|
|
|
}
|
|
|
|
|
|
+//==============================================================================
|
|
|
+static ShaderVariableDataType getBuiltinType(BuiltinMaterialVariableId in)
|
|
|
+{
|
|
|
+ ShaderVariableDataType out = ShaderVariableDataType::SAMPLER_2D;
|
|
|
+
|
|
|
+ switch(in)
|
|
|
+ {
|
|
|
+ case BuiltinMaterialVariableId::MVP_MATRIX:
|
|
|
+ out = ShaderVariableDataType::MAT4;
|
|
|
+ break;
|
|
|
+ case BuiltinMaterialVariableId::MV_MATRIX:
|
|
|
+ out = ShaderVariableDataType::MAT4;
|
|
|
+ break;
|
|
|
+ case BuiltinMaterialVariableId::VP_MATRIX:
|
|
|
+ out = ShaderVariableDataType::MAT4;
|
|
|
+ break;
|
|
|
+ case BuiltinMaterialVariableId::NORMAL_MATRIX:
|
|
|
+ out = ShaderVariableDataType::MAT3;
|
|
|
+ break;
|
|
|
+ case BuiltinMaterialVariableId::BILLBOARD_MVP_MATRIX:
|
|
|
+ out = ShaderVariableDataType::MAT4;
|
|
|
+ break;
|
|
|
+ case BuiltinMaterialVariableId::MAX_TESS_LEVEL:
|
|
|
+ out = ShaderVariableDataType::FLOAT;
|
|
|
+ break;
|
|
|
+ case BuiltinMaterialVariableId::MS_DEPTH_MAP:
|
|
|
+ out = ShaderVariableDataType::SAMPLER_2D;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ANKI_ASSERT(0);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return out;
|
|
|
+}
|
|
|
+
|
|
|
//==============================================================================
|
|
|
// MaterialLoaderInputVariable =
|
|
|
//==============================================================================
|
|
|
@@ -166,21 +243,26 @@ static ANKI_USE_RESULT Error computeBuiltin(const CString& name,
|
|
|
void MaterialLoaderInputVariable::move(MaterialLoaderInputVariable& b)
|
|
|
{
|
|
|
m_alloc = std::move(b.m_alloc);
|
|
|
+
|
|
|
m_name = std::move(b.m_name);
|
|
|
- m_typeStr = std::move(b.m_typeStr);
|
|
|
- m_type = b.m_type;
|
|
|
m_value = std::move(b.m_value);
|
|
|
- m_constant = b.m_constant;
|
|
|
- m_instanced = b.m_instanced;
|
|
|
- m_builtin = b.m_builtin;
|
|
|
m_line = std::move(b.m_line);
|
|
|
- m_shaderDefinedMask = b.m_shaderDefinedMask;
|
|
|
- m_shaderReferencedMask = b.m_shaderReferencedMask;
|
|
|
- m_inBlock = b.m_inBlock;
|
|
|
+
|
|
|
+ m_type = b.m_type;
|
|
|
+ m_builtin = b.m_builtin;
|
|
|
+ m_flags = b.m_flags;
|
|
|
+
|
|
|
m_binding = b.m_binding;
|
|
|
m_index = b.m_index;
|
|
|
- m_blockInfo = b.m_blockInfo;
|
|
|
- m_inShadow = b.m_inShadow;
|
|
|
+
|
|
|
+ m_shaderDefinedMask = b.m_shaderDefinedMask;
|
|
|
+ m_shaderReferencedMask = b.m_shaderReferencedMask;
|
|
|
+}
|
|
|
+
|
|
|
+//==============================================================================
|
|
|
+CString MaterialLoaderInputVariable::typeStr() const
|
|
|
+{
|
|
|
+ return toString(m_type);
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
@@ -188,7 +270,7 @@ void MaterialLoaderInputVariable::move(MaterialLoaderInputVariable& b)
|
|
|
//==============================================================================
|
|
|
|
|
|
//==============================================================================
|
|
|
-MaterialLoader::MaterialLoader(TempResourceAllocator<U8> alloc)
|
|
|
+MaterialLoader::MaterialLoader(GenericMemoryPoolAllocator<U8> alloc)
|
|
|
: m_alloc(alloc)
|
|
|
{}
|
|
|
|
|
|
@@ -206,7 +288,6 @@ MaterialLoader::~MaterialLoader()
|
|
|
}
|
|
|
|
|
|
m_inputs.destroy(m_alloc);
|
|
|
- m_uniformBlock.destroy(m_alloc);
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
@@ -276,11 +357,7 @@ Error MaterialLoader::parseProgramsTag(const XmlElement& el)
|
|
|
ANKI_CHECK(programEl.getNextSiblingElement("program", programEl));
|
|
|
} while(programEl);
|
|
|
|
|
|
- // Sort them by name to decrease the change of creating unique shaders
|
|
|
- m_inputs.sort([](const Input& a, const Input& b)
|
|
|
- {
|
|
|
- return a.m_name < b.m_name;
|
|
|
- });
|
|
|
+ processInputs();
|
|
|
|
|
|
//
|
|
|
// Then parse the includes, operations and other parts of the program
|
|
|
@@ -335,6 +412,17 @@ Error MaterialLoader::parseProgramTag(
|
|
|
m_tessellation = true;
|
|
|
}
|
|
|
|
|
|
+ // Some instancing crap
|
|
|
+ lines.pushBackSprintf(m_alloc,
|
|
|
+ "\n#if INSTANCE_COUNT > 1\n"
|
|
|
+ "#define INSTANCE_ID [%s]\n"
|
|
|
+ "#define INSTANCED [INSTANCE_COUNT]\n"
|
|
|
+ "#else\n"
|
|
|
+ "#define INSTANCE_ID\n"
|
|
|
+ "#define INSTANCED\n"
|
|
|
+ "#endif\n",
|
|
|
+ glshader == ShaderType::VERTEX ? "gl_InstanceID" : "in_instanceId");
|
|
|
+
|
|
|
// <includes></includes>
|
|
|
XmlElement includesEl;
|
|
|
ANKI_CHECK(programEl.getChildElement("includes", includesEl));
|
|
|
@@ -353,16 +441,18 @@ Error MaterialLoader::parseProgramTag(
|
|
|
// Inputs
|
|
|
|
|
|
// Block
|
|
|
- if(!m_uniformBlock.isEmpty()
|
|
|
- && (m_uniformBlockReferencedMask & glshaderbit) != ShaderTypeBit::NONE)
|
|
|
+ if((m_uniformBlockReferencedMask & glshaderbit) != ShaderTypeBit::NONE)
|
|
|
{
|
|
|
lines.pushBackSprintf(m_alloc,
|
|
|
"\nlayout(UBO_BINDING(0, 0), std140, row_major) "
|
|
|
"uniform _ublk00\n{");
|
|
|
|
|
|
- for(auto& str : m_uniformBlock)
|
|
|
+ for(Input& in : m_inputs)
|
|
|
{
|
|
|
- lines.pushBackSprintf(m_alloc, &str[0]);
|
|
|
+ if(in.m_flags.m_inBlock)
|
|
|
+ {
|
|
|
+ lines.pushBackSprintf(m_alloc, &in.m_line[0]);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
lines.pushBackSprintf(m_alloc, "};");
|
|
|
@@ -371,8 +461,9 @@ Error MaterialLoader::parseProgramTag(
|
|
|
// Other variables
|
|
|
for(Input& in : m_inputs)
|
|
|
{
|
|
|
- if(!in.m_inBlock
|
|
|
- && (in.m_shaderDefinedMask & glshaderbit) != ShaderTypeBit::NONE)
|
|
|
+ if(!in.m_flags.m_inBlock
|
|
|
+ && (in.m_shaderDefinedMask & glshaderbit) != ShaderTypeBit::NONE
|
|
|
+ && !in.m_flags.m_specialBuiltin)
|
|
|
{
|
|
|
lines.pushBackSprintf(m_alloc, &in.m_line[0]);
|
|
|
}
|
|
|
@@ -424,51 +515,46 @@ Error MaterialLoader::parseInputsTag(const XmlElement& programEl)
|
|
|
ANKI_CHECK(inputsEl.getChildElement("input", inputEl));
|
|
|
do
|
|
|
{
|
|
|
- Input inpvar;
|
|
|
- inpvar.m_alloc = m_alloc;
|
|
|
+ Input in;
|
|
|
+ in.m_alloc = m_alloc;
|
|
|
|
|
|
// <name>
|
|
|
ANKI_CHECK(inputEl.getChildElement("name", el));
|
|
|
ANKI_CHECK(el.getText(cstr));
|
|
|
- inpvar.m_name.create(m_alloc, cstr);
|
|
|
+ in.m_name.create(m_alloc, cstr);
|
|
|
|
|
|
- ANKI_CHECK(computeBuiltin(inpvar.m_name.toCString(), inpvar.m_builtin));
|
|
|
+ ANKI_CHECK(computeBuiltin(in.m_name.toCString(), in.m_builtin));
|
|
|
+
|
|
|
+ if(in.m_builtin != BuiltinMaterialVariableId::NONE)
|
|
|
+ {
|
|
|
+ in.m_flags.m_builtin = true;
|
|
|
+ if(in.m_builtin == BuiltinMaterialVariableId::MS_DEPTH_MAP)
|
|
|
+ {
|
|
|
+ in.m_flags.m_specialBuiltin = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// Check if instanced
|
|
|
- if(inpvar.m_builtin == BuiltinMaterialVariableId::MVP_MATRIX
|
|
|
- || inpvar.m_builtin == BuiltinMaterialVariableId::NORMAL_MATRIX
|
|
|
- || inpvar.m_builtin
|
|
|
+ if(in.m_builtin == BuiltinMaterialVariableId::MVP_MATRIX
|
|
|
+ || in.m_builtin == BuiltinMaterialVariableId::NORMAL_MATRIX
|
|
|
+ || in.m_builtin
|
|
|
== BuiltinMaterialVariableId::BILLBOARD_MVP_MATRIX)
|
|
|
{
|
|
|
- inpvar.m_instanced = true;
|
|
|
+ in.m_flags.m_instanced = true;
|
|
|
m_instanced = true;
|
|
|
}
|
|
|
|
|
|
// <type>
|
|
|
ANKI_CHECK(inputEl.getChildElement("type", el));
|
|
|
ANKI_CHECK(el.getText(cstr));
|
|
|
- inpvar.m_typeStr.create(m_alloc, cstr);
|
|
|
- ANKI_CHECK(computeShaderVariableDataType(cstr, inpvar.m_type));
|
|
|
+ ANKI_CHECK(computeShaderVariableDataType(cstr, in.m_type));
|
|
|
|
|
|
- // <value>
|
|
|
- ANKI_CHECK(inputEl.getChildElement("value", el));
|
|
|
- ANKI_CHECK(el.getText(cstr));
|
|
|
- if(cstr)
|
|
|
- {
|
|
|
- inpvar.m_value.splitString(m_alloc, cstr, ' ');
|
|
|
-
|
|
|
- if(inpvar.m_builtin != BuiltinMaterialVariableId::NONE)
|
|
|
- {
|
|
|
- ANKI_LOGE("Builtins cannot have value %s", &inpvar.m_name[0]);
|
|
|
- return ErrorCode::USER_DATA;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
+ if(in.m_flags.m_builtin)
|
|
|
{
|
|
|
- if(inpvar.m_builtin == BuiltinMaterialVariableId::NONE)
|
|
|
+ if(getBuiltinType(in.m_builtin) != in.m_type)
|
|
|
{
|
|
|
- ANKI_LOGE("Non-builtins should have a value %s",
|
|
|
- &inpvar.m_name[0]);
|
|
|
+ ANKI_LOGE("Builtin variable %s cannot be of type %s",
|
|
|
+ &in.m_name[0], &cstr[0]);
|
|
|
return ErrorCode::USER_DATA;
|
|
|
}
|
|
|
}
|
|
|
@@ -479,18 +565,43 @@ Error MaterialLoader::parseInputsTag(const XmlElement& programEl)
|
|
|
{
|
|
|
I64 tmp;
|
|
|
ANKI_CHECK(el.getI64(tmp));
|
|
|
- inpvar.m_constant = tmp;
|
|
|
+ in.m_flags.m_const = tmp;
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ if(in.m_flags.m_builtin && in.m_flags.m_const)
|
|
|
{
|
|
|
- inpvar.m_constant = false;
|
|
|
+ ANKI_LOGE("Builtins cannot be consts: %s", &in.m_name[0]);
|
|
|
+ return ErrorCode::USER_DATA;
|
|
|
}
|
|
|
|
|
|
- if(inpvar.m_builtin != BuiltinMaterialVariableId::NONE
|
|
|
- && inpvar.m_constant)
|
|
|
+ // <value>
|
|
|
+ ANKI_CHECK(inputEl.getChildElementOptional("value", el));
|
|
|
+ if(el)
|
|
|
{
|
|
|
- ANKI_LOGE("Builtins cannot be consts %s", &inpvar.m_name[0]);
|
|
|
- return ErrorCode::USER_DATA;
|
|
|
+ ANKI_CHECK(el.getText(cstr));
|
|
|
+
|
|
|
+ if(in.m_flags.m_builtin)
|
|
|
+ {
|
|
|
+ ANKI_LOGE("Builtins cannot have value: %s", &in.m_name[0]);
|
|
|
+ return ErrorCode::USER_DATA;
|
|
|
+ }
|
|
|
+
|
|
|
+ in.m_value.splitString(m_alloc, cstr, ' ');
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if(!in.m_flags.m_builtin)
|
|
|
+ {
|
|
|
+ ANKI_LOGE("Non-builtins should have a value: %s",
|
|
|
+ &in.m_name[0]);
|
|
|
+ return ErrorCode::USER_DATA;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(in.m_flags.m_const)
|
|
|
+ {
|
|
|
+ ANKI_LOGE("Consts should have a value: %s", &in.m_name[0]);
|
|
|
+ return ErrorCode::USER_DATA;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// <inShadow>
|
|
|
@@ -499,19 +610,31 @@ Error MaterialLoader::parseInputsTag(const XmlElement& programEl)
|
|
|
{
|
|
|
I64 tmp;
|
|
|
ANKI_CHECK(el.getI64(tmp));
|
|
|
- inpvar.m_inShadow = tmp;
|
|
|
+ in.m_flags.m_inShadow = tmp;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- inpvar.m_inShadow = true;
|
|
|
+ in.m_flags.m_inShadow = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set some stuff
|
|
|
+ if(in.m_type >= ShaderVariableDataType::SAMPLERS_FIRST
|
|
|
+ && in.m_type <= ShaderVariableDataType::SAMPLERS_LAST)
|
|
|
+ {
|
|
|
+ in.m_flags.m_texture = true;
|
|
|
+ }
|
|
|
+ else if(!in.m_flags.m_const)
|
|
|
+ {
|
|
|
+ in.m_flags.m_inBlock = true;
|
|
|
+ m_uniformBlockReferencedMask |= glshaderbit;
|
|
|
}
|
|
|
|
|
|
// Now you have the info to check if duplicate
|
|
|
Input* duplicateInp = nullptr;
|
|
|
Error err = m_inputs.iterateForward(
|
|
|
- [&duplicateInp, &inpvar](Input& in) -> Error
|
|
|
+ [&duplicateInp, &in](Input& inp) -> Error
|
|
|
{
|
|
|
- if(in.m_name == inpvar.m_name)
|
|
|
+ if(in.m_name == inp.m_name)
|
|
|
{
|
|
|
duplicateInp = ∈
|
|
|
return ErrorCode::NONE;
|
|
|
@@ -524,100 +647,104 @@ Error MaterialLoader::parseInputsTag(const XmlElement& programEl)
|
|
|
if(duplicateInp != nullptr)
|
|
|
{
|
|
|
// Duplicate. Make sure it's the same as the other shader
|
|
|
- Bool same = duplicateInp->duplicate(inpvar);
|
|
|
+ Bool same = duplicateInp->duplicate(in);
|
|
|
|
|
|
if(!same)
|
|
|
{
|
|
|
ANKI_LOGE("Variable defined differently between "
|
|
|
- "shaders: %s", &inpvar.m_name[0]);
|
|
|
+ "shaders: %s", &in.m_name[0]);
|
|
|
return ErrorCode::USER_DATA;
|
|
|
}
|
|
|
|
|
|
duplicateInp->m_shaderDefinedMask |= glshaderbit;
|
|
|
|
|
|
- if(duplicateInp->m_inBlock)
|
|
|
+ if(duplicateInp->m_flags.m_inBlock)
|
|
|
{
|
|
|
m_uniformBlockReferencedMask |= glshaderbit;
|
|
|
}
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ in.m_shaderDefinedMask = glshaderbit;
|
|
|
|
|
|
- goto advance;
|
|
|
+ m_inputs.emplaceBack(m_alloc);
|
|
|
+ m_inputs.getBack().move(in);
|
|
|
}
|
|
|
|
|
|
- if(!inpvar.m_constant)
|
|
|
+ // Advance
|
|
|
+ ANKI_CHECK(inputEl.getNextSiblingElement("input", inputEl));
|
|
|
+ } while(inputEl);
|
|
|
+
|
|
|
+ return ErrorCode::NONE;
|
|
|
+}
|
|
|
+
|
|
|
+//==============================================================================
|
|
|
+void MaterialLoader::processInputs()
|
|
|
+{
|
|
|
+ // Sort the variables to decrease the change of creating unique shaders
|
|
|
+ m_inputs.sort([](const Input& a, const Input& b)
|
|
|
+ {
|
|
|
+ return a.m_name < b.m_name;
|
|
|
+ });
|
|
|
+
|
|
|
+ for(auto& in : m_inputs)
|
|
|
+ {
|
|
|
+ if(!in.m_flags.m_const)
|
|
|
{
|
|
|
// Handle NON-consts
|
|
|
|
|
|
- if(inpvar.m_type >= ShaderVariableDataType::SAMPLERS_FIRST
|
|
|
- && inpvar.m_type <= ShaderVariableDataType::SAMPLERS_LAST)
|
|
|
+ if(in.m_flags.m_texture)
|
|
|
{
|
|
|
// Not in block
|
|
|
|
|
|
- inpvar.m_inBlock = false;
|
|
|
- inpvar.m_binding = m_texBinding++;
|
|
|
+ if(!in.m_flags.m_specialBuiltin)
|
|
|
+ {
|
|
|
+ in.m_binding = m_texBinding++;
|
|
|
|
|
|
- inpvar.m_line.sprintf(
|
|
|
- m_alloc, "layout(TEX_BINDING(0, %u)) uniform tex%u",
|
|
|
- inpvar.m_binding, inpvar.m_binding);
|
|
|
+ in.m_line.sprintf(
|
|
|
+ m_alloc, "layout(TEX_BINDING(0, %u)) uniform tex%u",
|
|
|
+ in.m_binding, in.m_binding);
|
|
|
+ }
|
|
|
}
|
|
|
- else
|
|
|
+ else if(in.m_flags.m_inBlock)
|
|
|
{
|
|
|
// In block
|
|
|
|
|
|
- inpvar.m_inBlock = true;
|
|
|
- inpvar.m_index = m_nextIndex++;
|
|
|
- m_uniformBlockReferencedMask |= glshaderbit;
|
|
|
+ in.m_index = m_nextIndex++;
|
|
|
|
|
|
- inpvar.m_line.sprintf(m_alloc,
|
|
|
+ in.m_line.sprintf(m_alloc,
|
|
|
"#if %s\n"
|
|
|
- "%s var%u %s\n;"
|
|
|
+ "%s var%u%s;\n"
|
|
|
"#endif",
|
|
|
- inpvar.m_inShadow ? "SHADOW" : "1",
|
|
|
- &inpvar.m_typeStr[0],
|
|
|
- inpvar.m_index,
|
|
|
- inpvar.m_instanced ? "[INSTANCE_COUNT]" : " ");
|
|
|
-
|
|
|
- String tmp;
|
|
|
- tmp.create(m_alloc, inpvar.m_line);
|
|
|
- m_uniformBlock.emplaceBack(m_alloc, std::move(tmp));
|
|
|
+ !in.m_flags.m_inShadow ? "PASS == COLOR" : "1",
|
|
|
+ &in.typeStr()[0],
|
|
|
+ in.m_index,
|
|
|
+ in.m_flags.m_instanced ? " INSTANCED" : "");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ANKI_ASSERT(0);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// Handle consts
|
|
|
|
|
|
- if(inpvar.m_value.isEmpty())
|
|
|
- {
|
|
|
- ANKI_LOGE("Empty value and const is illogical");
|
|
|
- return ErrorCode::USER_DATA;
|
|
|
- }
|
|
|
-
|
|
|
- inpvar.m_inBlock = false;
|
|
|
- inpvar.m_index = m_nextIndex++;
|
|
|
+ in.m_index = m_nextIndex++;
|
|
|
|
|
|
String initList;
|
|
|
- inpvar.m_value.join(m_alloc, ", ", initList);
|
|
|
+ in.m_value.join(m_alloc, ", ", initList);
|
|
|
|
|
|
- inpvar.m_line.sprintf(m_alloc,
|
|
|
+ in.m_line.sprintf(m_alloc,
|
|
|
"const %s var%u = %s(%s);",
|
|
|
- &inpvar.m_typeStr[0],
|
|
|
- &inpvar.m_index,
|
|
|
- &inpvar.m_typeStr[0],
|
|
|
+ &in.typeStr()[0],
|
|
|
+ in.m_index,
|
|
|
+ &in.typeStr()[0],
|
|
|
&initList[0]);
|
|
|
|
|
|
initList.destroy(m_alloc);
|
|
|
}
|
|
|
-
|
|
|
- inpvar.m_shaderDefinedMask = glshaderbit;
|
|
|
-
|
|
|
- m_inputs.emplaceBack(m_alloc);
|
|
|
- m_inputs.getBack().move(inpvar);
|
|
|
-
|
|
|
-advance:
|
|
|
- // Advance
|
|
|
- ANKI_CHECK(inputEl.getNextSiblingElement("input", inputEl));
|
|
|
- } while(inputEl);
|
|
|
-
|
|
|
- return ErrorCode::NONE;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
@@ -635,22 +762,22 @@ Error MaterialLoader::parseOperationTag(
|
|
|
CString funcName;
|
|
|
StringListAuto argsList(m_alloc);
|
|
|
|
|
|
- // <id></id>
|
|
|
+ // <id>
|
|
|
I64 id;
|
|
|
ANKI_CHECK(operationTag.getChildElement("id", el));
|
|
|
ANKI_CHECK(el.getI64(id));
|
|
|
|
|
|
- // <returnType></returnType>
|
|
|
+ // <returnType>
|
|
|
XmlElement retTypeEl;
|
|
|
ANKI_CHECK(operationTag.getChildElement("returnType", retTypeEl));
|
|
|
ANKI_CHECK(retTypeEl.getText(cstr));
|
|
|
Bool retTypeVoid = cstr == "void";
|
|
|
|
|
|
- // <function>functionName</function>
|
|
|
+ // <function>
|
|
|
ANKI_CHECK(operationTag.getChildElement("function", el));
|
|
|
ANKI_CHECK(el.getText(funcName));
|
|
|
|
|
|
- // <arguments></arguments>
|
|
|
+ // <arguments>
|
|
|
XmlElement argsEl;
|
|
|
ANKI_CHECK(operationTag.getChildElementOptional("arguments", argsEl));
|
|
|
|
|
|
@@ -681,7 +808,7 @@ Error MaterialLoader::parseOperationTag(
|
|
|
// The argument should be an input variable or an outXX or global
|
|
|
if(input == nullptr)
|
|
|
{
|
|
|
- if(arg.find(OUT) != 0 && arg.find("anki_") != 0)
|
|
|
+ if(arg.find(OUT) != 0)
|
|
|
{
|
|
|
ANKI_LOGE("Incorrect argument: %s", &arg[0]);
|
|
|
return ErrorCode::USER_DATA;
|
|
|
@@ -689,31 +816,24 @@ Error MaterialLoader::parseOperationTag(
|
|
|
}
|
|
|
|
|
|
// Add to a list and do something special if instanced
|
|
|
- if(input && input->m_instanced)
|
|
|
+ if(input)
|
|
|
{
|
|
|
- ANKI_CHECK(argEl.getText(cstr));
|
|
|
-
|
|
|
- if(glshader == ShaderType::VERTEX
|
|
|
- || glshader == ShaderType::FRAGMENT)
|
|
|
+ if(!input->m_flags.m_specialBuiltin)
|
|
|
{
|
|
|
argsList.pushBackSprintf(
|
|
|
- "%s%u\n"
|
|
|
- "#if INSTANCE_COUNT > 1\n"
|
|
|
- "[%s]\n"
|
|
|
- "#endif",
|
|
|
- input->m_binding >= 0 ? "tex" : "var",
|
|
|
- input->m_binding >= 0
|
|
|
- ? input->m_binding : input->m_index,
|
|
|
- (glshader == ShaderType::VERTEX)
|
|
|
- ? "gl_InstanceID" : "vInstanceId");
|
|
|
-
|
|
|
- m_instanceIdMask |= glshaderbit;
|
|
|
+ "%s%d%s",
|
|
|
+ input->m_flags.m_texture ? "tex" : "var",
|
|
|
+ !input->m_flags.m_texture
|
|
|
+ ? input->m_index : input->m_binding,
|
|
|
+ input->m_flags.m_instanced ? " INSTANCE_ID" : "");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- ANKI_LOGE("Cannot access the instance ID in all shaders");
|
|
|
- return ErrorCode::USER_DATA;
|
|
|
+ ANKI_CHECK(argEl.getText(cstr));
|
|
|
+ argsList.pushBackSprintf(&cstr[0]);
|
|
|
}
|
|
|
+
|
|
|
+ m_instanceIdMask |= glshaderbit;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -744,12 +864,8 @@ Error MaterialLoader::parseOperationTag(
|
|
|
{
|
|
|
ANKI_CHECK(retTypeEl.getText(cstr));
|
|
|
lines.pushBackSprintf(
|
|
|
- "#\tdefine out%u_DEFINED\n"
|
|
|
- "\t%s out%u = ", id, &cstr[0], id);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- lines.pushBackSprintf("\t");
|
|
|
+ "#define out%u_DEFINED\n"
|
|
|
+ "%s out%u = ", id, &cstr[0], id);
|
|
|
}
|
|
|
|
|
|
// write the "func(args...)" of "blah = func(args...)"
|
|
|
@@ -765,7 +881,7 @@ Error MaterialLoader::parseOperationTag(
|
|
|
(argsStr.isEmpty()) ? "" : &argsStr[0]);
|
|
|
|
|
|
// Bake final string
|
|
|
- lines.join(m_alloc, " ", out);
|
|
|
+ lines.join(m_alloc, "", out);
|
|
|
|
|
|
return ErrorCode::NONE;
|
|
|
}
|
|
|
@@ -791,88 +907,88 @@ void MaterialLoader::mutate(const RenderingKey& key)
|
|
|
|
|
|
// Compute the block info for each var
|
|
|
m_blockSize = 0;
|
|
|
- for(Input& inpvar : m_inputs)
|
|
|
+ for(Input& in : m_inputs)
|
|
|
{
|
|
|
// Invalidate the var's block info
|
|
|
- inpvar.m_blockInfo = ShaderVariableBlockInfo();
|
|
|
+ in.m_blockInfo = ShaderVariableBlockInfo();
|
|
|
|
|
|
- if(!inpvar.m_inBlock)
|
|
|
+ if(!in.m_flags.m_inBlock)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- if(pass == Pass::SM && !inpvar.m_inShadow)
|
|
|
+ if(pass == Pass::SM && !in.m_flags.m_inShadow)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
// std140 rules
|
|
|
- inpvar.m_blockInfo.m_offset = m_blockSize;
|
|
|
- inpvar.m_blockInfo.m_arraySize = inpvar.m_instanced ? instanceCount : 1;
|
|
|
+ in.m_blockInfo.m_offset = m_blockSize;
|
|
|
+ in.m_blockInfo.m_arraySize = in.m_flags.m_instanced ? instanceCount : 1;
|
|
|
|
|
|
- if(inpvar.m_type == ShaderVariableDataType::FLOAT)
|
|
|
+ if(in.m_type == ShaderVariableDataType::FLOAT)
|
|
|
{
|
|
|
- inpvar.m_blockInfo.m_arrayStride = sizeof(Vec4);
|
|
|
+ in.m_blockInfo.m_arrayStride = sizeof(Vec4);
|
|
|
|
|
|
- if(inpvar.m_blockInfo.m_arraySize == 1)
|
|
|
+ if(in.m_blockInfo.m_arraySize == 1)
|
|
|
{
|
|
|
- // No need to align the inpvar.m_offset
|
|
|
+ // No need to align the in.m_offset
|
|
|
m_blockSize += sizeof(F32);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- alignRoundUp(sizeof(Vec4), inpvar.m_blockInfo.m_offset);
|
|
|
- m_blockSize += sizeof(Vec4) * inpvar.m_blockInfo.m_arraySize;
|
|
|
+ alignRoundUp(sizeof(Vec4), in.m_blockInfo.m_offset);
|
|
|
+ m_blockSize += sizeof(Vec4) * in.m_blockInfo.m_arraySize;
|
|
|
}
|
|
|
}
|
|
|
- else if(inpvar.m_type == ShaderVariableDataType::VEC2)
|
|
|
+ else if(in.m_type == ShaderVariableDataType::VEC2)
|
|
|
{
|
|
|
- inpvar.m_blockInfo.m_arrayStride = sizeof(Vec4);
|
|
|
+ in.m_blockInfo.m_arrayStride = sizeof(Vec4);
|
|
|
|
|
|
- if(inpvar.m_blockInfo.m_arraySize == 1)
|
|
|
+ if(in.m_blockInfo.m_arraySize == 1)
|
|
|
{
|
|
|
- alignRoundUp(sizeof(Vec2), inpvar.m_blockInfo.m_offset);
|
|
|
+ alignRoundUp(sizeof(Vec2), in.m_blockInfo.m_offset);
|
|
|
m_blockSize += sizeof(Vec2);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- alignRoundUp(sizeof(Vec4), inpvar.m_blockInfo.m_offset);
|
|
|
- m_blockSize += sizeof(Vec4) * inpvar.m_blockInfo.m_arraySize;
|
|
|
+ alignRoundUp(sizeof(Vec4), in.m_blockInfo.m_offset);
|
|
|
+ m_blockSize += sizeof(Vec4) * in.m_blockInfo.m_arraySize;
|
|
|
}
|
|
|
}
|
|
|
- else if(inpvar.m_type == ShaderVariableDataType::VEC3)
|
|
|
+ else if(in.m_type == ShaderVariableDataType::VEC3)
|
|
|
{
|
|
|
- alignRoundUp(sizeof(Vec4), inpvar.m_blockInfo.m_offset);
|
|
|
- inpvar.m_blockInfo.m_arrayStride = sizeof(Vec4);
|
|
|
+ alignRoundUp(sizeof(Vec4), in.m_blockInfo.m_offset);
|
|
|
+ in.m_blockInfo.m_arrayStride = sizeof(Vec4);
|
|
|
|
|
|
- if(inpvar.m_blockInfo.m_arraySize == 1)
|
|
|
+ if(in.m_blockInfo.m_arraySize == 1)
|
|
|
{
|
|
|
m_blockSize += sizeof(Vec3);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- m_blockSize += sizeof(Vec4) * inpvar.m_blockInfo.m_arraySize;
|
|
|
+ m_blockSize += sizeof(Vec4) * in.m_blockInfo.m_arraySize;
|
|
|
}
|
|
|
}
|
|
|
- else if(inpvar.m_type == ShaderVariableDataType::VEC4)
|
|
|
+ else if(in.m_type == ShaderVariableDataType::VEC4)
|
|
|
{
|
|
|
- inpvar.m_blockInfo.m_arrayStride = sizeof(Vec4);
|
|
|
- alignRoundUp(sizeof(Vec4), inpvar.m_blockInfo.m_offset);
|
|
|
- m_blockSize += sizeof(Vec4) * inpvar.m_blockInfo.m_arraySize;
|
|
|
+ in.m_blockInfo.m_arrayStride = sizeof(Vec4);
|
|
|
+ alignRoundUp(sizeof(Vec4), in.m_blockInfo.m_offset);
|
|
|
+ m_blockSize += sizeof(Vec4) * in.m_blockInfo.m_arraySize;
|
|
|
}
|
|
|
- else if(inpvar.m_type == ShaderVariableDataType::MAT3)
|
|
|
+ else if(in.m_type == ShaderVariableDataType::MAT3)
|
|
|
{
|
|
|
- alignRoundUp(sizeof(Vec4), inpvar.m_blockInfo.m_offset);
|
|
|
- inpvar.m_blockInfo.m_arrayStride = sizeof(Vec4) * 3;
|
|
|
- m_blockSize += sizeof(Vec4) * 3 * inpvar.m_blockInfo.m_arraySize;
|
|
|
- inpvar.m_blockInfo.m_matrixStride = sizeof(Vec4);
|
|
|
+ alignRoundUp(sizeof(Vec4), in.m_blockInfo.m_offset);
|
|
|
+ in.m_blockInfo.m_arrayStride = sizeof(Vec4) * 3;
|
|
|
+ m_blockSize += sizeof(Vec4) * 3 * in.m_blockInfo.m_arraySize;
|
|
|
+ in.m_blockInfo.m_matrixStride = sizeof(Vec4);
|
|
|
}
|
|
|
- else if(inpvar.m_type == ShaderVariableDataType::MAT4)
|
|
|
+ else if(in.m_type == ShaderVariableDataType::MAT4)
|
|
|
{
|
|
|
- alignRoundUp(sizeof(Vec4), inpvar.m_blockInfo.m_offset);
|
|
|
- inpvar.m_blockInfo.m_arrayStride = sizeof(Mat4);
|
|
|
- m_blockSize += sizeof(Mat4) * inpvar.m_blockInfo.m_arraySize;
|
|
|
- inpvar.m_blockInfo.m_matrixStride = sizeof(Vec4);
|
|
|
+ alignRoundUp(sizeof(Vec4), in.m_blockInfo.m_offset);
|
|
|
+ in.m_blockInfo.m_arrayStride = sizeof(Mat4);
|
|
|
+ m_blockSize += sizeof(Mat4) * in.m_blockInfo.m_arraySize;
|
|
|
+ in.m_blockInfo.m_matrixStride = sizeof(Vec4);
|
|
|
}
|
|
|
else
|
|
|
{
|