1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 Intel Corporation
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
21 * \brief Functional tests using vkrunner
22 *//*--------------------------------------------------------------------*/
23
24 #include <assert.h>
25 #if defined(DEQP_HAVE_VKRUNNER)
26 #include <vkrunner/vkrunner.h>
27 #endif
28
29 #include "vktVkRunnerTestCase.hpp"
30 #include "tcuTestLog.hpp"
31
32 namespace vkt
33 {
34 namespace vkrunner
35 {
36
37 #if defined(DEQP_HAVE_VKRUNNER)
38 static const char *
39 vr_stage_name[VR_SHADER_STAGE_N_STAGES] = {
40 "vertex",
41 "tess_ctrl",
42 "tess_eval",
43 "geometry",
44 "fragment",
45 "compute",
46 };
47 #endif
48
49 #if defined(DEQP_HAVE_VKRUNNER)
errorCb(const char * message,void * user_data)50 static void errorCb(const char* message,
51 void* user_data)
52 {
53 VkRunnerTestCase* test = (VkRunnerTestCase*) user_data;
54
55 test->getTestContext().getLog()
56 << tcu::TestLog::Message
57 << message
58 << "\n"
59 << tcu::TestLog::EndMessage;
60 }
61 #endif
62
VkRunnerTestCase(tcu::TestContext & testCtx,const char * categoryname,const char * filename,const char * name,const char * description)63 VkRunnerTestCase::VkRunnerTestCase (tcu::TestContext& testCtx,
64 const char* categoryname,
65 const char* filename,
66 const char* name,
67 const char* description)
68 : TestCase(testCtx, name, description)
69 {
70 #if defined(DEQP_HAVE_VKRUNNER)
71 m_testCaseData.categoryname = categoryname;
72 m_testCaseData.filename = filename;
73 m_testCaseData.num_shaders = 0;
74 m_testCaseData.script = DE_NULL;
75 m_testCaseData.shaders = DE_NULL;
76
77 std::string readFilename("vulkan/vkrunner/");
78 readFilename.append(m_testCaseData.categoryname);
79 readFilename.append("/");
80 readFilename.append(m_testCaseData.filename);
81 m_testCaseData.source = vr_source_from_file(readFilename.c_str());
82 #else
83 (void) categoryname;
84 (void) filename;
85 #endif
86 }
87
~VkRunnerTestCase(void)88 VkRunnerTestCase::~VkRunnerTestCase (void)
89 {
90 #if defined(DEQP_HAVE_VKRUNNER)
91 if (m_testCaseData.num_shaders)
92 {
93 for (int i = 0; i < m_testCaseData.num_shaders; i++)
94 {
95 /* shaders[i]->source were allocated by VkRunner. We don't need them anymore. */
96 deFree(m_testCaseData.shaders[i].source);
97 }
98 deFree(m_testCaseData.shaders);
99 }
100 if (m_testCaseData.script)
101 vr_script_free(m_testCaseData.script);
102 if (m_testCaseData.source)
103 vr_source_free(m_testCaseData.source);
104 #endif
105 }
106
addTokenReplacement(const char * token,const char * replacement)107 void VkRunnerTestCase::addTokenReplacement(const char *token,
108 const char *replacement)
109 {
110 #if defined(DEQP_HAVE_VKRUNNER)
111 vr_source_add_token_replacement(m_testCaseData.source,
112 token,
113 replacement);
114 #else
115 (void) token;
116 (void) replacement;
117 #endif
118 }
119
getShaders()120 bool VkRunnerTestCase::getShaders()
121 {
122 #if defined(DEQP_HAVE_VKRUNNER)
123 /* Create a temporary vr_config to log shader_test parsing errors to test's log file */
124 struct vr_config *config = vr_config_new();
125 vr_config_set_user_data(config, this);
126 vr_config_set_error_cb(config, errorCb);
127 m_testCaseData.script = vr_script_load(config, m_testCaseData.source);
128
129 if (m_testCaseData.script == DE_NULL)
130 {
131 /* Parser returned an error or shader_test file doesn't exist */
132 vr_config_free(config);
133 return false;
134 }
135
136 m_testCaseData.num_shaders = vr_script_get_num_shaders(m_testCaseData.script);
137 m_testCaseData.shaders = (struct vr_script_shader_code *)
138 malloc(sizeof(struct vr_script_shader_code)*m_testCaseData.num_shaders);
139 vr_script_get_shaders(m_testCaseData.script,
140 m_testCaseData.source,
141 m_testCaseData.shaders);
142 vr_config_free(config);
143 return true;
144 #else
145 return false;
146 #endif
147 }
148
createInstance(Context & ctx) const149 TestInstance* VkRunnerTestCase::createInstance(Context& ctx) const
150 {
151 if (m_testCaseData.script == DE_NULL)
152 TCU_THROW(InternalError, "Could not find script file");
153
154 return new VkRunnerTestInstance(ctx, m_testCaseData);
155 }
156
initPrograms(vk::SourceCollections & programCollection) const157 void VkRunnerTestCase::initPrograms(vk::SourceCollections& programCollection) const
158 {
159 #if defined(DEQP_HAVE_VKRUNNER)
160 int num_shader[VR_SHADER_STAGE_N_STAGES] = {0};
161
162 for (int i = 0; i < m_testCaseData.num_shaders; i++)
163 {
164 num_shader[m_testCaseData.shaders[i].stage]++;
165 if (num_shader[m_testCaseData.shaders[i].stage] > 1)
166 TCU_THROW(InternalError, "Multiple shaders per stage are not currently supported");
167
168 /* We ignore the SPIR-V shaders in binary form */
169 if (m_testCaseData.shaders[i].source_type == VR_SCRIPT_SOURCE_TYPE_GLSL)
170 {
171 switch (m_testCaseData.shaders[i].stage)
172 {
173 case VR_SHADER_STAGE_VERTEX:
174 programCollection.glslSources.add(vr_stage_name[m_testCaseData.shaders[i].stage]) << glu::VertexSource(m_testCaseData.shaders[i].source);
175 break;
176 case VR_SHADER_STAGE_TESS_CTRL:
177 programCollection.glslSources.add(vr_stage_name[m_testCaseData.shaders[i].stage]) << glu::TessellationControlSource(m_testCaseData.shaders[i].source);
178 break;
179 case VR_SHADER_STAGE_TESS_EVAL:
180 programCollection.glslSources.add(vr_stage_name[m_testCaseData.shaders[i].stage]) << glu::TessellationEvaluationSource(m_testCaseData.shaders[i].source);
181 break;
182 case VR_SHADER_STAGE_GEOMETRY:
183 programCollection.glslSources.add(vr_stage_name[m_testCaseData.shaders[i].stage]) << glu::GeometrySource(m_testCaseData.shaders[i].source);
184 break;
185 case VR_SHADER_STAGE_FRAGMENT:
186 programCollection.glslSources.add(vr_stage_name[m_testCaseData.shaders[i].stage]) << glu::FragmentSource(m_testCaseData.shaders[i].source);
187 break;
188 case VR_SHADER_STAGE_COMPUTE:
189 programCollection.glslSources.add(vr_stage_name[m_testCaseData.shaders[i].stage]) << glu::ComputeSource(m_testCaseData.shaders[i].source);
190 break;
191 default:
192 assert(0 && "Shader type is not supported");
193 }
194 } else if (m_testCaseData.shaders[i].source_type == VR_SCRIPT_SOURCE_TYPE_SPIRV)
195 {
196 programCollection.spirvAsmSources.add(vr_stage_name[m_testCaseData.shaders[i].stage]) << m_testCaseData.shaders[i].source;
197 }
198 }
199 #else
200 (void) programCollection;
201 #endif
202 }
203
iterate(void)204 tcu::TestStatus VkRunnerTestInstance::iterate (void)
205 {
206 #if defined(DEQP_HAVE_VKRUNNER)
207 /* Get the compiled version of the text-based shaders and replace them */
208 for (int stage = 0; stage < VR_SHADER_STAGE_N_STAGES; stage++)
209 {
210 std::string name(vr_stage_name[stage]);
211 if (!m_context.getBinaryCollection().contains(name))
212 continue;
213 size_t source_length = m_context.getBinaryCollection().get(name).getSize();
214 unsigned *source = (unsigned *) deMalloc(source_length);
215 deMemcpy(source,
216 m_context.getBinaryCollection().get(name).getBinary(),
217 source_length);
218 vr_script_replace_shaders_stage_binary(m_testCaseData.script,
219 (enum vr_shader_stage)stage,
220 source_length,
221 source);
222 deFree(source);
223 }
224
225 /* Replace text-based shaders by their binary equivalent and execute the test */
226 vr_result res = vr_executor_execute_script(m_context.getExecutor(), m_testCaseData.script);
227
228 switch (res)
229 {
230 case VR_RESULT_FAIL:
231 return tcu::TestStatus::fail("Fail");
232 case VR_RESULT_PASS:
233 return tcu::TestStatus::pass("Pass");
234 case VR_RESULT_SKIP:
235 return tcu::TestStatus::incomplete();
236 }
237
238 return tcu::TestStatus::fail("Fail");
239 #else
240 return tcu::TestStatus::fail("Not built with VkRunner support");
241 #endif
242 }
243
244 } // vkrunner
245 } // vkt
246