xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/util/vktDrawUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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, &copyRegion);
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