#include "renderer/VertexFormat.h" #include "unittest/TestSuite.h" #include "stem_core.h" static void testCreate(void) { VertexFormat * vertexFormat = VertexFormat_create(0, NULL); TestCase_assertPointerNonNULL(vertexFormat); TestCase_assertUIntEqual(vertexFormat->attributeCount, 0); TestCase_assertPointerNULL(vertexFormat->attributeTypes); TestCase_assertUIntEqual(vertexFormat->componentCountTotal, 0); TestCase_assertUIntEqual(vertexFormat->bytesPerVertex, 0); VertexFormat_dispose(vertexFormat); VertexAttributeTypeSpec attributeTypeSpec = {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 3}; vertexFormat = VertexFormat_create(1, &attributeTypeSpec); TestCase_assertPointerNonNULL(vertexFormat); TestCase_assertUIntEqual(vertexFormat->attributeCount, 1); TestCase_assertPointerNonNULL(vertexFormat->attributeTypes); TestCase_assertStringEqual(vertexFormat->attributeTypes[0].name, "position"); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].dataType, ATTRIBUTE_TYPE_FLOAT); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].usageHint, ATTRIBUTE_USAGE_POSITION); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].componentCount, 3); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].byteOffset, 0); TestCase_assertUIntEqual(vertexFormat->componentCountTotal, 3); TestCase_assertUIntEqual(vertexFormat->bytesPerVertex, 12); VertexFormat_dispose(vertexFormat); VertexAttributeTypeSpec attributeTypeSpecs1[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 2}, {"normal", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_NORMAL, 3} }; vertexFormat = VertexFormat_create(sizeof_count(attributeTypeSpecs1), attributeTypeSpecs1); TestCase_assertPointerNonNULL(vertexFormat); TestCase_assertUIntEqual(vertexFormat->attributeCount, 2); TestCase_assertPointerNonNULL(vertexFormat->attributeTypes); TestCase_assertStringEqual(vertexFormat->attributeTypes[0].name, "position"); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].dataType, ATTRIBUTE_TYPE_FLOAT); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].usageHint, ATTRIBUTE_USAGE_POSITION); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].componentCount, 2); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].byteOffset, 0); TestCase_assertStringEqual(vertexFormat->attributeTypes[1].name, "normal"); TestCase_assertIntEqual(vertexFormat->attributeTypes[1].dataType, ATTRIBUTE_TYPE_FLOAT); TestCase_assertIntEqual(vertexFormat->attributeTypes[1].usageHint, ATTRIBUTE_USAGE_NORMAL); TestCase_assertUIntEqual(vertexFormat->attributeTypes[1].componentCount, 3); TestCase_assertUIntEqual(vertexFormat->attributeTypes[1].byteOffset, sizeof(float) * 2); TestCase_assertUIntEqual(vertexFormat->componentCountTotal, 5); TestCase_assertUIntEqual(vertexFormat->bytesPerVertex, 20); VertexFormat_dispose(vertexFormat); VertexAttributeTypeSpec attributeTypeSpecs2[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 3}, {"color", ATTRIBUTE_TYPE_UINT8, ATTRIBUTE_USAGE_COLOR, 4}, {"normal", ATTRIBUTE_TYPE_INT16_NORM, ATTRIBUTE_USAGE_NORMAL, 3} }; vertexFormat = VertexFormat_create(sizeof_count(attributeTypeSpecs2), attributeTypeSpecs2); TestCase_assertPointerNonNULL(vertexFormat); TestCase_assertUIntEqual(vertexFormat->attributeCount, 3); TestCase_assertPointerNonNULL(vertexFormat->attributeTypes); TestCase_assertStringEqual(vertexFormat->attributeTypes[0].name, "position"); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].dataType, ATTRIBUTE_TYPE_FLOAT); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].usageHint, ATTRIBUTE_USAGE_POSITION); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].componentCount, 3); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].byteOffset, 0); TestCase_assertStringEqual(vertexFormat->attributeTypes[1].name, "color"); TestCase_assertIntEqual(vertexFormat->attributeTypes[1].dataType, ATTRIBUTE_TYPE_UINT8); TestCase_assertIntEqual(vertexFormat->attributeTypes[1].usageHint, ATTRIBUTE_USAGE_COLOR); TestCase_assertUIntEqual(vertexFormat->attributeTypes[1].componentCount, 4); TestCase_assertUIntEqual(vertexFormat->attributeTypes[1].byteOffset, 12); TestCase_assertStringEqual(vertexFormat->attributeTypes[2].name, "normal"); TestCase_assertIntEqual(vertexFormat->attributeTypes[2].dataType, ATTRIBUTE_TYPE_INT16_NORM); TestCase_assertIntEqual(vertexFormat->attributeTypes[2].usageHint, ATTRIBUTE_USAGE_NORMAL); TestCase_assertUIntEqual(vertexFormat->attributeTypes[2].componentCount, 3); TestCase_assertUIntEqual(vertexFormat->attributeTypes[2].byteOffset, 16); TestCase_assertUIntEqual(vertexFormat->componentCountTotal, 10); TestCase_assertUIntEqual(vertexFormat->bytesPerVertex, 22); VertexFormat_dispose(vertexFormat); } static void testCopy(void) { VertexFormat * originalVertexFormat = VertexFormat_create(0, NULL); VertexFormat * vertexFormat = VertexFormat_copy(originalVertexFormat); VertexFormat_dispose(originalVertexFormat); TestCase_assertPointerNonNULL(vertexFormat); TestCase_assertUIntEqual(vertexFormat->attributeCount, 0); TestCase_assertPointerNULL(vertexFormat->attributeTypes); TestCase_assertUIntEqual(vertexFormat->componentCountTotal, 0); TestCase_assertUIntEqual(vertexFormat->bytesPerVertex, 0); VertexFormat_dispose(vertexFormat); VertexAttributeTypeSpec attributeTypeSpec = {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 3}; originalVertexFormat = VertexFormat_create(1, &attributeTypeSpec); vertexFormat = VertexFormat_copy(originalVertexFormat); VertexFormat_dispose(originalVertexFormat); TestCase_assertPointerNonNULL(vertexFormat); TestCase_assertUIntEqual(vertexFormat->attributeCount, 1); TestCase_assertPointerNonNULL(vertexFormat->attributeTypes); TestCase_assertStringEqual(vertexFormat->attributeTypes[0].name, "position"); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].dataType, ATTRIBUTE_TYPE_FLOAT); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].usageHint, ATTRIBUTE_USAGE_POSITION); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].componentCount, 3); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].byteOffset, 0); TestCase_assertUIntEqual(vertexFormat->componentCountTotal, 3); TestCase_assertUIntEqual(vertexFormat->bytesPerVertex, 12); VertexFormat_dispose(vertexFormat); VertexAttributeTypeSpec attributeTypeSpecs1[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 2}, {"normal", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_NORMAL, 3} }; originalVertexFormat = VertexFormat_create(sizeof_count(attributeTypeSpecs1), attributeTypeSpecs1); vertexFormat = VertexFormat_copy(originalVertexFormat); VertexFormat_dispose(originalVertexFormat); TestCase_assertPointerNonNULL(vertexFormat); TestCase_assertUIntEqual(vertexFormat->attributeCount, 2); TestCase_assertPointerNonNULL(vertexFormat->attributeTypes); TestCase_assertStringEqual(vertexFormat->attributeTypes[0].name, "position"); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].dataType, ATTRIBUTE_TYPE_FLOAT); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].usageHint, ATTRIBUTE_USAGE_POSITION); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].componentCount, 2); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].byteOffset, 0); TestCase_assertStringEqual(vertexFormat->attributeTypes[1].name, "normal"); TestCase_assertIntEqual(vertexFormat->attributeTypes[1].dataType, ATTRIBUTE_TYPE_FLOAT); TestCase_assertIntEqual(vertexFormat->attributeTypes[1].usageHint, ATTRIBUTE_USAGE_NORMAL); TestCase_assertUIntEqual(vertexFormat->attributeTypes[1].componentCount, 3); TestCase_assertUIntEqual(vertexFormat->attributeTypes[1].byteOffset, sizeof(float) * 2); TestCase_assertUIntEqual(vertexFormat->componentCountTotal, 5); TestCase_assertUIntEqual(vertexFormat->bytesPerVertex, 20); VertexFormat_dispose(vertexFormat); VertexAttributeTypeSpec attributeTypeSpecs2[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 3}, {"color", ATTRIBUTE_TYPE_UINT8, ATTRIBUTE_USAGE_COLOR, 4}, {"normal", ATTRIBUTE_TYPE_INT16_NORM, ATTRIBUTE_USAGE_NORMAL, 3} }; originalVertexFormat = VertexFormat_create(sizeof_count(attributeTypeSpecs2), attributeTypeSpecs2); vertexFormat = VertexFormat_copy(originalVertexFormat); VertexFormat_dispose(originalVertexFormat); TestCase_assertPointerNonNULL(vertexFormat); TestCase_assertUIntEqual(vertexFormat->attributeCount, 3); TestCase_assertPointerNonNULL(vertexFormat->attributeTypes); TestCase_assertStringEqual(vertexFormat->attributeTypes[0].name, "position"); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].dataType, ATTRIBUTE_TYPE_FLOAT); TestCase_assertIntEqual(vertexFormat->attributeTypes[0].usageHint, ATTRIBUTE_USAGE_POSITION); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].componentCount, 3); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].byteOffset, 0); TestCase_assertStringEqual(vertexFormat->attributeTypes[1].name, "color"); TestCase_assertIntEqual(vertexFormat->attributeTypes[1].dataType, ATTRIBUTE_TYPE_UINT8); TestCase_assertIntEqual(vertexFormat->attributeTypes[1].usageHint, ATTRIBUTE_USAGE_COLOR); TestCase_assertUIntEqual(vertexFormat->attributeTypes[1].componentCount, 4); TestCase_assertUIntEqual(vertexFormat->attributeTypes[1].byteOffset, 12); TestCase_assertStringEqual(vertexFormat->attributeTypes[2].name, "normal"); TestCase_assertIntEqual(vertexFormat->attributeTypes[2].dataType, ATTRIBUTE_TYPE_INT16_NORM); TestCase_assertIntEqual(vertexFormat->attributeTypes[2].usageHint, ATTRIBUTE_USAGE_NORMAL); TestCase_assertUIntEqual(vertexFormat->attributeTypes[2].componentCount, 3); TestCase_assertUIntEqual(vertexFormat->attributeTypes[2].byteOffset, 16); TestCase_assertUIntEqual(vertexFormat->componentCountTotal, 10); TestCase_assertUIntEqual(vertexFormat->bytesPerVertex, 22); VertexFormat_dispose(vertexFormat); } void testMatchesSpec(void) { VertexAttributeTypeSpec attributeTypeSpecs1[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 2}, {"normal", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_NORMAL, 3} }; VertexAttributeTypeSpec attributeTypeSpecs2[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 3}, {"normal", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_NORMAL, 3} }; VertexAttributeTypeSpec attributeTypeSpecs3[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 2}, {"normal", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_NORMAL, 4} }; VertexAttributeTypeSpec attributeTypeSpecs4[] = { {"some_other_name_for_position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 2}, {"something_used_as_a_normal", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_NORMAL, 3} }; VertexAttributeTypeSpec attributeTypeSpecs5[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 2}, {"normal", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_NORMAL, 3}, {"color", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_COLOR, 4} }; VertexAttributeTypeSpec attributeTypeSpecs6[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_UNSPECIFIED, 2}, {"normal", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_NORMAL, 3} }; VertexAttributeTypeSpec attributeTypeSpecs7[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 2}, {"normal", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_TEXTURE_COORDINATE, 3} }; VertexAttributeTypeSpec attributeTypeSpecs8[] = { {"position", ATTRIBUTE_TYPE_INT32_NORM, ATTRIBUTE_USAGE_POSITION, 2}, {"normal", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_NORMAL, 3} }; VertexAttributeTypeSpec attributeTypeSpecs9[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 2}, {"normal", ATTRIBUTE_TYPE_UINT32, ATTRIBUTE_USAGE_NORMAL, 3} }; VertexFormat * vertexFormat = VertexFormat_create(sizeof_count(attributeTypeSpecs1), attributeTypeSpecs1); TestCase_assertBoolTrue(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs1), attributeTypeSpecs1)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, 1, attributeTypeSpecs1)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs2), attributeTypeSpecs2)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs3), attributeTypeSpecs3)); TestCase_assertBoolTrue(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs4), attributeTypeSpecs4)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs5), attributeTypeSpecs5)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs6), attributeTypeSpecs6)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs7), attributeTypeSpecs7)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs8), attributeTypeSpecs8)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs9), attributeTypeSpecs9)); VertexFormat_dispose(vertexFormat); vertexFormat = VertexFormat_create(sizeof_count(attributeTypeSpecs5), attributeTypeSpecs5); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs1), attributeTypeSpecs1)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs2), attributeTypeSpecs2)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs3), attributeTypeSpecs3)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs4), attributeTypeSpecs4)); TestCase_assertBoolTrue(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs5), attributeTypeSpecs5)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs6), attributeTypeSpecs6)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs7), attributeTypeSpecs7)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs8), attributeTypeSpecs8)); TestCase_assertBoolFalse(VertexFormat_matchesSpec(vertexFormat, sizeof_count(attributeTypeSpecs9), attributeTypeSpecs9)); VertexFormat_dispose(vertexFormat); } static void testUpdate(void) { VertexAttributeTypeSpec attributeTypeSpecs[] = { {"position", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_POSITION, 2}, {"normal", ATTRIBUTE_TYPE_FLOAT, ATTRIBUTE_USAGE_NORMAL, 3} }; VertexFormat * vertexFormat = VertexFormat_create(sizeof_count(attributeTypeSpecs), attributeTypeSpecs); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].byteOffset, 0); TestCase_assertUIntEqual(vertexFormat->attributeTypes[1].byteOffset, sizeof(float) * 2); TestCase_assertUIntEqual(vertexFormat->componentCountTotal, 5); TestCase_assertUIntEqual(vertexFormat->bytesPerVertex, 20); vertexFormat->attributeTypes[0].componentCount = 3; VertexFormat_update(vertexFormat); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].byteOffset, 0); TestCase_assertUIntEqual(vertexFormat->attributeTypes[1].byteOffset, sizeof(float) * 3); TestCase_assertUIntEqual(vertexFormat->componentCountTotal, 6); TestCase_assertUIntEqual(vertexFormat->bytesPerVertex, 24); vertexFormat->attributeTypes = realloc(vertexFormat->attributeTypes, (vertexFormat->attributeCount + 1) * sizeof(*vertexFormat->attributeTypes)); vertexFormat->attributeTypes[vertexFormat->attributeCount].name = strdup("color"); vertexFormat->attributeTypes[vertexFormat->attributeCount].dataType = ATTRIBUTE_TYPE_FLOAT; vertexFormat->attributeTypes[vertexFormat->attributeCount].usageHint = ATTRIBUTE_USAGE_COLOR; vertexFormat->attributeTypes[vertexFormat->attributeCount].componentCount = 4; vertexFormat->attributeCount++; VertexFormat_update(vertexFormat); TestCase_assertUIntEqual(vertexFormat->attributeTypes[0].byteOffset, 0); TestCase_assertUIntEqual(vertexFormat->attributeTypes[1].byteOffset, sizeof(float) * 3); TestCase_assertUIntEqual(vertexFormat->attributeTypes[2].byteOffset, sizeof(float) * 6); TestCase_assertUIntEqual(vertexFormat->componentCountTotal, 10); TestCase_assertUIntEqual(vertexFormat->bytesPerVertex, 40); VertexFormat_dispose(vertexFormat); } TEST_SUITE(VertexFormatTest, testCreate, testCopy, testMatchesSpec, testUpdate)