mCustomUniforms = customUniforms;
}
+ constexpr std::pair<uint32_t, uint32_t> GetUniformBufferArrayStrideAndTypeSize(TestGraphicsReflection::TestUniformInfo& uniformInfo, uint32_t requestedStride)
+ {
+ uint32_t dataTypeSize = 0;
+ uint32_t elementStride = 0;
+ switch(uniformInfo.type)
+ {
+ case Property::FLOAT:
+ case Property::INTEGER:
+ case Property::BOOLEAN:
+ {
+ dataTypeSize = sizeof(float);
+ break;
+ }
+ case Property::MATRIX:
+ {
+ dataTypeSize = sizeof(float) * 16;
+ break;
+ }
+ case Property::MATRIX3:
+ {
+ dataTypeSize = sizeof(float) * 9;
+ break;
+ }
+ case Property::VECTOR2:
+ {
+ dataTypeSize = sizeof(float) * 2;
+ break;
+ }
+ case Property::VECTOR3:
+ {
+ dataTypeSize = sizeof(float) * 3;
+ break;
+ }
+ case Property::VECTOR4:
+ {
+ dataTypeSize = sizeof(float) * 4;
+ break;
+ }
+ default:
+ {
+ }
+ }
+ if(uniformInfo.elementStride)
+ {
+ bool roundUp = (dataTypeSize % uniformInfo.elementStride);
+ elementStride = (dataTypeSize / uniformInfo.elementStride) * uniformInfo.elementStride + (roundUp ? uniformInfo.elementStride : 0);
+ }
+ return std::make_pair(dataTypeSize, elementStride);
+ }
+
+ void AddMemberToUniformBlock(TestGraphicsReflection::TestUniformBlockInfo& blockInfo,
+ std::string name,
+ Property::Type type,
+ uint32_t elementCount,
+ uint32_t elementStrideInBytes)
+ {
+ TestGraphicsReflection::TestUniformInfo info;
+ info.name = std::move(name);
+ info.type = type;
+ info.uniformClass = Graphics::UniformClass::UNIFORM;
+ info.numElements = elementCount;
+ info.locations = {0};
+ info.bufferIndex = 0; // this will update when AddCustomUniformBlock called
+
+ auto retval= GetUniformBufferArrayStrideAndTypeSize(info, elementStrideInBytes);
+ info.elementStride = std::max(retval.first, retval.second);
+ info.offsets = {blockInfo.size};
+ blockInfo.size += (elementCount == 0 ? 1 : elementCount) * std::max(retval.first, retval.second);
+ blockInfo.members.emplace_back(info);
+ }
+
void AddCustomUniformBlock(const TestGraphicsReflection::TestUniformBlockInfo& blockInfo)
{
mCustomUniformBlocks.push_back(blockInfo);
+ auto& info = mCustomUniformBlocks.back();
+ for(auto& member : info.members)
+ {
+ member.bufferIndex = mCustomUniformBlocks.size();
+ }
}
void ClearSubmitStack()
const int MAX_BONE_COUNT{300};
const int skinningBlockSize = MAX_BONE_COUNT * sizeof(Matrix);
- graphics.AddCustomUniformBlock(TestGraphicsReflection::TestUniformBlockInfo{"Skinning Block", 0, 0, skinningBlockSize, {{"uBone", Graphics::UniformClass::UNIFORM, 0, 0, {0}, {1}, MAX_BONE_COUNT, Property::Type::MATRIX}}});
+ graphics.AddCustomUniformBlock(TestGraphicsReflection::TestUniformBlockInfo{
+ "Skinning Block", 0, 0,
+ skinningBlockSize,
+ {{"uBone", Graphics::UniformClass::UNIFORM, 0, 0, {0}, {1}, MAX_BONE_COUNT, Property::Type::MATRIX}}});
const int MAX_MORPH_COUNT{128};
const int morphBlockSize = MAX_MORPH_COUNT * sizeof(float) + sizeof(float);
END_TEST;
}
+int UtcDaliRendererUniformBlocksWithStride(void)
+{
+ setenv("LOG_UNIFORM_BUFFER", "5f", 1); // Turns on buffer logging
+ TestApplication application;
+
+ tet_infoline("Test that repeated update/render cycles write into alternative buffers");
+ auto& graphics = application.GetGraphicsController();
+ auto& gl = application.GetGlAbstraction();
+ gl.mBufferTrace.EnableLogging(true);
+
+ const uint32_t UNIFORM_BLOCK_ALIGNMENT(512);
+ gl.SetUniformBufferOffsetAlignment(UNIFORM_BLOCK_ALIGNMENT);
+
+ const int MAX_BONE_COUNT{300};
+ TestGraphicsReflection::TestUniformBlockInfo skinningBlock;
+ skinningBlock.name = "SkinningBlock";
+ skinningBlock.binding = 0;
+ skinningBlock.descriptorSet = 0;
+ graphics.AddMemberToUniformBlock( skinningBlock, "uBone", Property::Type::MATRIX, MAX_BONE_COUNT, 16 );
+ graphics.AddCustomUniformBlock(skinningBlock);
+ const int skinningBlockSize = int(skinningBlock.size);
+
+ const int MAX_MORPH_COUNT{128};
+ TestGraphicsReflection::TestUniformBlockInfo morphBlock;
+ morphBlock.name = "MorphBlock";
+ morphBlock.binding = 1;
+ morphBlock.descriptorSet = 0;
+ graphics.AddMemberToUniformBlock( morphBlock, "uNumberOfBlendShapes", Property::Type::FLOAT, 0, 0 );
+ graphics.AddMemberToUniformBlock( morphBlock, "uBlendShapeWeight", Property::Type::FLOAT, MAX_MORPH_COUNT, 16 );
+ graphics.AddCustomUniformBlock(morphBlock);
+
+ Actor actor = CreateActor(application.GetScene().GetRootLayer(), 0, TEST_LOCATION);
+ Shader shader = CreateShader(); // Don't care about src content
+ Geometry geometry = CreateQuadGeometry();
+ Renderer renderer = CreateRenderer(actor, geometry, shader, 0);
+ Matrix m, n;
+ m.SetIdentity();
+ n.SetIdentity();
+ n.SetTransformComponents(Vector3(2.f, 2.f, 2.f), Quaternion(Radian(0.3f), Vector3::YAXIS), Vector3(200.0f, 1.0f, 20.0f));
+
+ CreateRendererProperties(renderer, m, n);
+ float w1 = 0.01f;
+ float w2 = 0.5f;
+ float w3 = 0.79f;
+ renderer["uBlendShapeWeight[0]"] = w1;
+ renderer["uBlendShapeWeight[55]"] = w2;
+ renderer["uBlendShapeWeight[127]"] = w3;
+
+ TraceCallStack& graphicsTrace = graphics.mCallStack;
+ TraceCallStack& cmdTrace = graphics.mCommandBufferCallStack;
+ graphicsTrace.EnableLogging(true);
+ cmdTrace.EnableLogging(true);
+
+ application.SendNotification();
+ application.Render();
+
+ // We expect 1 vertex buffer, 1 index buffer and 1 uniform buffer (representing 2 blocks)
+ DALI_TEST_EQUALS(cmdTrace.CountMethod("BindUniformBuffers"), 1, TEST_LOCATION);
+
+ const uint32_t MORPH_BLOCK_OFFSET = (skinningBlockSize % UNIFORM_BLOCK_ALIGNMENT == 0) ? skinningBlockSize : ((skinningBlockSize / UNIFORM_BLOCK_ALIGNMENT) + 1) * UNIFORM_BLOCK_ALIGNMENT;
+
+ for(int i = 0; i < 50; ++i)
+ {
+ tet_infoline("\nTest that uBone[299] is written correctly");
+ TestGraphicsBuffer* bufferPtr = FindUniformBuffer(i % 2, graphics);
+ DALI_TEST_CHECK(graphics.mAllocatedBuffers.size() == (i == 0 ? 4 : 5));
+ DALI_TEST_CHECK(bufferPtr != nullptr);
+ auto offset0 = sizeof(Dali::Matrix) * 299;
+ Matrix* mPtr = reinterpret_cast<Dali::Matrix*>(&bufferPtr->memory[0] + offset0);
+ DALI_TEST_EQUALS(*mPtr, n, 0.0001, TEST_LOCATION);
+
+ const auto size = morphBlock.members[1].elementStride;
+ const auto memberOffset = morphBlock.members[1].offsets[0];
+ float* wPtr1 = reinterpret_cast<float*>(&bufferPtr->memory[MORPH_BLOCK_OFFSET] + memberOffset + size * 0);
+ float* wPtr2 = reinterpret_cast<float*>(&bufferPtr->memory[MORPH_BLOCK_OFFSET] + memberOffset + size * 55);
+ float* wPtr3 = reinterpret_cast<float*>(&bufferPtr->memory[MORPH_BLOCK_OFFSET] + memberOffset + size * 127);
+
+ tet_printf("Test that uBlendShapeWeight[0] is written correctly as %4.2f\n", w1);
+ tet_printf("Test that uBlendShapeWeight[55] is written correctly as %4.2f\n", w2);
+ tet_printf("Test that uBlendShapeWeight[127] is written correctly as %4.2f\n", w3);
+
+ DALI_TEST_EQUALS(*wPtr1, w1, 0.0001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(*wPtr2, w2, 0.0001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(*wPtr3, w3, 0.0001f, TEST_LOCATION);
+
+ n.SetTransformComponents(Vector3(2.f, 2.f, 2.f), Quaternion(Radian(i * 0.3f), Vector3::YAXIS), Vector3(200.0f + i * 10.0f, -i, 20.0f));
+ renderer["uBone[299]"] = n;
+
+ w1 += 0.005f;
+ w2 += 0.005f;
+ w3 -= 0.01f;
+ renderer["uBlendShapeWeight[0]"] = w1;
+ renderer["uBlendShapeWeight[55]"] = w2;
+ renderer["uBlendShapeWeight[127]"] = w3;
+
+ application.SendNotification();
+ application.Render();
+ }
+
+ END_TEST;
+}
+
int AlignSize(int size, int align)
{
return (size % align == 0) ? size : ((size / align) + 1) * align;