/* * Copyright 2022 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "src/core/SkSLTypeShared.h" #include "src/gpu/graphite/Uniform.h" #include "src/gpu/graphite/UniformManager.h" #include "tests/Test.h" using namespace skgpu::graphite; namespace { // Used to test the exact alignment and size of an individual type. Returns the alignment and size // as a pair. struct AlignmentAndSize { size_t alignment; size_t size; }; static AlignmentAndSize calculate_alignment_and_size(Layout layout, SkSLType type, size_t arrayCount = Uniform::kNonArray) { // Set the start offset at 1 to force alignment. constexpr uint32_t kStart = 1; UniformOffsetCalculator calc(layout, kStart); size_t alignment = calc.advanceOffset(type, arrayCount); return {alignment, calc.size() - alignment}; } #define EXPECT(type, expectedAlignment, expectedSize) \ do { \ auto [alignment, size] = calculate_alignment_and_size(kLayout, type); \ REPORTER_ASSERT(r, \ alignment == expectedAlignment, \ "incorrect alignment for type '%s': expected %d, found %zu", \ SkSLTypeString(type), \ expectedAlignment, \ alignment); \ REPORTER_ASSERT(r, \ size == expectedSize, \ "incorrect size for type '%s': expected %d, found %zu", \ SkSLTypeString(type), \ expectedSize, \ size); \ } while (0) #define EXPECT_ARRAY(type, expectedAlignment, expectedStride, expectedSize) \ do { \ auto [alignment, size] = calculate_alignment_and_size(kLayout, type, kCount); \ size_t stride = size / kCount; \ REPORTER_ASSERT(r, \ alignment == expectedAlignment, \ "incorrect alignment for type '%s': expected %d, found %zu", \ SkSLTypeString(type), \ expectedAlignment, \ alignment); \ REPORTER_ASSERT(r, \ size == expectedSize, \ "incorrect size for type '%s': expected %d, found %zu", \ SkSLTypeString(type), \ expectedSize, \ size); \ REPORTER_ASSERT(r, \ stride == expectedStride, \ "incorrect stride for type '%s': expected %d, found %zu", \ SkSLTypeString(type), \ expectedStride, \ stride); \ } while (0) DEF_TEST(UniformOffsetCalculatorMetalBasicTypesTest, r) { constexpr Layout kLayout = Layout::kMetal; // scalars: int, float, short, half (unsigned types are disallowed) EXPECT(SkSLType::kInt, /*alignment=*/4, /*size=*/4); EXPECT(SkSLType::kFloat, /*alignment=*/4, /*size=*/4); EXPECT(SkSLType::kShort, /*alignment=*/2, /*size=*/2); EXPECT(SkSLType::kHalf, /*alignment=*/2, /*size=*/2); // int2, float2, short2, half2 EXPECT(SkSLType::kInt2, /*alignment=*/8, /*size=*/8); EXPECT(SkSLType::kFloat2, /*alignment=*/8, /*size=*/8); EXPECT(SkSLType::kShort2, /*alignment=*/4, /*size=*/4); EXPECT(SkSLType::kHalf2, /*alignment=*/4, /*size=*/4); // int3, float3, short3, half3 EXPECT(SkSLType::kInt3, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kFloat3, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kShort3, /*alignment=*/8, /*size=*/8); EXPECT(SkSLType::kHalf3, /*alignment=*/8, /*size=*/8); // int4, float4, short4, half4 EXPECT(SkSLType::kInt4, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kFloat4, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kShort4, /*alignment=*/8, /*size=*/8); EXPECT(SkSLType::kHalf4, /*alignment=*/8, /*size=*/8); // float2x2, half2x2 EXPECT(SkSLType::kFloat2x2, /*alignment=*/8, /*size=*/16); EXPECT(SkSLType::kHalf2x2, /*alignment=*/4, /*size=*/8); // float3x3, half3x3 EXPECT(SkSLType::kFloat3x3, /*alignment=*/16, /*size=*/48); EXPECT(SkSLType::kHalf3x3, /*alignment=*/8, /*size=*/24); // float4x4, half4x4 EXPECT(SkSLType::kFloat4x4, /*alignment=*/16, /*size=*/64); EXPECT(SkSLType::kHalf4x4, /*alignment=*/8, /*size=*/32); } DEF_TEST(UniformOffsetCalculatorMetalArrayTest, r) { constexpr Layout kLayout = Layout::kMetal; constexpr size_t kCount = 3; // int[3], float[3], short[3], half[3] EXPECT_ARRAY(SkSLType::kInt, /*alignment=*/4, /*stride=*/4, /*size=*/12); EXPECT_ARRAY(SkSLType::kFloat, /*alignment=*/4, /*stride=*/4, /*size=*/12); EXPECT_ARRAY(SkSLType::kShort, /*alignment=*/2, /*stride=*/2, /*size=*/6); EXPECT_ARRAY(SkSLType::kHalf, /*alignment=*/2, /*stride=*/2, /*size=*/6); // int2[3], float2[3], short2[3], half2[3] EXPECT_ARRAY(SkSLType::kInt2, /*alignment=*/8, /*stride=*/8, /*size=*/24); EXPECT_ARRAY(SkSLType::kFloat2, /*alignment=*/8, /*stride=*/8, /*size=*/24); EXPECT_ARRAY(SkSLType::kShort2, /*alignment=*/4, /*stride=*/4, /*size=*/12); EXPECT_ARRAY(SkSLType::kHalf2, /*alignment=*/4, /*stride=*/4, /*size=*/12); // int3[3], float3[3], short3[3], half3[3] EXPECT_ARRAY(SkSLType::kInt3, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kFloat3, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kShort3, /*alignment=*/8, /*stride=*/8, /*size=*/24); EXPECT_ARRAY(SkSLType::kHalf3, /*alignment=*/8, /*stride=*/8, /*size=*/24); // int4[3], float4[3], short4[3], half4[3] EXPECT_ARRAY(SkSLType::kInt4, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kFloat4, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kShort4, /*alignment=*/8, /*stride=*/8, /*size=*/24); EXPECT_ARRAY(SkSLType::kHalf4, /*alignment=*/8, /*stride=*/8, /*size=*/24); // float2x2[3], half2x2[3] EXPECT_ARRAY(SkSLType::kFloat2x2, /*alignment=*/8, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kHalf2x2, /*alignment=*/4, /*stride=*/8, /*size=*/24); // float3x3[3], half3x3[3] EXPECT_ARRAY(SkSLType::kFloat3x3, /*alignment=*/16, /*stride=*/48, /*size=*/144); EXPECT_ARRAY(SkSLType::kHalf3x3, /*alignment=*/8, /*stride=*/24, /*size=*/72); // float4x4[3], half4x4[3] EXPECT_ARRAY(SkSLType::kFloat4x4, /*alignment=*/16, /*stride=*/64, /*size=*/192); EXPECT_ARRAY(SkSLType::kHalf4x4, /*alignment=*/8, /*stride=*/32, /*size=*/96); } DEF_TEST(UniformOffsetCalculatorStd430BasicTypesTest, r) { constexpr Layout kLayout = Layout::kStd430; // scalars: int, float, short, half (unsigned types are disallowed) EXPECT(SkSLType::kInt, /*alignment=*/4, /*size=*/4); EXPECT(SkSLType::kFloat, /*alignment=*/4, /*size=*/4); EXPECT(SkSLType::kShort, /*alignment=*/4, /*size=*/4); EXPECT(SkSLType::kHalf, /*alignment=*/4, /*size=*/4); // int2, float2, short2, half2 EXPECT(SkSLType::kInt2, /*alignment=*/8, /*size=*/8); EXPECT(SkSLType::kFloat2, /*alignment=*/8, /*size=*/8); EXPECT(SkSLType::kShort2, /*alignment=*/8, /*size=*/8); EXPECT(SkSLType::kHalf2, /*alignment=*/8, /*size=*/8); // int3, float3, short3, half3 EXPECT(SkSLType::kInt3, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kFloat3, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kShort3, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kHalf3, /*alignment=*/16, /*size=*/16); // int4, float4, short4, half4 EXPECT(SkSLType::kInt4, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kFloat4, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kShort4, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kHalf4, /*alignment=*/16, /*size=*/16); // float2x2, half2x2 EXPECT(SkSLType::kFloat2x2, /*alignment=*/8, /*size=*/16); EXPECT(SkSLType::kHalf2x2, /*alignment=*/8, /*size=*/16); // float3x3, half3x3 EXPECT(SkSLType::kFloat3x3, /*alignment=*/16, /*size=*/48); EXPECT(SkSLType::kHalf3x3, /*alignment=*/16, /*size=*/48); // float4x4, half4x4 EXPECT(SkSLType::kFloat4x4, /*alignment=*/16, /*size=*/64); EXPECT(SkSLType::kHalf4x4, /*alignment=*/16, /*size=*/64); } DEF_TEST(UniformOffsetCalculatorStd430ArrayTest, r) { constexpr Layout kLayout = Layout::kStd430; constexpr size_t kCount = 3; // int[3], float[3], short[3], half[3] EXPECT_ARRAY(SkSLType::kInt, /*alignment=*/4, /*stride=*/4, /*size=*/12); EXPECT_ARRAY(SkSLType::kFloat, /*alignment=*/4, /*stride=*/4, /*size=*/12); EXPECT_ARRAY(SkSLType::kShort, /*alignment=*/4, /*stride=*/4, /*size=*/12); EXPECT_ARRAY(SkSLType::kHalf, /*alignment=*/4, /*stride=*/4, /*size=*/12); // int2[3], float2[3], short2[3], half2[3] EXPECT_ARRAY(SkSLType::kInt2, /*alignment=*/8, /*stride=*/8, /*size=*/24); EXPECT_ARRAY(SkSLType::kFloat2, /*alignment=*/8, /*stride=*/8, /*size=*/24); EXPECT_ARRAY(SkSLType::kShort2, /*alignment=*/8, /*stride=*/8, /*size=*/24); EXPECT_ARRAY(SkSLType::kHalf2, /*alignment=*/8, /*stride=*/8, /*size=*/24); // int3[3], float3[3], short3[3], half3[3] EXPECT_ARRAY(SkSLType::kInt3, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kFloat3, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kShort3, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kHalf3, /*alignment=*/16, /*stride=*/16, /*size=*/48); // int4[3], float4[3], short4[3], half4[3] EXPECT_ARRAY(SkSLType::kInt4, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kFloat4, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kShort4, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kHalf4, /*alignment=*/16, /*stride=*/16, /*size=*/48); // float2x2[3], half2x2[3] EXPECT_ARRAY(SkSLType::kFloat2x2, /*alignment=*/8, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kHalf2x2, /*alignment=*/8, /*stride=*/16, /*size=*/48); // float3x3[3], half3x3[3] EXPECT_ARRAY(SkSLType::kFloat3x3, /*alignment=*/16, /*stride=*/48, /*size=*/144); EXPECT_ARRAY(SkSLType::kHalf3x3, /*alignment=*/16, /*stride=*/48, /*size=*/144); // float4x4[3], half4x4[3] EXPECT_ARRAY(SkSLType::kFloat4x4, /*alignment=*/16, /*stride=*/64, /*size=*/192); EXPECT_ARRAY(SkSLType::kHalf4x4, /*alignment=*/16, /*stride=*/64, /*size=*/192); } DEF_TEST(UniformOffsetCalculatorStd140BasicTypesTest, r) { constexpr Layout kLayout = Layout::kStd140; // scalars: int, float, short, half (unsigned types are disallowed) EXPECT(SkSLType::kInt, /*alignment=*/4, /*size=*/4); EXPECT(SkSLType::kFloat, /*alignment=*/4, /*size=*/4); EXPECT(SkSLType::kShort, /*alignment=*/4, /*size=*/4); EXPECT(SkSLType::kHalf, /*alignment=*/4, /*size=*/4); // int2, float2, short2, half2 EXPECT(SkSLType::kInt2, /*alignment=*/8, /*size=*/8); EXPECT(SkSLType::kFloat2, /*alignment=*/8, /*size=*/8); EXPECT(SkSLType::kShort2, /*alignment=*/8, /*size=*/8); EXPECT(SkSLType::kHalf2, /*alignment=*/8, /*size=*/8); // int3, float3, short3, half3 EXPECT(SkSLType::kInt3, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kFloat3, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kShort3, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kHalf3, /*alignment=*/16, /*size=*/16); // int4, float4, short4, half4 EXPECT(SkSLType::kInt4, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kFloat4, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kShort4, /*alignment=*/16, /*size=*/16); EXPECT(SkSLType::kHalf4, /*alignment=*/16, /*size=*/16); // float2x2, half2x2 EXPECT(SkSLType::kFloat2x2, /*alignment=*/8, /*size=*/16); EXPECT(SkSLType::kHalf2x2, /*alignment=*/8, /*size=*/16); // float3x3, half3x3 EXPECT(SkSLType::kFloat3x3, /*alignment=*/16, /*size=*/48); EXPECT(SkSLType::kHalf3x3, /*alignment=*/16, /*size=*/48); // float4x4, half4x4 EXPECT(SkSLType::kFloat4x4, /*alignment=*/16, /*size=*/64); EXPECT(SkSLType::kHalf4x4, /*alignment=*/16, /*size=*/64); } DEF_TEST(UniformOffsetCalculatorStd140ArrayTest, r) { constexpr Layout kLayout = Layout::kStd140; constexpr uint32_t kCount = 3; // int[3], float[3], short[3], half[3] EXPECT_ARRAY(SkSLType::kInt, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kFloat, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kShort, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kHalf, /*alignment=*/16, /*stride=*/16, /*size=*/48); // int2[3], float2[3], short2[3], half2[3] EXPECT_ARRAY(SkSLType::kInt2, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kFloat2, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kShort2, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kHalf2, /*alignment=*/16, /*stride=*/16, /*size=*/48); // int3[3], float3[3], short3[3], half3[3] EXPECT_ARRAY(SkSLType::kInt3, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kFloat3, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kShort3, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kHalf3, /*alignment=*/16, /*stride=*/16, /*size=*/48); // int4[3], float4[3], short4[3], half4[3] EXPECT_ARRAY(SkSLType::kInt4, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kFloat4, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kShort4, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kHalf4, /*alignment=*/16, /*stride=*/16, /*size=*/48); // float2x2[3], half2x2[3] EXPECT_ARRAY(SkSLType::kFloat2x2, /*alignment=*/16, /*stride=*/16, /*size=*/48); EXPECT_ARRAY(SkSLType::kHalf2x2, /*alignment=*/16, /*stride=*/16, /*size=*/48); // float3x3[3], half3x3[3] EXPECT_ARRAY(SkSLType::kFloat3x3, /*alignment=*/16, /*stride=*/48, /*size=*/144); EXPECT_ARRAY(SkSLType::kHalf3x3, /*alignment=*/16, /*stride=*/48, /*size=*/144); // float4x4[3], half4x4[3] EXPECT_ARRAY(SkSLType::kFloat4x4, /*alignment=*/16, /*stride=*/64, /*size=*/192); EXPECT_ARRAY(SkSLType::kHalf4x4, /*alignment=*/16, /*stride=*/64, /*size=*/192); } } // namespace