Skip to content

Commit 95eb1d3

Browse files
committed
feat: add "get_data_type_size(...)" to graphics ext
1 parent 36f19e9 commit 95eb1d3

File tree

7 files changed

+68
-227
lines changed

7 files changed

+68
-227
lines changed

extensions/pl_graphics_ext.c

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ pl__get_vertex_attribute_size(plVertexFormat tFormat)
5959
return 0;
6060
}
6161

62-
static size_t
63-
pl__get_data_type_size(plDataType tType)
62+
size_t
63+
pl_get_data_type_size(plDataType tType)
6464
{
6565
switch(tType)
6666
{
@@ -74,53 +74,41 @@ pl__get_data_type_size(plDataType tType)
7474
case PL_DATA_TYPE_FLOAT3: return 3 * sizeof(float);
7575
case PL_DATA_TYPE_FLOAT4: return 4 * sizeof(float);
7676

77-
case PL_DATA_TYPE_UNSIGNED_BYTE:
78-
case PL_DATA_TYPE_BYTE: return sizeof(uint8_t);
77+
case PL_DATA_TYPE_UCHAR:
78+
case PL_DATA_TYPE_CHAR: return sizeof(uint8_t);
7979

80-
case PL_DATA_TYPE_UNSIGNED_SHORT:
80+
case PL_DATA_TYPE_USHORT:
8181
case PL_DATA_TYPE_SHORT: return sizeof(uint16_t);
8282

83-
case PL_DATA_TYPE_UNSIGNED_INT:
83+
case PL_DATA_TYPE_UINT:
8484
case PL_DATA_TYPE_INT: return sizeof(uint32_t);
8585

86-
case PL_DATA_TYPE_UNSIGNED_LONG:
87-
case PL_DATA_TYPE_LONG: return sizeof(uint64_t);
88-
89-
case PL_DATA_TYPE_UNSIGNED_BYTE2:
90-
case PL_DATA_TYPE_BYTE2: return 2 * sizeof(uint8_t);
86+
case PL_DATA_TYPE_UCHAR2:
87+
case PL_DATA_TYPE_CHAR2: return 2 * sizeof(uint8_t);
9188

92-
case PL_DATA_TYPE_UNSIGNED_SHORT2:
89+
case PL_DATA_TYPE_USHORT2:
9390
case PL_DATA_TYPE_SHORT2: return 2 * sizeof(uint16_t);
9491

95-
case PL_DATA_TYPE_UNSIGNED_INT2:
92+
case PL_DATA_TYPE_UINT2:
9693
case PL_DATA_TYPE_INT2: return 2 * sizeof(uint32_t);
9794

98-
case PL_DATA_TYPE_UNSIGNED_LONG2:
99-
case PL_DATA_TYPE_LONG2: return 2 * sizeof(uint64_t);
100-
101-
case PL_DATA_TYPE_UNSIGNED_BYTE3:
102-
case PL_DATA_TYPE_BYTE3: return 3 * sizeof(uint8_t);
95+
case PL_DATA_TYPE_UCHAR3:
96+
case PL_DATA_TYPE_CHAR3: return 3 * sizeof(uint8_t);
10397

104-
case PL_DATA_TYPE_UNSIGNED_SHORT3:
98+
case PL_DATA_TYPE_USHORT3:
10599
case PL_DATA_TYPE_SHORT3: return 3 * sizeof(uint16_t);
106100

107-
case PL_DATA_TYPE_UNSIGNED_INT3:
101+
case PL_DATA_TYPE_UINT3:
108102
case PL_DATA_TYPE_INT3: return 3 * sizeof(uint32_t);
109103

110-
case PL_DATA_TYPE_UNSIGNED_LONG3:
111-
case PL_DATA_TYPE_LONG3: return 3 * sizeof(uint64_t);
104+
case PL_DATA_TYPE_UCHAR4:
105+
case PL_DATA_TYPE_CHAR4: return 4 * sizeof(uint8_t);
112106

113-
case PL_DATA_TYPE_UNSIGNED_BYTE4:
114-
case PL_DATA_TYPE_BYTE4: return 4 * sizeof(uint8_t);
115-
116-
case PL_DATA_TYPE_UNSIGNED_SHORT4:
107+
case PL_DATA_TYPE_USHORT4:
117108
case PL_DATA_TYPE_SHORT4: return 4 * sizeof(uint16_t);
118109

119-
case PL_DATA_TYPE_UNSIGNED_INT4:
110+
case PL_DATA_TYPE_UINT4:
120111
case PL_DATA_TYPE_INT4: return 4 * sizeof(uint32_t);
121-
122-
case PL_DATA_TYPE_UNSIGNED_LONG4:
123-
case PL_DATA_TYPE_LONG4: return 4 * sizeof(uint64_t);
124112
}
125113

126114
PL_ASSERT(false && "Unsupported data type");
@@ -1117,6 +1105,7 @@ pl_load_graphics_ext(plApiRegistryI* ptApiRegistry, bool bReload)
11171105
.get_encoder_command_buffer = pl_get_encoder_command_buffer,
11181106
.invalidate_memory = pl_gfx_invalidate_memory,
11191107
.flush_memory = pl_gfx_flush_memory,
1108+
.get_data_type_size = pl_get_data_type_size,
11201109

11211110
#if defined(PL_GRAPHICS_EXPOSE_VULKAN) && defined(PL_VULKAN_BACKEND)
11221111
.get_vulkan_instance = pl_get_vulkan_instance,

extensions/pl_graphics_ext.h

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,10 @@ typedef struct _plGraphicsI
503503
bool (*invalidate_memory)(plDevice*, uint32_t rangeCount, const plDeviceMemoryRange*); // call after writing from device on non-coherent memory
504504
const plDeviceMemoryAllocation* (*get_allocations)(plDevice*, uint32_t* sizeOut);
505505

506+
//---------------------------------MISC----------------------------------------
507+
508+
size_t (*get_data_type_size)(plDataType);
509+
506510
//------------------------------NOT STABLE-------------------------------------
507511

508512
#ifdef PL_GRAPHICS_EXPOSE_VULKAN
@@ -1502,38 +1506,30 @@ enum _plDataType
15021506
PL_DATA_TYPE_FLOAT2,
15031507
PL_DATA_TYPE_FLOAT3,
15041508
PL_DATA_TYPE_FLOAT4,
1505-
PL_DATA_TYPE_BYTE,
1506-
PL_DATA_TYPE_BYTE2,
1507-
PL_DATA_TYPE_BYTE3,
1508-
PL_DATA_TYPE_BYTE4,
1509-
PL_DATA_TYPE_UNSIGNED_BYTE,
1510-
PL_DATA_TYPE_UNSIGNED_BYTE2,
1511-
PL_DATA_TYPE_UNSIGNED_BYTE3,
1512-
PL_DATA_TYPE_UNSIGNED_BYTE4,
1509+
PL_DATA_TYPE_CHAR,
1510+
PL_DATA_TYPE_CHAR2,
1511+
PL_DATA_TYPE_CHAR3,
1512+
PL_DATA_TYPE_CHAR4,
1513+
PL_DATA_TYPE_UCHAR,
1514+
PL_DATA_TYPE_UCHAR2,
1515+
PL_DATA_TYPE_UCHAR3,
1516+
PL_DATA_TYPE_UCHAR4,
15131517
PL_DATA_TYPE_SHORT,
15141518
PL_DATA_TYPE_SHORT2,
15151519
PL_DATA_TYPE_SHORT3,
15161520
PL_DATA_TYPE_SHORT4,
1517-
PL_DATA_TYPE_UNSIGNED_SHORT,
1518-
PL_DATA_TYPE_UNSIGNED_SHORT2,
1519-
PL_DATA_TYPE_UNSIGNED_SHORT3,
1520-
PL_DATA_TYPE_UNSIGNED_SHORT4,
1521+
PL_DATA_TYPE_USHORT,
1522+
PL_DATA_TYPE_USHORT2,
1523+
PL_DATA_TYPE_USHORT3,
1524+
PL_DATA_TYPE_USHORT4,
15211525
PL_DATA_TYPE_INT,
15221526
PL_DATA_TYPE_INT2,
15231527
PL_DATA_TYPE_INT3,
15241528
PL_DATA_TYPE_INT4,
1525-
PL_DATA_TYPE_UNSIGNED_INT,
1526-
PL_DATA_TYPE_UNSIGNED_INT2,
1527-
PL_DATA_TYPE_UNSIGNED_INT3,
1528-
PL_DATA_TYPE_UNSIGNED_INT4,
1529-
PL_DATA_TYPE_LONG,
1530-
PL_DATA_TYPE_LONG2,
1531-
PL_DATA_TYPE_LONG3,
1532-
PL_DATA_TYPE_LONG4,
1533-
PL_DATA_TYPE_UNSIGNED_LONG,
1534-
PL_DATA_TYPE_UNSIGNED_LONG2,
1535-
PL_DATA_TYPE_UNSIGNED_LONG3,
1536-
PL_DATA_TYPE_UNSIGNED_LONG4,
1529+
PL_DATA_TYPE_UINT,
1530+
PL_DATA_TYPE_UINT2,
1531+
PL_DATA_TYPE_UINT3,
1532+
PL_DATA_TYPE_UINT4
15371533
};
15381534

15391535
enum _plVertexFormat

extensions/pl_graphics_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ static void pl_queue_bind_group_layout_for_deletion(plDevice*, plBindGroupLayout
116116
static void pl_queue_sampler_for_deletion(plDevice*, plSamplerHandle);
117117

118118
// helpers
119-
static size_t pl__get_data_type_size(plDataType);
119+
static size_t pl_get_data_type_size(plDataType);
120120
static uint32_t pl__format_stride(plFormat);
121121
static size_t pl__get_vertex_attribute_size(plVertexFormat);
122122

extensions/pl_graphics_metal.m

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,7 +1210,7 @@
12101210
const plSpecializationConstant* ptConstant = &ptShader->tDesc.atConstants[i];
12111211
if(ptConstant->tType == PL_DATA_TYPE_UNSPECIFIED)
12121212
break;
1213-
uTotalConstantSize += pl__get_data_type_size(ptConstant->tType);
1213+
uTotalConstantSize += pl_get_data_type_size(ptConstant->tType);
12141214
ptShader->tDesc._uConstantCount++;
12151215
}
12161216

@@ -1235,7 +1235,7 @@
12351235
const uint32_t uConstantIndex = ptConstant->uID == 0 ? i : ptConstant->uID;
12361236
const uint32_t uAutoConstantOffset = ptConstant->uOffset == 0 ? uConstantOffset : ptConstant->uOffset;
12371237
[ptConstantValues setConstantValue:&pcConstantData[uAutoConstantOffset] type:pl__metal_data_type(ptConstant->tType) atIndex:uConstantIndex];
1238-
uConstantOffset += (uint32_t)pl__get_data_type_size(ptConstant->tType);
1238+
uConstantOffset += (uint32_t)pl_get_data_type_size(ptConstant->tType);
12391239
}
12401240

12411241
id<MTLFunction> computeFunction = [ptMetalShader->library newFunctionWithName:entryFunc constantValues:ptConstantValues error:&error];
@@ -1369,7 +1369,7 @@
13691369
const plSpecializationConstant* ptConstant = &ptShader->tDesc.atConstants[i];
13701370
if(ptConstant->tType == PL_DATA_TYPE_UNSPECIFIED)
13711371
break;
1372-
uTotalConstantSize += pl__get_data_type_size(ptConstant->tType);
1372+
uTotalConstantSize += pl_get_data_type_size(ptConstant->tType);
13731373
ptShader->tDesc._uConstantCount++;
13741374
}
13751375

@@ -1394,7 +1394,7 @@
13941394
const uint32_t uConstantIndex = ptConstant->uID == 0 ? i : ptConstant->uID;
13951395
const uint32_t uAutoConstantOffset = ptConstant->uOffset == 0 ? uConstantOffset : ptConstant->uOffset;
13961396
[ptConstantValues setConstantValue:&pcConstantData[uAutoConstantOffset] type:pl__metal_data_type(ptConstant->tType) atIndex:uConstantIndex];
1397-
uConstantOffset += (uint32_t)pl__get_data_type_size(ptConstant->tType);
1397+
uConstantOffset += (uint32_t)pl_get_data_type_size(ptConstant->tType);
13981398
}
13991399

14001400
id<MTLFunction> vertexFunction = [ptMetalShader->tVertexLibrary newFunctionWithName:vertexEntry constantValues:ptConstantValues error:&error];
@@ -2933,47 +2933,39 @@
29332933

29342934
case PL_DATA_TYPE_BOOL: return MTLDataTypeBool;
29352935
case PL_DATA_TYPE_FLOAT: return MTLDataTypeFloat;
2936-
case PL_DATA_TYPE_UNSIGNED_BYTE: return MTLDataTypeUChar;
2937-
case PL_DATA_TYPE_BYTE: return MTLDataTypeChar;
2938-
case PL_DATA_TYPE_UNSIGNED_SHORT: return MTLDataTypeUShort;
2936+
case PL_DATA_TYPE_UCHAR: return MTLDataTypeUChar;
2937+
case PL_DATA_TYPE_CHAR: return MTLDataTypeChar;
2938+
case PL_DATA_TYPE_USHORT: return MTLDataTypeUShort;
29392939
case PL_DATA_TYPE_SHORT: return MTLDataTypeShort;
2940-
case PL_DATA_TYPE_UNSIGNED_INT: return MTLDataTypeUInt;
2940+
case PL_DATA_TYPE_UINT: return MTLDataTypeUInt;
29412941
case PL_DATA_TYPE_INT: return MTLDataTypeInt;
2942-
case PL_DATA_TYPE_UNSIGNED_LONG: return MTLDataTypeULong;
2943-
case PL_DATA_TYPE_LONG: return MTLDataTypeLong;
29442942

29452943
case PL_DATA_TYPE_BOOL2: return MTLDataTypeBool2;
29462944
case PL_DATA_TYPE_FLOAT2: return MTLDataTypeFloat2;
2947-
case PL_DATA_TYPE_UNSIGNED_BYTE2: return MTLDataTypeUChar2;
2948-
case PL_DATA_TYPE_BYTE2: return MTLDataTypeChar2;
2949-
case PL_DATA_TYPE_UNSIGNED_SHORT2: return MTLDataTypeUShort2;
2945+
case PL_DATA_TYPE_UCHAR2: return MTLDataTypeUChar2;
2946+
case PL_DATA_TYPE_CHAR2: return MTLDataTypeChar2;
2947+
case PL_DATA_TYPE_USHORT2: return MTLDataTypeUShort2;
29502948
case PL_DATA_TYPE_SHORT2: return MTLDataTypeShort2;
2951-
case PL_DATA_TYPE_UNSIGNED_INT2: return MTLDataTypeUInt2;
2949+
case PL_DATA_TYPE_UINT2: return MTLDataTypeUInt2;
29522950
case PL_DATA_TYPE_INT2: return MTLDataTypeInt2;
2953-
case PL_DATA_TYPE_UNSIGNED_LONG2: return MTLDataTypeULong2;
2954-
case PL_DATA_TYPE_LONG2: return MTLDataTypeLong2;
29552951

29562952
case PL_DATA_TYPE_BOOL3: return MTLDataTypeBool3;
29572953
case PL_DATA_TYPE_FLOAT3: return MTLDataTypeFloat3;
2958-
case PL_DATA_TYPE_UNSIGNED_BYTE3: return MTLDataTypeUChar3;
2959-
case PL_DATA_TYPE_BYTE3: return MTLDataTypeChar3;
2960-
case PL_DATA_TYPE_UNSIGNED_SHORT3: return MTLDataTypeUShort3;
2954+
case PL_DATA_TYPE_UCHAR3: return MTLDataTypeUChar3;
2955+
case PL_DATA_TYPE_CHAR3: return MTLDataTypeChar3;
2956+
case PL_DATA_TYPE_USHORT3: return MTLDataTypeUShort3;
29612957
case PL_DATA_TYPE_SHORT3: return MTLDataTypeShort3;
2962-
case PL_DATA_TYPE_UNSIGNED_INT3: return MTLDataTypeUInt3;
2958+
case PL_DATA_TYPE_UINT3: return MTLDataTypeUInt3;
29632959
case PL_DATA_TYPE_INT3: return MTLDataTypeInt3;
2964-
case PL_DATA_TYPE_UNSIGNED_LONG3: return MTLDataTypeULong3;
2965-
case PL_DATA_TYPE_LONG3: return MTLDataTypeLong3;
29662960

29672961
case PL_DATA_TYPE_BOOL4: return MTLDataTypeBool4;
29682962
case PL_DATA_TYPE_FLOAT4: return MTLDataTypeFloat4;
2969-
case PL_DATA_TYPE_UNSIGNED_BYTE4: return MTLDataTypeUChar4;
2970-
case PL_DATA_TYPE_BYTE4: return MTLDataTypeChar4;
2971-
case PL_DATA_TYPE_UNSIGNED_SHORT4: return MTLDataTypeUShort4;
2963+
case PL_DATA_TYPE_UCHAR4: return MTLDataTypeUChar4;
2964+
case PL_DATA_TYPE_CHAR4: return MTLDataTypeChar4;
2965+
case PL_DATA_TYPE_USHORT4: return MTLDataTypeUShort4;
29722966
case PL_DATA_TYPE_SHORT4: return MTLDataTypeShort4;
2973-
case PL_DATA_TYPE_UNSIGNED_INT4: return MTLDataTypeUInt4;
2967+
case PL_DATA_TYPE_UINT4: return MTLDataTypeUInt4;
29742968
case PL_DATA_TYPE_INT4: return MTLDataTypeInt4;
2975-
case PL_DATA_TYPE_UNSIGNED_LONG4: return MTLDataTypeULong4;
2976-
case PL_DATA_TYPE_LONG4: return MTLDataTypeLong4;
29772969
}
29782970

29792971
PL_ASSERT(false && "Unsupported data type");

extensions/pl_graphics_vulkan.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,8 +1377,8 @@ pl_create_compute_shader(plDevice* ptDevice, const plComputeShaderDesc* ptDescri
13771377
break;
13781378
ptVulkanShader->atSpecializationEntries[i].constantID = ptConstant->uID == 0 ? ptShader->tDesc._uConstantCount : ptConstant->uID;
13791379
ptVulkanShader->atSpecializationEntries[i].offset = ptConstant->uOffset == 0 ? uConstantOffset : ptConstant->uOffset;
1380-
uConstantOffset += (uint32_t)pl__get_data_type_size(ptConstant->tType);
1381-
ptVulkanShader->atSpecializationEntries[i].size = pl__get_data_type_size(ptConstant->tType);
1380+
uConstantOffset += (uint32_t)pl_get_data_type_size(ptConstant->tType);
1381+
ptVulkanShader->atSpecializationEntries[i].size = pl_get_data_type_size(ptConstant->tType);
13821382
ptVulkanShader->szSpecializationSize += ptVulkanShader->atSpecializationEntries[i].size;
13831383
ptShader->tDesc._uConstantCount++;
13841384
}
@@ -1584,8 +1584,8 @@ pl_create_shader(plDevice* ptDevice, const plShaderDesc* ptDescription)
15841584
break;
15851585
ptVulkanShader->atSpecializationEntries[i].constantID = ptConstant->uID == 0 ? ptShader->tDesc._uConstantCount : ptConstant->uID;
15861586
ptVulkanShader->atSpecializationEntries[i].offset = ptConstant->uOffset == 0 ? uConstantOffset : ptConstant->uOffset;
1587-
uConstantOffset += (uint32_t)pl__get_data_type_size(ptConstant->tType);
1588-
ptVulkanShader->atSpecializationEntries[i].size = pl__get_data_type_size(ptConstant->tType);
1587+
uConstantOffset += (uint32_t)pl_get_data_type_size(ptConstant->tType);
1588+
ptVulkanShader->atSpecializationEntries[i].size = pl_get_data_type_size(ptConstant->tType);
15891589
ptVulkanShader->szSpecializationSize += ptVulkanShader->atSpecializationEntries[i].size;
15901590
ptShader->tDesc._uConstantCount++;
15911591
}

extensions/pl_renderer_internal.c

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2365,74 +2365,6 @@ pl__renderer_get_blend_state(plBlendMode tBlendMode)
23652365
return atStateMap[tBlendMode];
23662366
}
23672367

2368-
static size_t
2369-
pl__renderer_get_data_type_size2(plDataType tType)
2370-
{
2371-
switch(tType)
2372-
{
2373-
case PL_DATA_TYPE_BOOL: return sizeof(int);
2374-
case PL_DATA_TYPE_BOOL2: return 2 * sizeof(int);
2375-
case PL_DATA_TYPE_BOOL3: return 3 * sizeof(int);
2376-
case PL_DATA_TYPE_BOOL4: return 4 * sizeof(int);
2377-
2378-
case PL_DATA_TYPE_FLOAT: return sizeof(float);
2379-
case PL_DATA_TYPE_FLOAT2: return 2 * sizeof(float);
2380-
case PL_DATA_TYPE_FLOAT3: return 3 * sizeof(float);
2381-
case PL_DATA_TYPE_FLOAT4: return 4 * sizeof(float);
2382-
2383-
case PL_DATA_TYPE_UNSIGNED_BYTE:
2384-
case PL_DATA_TYPE_BYTE: return sizeof(uint8_t);
2385-
2386-
case PL_DATA_TYPE_UNSIGNED_SHORT:
2387-
case PL_DATA_TYPE_SHORT: return sizeof(uint16_t);
2388-
2389-
case PL_DATA_TYPE_UNSIGNED_INT:
2390-
case PL_DATA_TYPE_INT: return sizeof(uint32_t);
2391-
2392-
case PL_DATA_TYPE_UNSIGNED_LONG:
2393-
case PL_DATA_TYPE_LONG: return sizeof(uint64_t);
2394-
2395-
case PL_DATA_TYPE_UNSIGNED_BYTE2:
2396-
case PL_DATA_TYPE_BYTE2: return 2 * sizeof(uint8_t);
2397-
2398-
case PL_DATA_TYPE_UNSIGNED_SHORT2:
2399-
case PL_DATA_TYPE_SHORT2: return 2 * sizeof(uint16_t);
2400-
2401-
case PL_DATA_TYPE_UNSIGNED_INT2:
2402-
case PL_DATA_TYPE_INT2: return 2 * sizeof(uint32_t);
2403-
2404-
case PL_DATA_TYPE_UNSIGNED_LONG2:
2405-
case PL_DATA_TYPE_LONG2: return 2 * sizeof(uint64_t);
2406-
2407-
case PL_DATA_TYPE_UNSIGNED_BYTE3:
2408-
case PL_DATA_TYPE_BYTE3: return 3 * sizeof(uint8_t);
2409-
2410-
case PL_DATA_TYPE_UNSIGNED_SHORT3:
2411-
case PL_DATA_TYPE_SHORT3: return 3 * sizeof(uint16_t);
2412-
2413-
case PL_DATA_TYPE_UNSIGNED_INT3:
2414-
case PL_DATA_TYPE_INT3: return 3 * sizeof(uint32_t);
2415-
2416-
case PL_DATA_TYPE_UNSIGNED_LONG3:
2417-
case PL_DATA_TYPE_LONG3: return 3 * sizeof(uint64_t);
2418-
2419-
case PL_DATA_TYPE_UNSIGNED_BYTE4:
2420-
case PL_DATA_TYPE_BYTE4: return 4 * sizeof(uint8_t);
2421-
2422-
case PL_DATA_TYPE_UNSIGNED_SHORT4:
2423-
case PL_DATA_TYPE_SHORT4: return 4 * sizeof(uint16_t);
2424-
2425-
case PL_DATA_TYPE_UNSIGNED_INT4:
2426-
case PL_DATA_TYPE_INT4: return 4 * sizeof(uint32_t);
2427-
2428-
case PL_DATA_TYPE_UNSIGNED_LONG4:
2429-
case PL_DATA_TYPE_LONG4: return 4 * sizeof(uint64_t);
2430-
}
2431-
2432-
PL_ASSERT(false && "Unsupported data type");
2433-
return 0;
2434-
}
2435-
24362368
static uint32_t
24372369
pl__renderer_get_bindless_texture_index(plScene* ptScene, plTextureHandle tTexture)
24382370
{

0 commit comments

Comments
 (0)