/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
{
static const std::vector<UniformData> UNIFORMS =
{
+ UniformData("uColor", Property::Type::VECTOR4),
UniformData("uRendererColor", Property::Type::FLOAT),
UniformData("uCustom", Property::Type::INTEGER),
UniformData("uCustom3", Property::Type::VECTOR3),
UniformData("sTexture", Property::Type::FLOAT),
UniformData("sTextureRect", Property::Type::FLOAT),
UniformData("sGloss", Property::Type::FLOAT),
- UniformData("uColor", Property::Type::VECTOR4),
UniformData("uActorColor", Property::Type::VECTOR4),
UniformData("uModelMatrix", Property::Type::MATRIX),
UniformData("uModelView", Property::Type::MATRIX),
mDefaultUniformBlock.members.clear();
int offset = 0;
- for(const auto& data : UNIFORMS)
- {
- mDefaultUniformBlock.members.emplace_back();
- auto& item = mDefaultUniformBlock.members.back();
- item.name = data.name;
- item.binding = 0;
- item.offsets.push_back(offset);
- item.locations.push_back(gl.GetUniformLocation(programId, data.name.c_str()));
- item.bufferIndex = 0;
- item.uniformClass = Graphics::UniformClass::UNIFORM;
- item.type = data.type;
- offset += GetSizeForType(data.type);
- }
for(const auto& data : mCustomUniforms)
{
offset += GetSizeForType(data.type);
}
}
+
+ for(const auto& data : UNIFORMS)
+ {
+ mDefaultUniformBlock.members.emplace_back();
+ auto& item = mDefaultUniformBlock.members.back();
+ item.name = data.name;
+ item.binding = 0;
+ item.offsets.push_back(offset);
+ item.locations.push_back(gl.GetUniformLocation(programId, data.name.c_str()));
+ item.bufferIndex = 0;
+ item.uniformClass = Graphics::UniformClass::UNIFORM;
+ item.type = data.type;
+ offset += GetSizeForType(data.type);
+ }
+
mDefaultUniformBlock.size = offset;
mUniformBlocks.push_back(mDefaultUniformBlock);
out.members[i].uniformClass = Graphics::UniformClass::UNIFORM;
out.members[i].offset = memberUniform.offsets[0];
out.members[i].location = memberUniform.locations[0];
+ out.members[i].elementCount = memberUniform.numElements;
}
return true;
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
END_TEST;
}
+
+int UtcDaliRendererUniformNameCrop(void)
+{
+ TestApplication application;
+ tet_infoline("Tests against reflection cropping one character too many form array uniform name.\n");
+
+ auto& graphics = application.GetGraphicsController();
+
+ auto uniforms = std::vector<UniformData>{
+ {"uSomeColor", Dali::Property::Type::FLOAT},
+ {"uSomeColors[10]", Dali::Property::Type::FLOAT}};
+ graphics.AddCustomUniforms(uniforms);
+
+ auto& gl = application.GetGlAbstraction();
+ graphics.mCallStack.EnableLogging(true);
+ graphics.mCommandBufferCallStack.EnableLogging(true);
+ gl.mBufferTrace.EnableLogging(true);
+ gl.mBufferTrace.Enable(true);
+
+ gl.mSetUniformTrace.EnableLogging(true);
+ gl.mSetUniformTrace.Enable(true);
+
+ Geometry geometry = CreateQuadGeometry();
+ Shader shader = Shader::New("vertexSrc", "fragmentSrc");
+ Renderer renderer = Renderer::New(geometry, shader);
+ Actor actor = Actor::New();
+ actor.AddRenderer(renderer);
+ actor[Actor::Property::SIZE] = Vector2(120, 120);
+ application.GetScene().Add(actor);
+
+ std::ostringstream oss;
+ struct UniformIndexPair
+ {
+ Property::Index index;
+ std::string name;
+ UniformIndexPair(Property::Index index, std::string name)
+ : index(index),
+ name(std::move(name))
+ {
+ }
+ };
+ std::vector<UniformIndexPair> uniformIndices;
+ for(int i = 0; i < 10; ++i)
+ {
+ Property::Index index;
+ oss << "uArray[" << i + 1 << "]";
+ auto value = float(i);
+ index = renderer.RegisterProperty(oss.str(), value);
+ uniformIndices.emplace_back(index, oss.str());
+ oss.str("");
+ oss.clear();
+ }
+
+ // Cause overwrite, index 10 and uToOverflow should share same memory
+ [[maybe_unused]] auto badArrayIndex = renderer.RegisterProperty("uSomeColor", 100.0f);
+ [[maybe_unused]] auto badArrayIndex2 = renderer.RegisterProperty("uSomeColors[0]", 200.0f);
+
+ application.GetScene().Add(actor);
+ application.SendNotification();
+ application.Render(0);
+
+ float value = 0.0f;
+ gl.GetUniformValue("uSomeColor", value);
+
+ // Test against the bug when name is one character short and array may be mistaken for
+ // an individual uniform of the same name minut 1 character.
+ DALI_TEST_EQUALS(value, 100.0f, std::numeric_limits<float>::epsilon(), TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliRendererUniformArrayOverflow(void)
+{
+ TestApplication application;
+ tet_infoline("Overflow test whether uColor uniform would be overriden by array with out-of-bound index.\n");
+
+ auto& graphics = application.GetGraphicsController();
+ auto uniforms = std::vector<UniformData>{{"uArray[10]", Dali::Property::Type::FLOAT}};
+
+ graphics.AddCustomUniforms(uniforms);
+
+ auto& gl = application.GetGlAbstraction();
+ graphics.mCallStack.EnableLogging(true);
+ graphics.mCommandBufferCallStack.EnableLogging(true);
+ gl.mBufferTrace.EnableLogging(true);
+ gl.mBufferTrace.Enable(true);
+
+ gl.mSetUniformTrace.EnableLogging(true);
+ gl.mSetUniformTrace.Enable(true);
+
+ Geometry geometry = CreateQuadGeometry();
+ Shader shader = Shader::New("vertexSrc", "fragmentSrc");
+ Renderer renderer = Renderer::New(geometry, shader);
+ Actor actor = Actor::New();
+ actor.AddRenderer(renderer);
+ actor[Actor::Property::SIZE] = Vector2(120, 120);
+ application.GetScene().Add(actor);
+
+ std::ostringstream oss;
+ struct UniformIndexPair
+ {
+ Property::Index index;
+ std::string name;
+ UniformIndexPair(Property::Index index, std::string name)
+ : index(index),
+ name(std::move(name))
+ {
+ }
+ };
+ std::vector<UniformIndexPair> uniformIndices;
+ for(int i = 0; i < 10; ++i)
+ {
+ Property::Index index;
+ oss << "uArray[" << i << "]";
+ auto value = float(i);
+ index = renderer.RegisterProperty(oss.str(), value);
+ uniformIndices.emplace_back(index, oss.str());
+ oss.str("");
+ oss.clear();
+ }
+
+ // Cause overwrite, index 10 and uToOverflow should share same memory
+ [[maybe_unused]] auto badArrayIndex = renderer.RegisterProperty("uArray[10]", 0.0f);
+
+ application.GetScene().Add(actor);
+ application.SendNotification();
+ application.Render(0);
+
+ Vector4 uniformColor = Vector4::ZERO;
+ gl.GetUniformValue("uColor", uniformColor);
+ tet_printf("uColor value %f, %f, %f, %f\n",
+ uniformColor.r,
+ uniformColor.g,
+ uniformColor.b,
+ uniformColor.a);
+
+ // the r component of uColor uniform must not be changed.
+ // if r is 0.0f then test fails as the array stomped on the uniform's memory.
+ DALI_TEST_EQUALS((uniformColor.r != 0.0f), true, TEST_LOCATION);
+ END_TEST;
+}
\ No newline at end of file
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Hash hash = hashedName;
std::string_view match = name;
+ int arrayIndex = 0;
+
if(!name.empty() && name.back() == ']')
{
- hash = hashedNameNoArray;
- auto pos = name.rfind("[");
- match = name.substr(0, pos - 1); // Remove subscript
+ hash = hashedNameNoArray;
+ auto pos = name.rfind("[");
+ match = name.substr(0, pos); // Remove subscript
+ arrayIndex = atoi(&name[pos + 1]);
}
for(const ReflectionUniformInfo& item : mReflection)
if(!item.hasCollision || item.uniformInfo.name == match)
{
out = item.uniformInfo;
+
+ // Array out of bounds
+ if(item.uniformInfo.elementCount > 0 && arrayIndex >= int(item.uniformInfo.elementCount))
+ {
+ DALI_LOG_ERROR("Uniform %s, array index out of bound [%d >= %d]!\n",
+ item.uniformInfo.name.c_str(),
+ int(arrayIndex),
+ int(item.uniformInfo.elementCount));
+ return false;
+ }
return true;
}
else