Skip to content

Commit d27a75b

Browse files
rudybearmeta-codesync[bot]
authored andcommitted
igl | tests | Add hash coverage for Shader.h descriptor types
Reviewed By: corporateshark Differential Revision: D109920307 fbshipit-source-id: 55e0526c9c2aa915b00e25dddda21c3b9f28d180
1 parent 4809b96 commit d27a75b

1 file changed

Lines changed: 360 additions & 0 deletions

File tree

Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,360 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <gtest/gtest.h>
9+
10+
#include <cstring>
11+
#include <functional>
12+
#include <igl/Shader.h>
13+
14+
namespace igl::tests {
15+
16+
// ---------------------------------------------------------------------------
17+
// ShaderCompilerOptions — defaults and hashing
18+
// ---------------------------------------------------------------------------
19+
20+
TEST(ShaderCompilerOptionsHashTest, DefaultFastMathEnabled) {
21+
const ShaderCompilerOptions opts;
22+
EXPECT_TRUE(opts.fastMathEnabled);
23+
}
24+
25+
TEST(ShaderCompilerOptionsHashTest, HashConsistency) {
26+
const ShaderCompilerOptions opts;
27+
const size_t h1 = std::hash<ShaderCompilerOptions>()(opts);
28+
const size_t h2 = std::hash<ShaderCompilerOptions>()(opts);
29+
EXPECT_EQ(h1, h2);
30+
}
31+
32+
TEST(ShaderCompilerOptionsHashTest, EqualObjectsEqualHash) {
33+
const ShaderCompilerOptions a;
34+
const ShaderCompilerOptions b;
35+
EXPECT_EQ(a, b);
36+
EXPECT_EQ(std::hash<ShaderCompilerOptions>()(a), std::hash<ShaderCompilerOptions>()(b));
37+
}
38+
39+
TEST(ShaderCompilerOptionsHashTest, DifferentFastMathDifferentHash) {
40+
ShaderCompilerOptions a;
41+
ShaderCompilerOptions b;
42+
b.fastMathEnabled = false;
43+
EXPECT_NE(a, b);
44+
EXPECT_NE(std::hash<ShaderCompilerOptions>()(a), std::hash<ShaderCompilerOptions>()(b));
45+
}
46+
47+
// ---------------------------------------------------------------------------
48+
// ShaderModuleInfo — defaults and hashing
49+
// ---------------------------------------------------------------------------
50+
51+
TEST(ShaderModuleInfoHashTest, DefaultStageIsFragment) {
52+
const ShaderModuleInfo info;
53+
EXPECT_EQ(info.stage, ShaderStage::Fragment);
54+
}
55+
56+
TEST(ShaderModuleInfoHashTest, DefaultEntryPointEmpty) {
57+
const ShaderModuleInfo info;
58+
EXPECT_TRUE(info.entryPoint.empty());
59+
}
60+
61+
TEST(ShaderModuleInfoHashTest, HashConsistency) {
62+
const ShaderModuleInfo info{.stage = ShaderStage::Vertex, .entryPoint = "main"};
63+
const size_t h1 = std::hash<ShaderModuleInfo>()(info);
64+
const size_t h2 = std::hash<ShaderModuleInfo>()(info);
65+
EXPECT_EQ(h1, h2);
66+
}
67+
68+
TEST(ShaderModuleInfoHashTest, EqualObjectsEqualHash) {
69+
const ShaderModuleInfo a{.stage = ShaderStage::Vertex, .entryPoint = "main"};
70+
const ShaderModuleInfo b{.stage = ShaderStage::Vertex, .entryPoint = "main"};
71+
EXPECT_EQ(a, b);
72+
EXPECT_EQ(std::hash<ShaderModuleInfo>()(a), std::hash<ShaderModuleInfo>()(b));
73+
}
74+
75+
TEST(ShaderModuleInfoHashTest, DifferentStageDifferentHash) {
76+
const ShaderModuleInfo a{.stage = ShaderStage::Vertex, .entryPoint = "main"};
77+
const ShaderModuleInfo b{.stage = ShaderStage::Fragment, .entryPoint = "main"};
78+
EXPECT_NE(a, b);
79+
EXPECT_NE(std::hash<ShaderModuleInfo>()(a), std::hash<ShaderModuleInfo>()(b));
80+
}
81+
82+
TEST(ShaderModuleInfoHashTest, DifferentEntryPointDifferentHash) {
83+
const ShaderModuleInfo a{.stage = ShaderStage::Vertex, .entryPoint = "main"};
84+
const ShaderModuleInfo b{.stage = ShaderStage::Vertex, .entryPoint = "other"};
85+
EXPECT_NE(a, b);
86+
EXPECT_NE(std::hash<ShaderModuleInfo>()(a), std::hash<ShaderModuleInfo>()(b));
87+
}
88+
89+
TEST(ShaderModuleInfoHashTest, FunctionConstantsAffectHash) {
90+
ShaderModuleInfo a{.stage = ShaderStage::Vertex, .entryPoint = "main"};
91+
ShaderModuleInfo b{.stage = ShaderStage::Vertex, .entryPoint = "main"};
92+
const float val = 1.0f;
93+
b.functionConstantValues.setConstantValue(0, ConstantValueType::Float1, &val);
94+
EXPECT_NE(a, b);
95+
EXPECT_NE(std::hash<ShaderModuleInfo>()(a), std::hash<ShaderModuleInfo>()(b));
96+
}
97+
98+
// ---------------------------------------------------------------------------
99+
// ShaderInput — defaults and hashing
100+
// ---------------------------------------------------------------------------
101+
102+
TEST(ShaderInputHashTest, DefaultValues) {
103+
const ShaderInput input;
104+
EXPECT_EQ(input.source, nullptr);
105+
EXPECT_EQ(input.data, nullptr);
106+
EXPECT_EQ(input.length, 0u);
107+
EXPECT_EQ(input.type, ShaderInputType::String);
108+
}
109+
110+
TEST(ShaderInputHashTest, HashConsistency) {
111+
const char* source = "void main() {}";
112+
const ShaderInput input{.source = source, .type = ShaderInputType::String};
113+
const size_t h1 = std::hash<ShaderInput>()(input);
114+
const size_t h2 = std::hash<ShaderInput>()(input);
115+
EXPECT_EQ(h1, h2);
116+
}
117+
118+
TEST(ShaderInputHashTest, EqualStringInputsEqualHash) {
119+
const char* source = "void main() {}";
120+
const ShaderInput a{.source = source, .type = ShaderInputType::String};
121+
const ShaderInput b{.source = source, .type = ShaderInputType::String};
122+
EXPECT_EQ(a, b);
123+
EXPECT_EQ(std::hash<ShaderInput>()(a), std::hash<ShaderInput>()(b));
124+
}
125+
126+
TEST(ShaderInputHashTest, DifferentSourceDifferentHash) {
127+
const ShaderInput a{.source = "void main() {}", .type = ShaderInputType::String};
128+
const ShaderInput b{.source = "void other() {}", .type = ShaderInputType::String};
129+
EXPECT_NE(a, b);
130+
EXPECT_NE(std::hash<ShaderInput>()(a), std::hash<ShaderInput>()(b));
131+
}
132+
133+
TEST(ShaderInputHashTest, EqualBinaryInputsEqualHash) {
134+
const uint32_t blobA = 0x12345678;
135+
const uint32_t blobB = 0x12345678;
136+
const ShaderInput a{.data = &blobA, .length = sizeof(blobA), .type = ShaderInputType::Binary};
137+
const ShaderInput b{.data = &blobB, .length = sizeof(blobB), .type = ShaderInputType::Binary};
138+
EXPECT_EQ(a, b);
139+
EXPECT_EQ(std::hash<ShaderInput>()(a), std::hash<ShaderInput>()(b));
140+
}
141+
142+
TEST(ShaderInputHashTest, DifferentBinaryDataDifferentHash) {
143+
const uint32_t blobA = 0x12345678;
144+
const uint32_t blobB = 0xAABBCCDD;
145+
const ShaderInput a{.data = &blobA, .length = sizeof(blobA), .type = ShaderInputType::Binary};
146+
const ShaderInput b{.data = &blobB, .length = sizeof(blobB), .type = ShaderInputType::Binary};
147+
EXPECT_NE(a, b);
148+
EXPECT_NE(std::hash<ShaderInput>()(a), std::hash<ShaderInput>()(b));
149+
}
150+
151+
TEST(ShaderInputHashTest, DifferentOptionsNotEqual) {
152+
ShaderCompilerOptions optsA;
153+
optsA.fastMathEnabled = true;
154+
ShaderCompilerOptions optsB;
155+
optsB.fastMathEnabled = false;
156+
const ShaderInput a{
157+
.source = "void main() {}", .options = optsA, .type = ShaderInputType::String};
158+
const ShaderInput b{
159+
.source = "void main() {}", .options = optsB, .type = ShaderInputType::String};
160+
EXPECT_NE(a, b);
161+
}
162+
163+
// ---------------------------------------------------------------------------
164+
// ShaderModuleDesc — fromBinaryInput fields and hashing
165+
// ---------------------------------------------------------------------------
166+
167+
TEST(ShaderModuleDescHashTest, FromBinaryInputFields) {
168+
const uint8_t spirv[] = {0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00};
169+
const auto desc = ShaderModuleDesc::fromBinaryInput(
170+
spirv, sizeof(spirv), {.stage = ShaderStage::Compute, .entryPoint = "main"}, "computeShader");
171+
EXPECT_EQ(desc.info.stage, ShaderStage::Compute);
172+
EXPECT_EQ(desc.info.entryPoint, "main");
173+
EXPECT_EQ(desc.debugName, "computeShader");
174+
EXPECT_TRUE(desc.input.isValid());
175+
EXPECT_EQ(desc.input.type, ShaderInputType::Binary);
176+
EXPECT_EQ(desc.input.data, spirv);
177+
EXPECT_EQ(desc.input.length, sizeof(spirv));
178+
}
179+
180+
TEST(ShaderModuleDescHashTest, FromStringInputFields) {
181+
const char* source = "void main() {}";
182+
const auto desc = ShaderModuleDesc::fromStringInput(
183+
source, {.stage = ShaderStage::Vertex, .entryPoint = "main"}, "vertShader");
184+
EXPECT_EQ(desc.info.stage, ShaderStage::Vertex);
185+
EXPECT_EQ(desc.info.entryPoint, "main");
186+
EXPECT_EQ(desc.debugName, "vertShader");
187+
EXPECT_TRUE(desc.input.isValid());
188+
EXPECT_EQ(desc.input.type, ShaderInputType::String);
189+
EXPECT_EQ(desc.input.source, source);
190+
}
191+
192+
TEST(ShaderModuleDescHashTest, HashConsistency) {
193+
const auto desc = ShaderModuleDesc::fromStringInput(
194+
"src", {.stage = ShaderStage::Fragment, .entryPoint = "main"}, "frag");
195+
const size_t h1 = std::hash<ShaderModuleDesc>()(desc);
196+
const size_t h2 = std::hash<ShaderModuleDesc>()(desc);
197+
EXPECT_EQ(h1, h2);
198+
}
199+
200+
TEST(ShaderModuleDescHashTest, EqualDescsEqualHash) {
201+
const char* source = "void main() {}";
202+
const auto a = ShaderModuleDesc::fromStringInput(
203+
source, {.stage = ShaderStage::Vertex, .entryPoint = "main"}, "shader");
204+
const auto b = ShaderModuleDesc::fromStringInput(
205+
source, {.stage = ShaderStage::Vertex, .entryPoint = "main"}, "shader");
206+
EXPECT_EQ(a, b);
207+
EXPECT_EQ(std::hash<ShaderModuleDesc>()(a), std::hash<ShaderModuleDesc>()(b));
208+
}
209+
210+
TEST(ShaderModuleDescHashTest, DifferentDebugNameDifferentHash) {
211+
const char* source = "void main() {}";
212+
const auto a = ShaderModuleDesc::fromStringInput(
213+
source, {.stage = ShaderStage::Vertex, .entryPoint = "main"}, "shaderA");
214+
const auto b = ShaderModuleDesc::fromStringInput(
215+
source, {.stage = ShaderStage::Vertex, .entryPoint = "main"}, "shaderB");
216+
EXPECT_NE(a, b);
217+
EXPECT_NE(std::hash<ShaderModuleDesc>()(a), std::hash<ShaderModuleDesc>()(b));
218+
}
219+
220+
TEST(ShaderModuleDescHashTest, DifferentStageDifferentHash) {
221+
const char* source = "void main() {}";
222+
const auto a = ShaderModuleDesc::fromStringInput(
223+
source, {.stage = ShaderStage::Vertex, .entryPoint = "main"}, "shader");
224+
const auto b = ShaderModuleDesc::fromStringInput(
225+
source, {.stage = ShaderStage::Fragment, .entryPoint = "main"}, "shader");
226+
EXPECT_NE(a, b);
227+
EXPECT_NE(std::hash<ShaderModuleDesc>()(a), std::hash<ShaderModuleDesc>()(b));
228+
}
229+
230+
TEST(ShaderModuleDescHashTest, DifferentInputDifferentHash) {
231+
const auto a = ShaderModuleDesc::fromStringInput(
232+
"source A", {.stage = ShaderStage::Vertex, .entryPoint = "main"}, "shader");
233+
const auto b = ShaderModuleDesc::fromStringInput(
234+
"source B", {.stage = ShaderStage::Vertex, .entryPoint = "main"}, "shader");
235+
EXPECT_NE(a, b);
236+
EXPECT_NE(std::hash<ShaderModuleDesc>()(a), std::hash<ShaderModuleDesc>()(b));
237+
}
238+
239+
// ---------------------------------------------------------------------------
240+
// ShaderLibraryDesc — hashing
241+
// ---------------------------------------------------------------------------
242+
243+
TEST(ShaderLibraryDescHashTest, HashConsistency) {
244+
const auto desc = ShaderLibraryDesc::fromStringInput(
245+
"src", {{.stage = ShaderStage::Vertex, .entryPoint = "vs"}}, "lib");
246+
const size_t h1 = std::hash<ShaderLibraryDesc>()(desc);
247+
const size_t h2 = std::hash<ShaderLibraryDesc>()(desc);
248+
EXPECT_EQ(h1, h2);
249+
}
250+
251+
TEST(ShaderLibraryDescHashTest, EqualDescsEqualHash) {
252+
const char* source = "void main() {}";
253+
const auto a = ShaderLibraryDesc::fromStringInput(
254+
source, {{.stage = ShaderStage::Vertex, .entryPoint = "main"}}, "lib");
255+
const auto b = ShaderLibraryDesc::fromStringInput(
256+
source, {{.stage = ShaderStage::Vertex, .entryPoint = "main"}}, "lib");
257+
EXPECT_EQ(a, b);
258+
EXPECT_EQ(std::hash<ShaderLibraryDesc>()(a), std::hash<ShaderLibraryDesc>()(b));
259+
}
260+
261+
TEST(ShaderLibraryDescHashTest, DifferentDebugNameDifferentHash) {
262+
const char* source = "void main() {}";
263+
const auto a = ShaderLibraryDesc::fromStringInput(
264+
source, {{.stage = ShaderStage::Vertex, .entryPoint = "main"}}, "libA");
265+
const auto b = ShaderLibraryDesc::fromStringInput(
266+
source, {{.stage = ShaderStage::Vertex, .entryPoint = "main"}}, "libB");
267+
EXPECT_NE(a, b);
268+
EXPECT_NE(std::hash<ShaderLibraryDesc>()(a), std::hash<ShaderLibraryDesc>()(b));
269+
}
270+
271+
TEST(ShaderLibraryDescHashTest, DifferentModuleInfoDifferentHash) {
272+
const char* source = "void main() {}";
273+
const auto a = ShaderLibraryDesc::fromStringInput(
274+
source, {{.stage = ShaderStage::Vertex, .entryPoint = "main"}}, "lib");
275+
const auto b = ShaderLibraryDesc::fromStringInput(
276+
source, {{.stage = ShaderStage::Fragment, .entryPoint = "main"}}, "lib");
277+
EXPECT_NE(a, b);
278+
EXPECT_NE(std::hash<ShaderLibraryDesc>()(a), std::hash<ShaderLibraryDesc>()(b));
279+
}
280+
281+
TEST(ShaderLibraryDescHashTest, DifferentInputDifferentHash) {
282+
const auto a = ShaderLibraryDesc::fromStringInput(
283+
"source A", {{.stage = ShaderStage::Vertex, .entryPoint = "main"}}, "lib");
284+
const auto b = ShaderLibraryDesc::fromStringInput(
285+
"source B", {{.stage = ShaderStage::Vertex, .entryPoint = "main"}}, "lib");
286+
EXPECT_NE(a, b);
287+
EXPECT_NE(std::hash<ShaderLibraryDesc>()(a), std::hash<ShaderLibraryDesc>()(b));
288+
}
289+
290+
// ---------------------------------------------------------------------------
291+
// FunctionConstantValues — hashing
292+
// ---------------------------------------------------------------------------
293+
294+
TEST(FunctionConstantValuesHashTest, EmptyHashConsistency) {
295+
const FunctionConstantValues fcv;
296+
const size_t h1 = std::hash<FunctionConstantValues>()(fcv);
297+
const size_t h2 = std::hash<FunctionConstantValues>()(fcv);
298+
EXPECT_EQ(h1, h2);
299+
}
300+
301+
TEST(FunctionConstantValuesHashTest, EqualContentEqualHash) {
302+
FunctionConstantValues a;
303+
FunctionConstantValues b;
304+
const float val = 3.14f;
305+
a.setConstantValue(0, ConstantValueType::Float1, &val);
306+
b.setConstantValue(0, ConstantValueType::Float1, &val);
307+
EXPECT_EQ(a, b);
308+
EXPECT_EQ(std::hash<FunctionConstantValues>()(a), std::hash<FunctionConstantValues>()(b));
309+
}
310+
311+
TEST(FunctionConstantValuesHashTest, DifferentValueDifferentHash) {
312+
FunctionConstantValues a;
313+
FunctionConstantValues b;
314+
const float v1 = 1.0f;
315+
const float v2 = 2.0f;
316+
a.setConstantValue(0, ConstantValueType::Float1, &v1);
317+
b.setConstantValue(0, ConstantValueType::Float1, &v2);
318+
EXPECT_NE(a, b);
319+
EXPECT_NE(std::hash<FunctionConstantValues>()(a), std::hash<FunctionConstantValues>()(b));
320+
}
321+
322+
TEST(FunctionConstantValuesHashTest, DifferentBindingDifferentHash) {
323+
FunctionConstantValues a;
324+
FunctionConstantValues b;
325+
const int32_t val = 42;
326+
a.setConstantValue(0, ConstantValueType::Int1, &val);
327+
b.setConstantValue(1, ConstantValueType::Int1, &val);
328+
EXPECT_NE(a, b);
329+
EXPECT_NE(std::hash<FunctionConstantValues>()(a), std::hash<FunctionConstantValues>()(b));
330+
}
331+
332+
TEST(FunctionConstantValuesHashTest, GapBytesIgnoredInHash) {
333+
FunctionConstantValues a;
334+
FunctionConstantValues b;
335+
const float vFloat1 = 7.0f;
336+
const float vFloat4[4] = {1.0f, 2.0f, 3.0f, 4.0f};
337+
338+
a.setConstantValue(0, ConstantValueType::Float4, &vFloat4);
339+
340+
b.setConstantValue(0, ConstantValueType::Float1, &vFloat1);
341+
b.setConstantValue(0, ConstantValueType::Float4, &vFloat4);
342+
343+
EXPECT_EQ(a, b);
344+
EXPECT_EQ(std::hash<FunctionConstantValues>()(a), std::hash<FunctionConstantValues>()(b));
345+
}
346+
347+
// ---------------------------------------------------------------------------
348+
// ShaderInputType — enum values
349+
// ---------------------------------------------------------------------------
350+
351+
TEST(ShaderInputTypeTest, EnumValues) {
352+
EXPECT_EQ(static_cast<uint8_t>(ShaderInputType::String), 0u);
353+
EXPECT_EQ(static_cast<uint8_t>(ShaderInputType::Binary), 1u);
354+
}
355+
356+
TEST(ShaderInputTypeTest, ValuesAreDistinct) {
357+
EXPECT_NE(ShaderInputType::String, ShaderInputType::Binary);
358+
}
359+
360+
} // namespace igl::tests

0 commit comments

Comments
 (0)