1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel Corporation
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Dynamic State Tests - Base Class
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktDynamicStateBaseClass.hpp"
28
29 #include "vkPrograms.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkBuilderUtil.hpp"
34 #include "vkBarrierUtil.hpp"
35
36 namespace vkt
37 {
38 namespace DynamicState
39 {
40
41 using namespace Draw;
42
DynamicStateBaseClass(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName,const char * meshShaderName)43 DynamicStateBaseClass::DynamicStateBaseClass (Context& context,
44 vk::PipelineConstructionType pipelineConstructionType,
45 const char* vertexShaderName,
46 const char* fragmentShaderName,
47 const char* meshShaderName)
48 : TestInstance (context)
49 , m_pipelineConstructionType (pipelineConstructionType)
50 , m_colorAttachmentFormat (vk::VK_FORMAT_R8G8B8A8_UNORM)
51 , m_topology (vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
52 , m_vk (context.getDeviceInterface())
53 , m_pipeline (context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType)
54 , m_vertexShaderName (vertexShaderName ? vertexShaderName : "")
55 , m_fragmentShaderName (fragmentShaderName)
56 , m_meshShaderName (meshShaderName ? meshShaderName : "")
57 , m_isMesh (meshShaderName != nullptr)
58 {
59 // We must provide either the mesh shader or the vertex shader.
60 DE_ASSERT(static_cast<bool>(vertexShaderName) != static_cast<bool>(meshShaderName));
61 }
62
initialize(void)63 void DynamicStateBaseClass::initialize (void)
64 {
65 const vk::VkDevice device = m_context.getDevice();
66 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
67 const auto vertDescType = (m_isMesh ? vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER : vk::VK_DESCRIPTOR_TYPE_MAX_ENUM);
68 std::vector<vk::VkPushConstantRange> pcRanges;
69
70 // The mesh shading pipeline will contain a set with vertex data.
71 #ifndef CTS_USES_VULKANSC
72 if (m_isMesh)
73 {
74 vk::DescriptorSetLayoutBuilder setLayoutBuilder;
75 vk::DescriptorPoolBuilder poolBuilder;
76
77 setLayoutBuilder.addSingleBinding(vertDescType, vk::VK_SHADER_STAGE_MESH_BIT_EXT);
78 m_meshSetLayout = setLayoutBuilder.build(m_vk, device);
79
80 poolBuilder.addType(vertDescType);
81 m_descriptorPool = poolBuilder.build(m_vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
82
83 m_descriptorSet = vk::makeDescriptorSet(m_vk, device, m_descriptorPool.get(), m_meshSetLayout.get());
84 pcRanges.push_back(vk::makePushConstantRange(vk::VK_SHADER_STAGE_MESH_BIT_EXT, 0u, static_cast<uint32_t>(sizeof(uint32_t))));
85 }
86 #endif // CTS_USES_VULKANSC
87
88 std::vector<vk::VkDescriptorSetLayout> rawSetLayouts;
89
90 if (m_meshSetLayout)
91 rawSetLayouts.push_back(m_meshSetLayout.get());
92
93 if (m_otherSetLayout)
94 rawSetLayouts.push_back(m_otherSetLayout.get());
95
96 m_pipelineLayout = vk::PipelineLayoutWrapper(m_pipelineConstructionType, m_vk, device, de::sizeU32(rawSetLayouts), de::dataOrNull(rawSetLayouts), de::sizeU32(pcRanges), de::dataOrNull(pcRanges));
97
98 const vk::VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
99 const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
100 vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
101
102 m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
103
104 const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
105 m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo);
106
107 const vk::VkVertexInputBindingDescription vertexInputBindingDescription =
108 {
109 0,
110 (deUint32)sizeof(tcu::Vec4) * 2,
111 vk::VK_VERTEX_INPUT_RATE_VERTEX,
112 };
113
114 const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
115 {
116 {
117 0u,
118 0u,
119 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
120 0u
121 },
122 {
123 1u,
124 0u,
125 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
126 (deUint32)(sizeof(float)* 4),
127 }
128 };
129
130 m_vertexInputState = PipelineCreateInfo::VertexInputState(
131 1,
132 &vertexInputBindingDescription,
133 2,
134 vertexInputAttributeDescriptions);
135
136 const vk::VkDeviceSize dataSize = de::dataSize(m_data);
137 const vk::VkBufferUsageFlags bufferUsage = (m_isMesh ? vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
138 m_vertexBuffer = Buffer::createAndAlloc(m_vk, device, BufferCreateInfo(dataSize, bufferUsage),
139 m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
140
141 deUint8* ptr = reinterpret_cast<unsigned char *>(m_vertexBuffer->getBoundMemory().getHostPtr());
142 deMemcpy(ptr, &m_data[0], (size_t)dataSize);
143
144 vk::flushAlloc(m_vk, device, m_vertexBuffer->getBoundMemory());
145
146 // Update descriptor set for mesh shaders.
147 if (m_isMesh)
148 {
149 vk::DescriptorSetUpdateBuilder updateBuilder;
150 const auto location = vk::DescriptorSetUpdateBuilder::Location::binding(0u);
151 const auto bufferInfo = vk::makeDescriptorBufferInfo(m_vertexBuffer->object(), 0ull, dataSize);
152
153 updateBuilder.writeSingle(m_descriptorSet.get(), location, vertDescType, &bufferInfo);
154 updateBuilder.update(m_vk, device);
155 }
156
157 const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
158 m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
159
160 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
161 {
162 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
163 DE_NULL, // const void* pNext;
164 *m_cmdPool, // VkCommandPool commandPool;
165 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
166 1u, // deUint32 bufferCount;
167 };
168 m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, &cmdBufferAllocateInfo);
169
170 initRenderPass(device);
171 initFramebuffer(device);
172 initPipeline(device);
173 }
174
175
initRenderPass(const vk::VkDevice device)176 void DynamicStateBaseClass::initRenderPass (const vk::VkDevice device)
177 {
178 RenderPassCreateInfo renderPassCreateInfo;
179 renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
180 vk::VK_SAMPLE_COUNT_1_BIT,
181 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
182 vk::VK_ATTACHMENT_STORE_OP_STORE,
183 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
184 vk::VK_ATTACHMENT_STORE_OP_STORE,
185 vk::VK_IMAGE_LAYOUT_GENERAL,
186 vk::VK_IMAGE_LAYOUT_GENERAL));
187
188 const vk::VkAttachmentReference colorAttachmentReference =
189 {
190 0,
191 vk::VK_IMAGE_LAYOUT_GENERAL
192 };
193
194 renderPassCreateInfo.addSubpass(SubpassDescription(
195 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
196 0,
197 0,
198 DE_NULL,
199 1,
200 &colorAttachmentReference,
201 DE_NULL,
202 AttachmentReference(),
203 0,
204 DE_NULL
205 )
206 );
207
208 m_renderPass = vk::RenderPassWrapper(m_pipelineConstructionType, m_vk, device, &renderPassCreateInfo);
209 }
210
initFramebuffer(const vk::VkDevice device)211 void DynamicStateBaseClass::initFramebuffer (const vk::VkDevice device)
212 {
213 std::vector<vk::VkImageView> colorAttachments(1);
214 colorAttachments[0] = *m_colorTargetView;
215
216 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
217
218 m_renderPass.createFramebuffer(m_vk, device, &framebufferCreateInfo, m_colorTargetImage->object());
219 }
220
initPipeline(const vk::VkDevice device)221 void DynamicStateBaseClass::initPipeline (const vk::VkDevice device)
222 {
223 const PipelineCreateInfo::ColorBlendState colorBlendState(1, &m_attachmentState);
224 const PipelineCreateInfo::RasterizerState rasterizerState;
225 const PipelineCreateInfo::DepthStencilState depthStencilState;
226 const PipelineCreateInfo::DynamicState dynamicState;
227 const PipelineCreateInfo::MultiSampleState multisampleState;
228
229 const auto& binaries = m_context.getBinaryCollection();
230 const vk::ShaderWrapper ms (m_isMesh ? vk::ShaderWrapper(m_vk, device, binaries.get(m_meshShaderName), 0) : vk::ShaderWrapper());
231 const vk::ShaderWrapper vs (m_isMesh ? vk::ShaderWrapper() : vk::ShaderWrapper(m_vk, device, binaries.get(m_vertexShaderName), 0));
232 const vk::ShaderWrapper fs (vk::ShaderWrapper(m_vk, device, binaries.get(m_fragmentShaderName), 0));
233 std::vector<vk::VkViewport> viewports { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } };
234 std::vector<vk::VkRect2D> scissors { { { 0u, 0u }, { 0u, 0u } }};
235
236 m_pipeline.setDefaultTopology(m_topology)
237 .setDynamicState(static_cast<const vk::VkPipelineDynamicStateCreateInfo*>(&dynamicState));
238
239 #ifndef CTS_USES_VULKANSC
240 if (m_isMesh)
241 {
242 m_pipeline
243 .setupPreRasterizationMeshShaderState(viewports,
244 scissors,
245 m_pipelineLayout,
246 *m_renderPass,
247 0u,
248 vk::ShaderWrapper(),
249 ms,
250 static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState));
251 }
252 else
253 #endif // CTS_USES_VULKANSC
254 {
255 m_pipeline
256 .setupVertexInputState(&m_vertexInputState)
257 .setupPreRasterizationShaderState(viewports,
258 scissors,
259 m_pipelineLayout,
260 *m_renderPass,
261 0u,
262 vs,
263 static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState));
264 }
265
266 m_pipeline.setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fs, static_cast<const vk::VkPipelineDepthStencilStateCreateInfo*>(&depthStencilState), &multisampleState)
267 .setupFragmentOutputState(*m_renderPass, 0u, static_cast<const vk::VkPipelineColorBlendStateCreateInfo*>(&colorBlendState), &multisampleState)
268 .setMonolithicPipelineLayout(m_pipelineLayout)
269 .buildPipeline();
270 }
271
iterate(void)272 tcu::TestStatus DynamicStateBaseClass::iterate (void)
273 {
274 DE_ASSERT(false);
275 return tcu::TestStatus::fail("Implement iterate() method!");
276 }
277
beginRenderPass(void)278 void DynamicStateBaseClass::beginRenderPass (void)
279 {
280 const vk::VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } };
281 beginRenderPassWithClearColor(clearColor);
282 }
283
beginRenderPassWithClearColor(const vk::VkClearColorValue & clearColor,const bool skipBeginCmdBuffer,const bool previousTransfer)284 void DynamicStateBaseClass::beginRenderPassWithClearColor(const vk::VkClearColorValue& clearColor, const bool skipBeginCmdBuffer, const bool previousTransfer)
285 {
286 if (!skipBeginCmdBuffer)
287 {
288 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
289 }
290
291 if (previousTransfer)
292 {
293 const auto transfer2Transfer = vk::makeMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, (vk::VK_ACCESS_TRANSFER_WRITE_BIT | vk::VK_ACCESS_TRANSFER_READ_BIT));
294 vk::cmdPipelineMemoryBarrier(m_vk, *m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, &transfer2Transfer);
295 }
296 else
297 {
298 initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
299 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
300 }
301
302 const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
303 m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
304 vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
305
306 const vk::VkMemoryBarrier memBarrier =
307 {
308 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
309 DE_NULL,
310 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
311 vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
312 };
313
314 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
315 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
316 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
317
318 m_renderPass.begin(m_vk, *m_cmdBuffer, vk::makeRect2D(0, 0, WIDTH, HEIGHT));
319 }
320
setDynamicViewportState(const deUint32 width,const deUint32 height)321 void DynamicStateBaseClass::setDynamicViewportState (const deUint32 width, const deUint32 height)
322 {
323 vk::VkViewport viewport = vk::makeViewport(tcu::UVec2(width, height));
324 vk::VkRect2D scissor = vk::makeRect2D(tcu::UVec2(width, height));
325 if (vk::isConstructionTypeShaderObject(m_pipelineConstructionType))
326 {
327 #ifndef CTS_USES_VULKANSC
328 m_vk.cmdSetViewportWithCount(*m_cmdBuffer, 1, &viewport);
329 m_vk.cmdSetScissorWithCount(*m_cmdBuffer, 1, &scissor);
330 #else
331 m_vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, 1, &viewport);
332 m_vk.cmdSetScissorWithCountEXT(*m_cmdBuffer, 1, &scissor);
333 #endif
334 }
335 else
336 {
337 m_vk.cmdSetViewport(*m_cmdBuffer, 0, 1, &viewport);
338 m_vk.cmdSetScissor(*m_cmdBuffer, 0, 1, &scissor);
339 }
340 }
341
setDynamicViewportState(deUint32 viewportCount,const vk::VkViewport * pViewports,const vk::VkRect2D * pScissors)342 void DynamicStateBaseClass::setDynamicViewportState (deUint32 viewportCount, const vk::VkViewport* pViewports, const vk::VkRect2D* pScissors)
343 {
344 if (vk::isConstructionTypeShaderObject(m_pipelineConstructionType))
345 {
346 #ifndef CTS_USES_VULKANSC
347 m_vk.cmdSetViewportWithCount(*m_cmdBuffer, viewportCount, pViewports);
348 m_vk.cmdSetScissorWithCount(*m_cmdBuffer, viewportCount, pScissors);
349 #else
350 m_vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, viewportCount, pViewports);
351 m_vk.cmdSetScissorWithCountEXT(*m_cmdBuffer, viewportCount, pScissors);
352 #endif
353 }
354 else
355 {
356 m_vk.cmdSetViewport(*m_cmdBuffer, 0, viewportCount, pViewports);
357 m_vk.cmdSetScissor(*m_cmdBuffer, 0, viewportCount, pScissors);
358 }
359 }
360
setDynamicRasterizationState(const float lineWidth,const float depthBiasConstantFactor,const float depthBiasClamp,const float depthBiasSlopeFactor)361 void DynamicStateBaseClass::setDynamicRasterizationState (const float lineWidth,
362 const float depthBiasConstantFactor,
363 const float depthBiasClamp,
364 const float depthBiasSlopeFactor)
365 {
366 m_vk.cmdSetLineWidth(*m_cmdBuffer, lineWidth);
367 m_vk.cmdSetDepthBias(*m_cmdBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
368 }
369
setDynamicBlendState(const float const1,const float const2,const float const3,const float const4)370 void DynamicStateBaseClass::setDynamicBlendState (const float const1, const float const2, const float const3, const float const4)
371 {
372 float blendConstantsants[4] = { const1, const2, const3, const4 };
373 m_vk.cmdSetBlendConstants(*m_cmdBuffer, blendConstantsants);
374 }
375
setDynamicDepthStencilState(const float minDepthBounds,const float maxDepthBounds,const deUint32 stencilFrontCompareMask,const deUint32 stencilFrontWriteMask,const deUint32 stencilFrontReference,const deUint32 stencilBackCompareMask,const deUint32 stencilBackWriteMask,const deUint32 stencilBackReference)376 void DynamicStateBaseClass::setDynamicDepthStencilState (const float minDepthBounds,
377 const float maxDepthBounds,
378 const deUint32 stencilFrontCompareMask,
379 const deUint32 stencilFrontWriteMask,
380 const deUint32 stencilFrontReference,
381 const deUint32 stencilBackCompareMask,
382 const deUint32 stencilBackWriteMask,
383 const deUint32 stencilBackReference)
384 {
385 m_vk.cmdSetDepthBounds(*m_cmdBuffer, minDepthBounds, maxDepthBounds);
386 m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontCompareMask);
387 m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontWriteMask);
388 m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontReference);
389 m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackCompareMask);
390 m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackWriteMask);
391 m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackReference);
392 }
393
394 #ifndef CTS_USES_VULKANSC
pushVertexOffset(const uint32_t vertexOffset,const vk::VkPipelineLayout pipelineLayout,const vk::VkShaderStageFlags stageFlags)395 void DynamicStateBaseClass::pushVertexOffset (const uint32_t vertexOffset,
396 const vk::VkPipelineLayout pipelineLayout,
397 const vk::VkShaderStageFlags stageFlags)
398 {
399 m_vk.cmdPushConstants(*m_cmdBuffer, pipelineLayout, stageFlags, 0u, static_cast<uint32_t>(sizeof(uint32_t)), &vertexOffset);
400 }
401 #endif // CTS_USES_VULKANSC
402
403 } // DynamicState
404 } // vkt
405