1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*
20  * \file  vktSparseResourcesShaderIntrinsics.cpp
21  * \brief Sparse Resources Shader Intrinsics
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSparseResourcesShaderIntrinsicsSampled.hpp"
25 #include "vktSparseResourcesShaderIntrinsicsStorage.hpp"
26 
27 using namespace vk;
28 
29 namespace vkt
30 {
31 namespace sparse
32 {
33 
34 struct SparseCaseParams
35 {
36     std::string name;
37     SpirVFunction function;
38     ImageType imageType;
39     tcu::UVec3 imageSize;
40     vk::VkFormat format;
41     std::string operand;
42 };
43 
44 template <typename SparseCase>
addSparseCase(const SparseCaseParams & params,tcu::TestContext & testCtx,tcu::TestCaseGroup * group)45 void addSparseCase(const SparseCaseParams &params, tcu::TestContext &testCtx, tcu::TestCaseGroup *group)
46 {
47     group->addChild(new SparseCase(testCtx, params.name, params.function, params.imageType, params.imageSize,
48                                    params.format, params.operand));
49 }
50 
createSparseResourcesShaderIntrinsicsTests(tcu::TestContext & testCtx)51 tcu::TestCaseGroup *createSparseResourcesShaderIntrinsicsTests(tcu::TestContext &testCtx)
52 {
53     de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "shader_intrinsics"));
54 
55     const std::vector<TestImageParameters> imageParameters{
56         {IMAGE_TYPE_2D,
57          {tcu::UVec3(512u, 256u, 1u), tcu::UVec3(128u, 128u, 1u), tcu::UVec3(503u, 137u, 1u), tcu::UVec3(11u, 37u, 1u)},
58          getTestFormats(IMAGE_TYPE_2D)},
59         {IMAGE_TYPE_2D_ARRAY,
60          {tcu::UVec3(512u, 256u, 6u), tcu::UVec3(128u, 128u, 8u), tcu::UVec3(503u, 137u, 3u), tcu::UVec3(11u, 37u, 3u)},
61          getTestFormats(IMAGE_TYPE_2D_ARRAY)},
62         {IMAGE_TYPE_CUBE,
63          {tcu::UVec3(256u, 256u, 1u), tcu::UVec3(128u, 128u, 1u), tcu::UVec3(137u, 137u, 1u), tcu::UVec3(11u, 11u, 1u)},
64          getTestFormats(IMAGE_TYPE_CUBE)},
65         {IMAGE_TYPE_CUBE_ARRAY,
66          {tcu::UVec3(256u, 256u, 6u), tcu::UVec3(128u, 128u, 8u), tcu::UVec3(137u, 137u, 3u), tcu::UVec3(11u, 11u, 3u)},
67          getTestFormats(IMAGE_TYPE_CUBE_ARRAY)},
68         {IMAGE_TYPE_3D,
69          {tcu::UVec3(256u, 256u, 16u), tcu::UVec3(128u, 128u, 8u), tcu::UVec3(503u, 137u, 3u),
70           tcu::UVec3(11u, 37u, 3u)},
71          getTestFormats(IMAGE_TYPE_3D)}};
72 
73     static const std::string functions[SPARSE_SPIRV_FUNCTION_TYPE_LAST]{
74         "_sparse_fetch", "_sparse_read", "_sparse_sample_explicit_lod", "_sparse_sample_implicit_lod", "_sparse_gather",
75     };
76 
77     // store functions constructing cases in a map to avoid switch in a loop
78     typedef void (*AddSparseCaseFun)(const SparseCaseParams &, tcu::TestContext &, tcu::TestCaseGroup *);
79     const std::map<SpirVFunction, AddSparseCaseFun> sparseCaseFunMap{
80         {SPARSE_FETCH, &addSparseCase<SparseCaseOpImageSparseFetch>},
81         {SPARSE_READ, &addSparseCase<SparseCaseOpImageSparseRead>},
82         {SPARSE_SAMPLE_EXPLICIT_LOD, &addSparseCase<SparseCaseOpImageSparseSampleExplicitLod>},
83         {SPARSE_SAMPLE_IMPLICIT_LOD, &addSparseCase<SparseCaseOpImageSparseSampleImplicitLod>},
84         {SPARSE_GATHER, &addSparseCase<SparseCaseOpImageSparseGather>}};
85 
86     SparseCaseParams caseParams;
87 
88     for (uint32_t functionNdx = 0; functionNdx < SPARSE_SPIRV_FUNCTION_TYPE_LAST; ++functionNdx)
89     {
90         caseParams.function = static_cast<SpirVFunction>(functionNdx);
91 
92         // grab function that should be used to construct case of proper type
93         auto addCaseFunctionPtr = sparseCaseFunMap.at(caseParams.function);
94 
95         for (const auto &imageParams : imageParameters)
96         {
97             caseParams.imageType = imageParams.imageType;
98 
99             de::MovePtr<tcu::TestCaseGroup> imageTypeGroup(new tcu::TestCaseGroup(
100                 testCtx, (getImageTypeName(caseParams.imageType) + functions[functionNdx]).c_str()));
101 
102             for (const auto &testFormat : imageParams.formats)
103             {
104                 caseParams.format = testFormat.format;
105 
106                 tcu::UVec3 imageSizeAlignment = getImageSizeAlignment(caseParams.format);
107                 de::MovePtr<tcu::TestCaseGroup> formatGroup(
108                     new tcu::TestCaseGroup(testCtx, getImageFormatID(caseParams.format).c_str()));
109 
110                 for (size_t imageSizeNdx = 0; imageSizeNdx < imageParams.imageSizes.size(); ++imageSizeNdx)
111                 {
112                     caseParams.imageSize = imageParams.imageSizes[imageSizeNdx];
113 
114                     // skip test for images with odd sizes for some YCbCr formats
115                     if (((caseParams.imageSize.x() % imageSizeAlignment.x()) != 0) ||
116                         ((caseParams.imageSize.y() % imageSizeAlignment.y()) != 0))
117                         continue;
118 
119                     // skip cases depending on image type
120                     switch (caseParams.function)
121                     {
122                     case SPARSE_FETCH:
123                         if ((caseParams.imageType == IMAGE_TYPE_CUBE) ||
124                             (caseParams.imageType == IMAGE_TYPE_CUBE_ARRAY))
125                             continue;
126                         break;
127                     case SPARSE_SAMPLE_EXPLICIT_LOD:
128                     case SPARSE_SAMPLE_IMPLICIT_LOD:
129                     case SPARSE_GATHER:
130                         if ((caseParams.imageType == IMAGE_TYPE_CUBE) ||
131                             (caseParams.imageType == IMAGE_TYPE_CUBE_ARRAY) || (caseParams.imageType == IMAGE_TYPE_3D))
132                             continue;
133                         break;
134                     default:
135                         break;
136                     }
137 
138                     std::ostringstream nameStream;
139                     nameStream << caseParams.imageSize.x() << "_" << caseParams.imageSize.y() << "_"
140                                << caseParams.imageSize.z();
141                     caseParams.name = nameStream.str();
142 
143                     caseParams.operand = "";
144                     (*addCaseFunctionPtr)(caseParams, testCtx, formatGroup.get());
145 
146                     // duplicate tests with Nontemporal operand just for smallest size (which is the last one)
147                     if (imageSizeNdx == (imageParams.imageSizes.size() - 1))
148                     {
149                         caseParams.operand = "Nontemporal";
150                         caseParams.name += "_nontemporal";
151                         (*addCaseFunctionPtr)(caseParams, testCtx, formatGroup.get());
152                     }
153                 }
154                 imageTypeGroup->addChild(formatGroup.release());
155             }
156             testGroup->addChild(imageTypeGroup.release());
157         }
158     }
159 
160     return testGroup.release();
161 }
162 
163 } // namespace sparse
164 } // namespace vkt
165