1 /*-------------------------------------------------------------------------
2 * Vulkan CTS Framework
3 * --------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 Google Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Utility for generating simple work
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawUtil.hpp"
26 #include "rrMultisamplePixelBufferAccess.hpp"
27 #include "vkBufferWithMemory.hpp"
28 #include "vkImageWithMemory.hpp"
29 #include "vkBarrierUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "rrRenderer.hpp"
34 #include "rrRenderState.hpp"
35 #include "rrPrimitiveTypes.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuTestLog.hpp"
38 #include "deArrayUtil.hpp"
39 #include "vkBuilderUtil.hpp"
40 #include "vkCmdUtil.hpp"
41
42 namespace vkt
43 {
44 namespace drawutil
45 {
46
47 using namespace de;
48 using namespace tcu;
49 using namespace vk;
50
mapCompareOp(rr::TestFunc compareFunc)51 static VkCompareOp mapCompareOp(rr::TestFunc compareFunc)
52 {
53 switch (compareFunc)
54 {
55 case rr::TESTFUNC_NEVER:
56 return VK_COMPARE_OP_NEVER;
57 case rr::TESTFUNC_LESS:
58 return VK_COMPARE_OP_LESS;
59 case rr::TESTFUNC_EQUAL:
60 return VK_COMPARE_OP_EQUAL;
61 case rr::TESTFUNC_LEQUAL:
62 return VK_COMPARE_OP_LESS_OR_EQUAL;
63 case rr::TESTFUNC_GREATER:
64 return VK_COMPARE_OP_GREATER;
65 case rr::TESTFUNC_NOTEQUAL:
66 return VK_COMPARE_OP_NOT_EQUAL;
67 case rr::TESTFUNC_GEQUAL:
68 return VK_COMPARE_OP_GREATER_OR_EQUAL;
69 case rr::TESTFUNC_ALWAYS:
70 return VK_COMPARE_OP_ALWAYS;
71 default:
72 DE_ASSERT(false);
73 }
74 return VK_COMPARE_OP_LAST;
75 }
76
mapVkPrimitiveToRRPrimitive(const vk::VkPrimitiveTopology & primitiveTopology)77 rr::PrimitiveType mapVkPrimitiveToRRPrimitive(const vk::VkPrimitiveTopology &primitiveTopology)
78 {
79 static const rr::PrimitiveType primitiveTypeTable[] = {rr::PRIMITIVETYPE_POINTS,
80 rr::PRIMITIVETYPE_LINES,
81 rr::PRIMITIVETYPE_LINE_STRIP,
82 rr::PRIMITIVETYPE_TRIANGLES,
83 rr::PRIMITIVETYPE_TRIANGLE_STRIP,
84 rr::PRIMITIVETYPE_TRIANGLE_FAN,
85 rr::PRIMITIVETYPE_LINES_ADJACENCY,
86 rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY,
87 rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY,
88 rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY};
89
90 return de::getSizedArrayElement<vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST>(primitiveTypeTable, primitiveTopology);
91 }
92
makeCommandBuffer(const DeviceInterface & vk,const VkDevice device,const VkCommandPool commandPool)93 Move<VkCommandBuffer> makeCommandBuffer(const DeviceInterface &vk, const VkDevice device,
94 const VkCommandPool commandPool)
95 {
96 const VkCommandBufferAllocateInfo info = {
97 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
98 DE_NULL, // const void* pNext;
99 commandPool, // VkCommandPool commandPool;
100 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
101 1u, // uint32_t commandBufferCount;
102 };
103 return allocateCommandBuffer(vk, device, &info);
104 }
105
getPrimitiveTopologyShortName(const VkPrimitiveTopology topology)106 std::string getPrimitiveTopologyShortName(const VkPrimitiveTopology topology)
107 {
108 std::string name(getPrimitiveTopologyName(topology));
109 return de::toLower(name.substr(22));
110 }
111
FrameBufferState(uint32_t renderWidth_,uint32_t renderHeight_)112 FrameBufferState::FrameBufferState(uint32_t renderWidth_, uint32_t renderHeight_)
113 : renderSize(renderWidth_, renderHeight_)
114 {
115 DE_ASSERT(renderSize.x() != 0 && renderSize.y() != 0);
116 }
117
PipelineState(const int subpixelBits_)118 PipelineState::PipelineState(const int subpixelBits_) : subpixelBits(subpixelBits_)
119 {
120 }
121
DrawCallData(const vk::VkPrimitiveTopology topology_,const std::vector<tcu::Vec4> & vertices_)122 DrawCallData::DrawCallData(const vk::VkPrimitiveTopology topology_, const std::vector<tcu::Vec4> &vertices_)
123 : topology(topology_)
124 , vertices(vertices_)
125 {
126 }
127
ReferenceDrawContext(const FrameBufferState & framebufferState)128 ReferenceDrawContext::ReferenceDrawContext(const FrameBufferState &framebufferState) : DrawContext(framebufferState)
129 {
130 }
131
~ReferenceDrawContext(void)132 ReferenceDrawContext::~ReferenceDrawContext(void)
133 {
134 }
135
registerDrawObject(const PipelineState & pipelineState,std::shared_ptr<rr::VertexShader> & vertexShader,std::shared_ptr<rr::FragmentShader> & fragmentShader,const DrawCallData & drawCallData)136 void ReferenceDrawContext::registerDrawObject(const PipelineState &pipelineState,
137 std::shared_ptr<rr::VertexShader> &vertexShader,
138 std::shared_ptr<rr::FragmentShader> &fragmentShader,
139 const DrawCallData &drawCallData)
140 {
141 m_pipelineStates.push_back(pipelineState);
142 m_vertexShaders.push_back(vertexShader);
143 m_fragmentShaders.push_back(fragmentShader);
144 m_drawCallData.push_back(drawCallData);
145 }
146
draw(void)147 void ReferenceDrawContext::draw(void)
148 {
149 DE_ASSERT(m_fragmentShaders.size() == m_vertexShaders.size());
150 DE_ASSERT(m_vertexShaders.size() == m_drawCallData.size());
151 DE_ASSERT(m_drawCallData.size() == m_pipelineStates.size());
152
153 m_refImage.setStorage(vk::mapVkFormat(m_framebufferState.colorFormat), m_framebufferState.renderSize.x(),
154 m_framebufferState.renderSize.y());
155 tcu::clear(m_refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
156
157 const rr::MultisamplePixelBufferAccess referenceColorBuffer =
158 rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(m_refImage.getAccess());
159 const rr::RenderTarget renderTarget(referenceColorBuffer);
160 const rr::Renderer renderer;
161 for (uint32_t objectNdx = 0; objectNdx < m_drawCallData.size(); objectNdx++)
162 {
163 const rr::RenderState renderState((rr::ViewportState(referenceColorBuffer)),
164 m_pipelineStates[objectNdx].subpixelBits, rr::VIEWPORTORIENTATION_UPPER_LEFT);
165 const rr::Program program(m_vertexShaders[objectNdx].get(), m_fragmentShaders[objectNdx].get());
166 const rr::VertexAttrib vertexAttrib[] = {rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0,
167 m_drawCallData[objectNdx].vertices.data())};
168
169 renderer.draw(rr::DrawCommand(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttrib),
170 &vertexAttrib[0],
171 rr::PrimitiveList(mapVkPrimitiveToRRPrimitive(m_drawCallData[objectNdx].topology),
172 (int)m_drawCallData[objectNdx].vertices.size(), 0)));
173 }
174 }
175
getColorPixels(void) const176 tcu::ConstPixelBufferAccess ReferenceDrawContext::getColorPixels(void) const
177 {
178 return tcu::ConstPixelBufferAccess(m_refImage.getAccess().getFormat(), m_refImage.getAccess().getWidth(),
179 m_refImage.getAccess().getHeight(), m_refImage.getAccess().getDepth(),
180 m_refImage.getAccess().getDataPtr());
181 }
182
VulkanShader(const vk::VkShaderStageFlagBits stage_,const vk::ProgramBinary & binary_)183 VulkanShader::VulkanShader(const vk::VkShaderStageFlagBits stage_, const vk::ProgramBinary &binary_)
184 : stage(stage_)
185 , binary(&binary_)
186 {
187 }
188
VulkanProgram(const std::vector<VulkanShader> & shaders_)189 VulkanProgram::VulkanProgram(const std::vector<VulkanShader> &shaders_) : shaders(shaders_)
190 {
191 }
192
VulkanDrawContext(Context & context,const FrameBufferState & frameBufferState)193 VulkanDrawContext::VulkanDrawContext(Context &context, const FrameBufferState &frameBufferState)
194 : DrawContext(frameBufferState)
195 , m_context(context)
196 {
197 const DeviceInterface &vk = m_context.getDeviceInterface();
198 const VkDevice device = m_context.getDevice();
199 Allocator &allocator = m_context.getDefaultAllocator();
200
201 // Color attachment image
202 {
203 const VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
204 VkImageSubresourceRange colorSubresourceRange =
205 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
206 const VkImageCreateInfo imageCreateInfo = {
207 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
208 DE_NULL, // const void* pNext;
209 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
210 VK_IMAGE_TYPE_2D, // VkImageType imageType;
211 m_framebufferState.colorFormat, // VkFormat format;
212 makeExtent3D(m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y(),
213 1u), // VkExtent3D extent;
214 1u, // uint32_t mipLevels;
215 1u, // uint32_t arrayLayers;
216 (VkSampleCountFlagBits)m_framebufferState.numSamples, // VkSampleCountFlagBits samples;
217 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
218 usage, // VkImageUsageFlags usage;
219 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
220 0u, // uint32_t queueFamilyIndexCount;
221 DE_NULL, // const uint32_t* pQueueFamilyIndices;
222 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
223 };
224
225 m_colorImage = MovePtr<ImageWithMemory>(
226 new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
227 m_colorImageView = makeImageView(vk, device, **m_colorImage, VK_IMAGE_VIEW_TYPE_2D,
228 m_framebufferState.colorFormat, colorSubresourceRange);
229
230 // Buffer to copy attachment data after rendering
231
232 const VkDeviceSize bitmapSize = tcu::getPixelSize(mapVkFormat(m_framebufferState.colorFormat)) *
233 m_framebufferState.renderSize.x() * m_framebufferState.renderSize.y();
234 m_colorAttachmentBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(
235 vk, device, allocator, makeBufferCreateInfo(bitmapSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
236 MemoryRequirement::HostVisible));
237
238 {
239 const Allocation &alloc = m_colorAttachmentBuffer->getAllocation();
240 deMemset(alloc.getHostPtr(), 0, (size_t)bitmapSize);
241 flushAlloc(vk, device, alloc);
242 }
243 }
244
245 // Depth buffer - create image when user didn't deliver its own, but configured depthFormat
246 vk::VkImageView depthImageView = m_framebufferState.depthImageView;
247 if (!m_framebufferState.depthImageView && m_framebufferState.depthFormat != VK_FORMAT_UNDEFINED)
248 {
249 const VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
250 VkImageSubresourceRange depthSubresourceRange =
251 makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
252
253 const VkImageCreateInfo depthImageCreateInfo = {
254 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
255 DE_NULL, // const void* pNext
256 (VkImageCreateFlags)0, // VkImageCreateFlags flags
257 VK_IMAGE_TYPE_2D, // VkIMageType imageType
258 m_framebufferState.depthFormat, // VkFormat format
259 makeExtent3D(m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y(),
260 1u), // VkExtent3D extent;
261 1u, // uint32_t mipLevels
262 1u, // uint32_t arrayLayers
263 (VkSampleCountFlagBits)m_framebufferState.numSamples, // VkSampleCountFlagsBits samples
264 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling
265 usage, // VkImageUsageFlags usage
266 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode
267 0u, // uint32_t queueFamilyIndexCount
268 DE_NULL, // const uint32_t pQueueFamilyIndices
269 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout
270 };
271
272 m_depthImage = MovePtr<ImageWithMemory>(
273 new ImageWithMemory(vk, device, allocator, depthImageCreateInfo, MemoryRequirement::Any));
274 m_depthImageView = makeImageView(vk, device, **m_depthImage, VK_IMAGE_VIEW_TYPE_2D,
275 m_framebufferState.depthFormat, depthSubresourceRange);
276 depthImageView = *m_depthImageView;
277 }
278
279 // Renderpass
280 {
281 std::vector<VkAttachmentDescription> attachmentDescriptions;
282 const VkAttachmentDescription attachDescriptors[] = {
283 {
284 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
285 m_framebufferState.colorFormat, // VkFormat format;
286 (VkSampleCountFlagBits)m_framebufferState.numSamples, // VkSampleCountFlagBits samples;
287 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
288 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
289 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
290 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
291 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
292 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
293 },
294 {
295 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
296 m_framebufferState.depthFormat, // VkFormat format
297 (VkSampleCountFlagBits)m_framebufferState.numSamples, // VkSampleCountFlagBits samples
298 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
299 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
300 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
301 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
302 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
303 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout
304 }};
305
306 const VkAttachmentReference attachmentReferences[] = {
307 {
308 0u, // uint32_t attachment
309 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout
310 },
311 {
312 1u, // uint32_t attachment
313 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout
314 },
315 {
316 VK_ATTACHMENT_UNUSED, // uint32_t attachment;
317 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout;
318 }};
319
320 attachmentDescriptions.push_back(attachDescriptors[0]);
321 uint32_t depthReferenceNdx = 2;
322 if (depthImageView != 0)
323 {
324 attachmentDescriptions.push_back(attachDescriptors[1]);
325 depthReferenceNdx = 1;
326 }
327
328 const VkSubpassDescription subpassDescription = {
329 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
330 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
331 0u, // uint32_t inputAttachmentCount;
332 DE_NULL, // const VkAttachmentReference* pInputAttachments;
333 1u, // uint32_t colorAttachmentCount;
334 &attachmentReferences[0], // const VkAttachmentReference* pColorAttachments;
335 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
336 &attachmentReferences[depthReferenceNdx], // const VkAttachmentReference* pDepthStencilAttachment;
337 0u, // uint32_t preserveAttachmentCount;
338 DE_NULL // const uint32_t* pPreserveAttachments;
339 };
340
341 const VkRenderPassCreateInfo renderPassInfo = {
342 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
343 DE_NULL, // const void* pNext;
344 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
345 (uint32_t)attachmentDescriptions.size(), // uint32_t attachmentCount;
346 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments;
347 1u, // uint32_t subpassCount;
348 &subpassDescription, // const VkSubpassDescription* pSubpasses;
349 0u, // uint32_t dependencyCount;
350 DE_NULL // const VkSubpassDependency* pDependencies;
351 };
352
353 m_renderPass = createRenderPass(vk, device, &renderPassInfo);
354 }
355
356 // Framebuffer
357 {
358 std::vector<VkImageView> attachmentBindInfos;
359 uint32_t numAttachments;
360 attachmentBindInfos.push_back(*m_colorImageView);
361 if (depthImageView != 0)
362 attachmentBindInfos.push_back(depthImageView);
363
364 numAttachments = (uint32_t)(attachmentBindInfos.size());
365 const VkFramebufferCreateInfo framebufferInfo = {
366 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
367 DE_NULL, // const void* pNext;
368 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
369 *m_renderPass, // VkRenderPass renderPass;
370 numAttachments, // uint32_t attachmentCount;
371 &attachmentBindInfos[0], // const VkImageView* pAttachments;
372 m_framebufferState.renderSize.x(), // uint32_t width;
373 m_framebufferState.renderSize.y(), // uint32_t height;
374 1u, // uint32_t layers;
375 };
376
377 m_framebuffer = createFramebuffer(vk, device, &framebufferInfo);
378 }
379
380 // Command buffer
381 m_cmdPool = makeCommandPool(vk, device, m_context.getUniversalQueueFamilyIndex());
382 m_cmdBuffer = makeCommandBuffer(vk, device, *m_cmdPool);
383 }
384
~VulkanDrawContext(void)385 VulkanDrawContext::~VulkanDrawContext(void)
386 {
387 }
388
registerDrawObject(const PipelineState & pipelineState,const VulkanProgram & vulkanProgram,const DrawCallData & drawCallData)389 void VulkanDrawContext::registerDrawObject(const PipelineState &pipelineState, const VulkanProgram &vulkanProgram,
390 const DrawCallData &drawCallData)
391 {
392 const DeviceInterface &vk = m_context.getDeviceInterface();
393 const VkDevice device = m_context.getDevice();
394 Allocator &allocator = m_context.getDefaultAllocator();
395 auto object = std::make_shared<RenderObject>();
396
397 // Vertex buffer
398 {
399 const VkDeviceSize bufferSize = drawCallData.vertices.size() * sizeof(drawCallData.vertices[0]);
400 object->vertexBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(
401 vk, device, allocator, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
402 MemoryRequirement::HostVisible));
403 object->vertexCount = static_cast<uint32_t>(drawCallData.vertices.size());
404 const Allocation &alloc = object->vertexBuffer->getAllocation();
405 deMemcpy(alloc.getHostPtr(), &drawCallData.vertices[0], (size_t)bufferSize);
406 flushAlloc(vk, device, alloc);
407 }
408
409 // bind descriptor sets
410 {
411 object->pipelineLayout = makePipelineLayout(vk, device, vulkanProgram.descriptorSetLayout);
412 }
413
414 // Graphics pipeline
415 {
416 VkShaderModule vertShader = DE_NULL;
417 VkShaderModule tessControlShader = DE_NULL;
418 VkShaderModule tessEvalShader = DE_NULL;
419 VkShaderModule geomShader = DE_NULL;
420 VkShaderModule fragShader = DE_NULL;
421
422 DE_ASSERT(drawCallData.topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST || pipelineState.numPatchControlPoints > 0);
423
424 const std::vector<VkViewport> viewports(1, makeViewport(m_framebufferState.renderSize));
425 const std::vector<VkRect2D> scissors(1, makeRect2D(m_framebufferState.renderSize));
426
427 VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = {
428 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
429 DE_NULL, // const void* pNext;
430 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
431 pipelineState.depthClampEnable, // VkBool32 depthClampEnable;
432 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
433 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
434 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
435 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
436 VK_FALSE, // VkBool32 depthBiasEnable;
437 0.0f, // float depthBiasConstantFactor;
438 0.0f, // float depthBiasClamp;
439 0.0f, // float depthBiasSlopeFactor;
440 pipelineState.lineWidth, // float lineWidth;
441 };
442
443 VkPipelineRasterizationDepthClipStateCreateInfoEXT pipelineRasterizationDepthCliptateInfo = {
444 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT, // VkStructureType sType;
445 DE_NULL, // const void* pNext;
446 (VkPipelineRasterizationDepthClipStateCreateFlagsEXT)0, // VkPipelineRasterizationDepthClipStateCreateFlagsEXT flags;
447 pipelineState.depthClipEnable, // VkBool32 depthClipEnable;
448 };
449 if (pipelineState.explicitDepthClipEnable)
450 pipelineRasterizationStateInfo.pNext = &pipelineRasterizationDepthCliptateInfo;
451
452 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = {
453 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
454 DE_NULL, // const void* pNext;
455 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
456 (VkSampleCountFlagBits)m_framebufferState.numSamples, // VkSampleCountFlagBits rasterizationSamples;
457 pipelineState.sampleShadingEnable ? VK_TRUE : VK_FALSE, // VkBool32 sampleShadingEnable;
458 pipelineState.sampleShadingEnable ? 1.0f : 0.0f, // float minSampleShading;
459 !pipelineState.sampleMasks.empty() ? pipelineState.sampleMasks.data() :
460 DE_NULL, // const VkSampleMask* pSampleMask;
461 VK_FALSE, // VkBool32 alphaToCoverageEnable;
462 VK_FALSE // VkBool32 alphaToOneEnable;
463 };
464
465 const VkStencilOpState stencilOpState = makeStencilOpState(VK_STENCIL_OP_KEEP, // stencil fail
466 VK_STENCIL_OP_KEEP, // depth & stencil pass
467 VK_STENCIL_OP_KEEP, // depth only fail
468 VK_COMPARE_OP_NEVER, // compare op
469 0u, // compare mask
470 0u, // write mask
471 0u); // reference
472
473 if (pipelineState.depthBoundsTestEnable && !m_context.getDeviceFeatures().depthBounds)
474 TCU_THROW(NotSupportedError, "depthBounds not supported");
475
476 const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = {
477 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
478 DE_NULL, // const void* pNext;
479 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
480 pipelineState.depthTestEnable, // VkBool32 depthTestEnable;
481 pipelineState.depthWriteEnable, // VkBool32 depthWriteEnable;
482 mapCompareOp(pipelineState.compareOp), // VkCompareOp depthCompareOp;
483 pipelineState.depthBoundsTestEnable, // VkBool32 depthBoundsTestEnable
484 VK_FALSE, // VkBool32 stencilTestEnable;
485 stencilOpState, // VkStencilOpState front;
486 stencilOpState, // VkStencilOpState back;
487 0.0f, // float minDepthBounds;
488 1.0f, // float maxDepthBounds;
489 };
490
491 const VkColorComponentFlags colorComponentsAll =
492 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
493 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {
494 pipelineState.blendEnable, // VkBool32 blendEnable;
495 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor;
496 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor;
497 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
498 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor;
499 VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor;
500 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
501 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
502 };
503
504 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = {
505 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
506 DE_NULL, // const void* pNext;
507 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
508 VK_FALSE, // VkBool32 logicOpEnable;
509 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
510 1u, // uint32_t attachmentCount;
511 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
512 {0.0f, 0.0f, 0.0f, 0.0f}, // float blendConstants[4];
513 };
514
515 VkShaderStageFlags stageFlags = (VkShaderStageFlags)0;
516
517 DE_ASSERT(vulkanProgram.shaders.size() <= RenderObject::MAX_NUM_SHADER_MODULES);
518 for (uint32_t shaderNdx = 0; shaderNdx < vulkanProgram.shaders.size(); ++shaderNdx)
519 {
520 object->shaderModules[shaderNdx] =
521 createShaderModule(vk, device, *vulkanProgram.shaders[shaderNdx].binary, (VkShaderModuleCreateFlags)0);
522
523 stageFlags |= vulkanProgram.shaders[shaderNdx].stage;
524
525 switch (vulkanProgram.shaders[shaderNdx].stage)
526 {
527 case VK_SHADER_STAGE_VERTEX_BIT:
528 vertShader = *object->shaderModules[shaderNdx];
529 break;
530 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
531 tessControlShader = *object->shaderModules[shaderNdx];
532 break;
533 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
534 tessEvalShader = *object->shaderModules[shaderNdx];
535 break;
536 case VK_SHADER_STAGE_GEOMETRY_BIT:
537 geomShader = *object->shaderModules[shaderNdx];
538 break;
539 default:
540 DE_ASSERT(vulkanProgram.shaders[shaderNdx].stage == VK_SHADER_STAGE_FRAGMENT_BIT);
541 fragShader = *object->shaderModules[shaderNdx];
542 break;
543 }
544 }
545
546 DE_UNREF(stageFlags); // For release builds.
547
548 DE_ASSERT(
549 (drawCallData.topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) ||
550 (stageFlags & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)));
551
552 object->pipeline = makeGraphicsPipeline(
553 vk, // const DeviceInterface& vk
554 device, // const VkDevice device
555 *(object->pipelineLayout), // const VkPipelineLayout pipelineLayout
556 vertShader, // const VkShaderModule vertexShaderModule
557 tessControlShader, // const VkShaderModule tessellationControlShaderModule
558 tessEvalShader, // const VkShaderModule tessellationEvalShaderModule
559 geomShader, // const VkShaderModule geometryShaderModule
560 fragShader, // const VkShaderModule fragmentShaderModule
561 *m_renderPass, // const VkRenderPass renderPass
562 viewports, // const std::vector<VkViewport>& viewports
563 scissors, // const std::vector<VkRect2D>& scissors
564 drawCallData.topology, // const VkPrimitiveTopology topology
565 0u, // const uint32_t subpass
566 pipelineState.numPatchControlPoints, // const uint32_t patchControlPoints
567 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
568 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
569 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
570 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
571 &pipelineColorBlendStateInfo); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
572 object->descriptorSet = vulkanProgram.descriptorSet;
573 object->descriptorSetLayout = vulkanProgram.descriptorSetLayout;
574 }
575 m_renderObjects.push_back(object);
576 }
577
draw(void)578 void VulkanDrawContext::draw(void)
579 {
580 const DeviceInterface &vk = m_context.getDeviceInterface();
581 const VkDevice device = m_context.getDevice();
582 const VkQueue queue = m_context.getUniversalQueue();
583 Allocator &allocator = m_context.getDefaultAllocator();
584 tcu::TestLog &log = m_context.getTestContext().getLog();
585
586 // Record commands
587 {
588 const VkDeviceSize zeroOffset = 0ull;
589
590 beginCommandBuffer(vk, *m_cmdBuffer);
591
592 // Begin render pass
593 if (!!m_framebufferState.depthImageView || !!*m_depthImageView)
594 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer,
595 makeRect2D(0, 0, m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y()),
596 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0.0f, 0);
597 else
598 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer,
599 makeRect2D(0, 0, m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y()),
600 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
601
602 for (const auto &object : m_renderObjects)
603 {
604 if (!!object->descriptorSet)
605 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *(object->pipelineLayout), 0u,
606 1u, &(object->descriptorSet), 0u, DE_NULL);
607 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *(object->pipeline));
608 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &(**(object->vertexBuffer)), &zeroOffset);
609 vk.cmdDraw(*m_cmdBuffer, static_cast<uint32_t>(object->vertexCount), 1u, 0u, 0u);
610 }
611 endRenderPass(vk, *m_cmdBuffer);
612
613 // Barrier: draw -> copy from image
614 {
615 const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
616 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
617 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_colorImage,
618 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
619
620 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
621 VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u,
622 &barrier);
623 }
624
625 // Resolve multisample image
626 {
627 if (m_framebufferState.numSamples != VK_SAMPLE_COUNT_1_BIT)
628 {
629 const VkImageResolve imageResolve = {
630 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),
631 {0, 0, 0},
632 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),
633 {0, 0, 0},
634 makeExtent3D(m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y(), 1u)};
635
636 const VkImageCreateInfo resolveImageCreateInfo = {
637 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType
638 DE_NULL, // const void* pNext
639 (VkImageCreateFlags)0, // VkImageCreateFlags flags
640 VK_IMAGE_TYPE_2D, // VkImageType imageType
641 m_framebufferState.colorFormat, // VkFormat format
642 makeExtent3D(m_framebufferState.renderSize.x(), // VkExtent3D extent;
643 m_framebufferState.renderSize.y(), 1u),
644 1u, // uint32_t mipLevels
645 1u, // uint32_t arrayLayers
646 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
647 VK_IMAGE_TILING_OPTIMAL, // VkImaageTiling tiling
648 VK_IMAGE_USAGE_TRANSFER_DST_BIT | // VkImageUsageFlags usage
649 VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
650 VK_SHARING_MODE_EXCLUSIVE, // VkSharingModeExclusive sharingMode
651 0u, // uint32_t queueFamilyIndexCount
652 DE_NULL, // const uint32_t* pQueueFamilyIndices
653 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout
654 };
655
656 m_resolveImage = MovePtr<ImageWithMemory>(
657 new ImageWithMemory(vk, device, allocator, resolveImageCreateInfo, MemoryRequirement::Any));
658
659 const VkImageMemoryBarrier resolveBarrier = makeImageMemoryBarrier(
660 0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
661 **m_resolveImage, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
662
663 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
664 VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL,
665 1u, &resolveBarrier);
666
667 vk.cmdResolveImage(*m_cmdBuffer, **m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_resolveImage,
668 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &imageResolve);
669
670 const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
671 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
672 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_resolveImage,
673 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
674
675 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
676 (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
677 }
678 else
679 m_resolveImage = m_colorImage;
680
681 const VkBufferImageCopy copyRegion = makeBufferImageCopy(
682 makeExtent3D(m_framebufferState.renderSize.x(), m_framebufferState.renderSize.y(), 1u),
683 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
684 vk.cmdCopyImageToBuffer(*m_cmdBuffer, **m_resolveImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
685 **m_colorAttachmentBuffer, 1u, ©Region);
686 }
687
688 // Barrier: copy to buffer -> host read
689 {
690 const VkBufferMemoryBarrier barrier = makeBufferMemoryBarrier(
691 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **m_colorAttachmentBuffer, 0ull, VK_WHOLE_SIZE);
692
693 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
694 (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
695 }
696
697 endCommandBuffer(vk, *m_cmdBuffer);
698 }
699
700 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
701
702 log << tcu::LogImageSet("attachments", "") << tcu::LogImage("color0", "", getColorPixels())
703 << tcu::TestLog::EndImageSet;
704 }
705
getColorPixels(void) const706 tcu::ConstPixelBufferAccess VulkanDrawContext::getColorPixels(void) const
707 {
708 const DeviceInterface &vk = m_context.getDeviceInterface();
709 const VkDevice device = m_context.getDevice();
710
711 const Allocation &alloc = m_colorAttachmentBuffer->getAllocation();
712 invalidateAlloc(vk, device, alloc);
713
714 return tcu::ConstPixelBufferAccess(mapVkFormat(m_framebufferState.colorFormat), m_framebufferState.renderSize.x(),
715 m_framebufferState.renderSize.y(), 1u, alloc.getHostPtr());
716 }
717 } // namespace drawutil
718 } // namespace vkt
719