1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * Copyright (c) 2016 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Vulkan ShaderExecutor
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktShaderExecutor.hpp"
27 #include <map>
28 #include <sstream>
29 #include <iostream>
30
31 #include "tcuVector.hpp"
32 #include "tcuTestLog.hpp"
33 #include "tcuFormatUtil.hpp"
34 #include "tcuTextureUtil.hpp"
35 #include "deUniquePtr.hpp"
36 #include "deStringUtil.hpp"
37 #include "deSharedPtr.hpp"
38
39 #include "vkMemUtil.hpp"
40 #include "vkRef.hpp"
41 #include "vkPlatform.hpp"
42 #include "vkPrograms.hpp"
43 #include "vkStrUtil.hpp"
44 #include "vkRefUtil.hpp"
45 #include "vkTypeUtil.hpp"
46 #include "vkQueryUtil.hpp"
47 #include "vkDeviceUtil.hpp"
48 #include "vkImageUtil.hpp"
49
50 #include "gluShaderUtil.hpp"
51
52 using std::vector;
53 using namespace vk;
54
55 namespace vkt
56 {
57 namespace shaderexecutor
58 {
59 namespace
60 {
61
62 enum
63 {
64 DEFAULT_RENDER_WIDTH = 100,
65 DEFAULT_RENDER_HEIGHT = 100,
66 };
67
68 // Shader utilities
69
getDefaultClearColor(void)70 static VkClearValue getDefaultClearColor (void)
71 {
72 return makeClearValueColorF32(0.125f, 0.25f, 0.5f, 1.0f);
73 }
74
checkSupported(const Context & ctx,glu::ShaderType shaderType)75 static void checkSupported (const Context& ctx, glu::ShaderType shaderType)
76 {
77 const VkPhysicalDeviceFeatures& features = ctx.getDeviceFeatures();
78
79 if (shaderType == glu::SHADERTYPE_GEOMETRY && !features.geometryShader)
80 TCU_THROW(NotSupportedError, "Geometry shader type not supported by device");
81 else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL && !features.tessellationShader)
82 TCU_THROW(NotSupportedError, "Tessellation shader type not supported by device");
83 else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION && !features.tessellationShader)
84 TCU_THROW(NotSupportedError, "Tessellation shader type not supported by device");
85 }
86
generateEmptyFragmentSource()87 static std::string generateEmptyFragmentSource ()
88 {
89 std::ostringstream src;
90
91 src << "#version 310 es\n"
92 "layout(location=0) out highp vec4 o_color;\n";
93
94 src << "void main (void)\n{\n";
95 src << " o_color = vec4(0.0);\n";
96 src << "}\n";
97
98 return src.str();
99 }
100
generatePassthroughVertexShader(const std::vector<Symbol> & inputs,const char * inputPrefix,const char * outputPrefix)101 static std::string generatePassthroughVertexShader (const std::vector<Symbol>& inputs, const char* inputPrefix, const char* outputPrefix)
102 {
103
104 std::ostringstream src;
105 int location = 0;
106
107 src << "#version 310 es\n"
108 "layout(location = " << location << ") in highp vec4 a_position;\n";
109
110 for (vector<Symbol>::const_iterator input = inputs.begin(); input != inputs.end(); ++input)
111 {
112 location++;
113 src << "layout(location = "<< location << ") in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n"
114 << "layout(location = " << location - 1 << ") flat out " << glu::declare(input->varType, outputPrefix + input->name) << ";\n";
115 }
116
117 src << "\nvoid main (void)\n{\n"
118 << " gl_Position = a_position;\n"
119 << " gl_PointSize = 1.0;\n";
120
121 for (vector<Symbol>::const_iterator input = inputs.begin(); input != inputs.end(); ++input)
122 src << "\t" << outputPrefix << input->name << " = " << inputPrefix << input->name << ";\n";
123
124 src << "}\n";
125
126 return src.str();
127 }
128
generateVertexShader(const ShaderSpec & shaderSpec,const std::string & inputPrefix,const std::string & outputPrefix)129 static std::string generateVertexShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix)
130 {
131 DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty());
132
133 std::ostringstream src;
134
135 src << "#version 310 es\n";
136
137 if (!shaderSpec.globalDeclarations.empty())
138 src << shaderSpec.globalDeclarations << "\n";
139
140 src << "layout(location = 0) in highp vec4 a_position;\n";
141
142 int locationNumber = 1;
143 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input, ++locationNumber)
144 src << "layout(location = " << locationNumber << ") in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n";
145
146 locationNumber = 0;
147 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output, ++locationNumber)
148 {
149 DE_ASSERT(output->varType.isBasicType());
150
151 if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
152 {
153 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType());
154 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
155 const glu::VarType intType (intBaseType, glu::PRECISION_HIGHP);
156
157 src << "layout(location = " << locationNumber << ") flat out " << glu::declare(intType, outputPrefix + output->name) << ";\n";
158 }
159 else
160 src << "layout(location = " << locationNumber << ") flat out " << glu::declare(output->varType, outputPrefix + output->name) << ";\n";
161 }
162
163 src << "\n"
164 << "void main (void)\n"
165 << "{\n"
166 << " gl_Position = a_position;\n"
167 << " gl_PointSize = 1.0;\n";
168
169 // Declare & fetch local input variables
170 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
171 src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n";
172
173 // Declare local output variables
174 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
175 src << "\t" << glu::declare(output->varType, output->name) << ";\n";
176
177 // Operation - indented to correct level.
178 {
179 std::istringstream opSrc (shaderSpec.source);
180 std::string line;
181
182 while (std::getline(opSrc, line))
183 src << "\t" << line << "\n";
184 }
185
186 // Assignments to outputs.
187 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
188 {
189 if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
190 {
191 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType());
192 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
193
194 src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n";
195 }
196 else
197 src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n";
198 }
199
200 src << "}\n";
201
202 return src.str();
203 }
204
205 struct FragmentOutputLayout
206 {
207 std::vector<const Symbol*> locationSymbols; //! Symbols by location
208 std::map<std::string, int> locationMap; //! Map from symbol name to start location
209 };
210
generateFragShaderOutputDecl(std::ostream & src,const ShaderSpec & shaderSpec,bool useIntOutputs,const std::map<std::string,int> & outLocationMap,const std::string & outputPrefix)211 static void generateFragShaderOutputDecl (std::ostream& src, const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& outputPrefix)
212 {
213 for (int outNdx = 0; outNdx < (int)shaderSpec.outputs.size(); ++outNdx)
214 {
215 const Symbol& output = shaderSpec.outputs[outNdx];
216 const int location = de::lookup(outLocationMap, output.name);
217 const std::string outVarName = outputPrefix + output.name;
218 glu::VariableDeclaration decl (output.varType, outVarName, glu::STORAGE_OUT, glu::INTERPOLATION_LAST, glu::Layout(location));
219
220 TCU_CHECK_INTERNAL(output.varType.isBasicType());
221
222 if (useIntOutputs && glu::isDataTypeFloatOrVec(output.varType.getBasicType()))
223 {
224 const int vecSize = glu::getDataTypeScalarSize(output.varType.getBasicType());
225 const glu::DataType uintBasicType = vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT;
226 const glu::VarType uintType (uintBasicType, glu::PRECISION_HIGHP);
227
228 decl.varType = uintType;
229 src << decl << ";\n";
230 }
231 else if (glu::isDataTypeBoolOrBVec(output.varType.getBasicType()))
232 {
233 const int vecSize = glu::getDataTypeScalarSize(output.varType.getBasicType());
234 const glu::DataType intBasicType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
235 const glu::VarType intType (intBasicType, glu::PRECISION_HIGHP);
236
237 decl.varType = intType;
238 src << decl << ";\n";
239 }
240 else if (glu::isDataTypeMatrix(output.varType.getBasicType()))
241 {
242 const int vecSize = glu::getDataTypeMatrixNumRows(output.varType.getBasicType());
243 const int numVecs = glu::getDataTypeMatrixNumColumns(output.varType.getBasicType());
244 const glu::DataType uintBasicType = glu::getDataTypeUintVec(vecSize);
245 const glu::VarType uintType (uintBasicType, glu::PRECISION_HIGHP);
246
247 decl.varType = uintType;
248 for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx)
249 {
250 decl.name = outVarName + "_" + de::toString(vecNdx);
251 decl.layout.location = location + vecNdx;
252 src << decl << ";\n";
253 }
254 }
255 else
256 src << decl << ";\n";
257 }
258 }
259
generateFragShaderOutAssign(std::ostream & src,const ShaderSpec & shaderSpec,bool useIntOutputs,const std::string & valuePrefix,const std::string & outputPrefix)260 static void generateFragShaderOutAssign (std::ostream& src, const ShaderSpec& shaderSpec, bool useIntOutputs, const std::string& valuePrefix, const std::string& outputPrefix)
261 {
262 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
263 {
264 if (useIntOutputs && glu::isDataTypeFloatOrVec(output->varType.getBasicType()))
265 src << " o_" << output->name << " = floatBitsToUint(" << valuePrefix << output->name << ");\n";
266 else if (glu::isDataTypeMatrix(output->varType.getBasicType()))
267 {
268 const int numVecs = glu::getDataTypeMatrixNumColumns(output->varType.getBasicType());
269
270 for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx)
271 if (useIntOutputs)
272 src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = floatBitsToUint(" << valuePrefix << output->name << "[" << vecNdx << "]);\n";
273 else
274 src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = " << valuePrefix << output->name << "[" << vecNdx << "];\n";
275 }
276 else if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
277 {
278 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType());
279 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
280
281 src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << valuePrefix << output->name << ");\n";
282 }
283 else
284 src << "\t" << outputPrefix << output->name << " = " << valuePrefix << output->name << ";\n";
285 }
286 }
287
generatePassthroughFragmentShader(const ShaderSpec & shaderSpec,bool useIntOutputs,const std::map<std::string,int> & outLocationMap,const std::string & inputPrefix,const std::string & outputPrefix)288 static std::string generatePassthroughFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& inputPrefix, const std::string& outputPrefix)
289 {
290 std::ostringstream src;
291
292 src << "#version 310 es\n";
293
294 if (!shaderSpec.globalDeclarations.empty())
295 src << shaderSpec.globalDeclarations << "\n";
296
297 int locationNumber = 0;
298 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output, ++locationNumber)
299 {
300 if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
301 {
302 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType());
303 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
304 const glu::VarType intType (intBaseType, glu::PRECISION_HIGHP);
305
306 src << "layout(location = " << locationNumber << ") flat in " << glu::declare(intType, inputPrefix + output->name) << ";\n";
307 }
308 else
309 src << "layout(location = " << locationNumber << ") flat in " << glu::declare(output->varType, inputPrefix + output->name) << ";\n";
310 }
311
312 generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix);
313
314 src << "\nvoid main (void)\n{\n";
315
316 generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, inputPrefix, outputPrefix);
317
318 src << "}\n";
319
320 return src.str();
321 }
322
generateGeometryShader(const ShaderSpec & shaderSpec,const std::string & inputPrefix,const std::string & outputPrefix)323 static std::string generateGeometryShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix)
324 {
325 DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty());
326
327 std::ostringstream src;
328
329 src << "#version 310 es\n"
330 "#extension GL_EXT_geometry_shader : require\n";
331
332 if (!shaderSpec.globalDeclarations.empty())
333 src << shaderSpec.globalDeclarations << "\n";
334
335 src << "layout(points) in;\n"
336 << "layout(points, max_vertices = 1) out;\n";
337
338 int locationNumber = 0;
339 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input, ++locationNumber)
340 src << "layout(location = " << locationNumber << ") flat in " << glu::declare(input->varType, inputPrefix + input->name) << "[];\n";
341
342 locationNumber = 0;
343 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output, ++locationNumber)
344 {
345 DE_ASSERT(output->varType.isBasicType());
346
347 if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
348 {
349 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType());
350 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
351 const glu::VarType intType (intBaseType, glu::PRECISION_HIGHP);
352
353 src << "layout(location = " << locationNumber << ") flat out " << glu::declare(intType, outputPrefix + output->name) << ";\n";
354 }
355 else
356 src << "layout(location = " << locationNumber << ") flat out " << glu::declare(output->varType, outputPrefix + output->name) << ";\n";
357 }
358
359 src << "\n"
360 << "void main (void)\n"
361 << "{\n"
362 << " gl_Position = gl_in[0].gl_Position;\n\n";
363
364 // Fetch input variables
365 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
366 src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << "[0];\n";
367
368 // Declare local output variables.
369 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
370 src << "\t" << glu::declare(output->varType, output->name) << ";\n";
371
372 src << "\n";
373
374 // Operation - indented to correct level.
375 {
376 std::istringstream opSrc (shaderSpec.source);
377 std::string line;
378
379 while (std::getline(opSrc, line))
380 src << "\t" << line << "\n";
381 }
382
383 // Assignments to outputs.
384 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
385 {
386 if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
387 {
388 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType());
389 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
390
391 src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n";
392 }
393 else
394 src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n";
395 }
396
397 src << " EmitVertex();\n"
398 << " EndPrimitive();\n"
399 << "}\n";
400
401 return src.str();
402 }
403
generateFragmentShader(const ShaderSpec & shaderSpec,bool useIntOutputs,const std::map<std::string,int> & outLocationMap,const std::string & inputPrefix,const std::string & outputPrefix)404 static std::string generateFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& inputPrefix, const std::string& outputPrefix)
405 {
406 std::ostringstream src;
407 src << "#version 310 es\n";
408 if (!shaderSpec.globalDeclarations.empty())
409 src << shaderSpec.globalDeclarations << "\n";
410
411 int locationNumber = 0;
412 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input, ++locationNumber)
413 src << "layout(location = " << locationNumber << ") flat in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n";
414
415 generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix);
416
417 src << "\nvoid main (void)\n{\n";
418
419 // Declare & fetch local input variables
420 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
421 src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n";
422
423 // Declare output variables
424 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
425 src << "\t" << glu::declare(output->varType, output->name) << ";\n";
426
427 // Operation - indented to correct level.
428 {
429 std::istringstream opSrc (shaderSpec.source);
430 std::string line;
431
432 while (std::getline(opSrc, line))
433 src << "\t" << line << "\n";
434 }
435
436 generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, "", outputPrefix);
437
438 src << "}\n";
439
440 return src.str();
441 }
442
443 // FragmentOutExecutor
444
445 class FragmentOutExecutor : public ShaderExecutor
446 {
447 public:
448 FragmentOutExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType);
449 virtual ~FragmentOutExecutor (void);
450
451 virtual void execute (const Context& ctx,
452 int numValues,
453 const void* const* inputs,
454 void* const* outputs);
455
456 protected:
457 const FragmentOutputLayout m_outputLayout;
458 private:
459 void bindAttributes (const Context& ctx,
460 Allocator& memAlloc,
461 int numValues,
462 const void* const* inputs);
463
464 void addAttribute (const Context& ctx,
465 Allocator& memAlloc,
466 deUint32 bindingLocation,
467 VkFormat format,
468 deUint32 sizePerElement,
469 deUint32 count,
470 const void* dataPtr);
471 // reinit render data members
472 virtual void clearRenderData (void);
473
474 typedef de::SharedPtr<Unique<VkImage> > VkImageSp;
475 typedef de::SharedPtr<Unique<VkImageView> > VkImageViewSp;
476 typedef de::SharedPtr<Unique<VkBuffer> > VkBufferSp;
477 typedef de::SharedPtr<de::UniquePtr<Allocation> > AllocationSp;
478
479 std::vector<VkVertexInputBindingDescription> m_vertexBindingDescriptions;
480 std::vector<VkVertexInputAttributeDescription> m_vertexAttributeDescriptions;
481 std::vector<VkBufferSp> m_vertexBuffers;
482 std::vector<AllocationSp> m_vertexBufferAllocs;
483 };
484
computeFragmentOutputLayout(const std::vector<Symbol> & symbols)485 static FragmentOutputLayout computeFragmentOutputLayout (const std::vector<Symbol>& symbols)
486 {
487 FragmentOutputLayout ret;
488 int location = 0;
489
490 for (std::vector<Symbol>::const_iterator it = symbols.begin(); it != symbols.end(); ++it)
491 {
492 const int numLocations = glu::getDataTypeNumLocations(it->varType.getBasicType());
493
494 TCU_CHECK_INTERNAL(!de::contains(ret.locationMap, it->name));
495 de::insert(ret.locationMap, it->name, location);
496 location += numLocations;
497
498 for (int ndx = 0; ndx < numLocations; ++ndx)
499 ret.locationSymbols.push_back(&*it);
500 }
501
502 return ret;
503 }
504
FragmentOutExecutor(const ShaderSpec & shaderSpec,glu::ShaderType shaderType)505 FragmentOutExecutor::FragmentOutExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
506 : ShaderExecutor (shaderSpec, shaderType)
507 , m_outputLayout (computeFragmentOutputLayout(m_shaderSpec.outputs))
508 {
509 }
510
~FragmentOutExecutor(void)511 FragmentOutExecutor::~FragmentOutExecutor (void)
512 {
513 }
514
computeVertexPositions(int numValues,const tcu::IVec2 & renderSize)515 static std::vector<tcu::Vec2> computeVertexPositions (int numValues, const tcu::IVec2& renderSize)
516 {
517 std::vector<tcu::Vec2> positions(numValues);
518 for (int valNdx = 0; valNdx < numValues; valNdx++)
519 {
520 const int ix = valNdx % renderSize.x();
521 const int iy = valNdx / renderSize.x();
522 const float fx = -1.0f + 2.0f*((float(ix) + 0.5f) / float(renderSize.x()));
523 const float fy = -1.0f + 2.0f*((float(iy) + 0.5f) / float(renderSize.y()));
524
525 positions[valNdx] = tcu::Vec2(fx, fy);
526 }
527
528 return positions;
529 }
530
getRenderbufferFormatForOutput(const glu::VarType & outputType,bool useIntOutputs)531 static tcu::TextureFormat getRenderbufferFormatForOutput (const glu::VarType& outputType, bool useIntOutputs)
532 {
533 const tcu::TextureFormat::ChannelOrder channelOrderMap[] =
534 {
535 tcu::TextureFormat::R,
536 tcu::TextureFormat::RG,
537 tcu::TextureFormat::RGBA, // No RGB variants available.
538 tcu::TextureFormat::RGBA
539 };
540
541 const glu::DataType basicType = outputType.getBasicType();
542 const int numComps = glu::getDataTypeNumComponents(basicType);
543 tcu::TextureFormat::ChannelType channelType;
544
545 switch (glu::getDataTypeScalarType(basicType))
546 {
547 case glu::TYPE_UINT: channelType = tcu::TextureFormat::UNSIGNED_INT32; break;
548 case glu::TYPE_INT: channelType = tcu::TextureFormat::SIGNED_INT32; break;
549 case glu::TYPE_BOOL: channelType = tcu::TextureFormat::SIGNED_INT32; break;
550 case glu::TYPE_FLOAT: channelType = useIntOutputs ? tcu::TextureFormat::UNSIGNED_INT32 : tcu::TextureFormat::FLOAT; break;
551 default:
552 throw tcu::InternalError("Invalid output type");
553 }
554
555 DE_ASSERT(de::inRange<int>(numComps, 1, DE_LENGTH_OF_ARRAY(channelOrderMap)));
556
557 return tcu::TextureFormat(channelOrderMap[numComps-1], channelType);
558 }
559
getAttributeFormat(const glu::DataType dataType)560 static VkFormat getAttributeFormat (const glu::DataType dataType)
561 {
562 switch (dataType)
563 {
564 case glu::TYPE_FLOAT: return VK_FORMAT_R32_SFLOAT;
565 case glu::TYPE_FLOAT_VEC2: return VK_FORMAT_R32G32_SFLOAT;
566 case glu::TYPE_FLOAT_VEC3: return VK_FORMAT_R32G32B32_SFLOAT;
567 case glu::TYPE_FLOAT_VEC4: return VK_FORMAT_R32G32B32A32_SFLOAT;
568
569 case glu::TYPE_INT: return VK_FORMAT_R32_SINT;
570 case glu::TYPE_INT_VEC2: return VK_FORMAT_R32G32_SINT;
571 case glu::TYPE_INT_VEC3: return VK_FORMAT_R32G32B32_SINT;
572 case glu::TYPE_INT_VEC4: return VK_FORMAT_R32G32B32A32_SINT;
573
574 case glu::TYPE_UINT: return VK_FORMAT_R32_UINT;
575 case glu::TYPE_UINT_VEC2: return VK_FORMAT_R32G32_UINT;
576 case glu::TYPE_UINT_VEC3: return VK_FORMAT_R32G32B32_UINT;
577 case glu::TYPE_UINT_VEC4: return VK_FORMAT_R32G32B32A32_UINT;
578
579 case glu::TYPE_FLOAT_MAT2: return VK_FORMAT_R32G32_SFLOAT;
580 case glu::TYPE_FLOAT_MAT2X3: return VK_FORMAT_R32G32B32_SFLOAT;
581 case glu::TYPE_FLOAT_MAT2X4: return VK_FORMAT_R32G32B32A32_SFLOAT;
582 case glu::TYPE_FLOAT_MAT3X2: return VK_FORMAT_R32G32_SFLOAT;
583 case glu::TYPE_FLOAT_MAT3: return VK_FORMAT_R32G32B32_SFLOAT;
584 case glu::TYPE_FLOAT_MAT3X4: return VK_FORMAT_R32G32B32A32_SFLOAT;
585 case glu::TYPE_FLOAT_MAT4X2: return VK_FORMAT_R32G32_SFLOAT;
586 case glu::TYPE_FLOAT_MAT4X3: return VK_FORMAT_R32G32B32_SFLOAT;
587 case glu::TYPE_FLOAT_MAT4: return VK_FORMAT_R32G32B32A32_SFLOAT;
588 default:
589 DE_ASSERT(false);
590 return VK_FORMAT_UNDEFINED;
591 }
592 }
593
addAttribute(const Context & ctx,Allocator & memAlloc,deUint32 bindingLocation,VkFormat format,deUint32 sizePerElement,deUint32 count,const void * dataPtr)594 void FragmentOutExecutor::addAttribute (const Context& ctx, Allocator& memAlloc, deUint32 bindingLocation, VkFormat format, deUint32 sizePerElement, deUint32 count, const void* dataPtr)
595 {
596 // Add binding specification
597 const deUint32 binding = (deUint32)m_vertexBindingDescriptions.size();
598 const VkVertexInputBindingDescription bindingDescription =
599 {
600 binding,
601 sizePerElement,
602 VK_VERTEX_INPUT_RATE_VERTEX
603 };
604
605 m_vertexBindingDescriptions.push_back(bindingDescription);
606
607 // Add location and format specification
608 const VkVertexInputAttributeDescription attributeDescription =
609 {
610 bindingLocation, // deUint32 location;
611 binding, // deUint32 binding;
612 format, // VkFormat format;
613 0u, // deUint32 offsetInBytes;
614 };
615
616 m_vertexAttributeDescriptions.push_back(attributeDescription);
617
618 // Upload data to buffer
619 const VkDevice vkDevice = ctx.getDevice();
620 const DeviceInterface& vk = ctx.getDeviceInterface();
621 const deUint32 queueFamilyIndex = ctx.getUniversalQueueFamilyIndex();
622
623 const VkDeviceSize inputSize = sizePerElement * count;
624 const VkBufferCreateInfo vertexBufferParams =
625 {
626 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
627 DE_NULL, // const void* pNext;
628 0u, // VkBufferCreateFlags flags;
629 inputSize, // VkDeviceSize size;
630 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
631 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
632 1u, // deUint32 queueFamilyCount;
633 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
634 };
635
636 Move<VkBuffer> buffer = createBuffer(vk, vkDevice, &vertexBufferParams);
637 de::MovePtr<Allocation> alloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
638 VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
639
640 deMemcpy(alloc->getHostPtr(), dataPtr, (size_t)inputSize);
641 flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), inputSize);
642
643 m_vertexBuffers.push_back(de::SharedPtr<Unique<VkBuffer> >(new Unique<VkBuffer>(buffer)));
644 m_vertexBufferAllocs.push_back(de::SharedPtr<de::UniquePtr<Allocation> >(new de::UniquePtr<Allocation>(alloc)));
645 }
646
bindAttributes(const Context & ctx,Allocator & memAlloc,int numValues,const void * const * inputs)647 void FragmentOutExecutor::bindAttributes (const Context& ctx, Allocator& memAlloc, int numValues, const void* const* inputs)
648 {
649 // Input attributes
650 for (int inputNdx = 0; inputNdx < (int)m_shaderSpec.inputs.size(); inputNdx++)
651 {
652 const Symbol& symbol = m_shaderSpec.inputs[inputNdx];
653 const void* ptr = inputs[inputNdx];
654 const glu::DataType basicType = symbol.varType.getBasicType();
655 const int vecSize = glu::getDataTypeScalarSize(basicType);
656 const VkFormat format = getAttributeFormat(basicType);
657 int elementSize = 0;
658 int numAttrsToAdd = 1;
659
660 if (glu::isDataTypeFloatOrVec(basicType))
661 elementSize = sizeof(float);
662 else if (glu::isDataTypeIntOrIVec(basicType))
663 elementSize = sizeof(int);
664 else if (glu::isDataTypeUintOrUVec(basicType))
665 elementSize = sizeof(deUint32);
666 else if (glu::isDataTypeMatrix(basicType))
667 {
668 int numRows = glu::getDataTypeMatrixNumRows(basicType);
669 int numCols = glu::getDataTypeMatrixNumColumns(basicType);
670
671 elementSize = numRows * numCols * (int)sizeof(float);
672 numAttrsToAdd = numCols;
673 }
674 else
675 DE_ASSERT(false);
676
677 // add attributes, in case of matrix every column is binded as an attribute
678 for (int attrNdx = 0; attrNdx < numAttrsToAdd; attrNdx++)
679 {
680 addAttribute(ctx, memAlloc, (deUint32)m_vertexBindingDescriptions.size(), format, elementSize * vecSize, numValues, ptr);
681 }
682 }
683 }
684
clearRenderData(void)685 void FragmentOutExecutor::clearRenderData (void)
686 {
687 m_vertexBindingDescriptions.clear();
688 m_vertexAttributeDescriptions.clear();
689 m_vertexBuffers.clear();
690 m_vertexBufferAllocs.clear();
691 }
692
execute(const Context & ctx,int numValues,const void * const * inputs,void * const * outputs)693 void FragmentOutExecutor::execute (const Context& ctx, int numValues, const void* const* inputs, void* const* outputs)
694 {
695 checkSupported(ctx, m_shaderType);
696
697 const VkDevice vkDevice = ctx.getDevice();
698 const DeviceInterface& vk = ctx.getDeviceInterface();
699 const VkQueue queue = ctx.getUniversalQueue();
700 const deUint32 queueFamilyIndex = ctx.getUniversalQueueFamilyIndex();
701 Allocator& memAlloc = ctx.getDefaultAllocator();
702
703 const deUint32 renderSizeX = de::min(static_cast<deUint32>(DEFAULT_RENDER_WIDTH), (deUint32)numValues);
704 const deUint32 renderSizeY = ((deUint32)numValues / renderSizeX) + (((deUint32)numValues % renderSizeX != 0) ? 1u : 0u);
705 const tcu::UVec2 renderSize (renderSizeX, renderSizeY);
706 std::vector<tcu::Vec2> positions;
707
708 const bool useGeometryShader = m_shaderType == glu::SHADERTYPE_GEOMETRY;
709
710 std::vector<VkImageSp> colorImages;
711 std::vector<VkImageMemoryBarrier> colorImagePreRenderBarriers;
712 std::vector<VkImageMemoryBarrier> colorImagePostRenderBarriers;
713 std::vector<AllocationSp> colorImageAllocs;
714 std::vector<VkAttachmentDescription> attachments;
715 std::vector<VkClearValue> attachmentClearValues;
716 std::vector<VkImageViewSp> colorImageViews;
717
718 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
719 std::vector<VkAttachmentReference> colorAttachmentReferences;
720
721 Move<VkRenderPass> renderPass;
722 Move<VkFramebuffer> framebuffer;
723 Move<VkPipelineLayout> pipelineLayout;
724 Move<VkPipeline> graphicsPipeline;
725
726 Move<VkShaderModule> vertexShaderModule;
727 Move<VkShaderModule> geometryShaderModule;
728 Move<VkShaderModule> fragmentShaderModule;
729
730 Move<VkCommandPool> cmdPool;
731 Move<VkCommandBuffer> cmdBuffer;
732
733 Move<VkFence> fence;
734
735 Move<VkDescriptorPool> descriptorPool;
736 Move<VkDescriptorSetLayout> descriptorSetLayout;
737 Move<VkDescriptorSet> descriptorSet;
738
739 clearRenderData();
740
741 // Compute positions - 1px points are used to drive fragment shading.
742 positions = computeVertexPositions(numValues, renderSize.cast<int>());
743
744 // Bind attributes
745 addAttribute(ctx, memAlloc, 0u, VK_FORMAT_R32G32_SFLOAT, sizeof(tcu::Vec2), (deUint32)positions.size(), &positions[0]);
746 bindAttributes(ctx, memAlloc, numValues, inputs);
747
748 // Create color images
749 {
750 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
751 {
752 VK_FALSE, // VkBool32 blendEnable;
753 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
754 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
755 VK_BLEND_OP_ADD, // VkBlendOp blendOpColor;
756 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
757 VK_BLEND_FACTOR_ZERO, // VkBlendFactor destAlphaBlendFactor;
758 VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha;
759 (VK_COLOR_COMPONENT_R_BIT |
760 VK_COLOR_COMPONENT_G_BIT |
761 VK_COLOR_COMPONENT_B_BIT |
762 VK_COLOR_COMPONENT_A_BIT) // VkColorComponentFlags colorWriteMask;
763 };
764
765 for (int outNdx = 0; outNdx < (int)m_outputLayout.locationSymbols.size(); ++outNdx)
766 {
767 const bool isFloat = isDataTypeFloatOrVec(m_shaderSpec.outputs[outNdx].varType.getBasicType());
768 const bool isSigned = isDataTypeIntOrIVec (m_shaderSpec.outputs[outNdx].varType.getBasicType());
769 const bool isBool = isDataTypeBoolOrBVec(m_shaderSpec.outputs[outNdx].varType.getBasicType());
770 const VkFormat colorFormat = isFloat ? VK_FORMAT_R32G32B32A32_SFLOAT : (isSigned || isBool ? VK_FORMAT_R32G32B32A32_SINT : VK_FORMAT_R32G32B32A32_UINT);
771
772 const VkImageCreateInfo colorImageParams =
773 {
774 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
775 DE_NULL, // const void* pNext;
776 0u, // VkImageCreateFlags flags;
777 VK_IMAGE_TYPE_2D, // VkImageType imageType;
778 colorFormat, // VkFormat format;
779 { renderSize.x(), renderSize.y(), 1u }, // VkExtent3D extent;
780 1u, // deUint32 mipLevels;
781 1u, // deUint32 arraySize;
782 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
783 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
784 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
785 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
786 1u, // deUint32 queueFamilyCount;
787 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
788 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
789 };
790
791 const VkAttachmentDescription colorAttachmentDescription =
792 {
793 0u, // VkAttachmentDescriptorFlags flags;
794 colorFormat, // VkFormat format;
795 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
796 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
797 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
798 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
799 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
800 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
801 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
802 };
803
804 Move<VkImage> colorImage = createImage(vk, vkDevice, &colorImageParams);
805 colorImages.push_back(de::SharedPtr<Unique<VkImage> >(new Unique<VkImage>(colorImage)));
806 attachmentClearValues.push_back(getDefaultClearColor());
807
808 // Allocate and bind color image memory
809 {
810 de::MovePtr<Allocation> colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *((const VkImage*) colorImages.back().get())), MemoryRequirement::Any);
811 VK_CHECK(vk.bindImageMemory(vkDevice, colorImages.back().get()->get(), colorImageAlloc->getMemory(), colorImageAlloc->getOffset()));
812 colorImageAllocs.push_back(de::SharedPtr<de::UniquePtr<Allocation> >(new de::UniquePtr<Allocation>(colorImageAlloc)));
813
814 attachments.push_back(colorAttachmentDescription);
815 colorBlendAttachmentStates.push_back(colorBlendAttachmentState);
816
817 const VkAttachmentReference colorAttachmentReference = {
818 (deUint32) (colorImages.size() - 1), // deUint32 attachment;
819 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
820 };
821
822 colorAttachmentReferences.push_back(colorAttachmentReference);
823 }
824
825 // Create color attachment view
826 {
827 const VkImageViewCreateInfo colorImageViewParams =
828 {
829 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
830 DE_NULL, // const void* pNext;
831 0u, // VkImageViewCreateFlags flags;
832 colorImages.back().get()->get(), // VkImage image;
833 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
834 colorFormat, // VkFormat format;
835 {
836 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
837 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
838 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
839 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
840 }, // VkComponentMapping components;
841 {
842 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
843 0u, // deUint32 baseMipLevel;
844 1u, // deUint32 mipLevels;
845 0u, // deUint32 baseArraySlice;
846 1u // deUint32 arraySize;
847 } // VkImageSubresourceRange subresourceRange;
848 };
849
850 Move<VkImageView> colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
851 colorImageViews.push_back(de::SharedPtr<Unique<VkImageView> >(new Unique<VkImageView>(colorImageView)));
852
853 const VkImageMemoryBarrier colorImagePreRenderBarrier =
854 {
855 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
856 DE_NULL, // pNext
857 0u, // srcAccessMask
858 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
859 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), // dstAccessMask
860 VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
861 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
862 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
863 VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex
864 colorImages.back().get()->get(), // image
865 {
866 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
867 0u, // baseMipLevel
868 1u, // levelCount
869 0u, // baseArrayLayer
870 1u, // layerCount
871 } // subresourceRange
872 };
873 colorImagePreRenderBarriers.push_back(colorImagePreRenderBarrier);
874
875 const VkImageMemoryBarrier colorImagePostRenderBarrier =
876 {
877 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
878 DE_NULL, // pNext
879 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
880 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), // srcAccessMask
881 VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask
882 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
883 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
884 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
885 VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex
886 colorImages.back().get()->get(), // image
887 {
888 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
889 0u, // baseMipLevel
890 1u, // levelCount
891 0u, // baseArrayLayer
892 1u, // layerCount
893 } // subresourceRange
894 };
895 colorImagePostRenderBarriers.push_back(colorImagePostRenderBarrier);
896 }
897 }
898 }
899
900 // Create render pass
901 {
902 const VkSubpassDescription subpassDescription =
903 {
904 0u, // VkSubpassDescriptionFlags flags;
905 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
906 0u, // deUint32 inputCount;
907 DE_NULL, // const VkAttachmentReference* pInputAttachments;
908 (deUint32)colorImages.size(), // deUint32 colorCount;
909 &colorAttachmentReferences[0], // const VkAttachmentReference* colorAttachments;
910 DE_NULL, // const VkAttachmentReference* resolveAttachments;
911 DE_NULL, // VkAttachmentReference depthStencilAttachment;
912 0u, // deUint32 preserveCount;
913 DE_NULL // const VkAttachmentReference* pPreserveAttachments;
914 };
915
916 const VkRenderPassCreateInfo renderPassParams =
917 {
918 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
919 DE_NULL, // const void* pNext;
920 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
921 (deUint32)attachments.size(), // deUint32 attachmentCount;
922 &attachments[0], // const VkAttachmentDescription* pAttachments;
923 1u, // deUint32 subpassCount;
924 &subpassDescription, // const VkSubpassDescription* pSubpasses;
925 0u, // deUint32 dependencyCount;
926 DE_NULL // const VkSubpassDependency* pDependencies;
927 };
928
929 renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
930 }
931
932 // Create framebuffer
933 {
934 std::vector<VkImageView> views(colorImageViews.size());
935 for (size_t i = 0; i < colorImageViews.size(); i++)
936 {
937 views[i] = colorImageViews[i].get()->get();
938 }
939
940 const VkFramebufferCreateInfo framebufferParams =
941 {
942 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
943 DE_NULL, // const void* pNext;
944 0u, // VkFramebufferCreateFlags flags;
945 *renderPass, // VkRenderPass renderPass;
946 (deUint32)views.size(), // deUint32 attachmentCount;
947 &views[0], // const VkImageView* pAttachments;
948 (deUint32)renderSize.x(), // deUint32 width;
949 (deUint32)renderSize.y(), // deUint32 height;
950 1u // deUint32 layers;
951 };
952
953 framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
954 }
955
956 // Create descriptors
957 {
958 addUniforms(vkDevice, vk, queue, queueFamilyIndex, memAlloc);
959
960 descriptorSetLayout = m_descriptorSetLayoutBuilder.build(vk, vkDevice);
961 if (!m_uniformInfos.empty())
962 descriptorPool = m_descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
963 else
964 {
965 const VkDescriptorPoolSize poolSizeCount = { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1 };
966 const VkDescriptorPoolCreateInfo createInfo =
967 {
968 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
969 DE_NULL,
970 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
971 1u,
972 1u,
973 &poolSizeCount,
974 };
975
976 descriptorPool = createDescriptorPool(vk, vkDevice, &createInfo);
977 }
978
979 const VkDescriptorSetAllocateInfo allocInfo =
980 {
981 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
982 DE_NULL,
983 *descriptorPool,
984 1u,
985 &*descriptorSetLayout
986 };
987
988 descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
989
990 // Update descriptors
991 {
992 vk::DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
993
994 uploadUniforms(descriptorSetUpdateBuilder, *descriptorSet);
995
996 descriptorSetUpdateBuilder.update(vk, vkDevice);
997 }
998 }
999
1000 // Create pipeline layout
1001 {
1002 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1003 {
1004 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1005 DE_NULL, // const void* pNext;
1006 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
1007 1, // deUint32 descriptorSetCount;
1008 &*descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts;
1009 0u, // deUint32 pushConstantRangeCount;
1010 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
1011 };
1012
1013 pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1014 }
1015
1016 // Create shaders
1017 {
1018 vertexShaderModule = createShaderModule(vk, vkDevice, ctx.getBinaryCollection().get("vert"), 0);
1019 fragmentShaderModule = createShaderModule(vk, vkDevice, ctx.getBinaryCollection().get("frag"), 0);
1020
1021 if (useGeometryShader)
1022 {
1023 geometryShaderModule = createShaderModule(vk, vkDevice, ctx.getBinaryCollection().get("geom"), 0);
1024 }
1025 }
1026
1027 // Create pipeline
1028 {
1029 std::vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
1030
1031 const VkPipelineShaderStageCreateInfo vertexShaderStageParams =
1032 {
1033 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1034 DE_NULL, // const void* pNext;
1035 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
1036 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
1037 *vertexShaderModule, // VkShaderModule module;
1038 "main", // const char* pName;
1039 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
1040 };
1041
1042 const VkPipelineShaderStageCreateInfo fragmentShaderStageParams =
1043 {
1044 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1045 DE_NULL, // const void* pNext;
1046 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
1047 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
1048 *fragmentShaderModule, // VkShaderModule module;
1049 "main", // const char* pName;
1050 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
1051 };
1052
1053 shaderStageParams.push_back(vertexShaderStageParams);
1054 shaderStageParams.push_back(fragmentShaderStageParams);
1055
1056 if (useGeometryShader)
1057 {
1058 const VkPipelineShaderStageCreateInfo geometryShaderStageParams =
1059 {
1060 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1061 DE_NULL, // const void* pNext;
1062 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
1063 VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage;
1064 *geometryShaderModule, // VkShaderModule module;
1065 "main", // VkShader shader;
1066 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
1067 };
1068
1069 shaderStageParams.push_back(geometryShaderStageParams);
1070 }
1071
1072 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1073 {
1074 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1075 DE_NULL, // const void* pNext;
1076 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
1077 (deUint32)m_vertexBindingDescriptions.size(), // deUint32 bindingCount;
1078 &m_vertexBindingDescriptions[0], // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1079 (deUint32)m_vertexAttributeDescriptions.size(), // deUint32 attributeCount;
1080 &m_vertexAttributeDescriptions[0], // const VkVertexInputAttributeDescription* pvertexAttributeDescriptions;
1081 };
1082
1083 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
1084 {
1085 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1086 DE_NULL, // const void* pNext;
1087 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
1088 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology;
1089 DE_FALSE // VkBool32 primitiveRestartEnable;
1090 };
1091
1092 const VkViewport viewport =
1093 {
1094 0.0f, // float originX;
1095 0.0f, // float originY;
1096 (float)renderSize.x(), // float width;
1097 (float)renderSize.y(), // float height;
1098 0.0f, // float minDepth;
1099 1.0f // float maxDepth;
1100 };
1101
1102 const VkRect2D scissor =
1103 {
1104 {
1105 0u, // deUint32 x;
1106 0u, // deUint32 y;
1107 }, // VkOffset2D offset;
1108 {
1109 renderSize.x(), // deUint32 width;
1110 renderSize.y(), // deUint32 height;
1111 }, // VkExtent2D extent;
1112 };
1113
1114 const VkPipelineViewportStateCreateInfo viewportStateParams =
1115 {
1116 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
1117 DE_NULL, // const void* pNext;
1118 0u, // VkPipelineViewportStateCreateFlags flags;
1119 1u, // deUint32 viewportCount;
1120 &viewport, // const VkViewport* pViewports;
1121 1u, // deUint32 scissorsCount;
1122 &scissor // const VkRect2D* pScissors;
1123 };
1124
1125 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
1126 {
1127 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1128 DE_NULL, // const void* pNext;
1129 (VkPipelineRasterizationStateCreateFlags)0u, //VkPipelineRasterizationStateCreateFlags flags;
1130 VK_FALSE, // VkBool32 depthClipEnable;
1131 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
1132 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
1133 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
1134 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
1135 VK_FALSE, // VkBool32 depthBiasEnable;
1136 0.0f, // float depthBias;
1137 0.0f, // float depthBiasClamp;
1138 0.0f, // float slopeScaledDepthBias;
1139 1.0f // float lineWidth;
1140 };
1141
1142 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1143 {
1144 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1145 DE_NULL, // const void* pNext;
1146 0u, // VkPipelineMultisampleStateCreateFlags flags;
1147 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
1148 VK_FALSE, // VkBool32 sampleShadingEnable;
1149 0.0f, // float minSampleShading;
1150 DE_NULL, // const VkSampleMask* pSampleMask;
1151 VK_FALSE, // VkBool32 alphaToCoverageEnable;
1152 VK_FALSE // VkBool32 alphaToOneEnable;
1153 };
1154
1155 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1156 {
1157 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1158 DE_NULL, // const void* pNext;
1159 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
1160 VK_FALSE, // VkBool32 logicOpEnable;
1161 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
1162 (deUint32)colorBlendAttachmentStates.size(), // deUint32 attachmentCount;
1163 &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments;
1164 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConst[4];
1165 };
1166
1167 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
1168 {
1169 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
1170 DE_NULL, // const void* pNext;
1171 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
1172 (deUint32)shaderStageParams.size(), // deUint32 stageCount;
1173 &shaderStageParams[0], // const VkPipelineShaderStageCreateInfo* pStages;
1174 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
1175 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
1176 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
1177 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
1178 &rasterStateParams, // const VkPipelineRasterStateCreateInfo* pRasterState;
1179 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
1180 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
1181 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
1182 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
1183 *pipelineLayout, // VkPipelineLayout layout;
1184 *renderPass, // VkRenderPass renderPass;
1185 0u, // deUint32 subpass;
1186 0u, // VkPipeline basePipelineHandle;
1187 0u // deInt32 basePipelineIndex;
1188 };
1189
1190 graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
1191 }
1192
1193 // Create command pool
1194 {
1195 const VkCommandPoolCreateInfo cmdPoolParams =
1196 {
1197 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
1198 DE_NULL, // const void* pNext;
1199 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags;
1200 queueFamilyIndex, // deUint32 queueFamilyIndex;
1201 };
1202
1203 cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1204 }
1205
1206 // Create command buffer
1207 {
1208 const VkCommandBufferAllocateInfo cmdBufferParams =
1209 {
1210 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1211 DE_NULL, // const void* pNext;
1212 *cmdPool, // VkCmdPool cmdPool;
1213 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
1214 1 // deUint32 bufferCount;
1215 };
1216
1217 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1218 {
1219 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1220 DE_NULL, // const void* pNext;
1221 0u, // VkCmdBufferOptimizeFlags flags;
1222 (const VkCommandBufferInheritanceInfo*)DE_NULL,
1223 };
1224
1225 const VkRenderPassBeginInfo renderPassBeginInfo =
1226 {
1227 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1228 DE_NULL, // const void* pNext;
1229 *renderPass, // VkRenderPass renderPass;
1230 *framebuffer, // VkFramebuffer framebuffer;
1231 { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // VkRect2D renderArea;
1232 (deUint32)attachmentClearValues.size(), // deUint32 attachmentCount;
1233 &attachmentClearValues[0] // const VkClearValue* pAttachmentClearValues;
1234 };
1235
1236 cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
1237
1238 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
1239
1240 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
1241 0, (const VkMemoryBarrier*)DE_NULL,
1242 0, (const VkBufferMemoryBarrier*)DE_NULL,
1243 (deUint32)colorImagePreRenderBarriers.size(), colorImagePreRenderBarriers.empty() ? DE_NULL : &colorImagePreRenderBarriers[0]);
1244 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1245
1246 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1247 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
1248
1249 const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
1250
1251 std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
1252
1253 std::vector<VkBuffer> buffers(numberOfVertexAttributes);
1254 for (size_t i = 0; i < numberOfVertexAttributes; i++)
1255 {
1256 buffers[i] = m_vertexBuffers[i].get()->get();
1257 }
1258
1259 vk.cmdBindVertexBuffers(*cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]);
1260 vk.cmdDraw(*cmdBuffer, (deUint32)positions.size(), 1u, 0u, 0u);
1261
1262 vk.cmdEndRenderPass(*cmdBuffer);
1263 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
1264 0, (const VkMemoryBarrier*)DE_NULL,
1265 0, (const VkBufferMemoryBarrier*)DE_NULL,
1266 (deUint32)colorImagePostRenderBarriers.size(), colorImagePostRenderBarriers.empty() ? DE_NULL : &colorImagePostRenderBarriers[0]);
1267
1268 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1269 }
1270
1271 // Create fence
1272 {
1273 const VkFenceCreateInfo fenceParams =
1274 {
1275 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
1276 DE_NULL, // const void* pNext;
1277 0u // VkFenceCreateFlags flags;
1278 };
1279
1280 fence = createFence(vk, vkDevice, &fenceParams);
1281 }
1282
1283 // Execute Draw
1284 {
1285
1286 const VkSubmitInfo submitInfo =
1287 {
1288 VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
1289 DE_NULL, // pNext
1290 0u, // waitSemaphoreCount
1291 DE_NULL, // pWaitSemaphores
1292 (const VkPipelineStageFlags*)DE_NULL,
1293 1u, // commandBufferCount
1294 &cmdBuffer.get(), // pCommandBuffers
1295 0u, // signalSemaphoreCount
1296 DE_NULL // pSignalSemaphores
1297 };
1298
1299 VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
1300 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
1301 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), DE_TRUE, ~(0ull) /* infinity*/));
1302 }
1303
1304 // Read back result and output
1305 {
1306 const VkDeviceSize imageSizeBytes = (VkDeviceSize)(4 * sizeof(deUint32) * renderSize.x() * renderSize.y());
1307 const VkBufferCreateInfo readImageBufferParams =
1308 {
1309 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1310 DE_NULL, // const void* pNext;
1311 0u, // VkBufferCreateFlags flags;
1312 imageSizeBytes, // VkDeviceSize size;
1313 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
1314 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1315 1u, // deUint32 queueFamilyCount;
1316 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
1317 };
1318
1319 // constants for image copy
1320
1321 const VkCommandPoolCreateInfo cmdPoolParams =
1322 {
1323 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
1324 DE_NULL, // const void* pNext;
1325 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags;
1326 queueFamilyIndex // deUint32 queueFamilyIndex;
1327 };
1328
1329 Move<VkCommandPool> copyCmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1330
1331 const VkCommandBufferAllocateInfo cmdBufferParams =
1332 {
1333 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1334 DE_NULL, // const void* pNext;
1335 *copyCmdPool, // VkCmdPool cmdPool;
1336 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
1337 1u // deUint32 bufferCount;
1338 };
1339
1340 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1341 {
1342 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1343 DE_NULL, // const void* pNext;
1344 0u, // VkCmdBufferOptimizeFlags flags;
1345 (const VkCommandBufferInheritanceInfo*)DE_NULL,
1346 };
1347
1348 const VkBufferImageCopy copyParams =
1349 {
1350 0u, // VkDeviceSize bufferOffset;
1351 (deUint32)renderSize.x(), // deUint32 bufferRowLength;
1352 (deUint32)renderSize.y(), // deUint32 bufferImageHeight;
1353 {
1354 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
1355 0u, // deUint32 mipLevel;
1356 0u, // deUint32 arraySlice;
1357 1u, // deUint32 arraySize;
1358 }, // VkImageSubresource imageSubresource;
1359 { 0u, 0u, 0u }, // VkOffset3D imageOffset;
1360 { renderSize.x(), renderSize.y(), 1u } // VkExtent3D imageExtent;
1361 };
1362
1363 // Read back pixels.
1364 for (int outNdx = 0; outNdx < (int)m_shaderSpec.outputs.size(); ++outNdx)
1365 {
1366 const Symbol& output = m_shaderSpec.outputs[outNdx];
1367 const int outSize = output.varType.getScalarSize();
1368 const int outVecSize = glu::getDataTypeNumComponents(output.varType.getBasicType());
1369 const int outNumLocs = glu::getDataTypeNumLocations(output.varType.getBasicType());
1370 deUint32* dstPtrBase = static_cast<deUint32*>(outputs[outNdx]);
1371 const int outLocation = de::lookup(m_outputLayout.locationMap, output.name);
1372
1373 for (int locNdx = 0; locNdx < outNumLocs; ++locNdx)
1374 {
1375 tcu::TextureLevel tmpBuf;
1376 const tcu::TextureFormat format = getRenderbufferFormatForOutput(output.varType, false);
1377 const tcu::TextureFormat readFormat (tcu::TextureFormat::RGBA, format.type);
1378 const Unique<VkBuffer> readImageBuffer(createBuffer(vk, vkDevice, &readImageBufferParams));
1379 const de::UniquePtr<Allocation> readImageBufferMemory(memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
1380
1381 VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
1382
1383 // Copy image to buffer
1384 {
1385
1386 Move<VkCommandBuffer> copyCmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
1387
1388 const VkSubmitInfo submitInfo =
1389 {
1390 VK_STRUCTURE_TYPE_SUBMIT_INFO,
1391 DE_NULL,
1392 0u,
1393 (const VkSemaphore*)DE_NULL,
1394 (const VkPipelineStageFlags*)DE_NULL,
1395 1u,
1396 ©CmdBuffer.get(),
1397 0u,
1398 (const VkSemaphore*)DE_NULL,
1399 };
1400
1401 VK_CHECK(vk.beginCommandBuffer(*copyCmdBuffer, &cmdBufferBeginInfo));
1402 vk.cmdCopyImageToBuffer(*copyCmdBuffer, colorImages[outLocation + locNdx].get()->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params);
1403 VK_CHECK(vk.endCommandBuffer(*copyCmdBuffer));
1404
1405 VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
1406 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
1407 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity */));
1408 }
1409
1410 const VkMappedMemoryRange range =
1411 {
1412 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
1413 DE_NULL, // const void* pNext;
1414 readImageBufferMemory->getMemory(), // VkDeviceMemory mem;
1415 0, // VkDeviceSize offset;
1416 imageSizeBytes, // VkDeviceSize size;
1417 };
1418
1419 VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range));
1420
1421 tmpBuf.setStorage(readFormat, renderSize.x(), renderSize.y());
1422
1423 const tcu::TextureFormat resultFormat(tcu::TextureFormat::RGBA, format.type);
1424 const tcu::ConstPixelBufferAccess resultAccess(resultFormat, renderSize.x(), renderSize.y(), 1, readImageBufferMemory->getHostPtr());
1425
1426 tcu::copy(tmpBuf.getAccess(), resultAccess);
1427
1428 if (outSize == 4 && outNumLocs == 1)
1429 deMemcpy(dstPtrBase, tmpBuf.getAccess().getDataPtr(), numValues * outVecSize * sizeof(deUint32));
1430 else
1431 {
1432 for (int valNdx = 0; valNdx < numValues; valNdx++)
1433 {
1434 const deUint32* srcPtr = (const deUint32*)tmpBuf.getAccess().getDataPtr() + valNdx * 4;
1435 deUint32* dstPtr = &dstPtrBase[outSize * valNdx + outVecSize * locNdx];
1436 deMemcpy(dstPtr, srcPtr, outVecSize * sizeof(deUint32));
1437 }
1438 }
1439 }
1440 }
1441 }
1442 }
1443
1444 // VertexShaderExecutor
1445
1446 class VertexShaderExecutor : public FragmentOutExecutor
1447 {
1448 public:
1449 VertexShaderExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType);
1450 virtual ~VertexShaderExecutor (void);
1451
log(tcu::TestLog & dst) const1452 virtual void log (tcu::TestLog& dst) const { /* TODO */ (void)dst;}
1453
1454 virtual void setShaderSources (SourceCollections& programCollection) const;
1455
1456 };
1457
VertexShaderExecutor(const ShaderSpec & shaderSpec,glu::ShaderType shaderType)1458 VertexShaderExecutor::VertexShaderExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
1459 : FragmentOutExecutor (shaderSpec, shaderType)
1460 {
1461 }
1462
~VertexShaderExecutor(void)1463 VertexShaderExecutor::~VertexShaderExecutor (void)
1464 {
1465 }
1466
setShaderSources(SourceCollections & programCollection) const1467 void VertexShaderExecutor::setShaderSources (SourceCollections& programCollection) const
1468 {
1469 programCollection.glslSources.add("vert") << glu::VertexSource(generateVertexShader(m_shaderSpec, "a_", "vtx_out_"));
1470 /* \todo [2015-09-11 hegedusd] set useIntOutputs parameter if needed. */
1471 programCollection.glslSources.add("frag") << glu::FragmentSource(generatePassthroughFragmentShader(m_shaderSpec, false, m_outputLayout.locationMap, "vtx_out_", "o_"));
1472 }
1473
1474 // GeometryShaderExecutor
1475
1476 class GeometryShaderExecutor : public FragmentOutExecutor
1477 {
1478 public:
1479 GeometryShaderExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType);
1480 virtual ~GeometryShaderExecutor (void);
1481
log(tcu::TestLog & dst) const1482 virtual void log (tcu::TestLog& dst) const { /* TODO */ (void)dst; }
1483
1484 virtual void setShaderSources (SourceCollections& programCollection) const;
1485
1486 };
1487
GeometryShaderExecutor(const ShaderSpec & shaderSpec,glu::ShaderType shaderType)1488 GeometryShaderExecutor::GeometryShaderExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
1489 : FragmentOutExecutor (shaderSpec, shaderType)
1490 {
1491 }
1492
~GeometryShaderExecutor(void)1493 GeometryShaderExecutor::~GeometryShaderExecutor (void)
1494 {
1495 }
1496
setShaderSources(SourceCollections & programCollection) const1497 void GeometryShaderExecutor::setShaderSources (SourceCollections& programCollection) const
1498 {
1499 programCollection.glslSources.add("vert") << glu::VertexSource(generatePassthroughVertexShader(m_shaderSpec.inputs, "a_", "vtx_out_"));
1500
1501 programCollection.glslSources.add("geom") << glu::GeometrySource(generateGeometryShader(m_shaderSpec, "vtx_out_", "geom_out_"));
1502
1503 /* \todo [2015-09-18 rsipka] set useIntOutputs parameter if needed. */
1504 programCollection.glslSources.add("frag") << glu::FragmentSource(generatePassthroughFragmentShader(m_shaderSpec, false, m_outputLayout.locationMap, "geom_out_", "o_"));
1505
1506 }
1507
1508 // FragmentShaderExecutor
1509
1510 class FragmentShaderExecutor : public FragmentOutExecutor
1511 {
1512 public:
1513 FragmentShaderExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType);
1514 virtual ~FragmentShaderExecutor (void);
1515
log(tcu::TestLog & dst) const1516 virtual void log (tcu::TestLog& dst) const { /* TODO */ (void)dst; }
1517
1518 virtual void setShaderSources (SourceCollections& programCollection) const;
1519
1520 };
1521
FragmentShaderExecutor(const ShaderSpec & shaderSpec,glu::ShaderType shaderType)1522 FragmentShaderExecutor::FragmentShaderExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
1523 : FragmentOutExecutor (shaderSpec, shaderType)
1524 {
1525 }
1526
~FragmentShaderExecutor(void)1527 FragmentShaderExecutor::~FragmentShaderExecutor (void)
1528 {
1529 }
1530
setShaderSources(SourceCollections & programCollection) const1531 void FragmentShaderExecutor::setShaderSources (SourceCollections& programCollection) const
1532 {
1533 programCollection.glslSources.add("vert") << glu::VertexSource(generatePassthroughVertexShader(m_shaderSpec.inputs, "a_", "vtx_out_"));
1534 /* \todo [2015-09-11 hegedusd] set useIntOutputs parameter if needed. */
1535 programCollection.glslSources.add("frag") << glu::FragmentSource(generateFragmentShader(m_shaderSpec, false, m_outputLayout.locationMap, "vtx_out_", "o_"));
1536 }
1537
1538 // Shared utilities for compute and tess executors
1539
getVecStd430ByteAlignment(glu::DataType type)1540 static deUint32 getVecStd430ByteAlignment (glu::DataType type)
1541 {
1542 switch (glu::getDataTypeScalarSize(type))
1543 {
1544 case 1: return 4u;
1545 case 2: return 8u;
1546 case 3: return 16u;
1547 case 4: return 16u;
1548 default:
1549 DE_ASSERT(false);
1550 return 0u;
1551 }
1552 }
1553
1554 class BufferIoExecutor : public ShaderExecutor
1555 {
1556 public:
1557 BufferIoExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType);
1558 virtual ~BufferIoExecutor (void);
1559
log(tcu::TestLog & dst) const1560 virtual void log (tcu::TestLog& dst) const { /* TODO */ (void)dst; }
1561
1562 protected:
1563 enum
1564 {
1565 INPUT_BUFFER_BINDING = 0,
1566 OUTPUT_BUFFER_BINDING = 1,
1567 };
1568
1569 void initBuffers (const Context& ctx, int numValues);
getInputBuffer(void) const1570 VkBuffer getInputBuffer (void) const { return *m_inputBuffer; }
getOutputBuffer(void) const1571 VkBuffer getOutputBuffer (void) const { return *m_outputBuffer; }
getInputStride(void) const1572 deUint32 getInputStride (void) const { return getLayoutStride(m_inputLayout); }
getOutputStride(void) const1573 deUint32 getOutputStride (void) const { return getLayoutStride(m_outputLayout); }
1574
1575 void uploadInputBuffer (const Context& ctx, const void* const* inputPtrs, int numValues);
1576 void readOutputBuffer (const Context& ctx, void* const* outputPtrs, int numValues);
1577
1578 static void declareBufferBlocks (std::ostream& src, const ShaderSpec& spec);
1579 static void generateExecBufferIo(std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName);
1580
1581 protected:
1582 Move<VkBuffer> m_inputBuffer;
1583 Move<VkBuffer> m_outputBuffer;
1584
1585 private:
1586 struct VarLayout
1587 {
1588 deUint32 offset;
1589 deUint32 stride;
1590 deUint32 matrixStride;
1591
VarLayoutvkt::shaderexecutor::__anon9d58b36f0111::BufferIoExecutor::VarLayout1592 VarLayout (void) : offset(0), stride(0), matrixStride(0) {}
1593 };
1594
1595 static void computeVarLayout (const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout);
1596 static deUint32 getLayoutStride (const vector<VarLayout>& layout);
1597
1598 static void copyToBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr);
1599 static void copyFromBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr);
1600
1601 de::MovePtr<Allocation> m_inputAlloc;
1602 de::MovePtr<Allocation> m_outputAlloc;
1603
1604 vector<VarLayout> m_inputLayout;
1605 vector<VarLayout> m_outputLayout;
1606 };
1607
BufferIoExecutor(const ShaderSpec & shaderSpec,glu::ShaderType shaderType)1608 BufferIoExecutor::BufferIoExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
1609 : ShaderExecutor (shaderSpec, shaderType)
1610 {
1611 computeVarLayout(m_shaderSpec.inputs, &m_inputLayout);
1612 computeVarLayout(m_shaderSpec.outputs, &m_outputLayout);
1613 }
1614
~BufferIoExecutor(void)1615 BufferIoExecutor::~BufferIoExecutor (void)
1616 {
1617 }
1618
getLayoutStride(const vector<VarLayout> & layout)1619 inline deUint32 BufferIoExecutor::getLayoutStride (const vector<VarLayout>& layout)
1620 {
1621 return layout.empty() ? 0 : layout[0].stride;
1622 }
1623
computeVarLayout(const std::vector<Symbol> & symbols,std::vector<VarLayout> * layout)1624 void BufferIoExecutor::computeVarLayout (const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout)
1625 {
1626 deUint32 maxAlignment = 0;
1627 deUint32 curOffset = 0;
1628
1629 DE_ASSERT(layout != DE_NULL);
1630 DE_ASSERT(layout->empty());
1631 layout->resize(symbols.size());
1632
1633 for (size_t varNdx = 0; varNdx < symbols.size(); varNdx++)
1634 {
1635 const Symbol& symbol = symbols[varNdx];
1636 const glu::DataType basicType = symbol.varType.getBasicType();
1637 VarLayout& layoutEntry = (*layout)[varNdx];
1638
1639 if (glu::isDataTypeScalarOrVector(basicType))
1640 {
1641 const deUint32 alignment = getVecStd430ByteAlignment(basicType);
1642 const deUint32 size = (deUint32)glu::getDataTypeScalarSize(basicType) * (int)sizeof(deUint32);
1643
1644 curOffset = (deUint32)deAlign32((int)curOffset, (int)alignment);
1645 maxAlignment = de::max(maxAlignment, alignment);
1646
1647 layoutEntry.offset = curOffset;
1648 layoutEntry.matrixStride = 0;
1649
1650 curOffset += size;
1651 }
1652 else if (glu::isDataTypeMatrix(basicType))
1653 {
1654 const int numVecs = glu::getDataTypeMatrixNumColumns(basicType);
1655 const glu::DataType vecType = glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType));
1656 const deUint32 vecAlignment = getVecStd430ByteAlignment(vecType);
1657
1658 curOffset = (deUint32)deAlign32((int)curOffset, (int)vecAlignment);
1659 maxAlignment = de::max(maxAlignment, vecAlignment);
1660
1661 layoutEntry.offset = curOffset;
1662 layoutEntry.matrixStride = vecAlignment;
1663
1664 curOffset += vecAlignment*numVecs;
1665 }
1666 else
1667 DE_ASSERT(false);
1668 }
1669
1670 {
1671 const deUint32 totalSize = (deUint32)deAlign32(curOffset, maxAlignment);
1672
1673 for (vector<VarLayout>::iterator varIter = layout->begin(); varIter != layout->end(); ++varIter)
1674 varIter->stride = totalSize;
1675 }
1676 }
1677
declareBufferBlocks(std::ostream & src,const ShaderSpec & spec)1678 void BufferIoExecutor::declareBufferBlocks (std::ostream& src, const ShaderSpec& spec)
1679 {
1680 // Input struct
1681 if (!spec.inputs.empty())
1682 {
1683 glu::StructType inputStruct("Inputs");
1684 for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter)
1685 inputStruct.addMember(symIter->name.c_str(), symIter->varType);
1686 src << glu::declare(&inputStruct) << ";\n";
1687 }
1688
1689 // Output struct
1690 {
1691 glu::StructType outputStruct("Outputs");
1692 for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
1693 outputStruct.addMember(symIter->name.c_str(), symIter->varType);
1694 src << glu::declare(&outputStruct) << ";\n";
1695 }
1696
1697 src << "\n";
1698
1699 if (!spec.inputs.empty())
1700 {
1701 src << "layout(set = 0, binding = " << int(INPUT_BUFFER_BINDING) << ", std430) buffer InBuffer\n"
1702 << "{\n"
1703 << " Inputs inputs[];\n"
1704 << "};\n";
1705 }
1706
1707 src << "layout(set = 0, binding = " << int(OUTPUT_BUFFER_BINDING) << ", std430) buffer OutBuffer\n"
1708 << "{\n"
1709 << " Outputs outputs[];\n"
1710 << "};\n"
1711 << "\n";
1712 }
1713
generateExecBufferIo(std::ostream & src,const ShaderSpec & spec,const char * invocationNdxName)1714 void BufferIoExecutor::generateExecBufferIo (std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName)
1715 {
1716 for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter)
1717 src << "\t" << glu::declare(symIter->varType, symIter->name) << " = inputs[" << invocationNdxName << "]." << symIter->name << ";\n";
1718
1719 for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
1720 src << "\t" << glu::declare(symIter->varType, symIter->name) << ";\n";
1721
1722 src << "\n";
1723
1724 {
1725 std::istringstream opSrc (spec.source);
1726 std::string line;
1727
1728 while (std::getline(opSrc, line))
1729 src << "\t" << line << "\n";
1730 }
1731
1732 src << "\n";
1733 for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
1734 src << "\toutputs[" << invocationNdxName << "]." << symIter->name << " = " << symIter->name << ";\n";
1735 }
1736
copyToBuffer(const glu::VarType & varType,const VarLayout & layout,int numValues,const void * srcBasePtr,void * dstBasePtr)1737 void BufferIoExecutor::copyToBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr)
1738 {
1739 if (varType.isBasicType())
1740 {
1741 const glu::DataType basicType = varType.getBasicType();
1742 const bool isMatrix = glu::isDataTypeMatrix(basicType);
1743 const int scalarSize = glu::getDataTypeScalarSize(basicType);
1744 const int numVecs = isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1;
1745 const int numComps = scalarSize / numVecs;
1746
1747 for (int elemNdx = 0; elemNdx < numValues; elemNdx++)
1748 {
1749 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
1750 {
1751 const int srcOffset = (int)sizeof(deUint32) * (elemNdx * scalarSize + vecNdx * numComps);
1752 const int dstOffset = layout.offset + layout.stride * elemNdx + (isMatrix ? layout.matrixStride * vecNdx : 0);
1753 const deUint8* srcPtr = (const deUint8*)srcBasePtr + srcOffset;
1754 deUint8* dstPtr = (deUint8*)dstBasePtr + dstOffset;
1755
1756 deMemcpy(dstPtr, srcPtr, sizeof(deUint32) * numComps);
1757 }
1758 }
1759 }
1760 else
1761 throw tcu::InternalError("Unsupported type");
1762 }
1763
copyFromBuffer(const glu::VarType & varType,const VarLayout & layout,int numValues,const void * srcBasePtr,void * dstBasePtr)1764 void BufferIoExecutor::copyFromBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr)
1765 {
1766 if (varType.isBasicType())
1767 {
1768 const glu::DataType basicType = varType.getBasicType();
1769 const bool isMatrix = glu::isDataTypeMatrix(basicType);
1770 const int scalarSize = glu::getDataTypeScalarSize(basicType);
1771 const int numVecs = isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1;
1772 const int numComps = scalarSize / numVecs;
1773
1774 for (int elemNdx = 0; elemNdx < numValues; elemNdx++)
1775 {
1776 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
1777 {
1778 const int srcOffset = layout.offset + layout.stride * elemNdx + (isMatrix ? layout.matrixStride * vecNdx : 0);
1779 const int dstOffset = (int)sizeof(deUint32) * (elemNdx * scalarSize + vecNdx * numComps);
1780 const deUint8* srcPtr = (const deUint8*)srcBasePtr + srcOffset;
1781 deUint8* dstPtr = (deUint8*)dstBasePtr + dstOffset;
1782
1783 deMemcpy(dstPtr, srcPtr, sizeof(deUint32) * numComps);
1784 }
1785 }
1786 }
1787 else
1788 throw tcu::InternalError("Unsupported type");
1789 }
1790
uploadInputBuffer(const Context & ctx,const void * const * inputPtrs,int numValues)1791 void BufferIoExecutor::uploadInputBuffer (const Context& ctx, const void* const* inputPtrs, int numValues)
1792 {
1793 const VkDevice vkDevice = ctx.getDevice();
1794 const DeviceInterface& vk = ctx.getDeviceInterface();
1795
1796 const deUint32 inputStride = getLayoutStride(m_inputLayout);
1797 const int inputBufferSize = inputStride * numValues;
1798
1799 if (inputBufferSize == 0)
1800 return; // No inputs
1801
1802 DE_ASSERT(m_shaderSpec.inputs.size() == m_inputLayout.size());
1803 for (size_t inputNdx = 0; inputNdx < m_shaderSpec.inputs.size(); ++inputNdx)
1804 {
1805 const glu::VarType& varType = m_shaderSpec.inputs[inputNdx].varType;
1806 const VarLayout& layout = m_inputLayout[inputNdx];
1807
1808 copyToBuffer(varType, layout, numValues, inputPtrs[inputNdx], m_inputAlloc->getHostPtr());
1809 }
1810
1811 flushMappedMemoryRange(vk, vkDevice, m_inputAlloc->getMemory(), m_inputAlloc->getOffset(), inputBufferSize);
1812 }
1813
readOutputBuffer(const Context & ctx,void * const * outputPtrs,int numValues)1814 void BufferIoExecutor::readOutputBuffer (const Context& ctx, void* const* outputPtrs, int numValues)
1815 {
1816 const VkDevice vkDevice = ctx.getDevice();
1817 const DeviceInterface& vk = ctx.getDeviceInterface();
1818
1819 const deUint32 outputStride = getLayoutStride(m_outputLayout);
1820 const int outputBufferSize = numValues * outputStride;
1821
1822 DE_ASSERT(outputBufferSize > 0); // At least some outputs are required.
1823
1824 invalidateMappedMemoryRange(vk, vkDevice, m_outputAlloc->getMemory(), m_outputAlloc->getOffset(), outputBufferSize);
1825
1826 DE_ASSERT(m_shaderSpec.outputs.size() == m_outputLayout.size());
1827 for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
1828 {
1829 const glu::VarType& varType = m_shaderSpec.outputs[outputNdx].varType;
1830 const VarLayout& layout = m_outputLayout[outputNdx];
1831
1832 copyFromBuffer(varType, layout, numValues, m_outputAlloc->getHostPtr(), outputPtrs[outputNdx]);
1833 }
1834 }
1835
initBuffers(const Context & ctx,int numValues)1836 void BufferIoExecutor::initBuffers (const Context& ctx, int numValues)
1837 {
1838 const deUint32 inputStride = getLayoutStride(m_inputLayout);
1839 const deUint32 outputStride = getLayoutStride(m_outputLayout);
1840 // Avoid creating zero-sized buffer/memory
1841 const size_t inputBufferSize = numValues * inputStride ? (numValues * inputStride) : 1;
1842 const size_t outputBufferSize = numValues * outputStride;
1843
1844 // Upload data to buffer
1845 const VkDevice vkDevice = ctx.getDevice();
1846 const DeviceInterface& vk = ctx.getDeviceInterface();
1847 const deUint32 queueFamilyIndex = ctx.getUniversalQueueFamilyIndex();
1848 Allocator& memAlloc = ctx.getDefaultAllocator();
1849
1850 const VkBufferCreateInfo inputBufferParams =
1851 {
1852 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1853 DE_NULL, // const void* pNext;
1854 0u, // VkBufferCreateFlags flags;
1855 inputBufferSize, // VkDeviceSize size;
1856 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage;
1857 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1858 1u, // deUint32 queueFamilyCount;
1859 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
1860 };
1861
1862 m_inputBuffer = createBuffer(vk, vkDevice, &inputBufferParams);
1863 m_inputAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_inputBuffer), MemoryRequirement::HostVisible);
1864
1865 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_inputBuffer, m_inputAlloc->getMemory(), m_inputAlloc->getOffset()));
1866
1867 const VkBufferCreateInfo outputBufferParams =
1868 {
1869 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1870 DE_NULL, // const void* pNext;
1871 0u, // VkBufferCreateFlags flags;
1872 outputBufferSize, // VkDeviceSize size;
1873 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage;
1874 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1875 1u, // deUint32 queueFamilyCount;
1876 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
1877 };
1878
1879 m_outputBuffer = createBuffer(vk, vkDevice, &outputBufferParams);
1880 m_outputAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outputBuffer), MemoryRequirement::HostVisible);
1881
1882 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outputBuffer, m_outputAlloc->getMemory(), m_outputAlloc->getOffset()));
1883 }
1884
1885 // ComputeShaderExecutor
1886
1887 class ComputeShaderExecutor : public BufferIoExecutor
1888 {
1889 public:
1890 ComputeShaderExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType);
1891 virtual ~ComputeShaderExecutor (void);
1892
1893 virtual void setShaderSources (SourceCollections& programCollection) const;
1894
1895 virtual void execute (const Context& ctx, int numValues, const void* const* inputs, void* const* outputs);
1896
1897 protected:
1898 static std::string generateComputeShader (const ShaderSpec& spec);
1899 };
1900
ComputeShaderExecutor(const ShaderSpec & shaderSpec,glu::ShaderType shaderType)1901 ComputeShaderExecutor::ComputeShaderExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
1902 : BufferIoExecutor (shaderSpec, shaderType)
1903 {
1904 }
1905
~ComputeShaderExecutor(void)1906 ComputeShaderExecutor::~ComputeShaderExecutor (void)
1907 {
1908 }
1909
generateComputeShader(const ShaderSpec & spec)1910 std::string ComputeShaderExecutor::generateComputeShader (const ShaderSpec& spec)
1911 {
1912 std::ostringstream src;
1913 src << "#version 310 es\n";
1914
1915 if (!spec.globalDeclarations.empty())
1916 src << spec.globalDeclarations << "\n";
1917
1918 src << "layout(local_size_x = 1) in;\n"
1919 << "\n";
1920
1921 declareBufferBlocks(src, spec);
1922
1923 src << "void main (void)\n"
1924 << "{\n"
1925 << " uint invocationNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z\n"
1926 << " + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n";
1927
1928 generateExecBufferIo(src, spec, "invocationNdx");
1929
1930 src << "}\n";
1931
1932 return src.str();
1933 }
1934
setShaderSources(SourceCollections & programCollection) const1935 void ComputeShaderExecutor::setShaderSources (SourceCollections& programCollection) const
1936 {
1937 programCollection.glslSources.add("compute") << glu::ComputeSource(generateComputeShader(m_shaderSpec));
1938 }
1939
execute(const Context & ctx,int numValues,const void * const * inputs,void * const * outputs)1940 void ComputeShaderExecutor::execute (const Context& ctx, int numValues, const void* const* inputs, void* const* outputs)
1941 {
1942 checkSupported(ctx, m_shaderType);
1943
1944 const VkDevice vkDevice = ctx.getDevice();
1945 const DeviceInterface& vk = ctx.getDeviceInterface();
1946 const VkQueue queue = ctx.getUniversalQueue();
1947 const deUint32 queueFamilyIndex = ctx.getUniversalQueueFamilyIndex();
1948 Allocator& memAlloc = ctx.getDefaultAllocator();
1949
1950 Move<VkShaderModule> computeShaderModule;
1951 Move<VkPipeline> computePipeline;
1952 Move<VkPipelineLayout> pipelineLayout;
1953 Move<VkCommandPool> cmdPool;
1954 Move<VkDescriptorPool> descriptorPool;
1955 Move<VkDescriptorSetLayout> descriptorSetLayout;
1956 Move<VkDescriptorSet> descriptorSet;
1957 Move<VkFence> fence;
1958
1959 initBuffers(ctx, numValues);
1960
1961 // Setup input buffer & copy data
1962 uploadInputBuffer(ctx, inputs, numValues);
1963
1964 // Create command pool
1965 {
1966 const VkCommandPoolCreateInfo cmdPoolParams =
1967 {
1968 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
1969 DE_NULL, // const void* pNext;
1970 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags;
1971 queueFamilyIndex // deUint32 queueFamilyIndex;
1972 };
1973
1974 cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1975 }
1976
1977 // Create command buffer
1978 const VkCommandBufferAllocateInfo cmdBufferParams =
1979 {
1980 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
1981 DE_NULL, // const void* pNext;
1982 *cmdPool, // VkCmdPool cmdPool;
1983 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
1984 1u // deUint32 bufferCount;
1985 };
1986
1987 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1988 {
1989 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1990 DE_NULL, // const void* pNext;
1991 0u, // VkCmdBufferOptimizeFlags flags;
1992 (const VkCommandBufferInheritanceInfo*)DE_NULL,
1993 };
1994
1995 m_descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
1996 m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1997 m_descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
1998 m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1999
2000 addUniforms(vkDevice, vk, queue, queueFamilyIndex, memAlloc);
2001
2002 descriptorSetLayout = m_descriptorSetLayoutBuilder.build(vk, vkDevice);
2003 descriptorPool = m_descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2004
2005 const VkDescriptorSetAllocateInfo allocInfo =
2006 {
2007 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
2008 DE_NULL,
2009 *descriptorPool,
2010 1u,
2011 &*descriptorSetLayout
2012 };
2013
2014 descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
2015
2016 // Create pipeline layout
2017 {
2018 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
2019 {
2020 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
2021 DE_NULL, // const void* pNext;
2022 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
2023 1u, // deUint32 CdescriptorSetCount;
2024 &*descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts;
2025 0u, // deUint32 pushConstantRangeCount;
2026 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
2027 };
2028
2029 pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
2030 }
2031
2032 // Create shaders
2033 {
2034 computeShaderModule = createShaderModule(vk, vkDevice, ctx.getBinaryCollection().get("compute"), 0);
2035 }
2036
2037 // create pipeline
2038 {
2039 const VkPipelineShaderStageCreateInfo shaderStageParams[1] =
2040 {
2041 {
2042 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2043 DE_NULL, // const void* pNext;
2044 (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags;
2045 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagsBit stage;
2046 *computeShaderModule, // VkShaderModule shader;
2047 "main", // const char* pName;
2048 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
2049 }
2050 };
2051
2052 const VkComputePipelineCreateInfo computePipelineParams =
2053 {
2054 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
2055 DE_NULL, // const void* pNext;
2056 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
2057 *shaderStageParams, // VkPipelineShaderStageCreateInfo cs;
2058 *pipelineLayout, // VkPipelineLayout layout;
2059 0u, // VkPipeline basePipelineHandle;
2060 0u, // int32_t basePipelineIndex;
2061 };
2062
2063 computePipeline = createComputePipeline(vk, vkDevice, DE_NULL, &computePipelineParams);
2064 }
2065
2066 // Create fence
2067 {
2068 const VkFenceCreateInfo fenceParams =
2069 {
2070 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
2071 DE_NULL, // const void* pNext;
2072 0u // VkFenceCreateFlags flags;
2073 };
2074 fence = createFence(vk, vkDevice, &fenceParams);
2075 }
2076
2077 const int maxValuesPerInvocation = ctx.getDeviceProperties().limits.maxComputeWorkGroupSize[0];
2078 int curOffset = 0;
2079 const deUint32 inputStride = getInputStride();
2080 const deUint32 outputStride = getOutputStride();
2081
2082 while (curOffset < numValues)
2083 {
2084 Move<VkCommandBuffer> cmdBuffer;
2085 const int numToExec = de::min(maxValuesPerInvocation, numValues-curOffset);
2086
2087 // Update descriptors
2088 {
2089 DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
2090
2091 const VkDescriptorBufferInfo outputDescriptorBufferInfo =
2092 {
2093 *m_outputBuffer, // VkBuffer buffer;
2094 curOffset * outputStride, // VkDeviceSize offset;
2095 numToExec * outputStride // VkDeviceSize range;
2096 };
2097
2098 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)OUTPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputDescriptorBufferInfo);
2099
2100 if (inputStride)
2101 {
2102 const VkDescriptorBufferInfo inputDescriptorBufferInfo =
2103 {
2104 *m_inputBuffer, // VkBuffer buffer;
2105 curOffset * inputStride, // VkDeviceSize offset;
2106 numToExec * inputStride // VkDeviceSize range;
2107 };
2108
2109 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)INPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inputDescriptorBufferInfo);
2110 }
2111
2112 uploadUniforms(descriptorSetUpdateBuilder, *descriptorSet);
2113
2114 descriptorSetUpdateBuilder.update(vk, vkDevice);
2115 }
2116
2117 cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
2118 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
2119 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
2120
2121 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
2122
2123 vk.cmdDispatch(*cmdBuffer, numToExec, 1, 1);
2124
2125 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
2126
2127 curOffset += numToExec;
2128
2129 // Execute
2130 {
2131 VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
2132
2133 const VkSubmitInfo submitInfo =
2134 {
2135 VK_STRUCTURE_TYPE_SUBMIT_INFO,
2136 DE_NULL,
2137 0u,
2138 (const VkSemaphore*)DE_NULL,
2139 (const VkPipelineStageFlags*)DE_NULL,
2140 1u,
2141 &cmdBuffer.get(),
2142 0u,
2143 (const VkSemaphore*)DE_NULL,
2144 };
2145
2146 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
2147 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/));
2148 }
2149 }
2150
2151 // Read back data
2152 readOutputBuffer(ctx, outputs, numValues);
2153 }
2154
2155 // Tessellation utils
2156
generateVertexShaderForTess(void)2157 static std::string generateVertexShaderForTess (void)
2158 {
2159 std::ostringstream src;
2160 src << "#version 310 es\n"
2161 << "void main (void)\n{\n"
2162 << " gl_Position = vec4(gl_VertexIndex/2, gl_VertexIndex%2, 0.0, 1.0);\n"
2163 << "}\n";
2164
2165 return src.str();
2166 }
2167
2168 class TessellationExecutor : public BufferIoExecutor
2169 {
2170 public:
2171 TessellationExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType);
2172 virtual ~TessellationExecutor (void);
2173
2174 void renderTess (const Context& ctx, deUint32 numValues, deUint32 vertexCount, deUint32 patchControlPoints);
2175 };
2176
TessellationExecutor(const ShaderSpec & shaderSpec,glu::ShaderType shaderType)2177 TessellationExecutor::TessellationExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
2178 : BufferIoExecutor (shaderSpec, shaderType)
2179 {
2180 }
2181
~TessellationExecutor(void)2182 TessellationExecutor::~TessellationExecutor (void)
2183 {
2184 }
2185
renderTess(const Context & ctx,deUint32 numValues,deUint32 vertexCount,deUint32 patchControlPoints)2186 void TessellationExecutor::renderTess (const Context& ctx, deUint32 numValues, deUint32 vertexCount, deUint32 patchControlPoints)
2187 {
2188 const size_t inputBufferSize = numValues * getInputStride();
2189 const VkDevice vkDevice = ctx.getDevice();
2190 const DeviceInterface& vk = ctx.getDeviceInterface();
2191 const VkQueue queue = ctx.getUniversalQueue();
2192 const deUint32 queueFamilyIndex = ctx.getUniversalQueueFamilyIndex();
2193 Allocator& memAlloc = ctx.getDefaultAllocator();
2194
2195 const tcu::UVec2 renderSize (DEFAULT_RENDER_WIDTH, DEFAULT_RENDER_HEIGHT);
2196
2197 Move<VkImage> colorImage;
2198 de::MovePtr<Allocation> colorImageAlloc;
2199 VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
2200 Move<VkImageView> colorImageView;
2201
2202 Move<VkRenderPass> renderPass;
2203 Move<VkFramebuffer> framebuffer;
2204 Move<VkPipelineLayout> pipelineLayout;
2205 Move<VkPipeline> graphicsPipeline;
2206
2207 Move<VkShaderModule> vertexShaderModule;
2208 Move<VkShaderModule> tessControlShaderModule;
2209 Move<VkShaderModule> tessEvalShaderModule;
2210 Move<VkShaderModule> fragmentShaderModule;
2211
2212 Move<VkCommandPool> cmdPool;
2213 Move<VkCommandBuffer> cmdBuffer;
2214
2215 Move<VkFence> fence;
2216
2217 Move<VkDescriptorPool> descriptorPool;
2218 Move<VkDescriptorSetLayout> descriptorSetLayout;
2219 Move<VkDescriptorSet> descriptorSet;
2220
2221 // Create color image
2222 {
2223 const VkImageCreateInfo colorImageParams =
2224 {
2225 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2226 DE_NULL, // const void* pNext;
2227 0u, // VkImageCreateFlags flags;
2228 VK_IMAGE_TYPE_2D, // VkImageType imageType;
2229 colorFormat, // VkFormat format;
2230 { renderSize.x(), renderSize.y(), 1u }, // VkExtent3D extent;
2231 1u, // deUint32 mipLevels;
2232 1u, // deUint32 arraySize;
2233 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
2234 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
2235 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
2236 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2237 1u, // deUint32 queueFamilyCount;
2238 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
2239 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
2240 };
2241
2242 colorImage = createImage(vk, vkDevice, &colorImageParams);
2243
2244 // Allocate and bind color image memory
2245 colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *colorImage), MemoryRequirement::Any);
2246 VK_CHECK(vk.bindImageMemory(vkDevice, *colorImage, colorImageAlloc->getMemory(), colorImageAlloc->getOffset()));
2247 }
2248
2249 // Create color attachment view
2250 {
2251 const VkImageViewCreateInfo colorImageViewParams =
2252 {
2253 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
2254 DE_NULL, // const void* pNext;
2255 0u, // VkImageViewCreateFlags flags;
2256 *colorImage, // VkImage image;
2257 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
2258 colorFormat, // VkFormat format;
2259 {
2260 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
2261 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
2262 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
2263 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
2264 }, // VkComponentsMapping components;
2265 {
2266 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
2267 0u, // deUint32 baseMipLevel;
2268 1u, // deUint32 mipLevels;
2269 0u, // deUint32 baseArraylayer;
2270 1u // deUint32 layerCount;
2271 } // VkImageSubresourceRange subresourceRange;
2272 };
2273
2274 colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
2275 }
2276
2277 // Create render pass
2278 {
2279 const VkAttachmentDescription colorAttachmentDescription =
2280 {
2281 0u, // VkAttachmentDescriptorFlags flags;
2282 colorFormat, // VkFormat format;
2283 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
2284 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
2285 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
2286 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
2287 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
2288 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
2289 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
2290 };
2291
2292 const VkAttachmentDescription attachments[1] =
2293 {
2294 colorAttachmentDescription
2295 };
2296
2297 const VkAttachmentReference colorAttachmentReference =
2298 {
2299 0u, // deUint32 attachment;
2300 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
2301 };
2302
2303 const VkSubpassDescription subpassDescription =
2304 {
2305 0u, // VkSubpassDescriptionFlags flags;
2306 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
2307 0u, // deUint32 inputCount;
2308 DE_NULL, // const VkAttachmentReference* pInputAttachments;
2309 1u, // deUint32 colorCount;
2310 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
2311 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
2312 DE_NULL, // VkAttachmentReference depthStencilAttachment;
2313 0u, // deUint32 preserveCount;
2314 DE_NULL // const VkAttachmentReference* pPreserveAttachments;
2315 };
2316
2317 const VkRenderPassCreateInfo renderPassParams =
2318 {
2319 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
2320 DE_NULL, // const void* pNext;
2321 0u, // VkRenderPassCreateFlags flags;
2322 1u, // deUint32 attachmentCount;
2323 attachments, // const VkAttachmentDescription* pAttachments;
2324 1u, // deUint32 subpassCount;
2325 &subpassDescription, // const VkSubpassDescription* pSubpasses;
2326 0u, // deUint32 dependencyCount;
2327 DE_NULL // const VkSubpassDependency* pDependencies;
2328 };
2329
2330 renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
2331 }
2332
2333 // Create framebuffer
2334 {
2335 const VkFramebufferCreateInfo framebufferParams =
2336 {
2337 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
2338 DE_NULL, // const void* pNext;
2339 0u, // VkFramebufferCreateFlags flags;
2340 *renderPass, // VkRenderPass renderPass;
2341 1u, // deUint32 attachmentCount;
2342 &*colorImageView, // const VkAttachmentBindInfo* pAttachments;
2343 (deUint32)renderSize.x(), // deUint32 width;
2344 (deUint32)renderSize.y(), // deUint32 height;
2345 1u // deUint32 layers;
2346 };
2347
2348 framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
2349 }
2350
2351 // Create descriptors
2352 {
2353 m_descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
2354 m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2355 m_descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
2356 m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2357
2358 addUniforms(vkDevice, vk, queue, queueFamilyIndex, memAlloc);
2359
2360 descriptorSetLayout = m_descriptorSetLayoutBuilder.build(vk, vkDevice);
2361 descriptorPool = m_descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2362
2363 const VkDescriptorSetAllocateInfo allocInfo =
2364 {
2365 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
2366 DE_NULL,
2367 *descriptorPool,
2368 1u,
2369 &*descriptorSetLayout
2370 };
2371
2372 descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
2373 // Update descriptors
2374 {
2375 DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
2376 const VkDescriptorBufferInfo outputDescriptorBufferInfo =
2377 {
2378 *m_outputBuffer, // VkBuffer buffer;
2379 0u, // VkDeviceSize offset;
2380 VK_WHOLE_SIZE // VkDeviceSize range;
2381 };
2382
2383 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)OUTPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputDescriptorBufferInfo);
2384
2385 VkDescriptorBufferInfo inputDescriptorBufferInfo =
2386 {
2387 0, // VkBuffer buffer;
2388 0u, // VkDeviceSize offset;
2389 VK_WHOLE_SIZE // VkDeviceSize range;
2390 };
2391
2392 if (inputBufferSize > 0)
2393 {
2394 inputDescriptorBufferInfo.buffer = *m_inputBuffer;
2395
2396 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)INPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inputDescriptorBufferInfo);
2397 }
2398
2399 uploadUniforms(descriptorSetUpdateBuilder, *descriptorSet);
2400
2401 descriptorSetUpdateBuilder.update(vk, vkDevice);
2402 }
2403 }
2404
2405 // Create pipeline layout
2406 {
2407 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
2408 {
2409 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
2410 DE_NULL, // const void* pNext;
2411 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
2412 1u, // deUint32 descriptorSetCount;
2413 &*descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts;
2414 0u, // deUint32 pushConstantRangeCount;
2415 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
2416 };
2417
2418 pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
2419 }
2420
2421 // Create shader modules
2422 {
2423 vertexShaderModule = createShaderModule(vk, vkDevice, ctx.getBinaryCollection().get("vert"), 0);
2424 tessControlShaderModule = createShaderModule(vk, vkDevice, ctx.getBinaryCollection().get("tess_control"), 0);
2425 tessEvalShaderModule = createShaderModule(vk, vkDevice, ctx.getBinaryCollection().get("tess_eval"), 0);
2426 fragmentShaderModule = createShaderModule(vk, vkDevice, ctx.getBinaryCollection().get("frag"), 0);
2427 }
2428
2429 // Create pipeline
2430 {
2431 const VkPipelineShaderStageCreateInfo shaderStageParams[4] =
2432 {
2433 {
2434 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2435 DE_NULL, // const void* pNext;
2436 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
2437 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBit stage;
2438 *vertexShaderModule, // VkShaderModule shader;
2439 "main", // const char* pName;
2440 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
2441 },
2442 {
2443 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2444 DE_NULL, // const void* pNext;
2445 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
2446 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBit stage;
2447 *tessControlShaderModule, // VkShaderModule shader;
2448 "main", // const char* pName;
2449 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
2450 },
2451 {
2452 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2453 DE_NULL, // const void* pNext;
2454 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
2455 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, // VkShaderStageFlagBit stage;
2456 *tessEvalShaderModule, // VkShaderModule shader;
2457 "main", // const char* pName;
2458 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
2459 },
2460 {
2461 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2462 DE_NULL, // const void* pNext;
2463 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
2464 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBit stage;
2465 *fragmentShaderModule, // VkShaderModule shader;
2466 "main", // const char* pName;
2467 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
2468 }
2469 };
2470
2471 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
2472 {
2473 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
2474 DE_NULL, // const void* pNext;
2475 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
2476 0u, // deUint32 bindingCount;
2477 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
2478 0u, // deUint32 attributeCount;
2479 DE_NULL, // const VkVertexInputAttributeDescription* pvertexAttributeDescriptions;
2480 };
2481
2482 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
2483 {
2484 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
2485 DE_NULL, // const void* pNext;
2486 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
2487 VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, // VkPrimitiveTopology topology;
2488 DE_FALSE // VkBool32 primitiveRestartEnable;
2489 };
2490
2491 struct VkPipelineTessellationStateCreateInfo tessellationStateParams =
2492 {
2493 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
2494 DE_NULL, // const void* pNext;
2495 (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags;
2496 patchControlPoints // uint32_t patchControlPoints;
2497 };
2498
2499 const VkViewport viewport =
2500 {
2501 0.0f, // float originX;
2502 0.0f, // float originY;
2503 (float)renderSize.x(), // float width;
2504 (float)renderSize.y(), // float height;
2505 0.0f, // float minDepth;
2506 1.0f // float maxDepth;
2507 };
2508
2509 const VkRect2D scissor =
2510 {
2511 {
2512 0u, // deUint32 x;
2513 0u, // deUint32 y;
2514 }, // VkOffset2D offset;
2515 {
2516 renderSize.x(), // deUint32 width;
2517 renderSize.y(), // deUint32 height;
2518 }, // VkExtent2D extent;
2519 };
2520
2521 const VkPipelineViewportStateCreateInfo viewportStateParams =
2522 {
2523 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
2524 DE_NULL, // const void* pNext;
2525 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewPortStateCreateFlags flags;
2526 1u, // deUint32 viewportCount;
2527 &viewport, // const VkViewport* pViewports;
2528 1u, // deUint32 scissorsCount;
2529 &scissor // const VkRect2D* pScissors;
2530 };
2531
2532 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
2533 {
2534 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
2535 DE_NULL, // const void* pNext;
2536 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStageCreateFlags flags;
2537 VK_FALSE, // VkBool32 depthClipEnable;
2538 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
2539 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
2540 VK_CULL_MODE_NONE, // VkCullMode cullMode;
2541 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
2542 VK_FALSE, // VkBool32 depthBiasEnable;
2543 0.0f, // float depthBias;
2544 0.0f, // float depthBiasClamp;
2545 0.0f, // float slopeScaledDepthBias;
2546 1.0f // float lineWidth;
2547 };
2548
2549 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
2550 {
2551 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
2552 DE_NULL, // const void* pNext;
2553 0u, // VkPipelineMultisampleStateCreateFlags flags;
2554 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
2555 VK_FALSE, // VkBool32 sampleShadingEnable;
2556 0.0f, // float minSampleShading;
2557 DE_NULL, // const VkSampleMask* pSampleMask;
2558 VK_FALSE, // VkBool32 alphaToCoverageEnable;
2559 VK_FALSE // VkBool32 alphaToOneEnable;
2560 };
2561
2562 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
2563 {
2564 VK_FALSE, // VkBool32 blendEnable;
2565 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcBlendColor;
2566 VK_BLEND_FACTOR_ZERO, // VkBlendFactor destBlendColor;
2567 VK_BLEND_OP_ADD, // VkBlendOp blendOpColor;
2568 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcBlendAlpha;
2569 VK_BLEND_FACTOR_ZERO, // VkBlendFactor destBlendAlpha;
2570 VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha;
2571 (VK_COLOR_COMPONENT_R_BIT |
2572 VK_COLOR_COMPONENT_G_BIT |
2573 VK_COLOR_COMPONENT_B_BIT |
2574 VK_COLOR_COMPONENT_A_BIT) // VkColorComponentFlags colorWriteMask;
2575 };
2576
2577 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
2578 {
2579 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
2580 DE_NULL, // const void* pNext;
2581 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags
2582 VK_FALSE, // VkBool32 logicOpEnable;
2583 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
2584 1u, // deUint32 attachmentCount;
2585 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
2586 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConst[4];
2587 };
2588
2589 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
2590 {
2591 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
2592 DE_NULL, // const void* pNext;
2593 0u, // VkPipelineCreateFlags flags;
2594 4u, // deUint32 stageCount;
2595 shaderStageParams, // const VkPipelineShaderStageCreateInfo* pStages;
2596 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
2597 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
2598 &tessellationStateParams, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
2599 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
2600 &rasterStateParams, // const VkPipelineRasterStateCreateInfo* pRasterState;
2601 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
2602 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
2603 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
2604 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
2605 *pipelineLayout, // VkPipelineLayout layout;
2606 *renderPass, // VkRenderPass renderPass;
2607 0u, // deUint32 subpass;
2608 0u, // VkPipeline basePipelineHandle;
2609 0u // deInt32 basePipelineIndex;
2610 };
2611
2612 graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
2613 }
2614
2615 // Create command pool
2616 {
2617 const VkCommandPoolCreateInfo cmdPoolParams =
2618 {
2619 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
2620 DE_NULL, // const void* pNext;
2621 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCmdPoolCreateFlags flags;
2622 queueFamilyIndex, // deUint32 queueFamilyIndex;
2623 };
2624
2625 cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
2626 }
2627
2628 // Create command buffer
2629 {
2630 const VkCommandBufferAllocateInfo cmdBufferParams =
2631 {
2632 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2633 DE_NULL, // const void* pNext;
2634 *cmdPool, // VkCmdPool cmdPool;
2635 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
2636 1u // uint32_t bufferCount;
2637 };
2638
2639 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
2640 {
2641 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
2642 DE_NULL, // const void* pNext;
2643 0u, // VkCmdBufferOptimizeFlags flags;
2644 (const VkCommandBufferInheritanceInfo*)DE_NULL,
2645 };
2646
2647 const VkClearValue clearValues[1] =
2648 {
2649 getDefaultClearColor()
2650 };
2651
2652 const VkRenderPassBeginInfo renderPassBeginInfo =
2653 {
2654 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
2655 DE_NULL, // const void* pNext;
2656 *renderPass, // VkRenderPass renderPass;
2657 *framebuffer, // VkFramebuffer framebuffer;
2658 { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // VkRect2D renderArea;
2659 1, // deUint32 attachmentCount;
2660 clearValues // const VkClearValue* pClearValues;
2661 };
2662
2663 cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
2664
2665 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
2666
2667 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2668
2669 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
2670
2671 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
2672
2673 vk.cmdDraw(*cmdBuffer, vertexCount, 1, 0, 0);
2674
2675 vk.cmdEndRenderPass(*cmdBuffer);
2676 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
2677 }
2678
2679 // Create fence
2680 {
2681 const VkFenceCreateInfo fenceParams =
2682 {
2683 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
2684 DE_NULL, // const void* pNext;
2685 0u // VkFenceCreateFlags flags;
2686 };
2687 fence = createFence(vk, vkDevice, &fenceParams);
2688 }
2689
2690 // Execute Draw
2691 {
2692 VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
2693 const VkSubmitInfo submitInfo =
2694 {
2695 VK_STRUCTURE_TYPE_SUBMIT_INFO,
2696 DE_NULL,
2697 0u,
2698 (const VkSemaphore*)0,
2699 (const VkPipelineStageFlags*)DE_NULL,
2700 1u,
2701 &cmdBuffer.get(),
2702 0u,
2703 (const VkSemaphore*)0,
2704 };
2705 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
2706 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/));
2707 }
2708 }
2709
2710 // TessControlExecutor
2711
2712 class TessControlExecutor : public TessellationExecutor
2713 {
2714 public:
2715 TessControlExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType);
2716 virtual ~TessControlExecutor (void);
2717
2718 virtual void setShaderSources (SourceCollections& programCollection) const;
2719
2720 virtual void execute (const Context& ctx, int numValues, const void* const* inputs, void* const* outputs);
2721
2722 protected:
2723 static std::string generateTessControlShader (const ShaderSpec& shaderSpec);
2724 };
2725
TessControlExecutor(const ShaderSpec & shaderSpec,glu::ShaderType shaderType)2726 TessControlExecutor::TessControlExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
2727 : TessellationExecutor (shaderSpec, shaderType)
2728 {
2729 }
2730
~TessControlExecutor(void)2731 TessControlExecutor::~TessControlExecutor (void)
2732 {
2733 }
2734
generateTessControlShader(const ShaderSpec & shaderSpec)2735 std::string TessControlExecutor::generateTessControlShader (const ShaderSpec& shaderSpec)
2736 {
2737 std::ostringstream src;
2738 src << "#version 310 es\n"
2739 "#extension GL_EXT_tessellation_shader : require\n\n";
2740
2741 if (!shaderSpec.globalDeclarations.empty())
2742 src << shaderSpec.globalDeclarations << "\n";
2743
2744 src << "\nlayout(vertices = 1) out;\n\n";
2745
2746 declareBufferBlocks(src, shaderSpec);
2747
2748 src << "void main (void)\n{\n";
2749
2750 for (int ndx = 0; ndx < 2; ndx++)
2751 src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n";
2752
2753 for (int ndx = 0; ndx < 4; ndx++)
2754 src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n";
2755
2756 src << "\n"
2757 << "\thighp uint invocationId = uint(gl_PrimitiveID);\n";
2758
2759 generateExecBufferIo(src, shaderSpec, "invocationId");
2760
2761 src << "}\n";
2762
2763 return src.str();
2764 }
2765
generateEmptyTessEvalShader()2766 static std::string generateEmptyTessEvalShader ()
2767 {
2768 std::ostringstream src;
2769
2770 src << "#version 310 es\n"
2771 "#extension GL_EXT_tessellation_shader : require\n\n";
2772
2773 src << "layout(triangles, ccw) in;\n";
2774
2775 src << "\nvoid main (void)\n{\n"
2776 << "\tgl_Position = vec4(gl_TessCoord.xy, 0.0, 1.0);\n"
2777 << "}\n";
2778
2779 return src.str();
2780 }
2781
setShaderSources(SourceCollections & programCollection) const2782 void TessControlExecutor::setShaderSources (SourceCollections& programCollection) const
2783 {
2784 programCollection.glslSources.add("vert") << glu::VertexSource(generateVertexShaderForTess());
2785 programCollection.glslSources.add("tess_control") << glu::TessellationControlSource(generateTessControlShader(m_shaderSpec));
2786 programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(generateEmptyTessEvalShader());
2787 programCollection.glslSources.add("frag") << glu::FragmentSource(generateEmptyFragmentSource());
2788 }
2789
execute(const Context & ctx,int numValues,const void * const * inputs,void * const * outputs)2790 void TessControlExecutor::execute (const Context& ctx, int numValues, const void* const* inputs, void* const* outputs)
2791 {
2792 const deUint32 patchSize = 3;
2793
2794 checkSupported(ctx, m_shaderType);
2795
2796 initBuffers(ctx, numValues);
2797
2798 // Setup input buffer & copy data
2799 uploadInputBuffer(ctx, inputs, numValues);
2800
2801 renderTess(ctx, numValues, patchSize * numValues, patchSize);
2802
2803 // Read back data
2804 readOutputBuffer(ctx, outputs, numValues);
2805 }
2806
2807 // TessEvaluationExecutor
2808
2809 class TessEvaluationExecutor : public TessellationExecutor
2810 {
2811 public:
2812 TessEvaluationExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType);
2813 virtual ~TessEvaluationExecutor (void);
2814
2815 virtual void setShaderSources (SourceCollections& programCollection) const;
2816
2817 virtual void execute (const Context& ctx, int numValues, const void* const* inputs, void* const* outputs);
2818
2819 protected:
2820 static std::string generateTessEvalShader (const ShaderSpec& shaderSpec);
2821 };
2822
TessEvaluationExecutor(const ShaderSpec & shaderSpec,glu::ShaderType shaderType)2823 TessEvaluationExecutor::TessEvaluationExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
2824 : TessellationExecutor (shaderSpec, shaderType)
2825 {
2826 }
2827
~TessEvaluationExecutor(void)2828 TessEvaluationExecutor::~TessEvaluationExecutor (void)
2829 {
2830 }
2831
generatePassthroughTessControlShader(void)2832 static std::string generatePassthroughTessControlShader (void)
2833 {
2834 std::ostringstream src;
2835
2836 src << "#version 310 es\n"
2837 "#extension GL_EXT_tessellation_shader : require\n\n";
2838
2839 src << "layout(vertices = 1) out;\n\n";
2840
2841 src << "void main (void)\n{\n";
2842
2843 for (int ndx = 0; ndx < 2; ndx++)
2844 src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n";
2845
2846 for (int ndx = 0; ndx < 4; ndx++)
2847 src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n";
2848
2849 src << "}\n";
2850
2851 return src.str();
2852 }
2853
generateTessEvalShader(const ShaderSpec & shaderSpec)2854 std::string TessEvaluationExecutor::generateTessEvalShader (const ShaderSpec& shaderSpec)
2855 {
2856 std::ostringstream src;
2857
2858 src << "#version 310 es\n"
2859 "#extension GL_EXT_tessellation_shader : require\n\n";
2860
2861 if (!shaderSpec.globalDeclarations.empty())
2862 src << shaderSpec.globalDeclarations << "\n";
2863
2864 src << "\n";
2865
2866 src << "layout(isolines, equal_spacing) in;\n\n";
2867
2868 declareBufferBlocks(src, shaderSpec);
2869
2870 src << "void main (void)\n{\n"
2871 << "\tgl_Position = vec4(gl_TessCoord.x, 0.0, 0.0, 1.0);\n"
2872 << "\thighp uint invocationId = uint(gl_PrimitiveID)*2u + (gl_TessCoord.x > 0.5 ? 1u : 0u);\n";
2873
2874 generateExecBufferIo(src, shaderSpec, "invocationId");
2875
2876 src << "}\n";
2877
2878 return src.str();
2879 }
2880
setShaderSources(SourceCollections & programCollection) const2881 void TessEvaluationExecutor::setShaderSources (SourceCollections& programCollection) const
2882 {
2883 programCollection.glslSources.add("vert") << glu::VertexSource(generateVertexShaderForTess());
2884 programCollection.glslSources.add("tess_control") << glu::TessellationControlSource(generatePassthroughTessControlShader());
2885 programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(generateTessEvalShader(m_shaderSpec));
2886 programCollection.glslSources.add("frag") << glu::FragmentSource(generateEmptyFragmentSource());
2887 }
2888
execute(const Context & ctx,int numValues,const void * const * inputs,void * const * outputs)2889 void TessEvaluationExecutor::execute (const Context& ctx, int numValues, const void* const* inputs, void* const* outputs)
2890 {
2891 checkSupported(ctx, m_shaderType);
2892
2893 const int patchSize = 2;
2894 const int alignedValues = deAlign32(numValues, patchSize);
2895
2896 // Initialize buffers with aligned value count to make room for padding
2897 initBuffers(ctx, alignedValues);
2898
2899 // Setup input buffer & copy data
2900 uploadInputBuffer(ctx, inputs, numValues);
2901
2902 renderTess(ctx, (deUint32)alignedValues, (deUint32)alignedValues, (deUint32)patchSize);
2903
2904 // Read back data
2905 readOutputBuffer(ctx, outputs, numValues);
2906 }
2907
2908 } // anonymous
2909
2910 // ShaderExecutor
2911
ShaderExecutor(const ShaderSpec & shaderSpec,glu::ShaderType shaderType)2912 ShaderExecutor::ShaderExecutor (const ShaderSpec& shaderSpec, glu::ShaderType shaderType)
2913 : m_shaderSpec (shaderSpec)
2914 , m_shaderType (shaderType)
2915 {
2916 }
2917
~ShaderExecutor(void)2918 ShaderExecutor::~ShaderExecutor (void)
2919 {
2920 }
2921
2922 // Utilities
2923
createExecutor(glu::ShaderType shaderType,const ShaderSpec & shaderSpec)2924 ShaderExecutor* createExecutor (glu::ShaderType shaderType, const ShaderSpec& shaderSpec)
2925 {
2926 switch (shaderType)
2927 {
2928 case glu::SHADERTYPE_VERTEX: return new VertexShaderExecutor (shaderSpec, shaderType);
2929 case glu::SHADERTYPE_TESSELLATION_CONTROL: return new TessControlExecutor (shaderSpec, shaderType);
2930 case glu::SHADERTYPE_TESSELLATION_EVALUATION: return new TessEvaluationExecutor (shaderSpec, shaderType);
2931 case glu::SHADERTYPE_GEOMETRY: return new GeometryShaderExecutor (shaderSpec, shaderType);
2932 case glu::SHADERTYPE_FRAGMENT: return new FragmentShaderExecutor (shaderSpec, shaderType);
2933 case glu::SHADERTYPE_COMPUTE: return new ComputeShaderExecutor (shaderSpec, shaderType);
2934 default:
2935 throw tcu::InternalError("Unsupported shader type");
2936 }
2937 }
2938
createBufferUniform(const VkDevice & vkDevice,const DeviceInterface & vk,const VkQueue,const deUint32 queueFamilyIndex,Allocator & memAlloc,deUint32 bindingLocation,VkDescriptorType descriptorType,deUint32 size,const void * dataPtr)2939 de::MovePtr<ShaderExecutor::BufferUniform> ShaderExecutor::createBufferUniform (const VkDevice& vkDevice,
2940 const DeviceInterface& vk,
2941 const VkQueue /*queue*/,
2942 const deUint32 queueFamilyIndex,
2943 Allocator& memAlloc,
2944 deUint32 bindingLocation,
2945 VkDescriptorType descriptorType,
2946 deUint32 size,
2947 const void* dataPtr)
2948 {
2949 DE_ASSERT(descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2950
2951 VkImageUsageFlags usage = descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
2952
2953 const VkBufferCreateInfo uniformBufferParams =
2954 {
2955 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
2956 DE_NULL, // const void* pNext;
2957 0u, // VkBufferCreateFlags flags;
2958 size, // VkDeviceSize size;
2959 usage, // VkBufferUsageFlags usage;
2960 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2961 1u, // deUint32 queueFamilyIndexCount;
2962 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
2963 };
2964
2965 Move<VkBuffer> buffer = createBuffer(vk, vkDevice, &uniformBufferParams);
2966 de::MovePtr<Allocation> alloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
2967 VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
2968
2969 deMemcpy(alloc->getHostPtr(), dataPtr, size);
2970 flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), size);
2971
2972 de::MovePtr<BufferUniform> uniformInfo(new BufferUniform());
2973 uniformInfo->type = descriptorType;
2974 uniformInfo->descriptor = makeDescriptorBufferInfo(*buffer, 0u, size);
2975 uniformInfo->location = bindingLocation;
2976 uniformInfo->buffer = VkBufferSp(new Unique<VkBuffer>(buffer));
2977 uniformInfo->alloc = AllocationSp(alloc.release());
2978
2979 return uniformInfo;
2980 }
2981
setupUniformData(const VkDevice & vkDevice,const DeviceInterface & vk,const VkQueue queue,const deUint32 queueFamilyIndex,Allocator & memAlloc,deUint32 bindingLocation,VkDescriptorType descriptorType,deUint32 size,const void * dataPtr)2982 void ShaderExecutor::setupUniformData (const VkDevice& vkDevice,
2983 const DeviceInterface& vk,
2984 const VkQueue queue,
2985 const deUint32 queueFamilyIndex,
2986 Allocator& memAlloc,
2987 deUint32 bindingLocation,
2988 VkDescriptorType descriptorType,
2989 deUint32 size,
2990 const void* dataPtr)
2991 {
2992 de::MovePtr<BufferUniform> uniform = createBufferUniform(vkDevice, vk, queue, queueFamilyIndex, memAlloc, bindingLocation, descriptorType, size, dataPtr);
2993
2994 m_descriptorSetLayoutBuilder.addSingleBinding(descriptorType, VK_SHADER_STAGE_ALL);
2995 m_descriptorPoolBuilder.addType(descriptorType);
2996
2997 m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniform)));
2998 }
2999
setupUniformArray(const VkDevice & vkDevice,const DeviceInterface & vk,const VkQueue queue,const deUint32 queueFamilyIndex,Allocator & memAlloc,deUint32 bindingLocation,VkDescriptorType descriptorType,deUint32 arraySize,deUint32 size,const void * dataPtr)3000 void ShaderExecutor::setupUniformArray (const VkDevice& vkDevice,
3001 const DeviceInterface& vk,
3002 const VkQueue queue,
3003 const deUint32 queueFamilyIndex,
3004 Allocator& memAlloc,
3005 deUint32 bindingLocation,
3006 VkDescriptorType descriptorType,
3007 deUint32 arraySize,
3008 deUint32 size,
3009 const void* dataPtr)
3010 {
3011 DE_ASSERT(arraySize > 0);
3012
3013 de::MovePtr<BufferArrayUniform> bufferArray (new BufferArrayUniform());
3014
3015 bufferArray->type = descriptorType;
3016 bufferArray->location = bindingLocation;
3017
3018 for (deUint32 ndx = 0; ndx < arraySize; ++ndx)
3019 {
3020 const void* bufferData = ((deUint8*)dataPtr) + (ndx * size);
3021 de::MovePtr<BufferUniform> uniform = createBufferUniform(vkDevice, vk, queue, queueFamilyIndex, memAlloc, bindingLocation, descriptorType, size, bufferData);
3022
3023 bufferArray->uniforms.push_back(BufferUniformSp(new de::UniquePtr<BufferUniform>(uniform)));
3024 }
3025
3026 m_descriptorSetLayoutBuilder.addArrayBinding(descriptorType, arraySize, VK_SHADER_STAGE_ALL);
3027 m_descriptorPoolBuilder.addType(descriptorType, arraySize);
3028
3029 m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(bufferArray)));
3030 }
3031
setupSamplerData(const VkDevice & vkDevice,const DeviceInterface & vk,const VkQueue queue,const deUint32 queueFamilyIndex,Allocator & memAlloc,deUint32 bindingLocation,deUint32 numSamplers,const tcu::Sampler & refSampler,const tcu::TextureFormat & texFormat,const tcu::IVec3 & texSize,VkImageType imageType,VkImageViewType imageViewType,const void * data)3032 void ShaderExecutor::setupSamplerData (const VkDevice& vkDevice,
3033 const DeviceInterface& vk,
3034 const VkQueue queue,
3035 const deUint32 queueFamilyIndex,
3036 Allocator& memAlloc,
3037 deUint32 bindingLocation,
3038 deUint32 numSamplers,
3039 const tcu::Sampler& refSampler,
3040 const tcu::TextureFormat& texFormat,
3041 const tcu::IVec3& texSize,
3042 VkImageType imageType,
3043 VkImageViewType imageViewType,
3044 const void* data)
3045 {
3046 DE_ASSERT(numSamplers > 0);
3047
3048 de::MovePtr<SamplerArrayUniform> samplers (new SamplerArrayUniform());
3049
3050 samplers->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
3051 samplers->location = bindingLocation;
3052
3053 for (deUint32 ndx = 0; ndx < numSamplers; ++ndx)
3054 {
3055 const int offset = ndx * texSize.x() * texSize.y() * texSize.z() * texFormat.getPixelSize();
3056 const void* samplerData = ((deUint8*)data) + offset;
3057 de::MovePtr<SamplerUniform> uniform = createSamplerUniform(vkDevice, vk, queue, queueFamilyIndex, memAlloc, bindingLocation, refSampler, texFormat, texSize, imageType, imageViewType, samplerData);
3058
3059 samplers->uniforms.push_back(SamplerUniformSp(new de::UniquePtr<SamplerUniform>(uniform)));
3060 }
3061
3062 m_descriptorSetLayoutBuilder.addArraySamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, numSamplers, VK_SHADER_STAGE_ALL, DE_NULL);
3063 m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, numSamplers);
3064
3065 m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(samplers)));
3066 }
3067
getBufferPtr(const deUint32 bindingLocation) const3068 const void* ShaderExecutor::getBufferPtr (const deUint32 bindingLocation) const
3069 {
3070 std::vector<UniformInfoSp>::const_iterator it = m_uniformInfos.begin();
3071 for (; it != m_uniformInfos.end(); it++)
3072 {
3073 const UniformInfo* uniformInfo = it->get()->get();
3074 if (uniformInfo->getType() == UniformInfo::UNIFORM_TYPE_BUFFER && uniformInfo->location == bindingLocation)
3075 {
3076 const BufferUniform* bufferUniform = static_cast<const BufferUniform*>(uniformInfo);
3077 return bufferUniform->alloc->getHostPtr();
3078 }
3079 }
3080
3081 return DE_NULL;
3082 }
3083
addUniforms(const VkDevice & vkDevice,const DeviceInterface & vk,const VkQueue queue,const deUint32 queueFamilyIndex,Allocator & memAlloc)3084 void ShaderExecutor::addUniforms (const VkDevice& vkDevice, const DeviceInterface& vk, const VkQueue queue, const deUint32 queueFamilyIndex, Allocator& memAlloc)
3085 {
3086 if (!m_uniformSetup)
3087 return;
3088
3089 for (std::vector<UniformDataSp>::const_iterator it = m_uniformSetup->uniforms().begin(); it != m_uniformSetup->uniforms().end(); ++it)
3090 {
3091 const UniformDataBase* uniformData = it->get()->get();
3092 uniformData->setup(*this, vkDevice, vk, queue, queueFamilyIndex, memAlloc);
3093 }
3094 }
3095
uploadUniforms(DescriptorSetUpdateBuilder & descriptorSetUpdateBuilder,VkDescriptorSet descriptorSet)3096 void ShaderExecutor::uploadUniforms (DescriptorSetUpdateBuilder& descriptorSetUpdateBuilder, VkDescriptorSet descriptorSet)
3097 {
3098 for (std::vector<UniformInfoSp>::const_iterator it = m_uniformInfos.begin(); it != m_uniformInfos.end(); ++it)
3099 {
3100 const UniformInfo* uniformInfo = it->get()->get();
3101 UniformInfo::UniformType uniformType = uniformInfo->getType();
3102
3103 if (uniformType == UniformInfo::UNIFORM_TYPE_BUFFER_ARRAY)
3104 {
3105 const BufferArrayUniform* arrayInfo = static_cast<const BufferArrayUniform*>(uniformInfo);
3106 std::vector<VkDescriptorBufferInfo> descriptors;
3107
3108 for (std::vector<BufferUniformSp>::const_iterator ait = arrayInfo->uniforms.begin(); ait != arrayInfo->uniforms.end(); ++ait)
3109 {
3110 descriptors.push_back(ait->get()->get()->descriptor);
3111 }
3112
3113 descriptorSetUpdateBuilder.writeArray(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(uniformInfo->location), uniformInfo->type, (deUint32)descriptors.size(), &descriptors[0]);
3114 }
3115 else if (uniformType == UniformInfo::UNIFORM_TYPE_SAMPLER_ARRAY)
3116 {
3117 const SamplerArrayUniform* arrayInfo = static_cast<const SamplerArrayUniform*>(uniformInfo);
3118 std::vector<VkDescriptorImageInfo> descriptors;
3119
3120 for (std::vector<SamplerUniformSp>::const_iterator ait = arrayInfo->uniforms.begin(); ait != arrayInfo->uniforms.end(); ++ait)
3121 {
3122 descriptors.push_back(ait->get()->get()->descriptor);
3123 }
3124
3125 descriptorSetUpdateBuilder.writeArray(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(uniformInfo->location), uniformInfo->type, (deUint32)descriptors.size(), &descriptors[0]);
3126 }
3127 else if (uniformType == UniformInfo::UNIFORM_TYPE_BUFFER)
3128 {
3129 const BufferUniform* bufferUniform = static_cast<const BufferUniform*>(uniformInfo);
3130 descriptorSetUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferUniform->location), bufferUniform->type, &bufferUniform->descriptor);
3131 }
3132 else if (uniformType == UniformInfo::UNIFORM_TYPE_SAMPLER)
3133 {
3134 const SamplerUniform* samplerUniform = static_cast<const SamplerUniform*>(uniformInfo);
3135 descriptorSetUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(samplerUniform->location), samplerUniform->type, &samplerUniform->descriptor);
3136 }
3137 }
3138 }
3139
uploadImage(const VkDevice & vkDevice,const DeviceInterface & vk,const VkQueue queue,const deUint32 queueFamilyIndex,Allocator & memAlloc,const tcu::TextureFormat & texFormat,const tcu::IVec3 & texSize,const void * data,const deUint32 arraySize,const VkImageAspectFlags aspectMask,VkImage destImage)3140 void ShaderExecutor::uploadImage (const VkDevice& vkDevice,
3141 const DeviceInterface& vk,
3142 const VkQueue queue,
3143 const deUint32 queueFamilyIndex,
3144 Allocator& memAlloc,
3145 const tcu::TextureFormat& texFormat,
3146 const tcu::IVec3& texSize,
3147 const void* data,
3148 const deUint32 arraySize,
3149 const VkImageAspectFlags aspectMask,
3150 VkImage destImage)
3151 {
3152 deUint32 textureSize = texSize.x() * texSize.y() * texSize.z() * texFormat.getPixelSize();
3153 deUint32 bufferSize;
3154 Move<VkBuffer> buffer;
3155 de::MovePtr<Allocation> bufferAlloc;
3156 Move<VkCommandPool> cmdPool;
3157 Move<VkCommandBuffer> cmdBuffer;
3158 Move<VkFence> fence;
3159 std::vector<deUint32> levelDataSizes;
3160
3161 // Calculate buffer size
3162 bufferSize = arraySize * textureSize;
3163
3164 // Create source buffer
3165 {
3166 const VkBufferCreateInfo bufferParams =
3167 {
3168 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
3169 DE_NULL, // const void* pNext;
3170 0u, // VkBufferCreateFlags flags;
3171 bufferSize, // VkDeviceSize size;
3172 VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // VkBufferUsageFlags usage;
3173 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
3174 0u, // deUint32 queueFamilyIndexCount;
3175 DE_NULL, // const deUint32* pQueueFamilyIndices;
3176 };
3177
3178 buffer = createBuffer(vk, vkDevice, &bufferParams);
3179 bufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
3180 VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
3181 }
3182
3183 // Create command pool and buffer
3184 {
3185 const VkCommandPoolCreateInfo cmdPoolParams =
3186 {
3187 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
3188 DE_NULL, // const void* pNext;
3189 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags;
3190 queueFamilyIndex, // deUint32 queueFamilyIndex;
3191 };
3192
3193 cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
3194
3195 const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
3196 {
3197 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
3198 DE_NULL, // const void* pNext;
3199 *cmdPool, // VkCommandPool commandPool;
3200 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
3201 1u, // deUint32 bufferCount;
3202 };
3203
3204 cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
3205 }
3206
3207 // Create fence
3208 {
3209 const VkFenceCreateInfo fenceParams =
3210 {
3211 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
3212 DE_NULL, // const void* pNext;
3213 0u // VkFenceCreateFlags flags;
3214 };
3215
3216 fence = createFence(vk, vkDevice, &fenceParams);
3217 }
3218
3219 // Barriers for copying buffer to image
3220 const VkBufferMemoryBarrier preBufferBarrier =
3221 {
3222 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
3223 DE_NULL, // const void* pNext;
3224 VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask;
3225 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
3226 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
3227 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
3228 *buffer, // VkBuffer buffer;
3229 0u, // VkDeviceSize offset;
3230 bufferSize // VkDeviceSize size;
3231 };
3232
3233 const VkImageMemoryBarrier preImageBarrier =
3234 {
3235 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
3236 DE_NULL, // const void* pNext;
3237 0u, // VkAccessFlags srcAccessMask;
3238 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
3239 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
3240 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
3241 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
3242 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
3243 destImage, // VkImage image;
3244 { // VkImageSubresourceRange subresourceRange;
3245 aspectMask, // VkImageAspect aspect;
3246 0u, // deUint32 baseMipLevel;
3247 1u, // deUint32 mipLevels;
3248 0u, // deUint32 baseArraySlice;
3249 arraySize // deUint32 arraySize;
3250 }
3251 };
3252
3253 const VkImageMemoryBarrier postImageBarrier =
3254 {
3255 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
3256 DE_NULL, // const void* pNext;
3257 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
3258 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
3259 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
3260 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout;
3261 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
3262 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
3263 destImage, // VkImage image;
3264 { // VkImageSubresourceRange subresourceRange;
3265 aspectMask, // VkImageAspect aspect;
3266 0u, // deUint32 baseMipLevel;
3267 1u, // deUint32 mipLevels;
3268 0u, // deUint32 baseArraySlice;
3269 arraySize // deUint32 arraySize;
3270 }
3271 };
3272
3273 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
3274 {
3275 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
3276 DE_NULL, // const void* pNext;
3277 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags;
3278 (const VkCommandBufferInheritanceInfo*)DE_NULL,
3279 };
3280
3281 std::vector<VkBufferImageCopy> copyRegions;
3282
3283 {
3284 deUint32 layerDataOffset = 0;
3285
3286 for (deUint32 layerNdx = 0; layerNdx < arraySize; ++layerNdx)
3287 {
3288 const VkBufferImageCopy layerRegion =
3289 {
3290 layerDataOffset, // VkDeviceSize bufferOffset;
3291 (deUint32)texSize.x(), // deUint32 bufferRowLength;
3292 (deUint32)texSize.y(), // deUint32 bufferImageHeight;
3293 { // VkImageSubresourceLayers imageSubresource;
3294 aspectMask,
3295 0u,
3296 (deUint32)layerNdx,
3297 1u
3298 },
3299 { 0u, 0u, 0u }, // VkOffset3D imageOffset;
3300 { // VkExtent3D imageExtent;
3301 (deUint32)texSize.x(),
3302 (deUint32)texSize.y(),
3303 (deUint32)texSize.z()
3304 }
3305 };
3306
3307 copyRegions.push_back(layerRegion);
3308 layerDataOffset += textureSize;
3309 }
3310 }
3311
3312 // Write buffer data
3313 {
3314 deUint8* destPtr = (deUint8*)bufferAlloc->getHostPtr();
3315 deUint32 levelOffset = 0;
3316
3317 for (deUint32 layerNdx = 0; layerNdx < arraySize; ++layerNdx)
3318 {
3319 tcu::ConstPixelBufferAccess access (texFormat, texSize, data);
3320 tcu::PixelBufferAccess destAccess (texFormat, texSize, destPtr + levelOffset);
3321
3322 tcu::copy(destAccess, access);
3323 levelOffset += textureSize;
3324 }
3325 }
3326
3327 flushMappedMemoryRange(vk, vkDevice, bufferAlloc->getMemory(), bufferAlloc->getOffset(), bufferSize);
3328
3329 // Copy buffer to image
3330 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
3331 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &preBufferBarrier, 1, &preImageBarrier);
3332 vk.cmdCopyBufferToImage(*cmdBuffer, *buffer, destImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copyRegions.size(), copyRegions.data());
3333 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
3334 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
3335
3336 const VkSubmitInfo submitInfo =
3337 {
3338 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
3339 DE_NULL, // const void* pNext;
3340 0u, // deUint32 waitSemaphoreCount;
3341 DE_NULL, // const VkSemaphore* pWaitSemaphores;
3342 DE_NULL,
3343 1u, // deUint32 commandBufferCount;
3344 &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
3345 0u, // deUint32 signalSemaphoreCount;
3346 DE_NULL // const VkSemaphore* pSignalSemaphores;
3347 };
3348
3349 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
3350 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity */));
3351 }
3352
createSamplerUniform(const VkDevice & vkDevice,const DeviceInterface & vk,const VkQueue queue,const deUint32 queueFamilyIndex,Allocator & memAlloc,deUint32 bindingLocation,const tcu::Sampler & refSampler,const tcu::TextureFormat & texFormat,const tcu::IVec3 & texSize,VkImageType imageType,VkImageViewType imageViewType,const void * data)3353 de::MovePtr<ShaderExecutor::SamplerUniform> ShaderExecutor::createSamplerUniform (const VkDevice& vkDevice,
3354 const DeviceInterface& vk,
3355 const VkQueue queue,
3356 const deUint32 queueFamilyIndex,
3357 Allocator& memAlloc,
3358 deUint32 bindingLocation,
3359 const tcu::Sampler& refSampler,
3360 const tcu::TextureFormat& texFormat,
3361 const tcu::IVec3& texSize,
3362 VkImageType imageType,
3363 VkImageViewType imageViewType,
3364 const void* data)
3365 {
3366 const VkFormat format = mapTextureFormat(texFormat);
3367 const bool isCube = imageViewType == VK_IMAGE_VIEW_TYPE_CUBE;
3368 const bool isShadowSampler = texFormat == tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
3369 const VkImageCreateFlags imageFlags = isCube ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlags)0;
3370 const deUint32 arraySize = isCube ? 6u : 1u;
3371 const VkImageAspectFlags aspectMask = isShadowSampler ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
3372 VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3373 Move<VkImage> vkTexture;
3374 de::MovePtr<Allocation> allocation;
3375
3376 if (isShadowSampler)
3377 imageUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
3378
3379 // Create image
3380 const VkImageCreateInfo imageParams =
3381 {
3382 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
3383 DE_NULL, // const void* pNext;
3384 imageFlags, // VkImageCreateFlags flags;
3385 imageType, // VkImageType imageType;
3386 format, // VkFormat format;
3387 { // VkExtent3D extent;
3388 (deUint32)texSize.x(),
3389 (deUint32)texSize.y(),
3390 (deUint32)texSize.z()
3391 },
3392 1u, // deUint32 mipLevels;
3393 arraySize, // deUint32 arrayLayers;
3394 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
3395 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
3396 imageUsage, // VkImageUsageFlags usage;
3397 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
3398 1u, // deUint32 queueFamilyIndexCount;
3399 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
3400 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
3401 };
3402
3403 vkTexture = createImage(vk, vkDevice, &imageParams);
3404 allocation = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *vkTexture), MemoryRequirement::Any);
3405 VK_CHECK(vk.bindImageMemory(vkDevice, *vkTexture, allocation->getMemory(), allocation->getOffset()));
3406
3407 // Upload texture data
3408 uploadImage(vkDevice, vk, queue, queueFamilyIndex, memAlloc, texFormat, texSize, data, arraySize, aspectMask, *vkTexture);
3409
3410 // Create sampler
3411 const VkSamplerCreateInfo samplerParams = mapSampler(refSampler, texFormat);
3412 Move<VkSampler> sampler = createSampler(vk, vkDevice, &samplerParams);
3413
3414 const VkImageViewCreateInfo viewParams =
3415 {
3416 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
3417 NULL, // const voide* pNexŧ;
3418 0u, // VkImageViewCreateFlags flags;
3419 *vkTexture, // VkImage image;
3420 imageViewType, // VkImageViewType viewType;
3421 format, // VkFormat format;
3422 {
3423 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
3424 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
3425 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
3426 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
3427 }, // VkComponentMapping components;
3428 {
3429 aspectMask, // VkImageAspectFlags aspectMask;
3430 0, // deUint32 baseMipLevel;
3431 1, // deUint32 mipLevels;
3432 0, // deUint32 baseArraySlice;
3433 arraySize // deUint32 arraySize;
3434 } // VkImageSubresourceRange subresourceRange;
3435 };
3436
3437 Move<VkImageView> imageView = createImageView(vk, vkDevice, &viewParams);
3438
3439 const VkDescriptorImageInfo descriptor =
3440 {
3441 sampler.get(), // VkSampler sampler;
3442 imageView.get(), // VkImageView imageView;
3443 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout;
3444 };
3445
3446 de::MovePtr<SamplerUniform> uniform(new SamplerUniform());
3447 uniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
3448 uniform->descriptor = descriptor;
3449 uniform->location = bindingLocation;
3450 uniform->image = VkImageSp(new Unique<VkImage>(vkTexture));
3451 uniform->imageView = VkImageViewSp(new Unique<VkImageView>(imageView));
3452 uniform->sampler = VkSamplerSp(new Unique<VkSampler>(sampler));
3453 uniform->alloc = AllocationSp(allocation.release());
3454
3455 return uniform;
3456 }
3457
SamplerUniformData(deUint32 bindingLocation,deUint32 numSamplers,const tcu::Sampler & refSampler,const tcu::TextureFormat & texFormat,const tcu::IVec3 & texSize,VkImageType imageType,VkImageViewType imageViewType,const void * data)3458 SamplerUniformData::SamplerUniformData (deUint32 bindingLocation,
3459 deUint32 numSamplers,
3460 const tcu::Sampler& refSampler,
3461 const tcu::TextureFormat& texFormat,
3462 const tcu::IVec3& texSize,
3463 VkImageType imageType,
3464 VkImageViewType imageViewType,
3465 const void* data)
3466 : UniformDataBase (bindingLocation)
3467 , m_numSamplers (numSamplers)
3468 , m_refSampler (refSampler)
3469 , m_texFormat (texFormat)
3470 , m_texSize (texSize)
3471 , m_imageType (imageType)
3472 , m_imageViewType (imageViewType)
3473 , m_data (data)
3474 {
3475 }
3476
~SamplerUniformData(void)3477 SamplerUniformData::~SamplerUniformData (void)
3478 {
3479 }
3480
setup(ShaderExecutor & executor,const VkDevice & vkDevice,const DeviceInterface & vk,const VkQueue queue,const deUint32 queueFamilyIndex,Allocator & memAlloc) const3481 void SamplerUniformData::setup (ShaderExecutor& executor, const VkDevice& vkDevice, const DeviceInterface& vk, const VkQueue queue, const deUint32 queueFamilyIndex, Allocator& memAlloc) const
3482 {
3483 executor.setupSamplerData(vkDevice, vk, queue, queueFamilyIndex, memAlloc, m_bindingLocation, m_numSamplers, m_refSampler, m_texFormat, m_texSize, m_imageType, m_imageViewType, m_data);
3484 }
3485
3486 } // shaderexecutor
3487 } // vkt
3488