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, vk::PipelineConstructionType pipelineConstructionType,
44 const char *vertexShaderName, const char *fragmentShaderName,
45 const char *meshShaderName)
46 : TestInstance(context)
47 , m_pipelineConstructionType(pipelineConstructionType)
48 , m_colorAttachmentFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
49 , m_topology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
50 , m_vk(context.getDeviceInterface())
51 , m_pipeline(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
52 context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType)
53 , m_vertexShaderName(vertexShaderName ? vertexShaderName : "")
54 , m_fragmentShaderName(fragmentShaderName)
55 , m_meshShaderName(meshShaderName ? meshShaderName : "")
56 , m_isMesh(meshShaderName != nullptr)
57 {
58 // We must provide either the mesh shader or the vertex shader.
59 DE_ASSERT(static_cast<bool>(vertexShaderName) != static_cast<bool>(meshShaderName));
60 }
61
initialize(void)62 void DynamicStateBaseClass::initialize(void)
63 {
64 const vk::VkDevice device = m_context.getDevice();
65 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
66 const auto vertDescType = (m_isMesh ? vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER : vk::VK_DESCRIPTOR_TYPE_MAX_ENUM);
67 std::vector<vk::VkPushConstantRange> pcRanges;
68
69 // The mesh shading pipeline will contain a set with vertex data.
70 #ifndef CTS_USES_VULKANSC
71 if (m_isMesh)
72 {
73 vk::DescriptorSetLayoutBuilder setLayoutBuilder;
74 vk::DescriptorPoolBuilder poolBuilder;
75
76 setLayoutBuilder.addSingleBinding(vertDescType, vk::VK_SHADER_STAGE_MESH_BIT_EXT);
77 m_meshSetLayout = setLayoutBuilder.build(m_vk, device);
78
79 poolBuilder.addType(vertDescType);
80 m_descriptorPool = poolBuilder.build(m_vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
81
82 m_descriptorSet = vk::makeDescriptorSet(m_vk, device, m_descriptorPool.get(), m_meshSetLayout.get());
83 pcRanges.push_back(
84 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 =
97 vk::PipelineLayoutWrapper(m_pipelineConstructionType, m_vk, device, de::sizeU32(rawSetLayouts),
98 de::dataOrNull(rawSetLayouts), de::sizeU32(pcRanges), de::dataOrNull(pcRanges));
99
100 const vk::VkExtent3D targetImageExtent = {WIDTH, HEIGHT, 1};
101 const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1,
102 vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
103 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
104 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
105 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
106
107 m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(),
108 m_context.getUniversalQueueFamilyIndex());
109
110 const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D,
111 m_colorAttachmentFormat);
112 m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo);
113
114 const vk::VkVertexInputBindingDescription vertexInputBindingDescription = {
115 0,
116 (uint32_t)sizeof(tcu::Vec4) * 2,
117 vk::VK_VERTEX_INPUT_RATE_VERTEX,
118 };
119
120 const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
121 {0u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u},
122 {
123 1u,
124 0u,
125 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
126 (uint32_t)(sizeof(float) * 4),
127 }};
128
129 m_vertexInputState =
130 PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
131
132 const vk::VkDeviceSize dataSize = de::dataSize(m_data);
133 const vk::VkBufferUsageFlags bufferUsage =
134 (m_isMesh ? vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
135 m_vertexBuffer = Buffer::createAndAlloc(m_vk, device, BufferCreateInfo(dataSize, bufferUsage),
136 m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
137
138 uint8_t *ptr = reinterpret_cast<unsigned char *>(m_vertexBuffer->getBoundMemory().getHostPtr());
139 deMemcpy(ptr, &m_data[0], (size_t)dataSize);
140
141 vk::flushAlloc(m_vk, device, m_vertexBuffer->getBoundMemory());
142
143 // Update descriptor set for mesh shaders.
144 if (m_isMesh)
145 {
146 vk::DescriptorSetUpdateBuilder updateBuilder;
147 const auto location = vk::DescriptorSetUpdateBuilder::Location::binding(0u);
148 const auto bufferInfo = vk::makeDescriptorBufferInfo(m_vertexBuffer->object(), 0ull, dataSize);
149
150 updateBuilder.writeSingle(m_descriptorSet.get(), location, vertDescType, &bufferInfo);
151 updateBuilder.update(m_vk, device);
152 }
153
154 const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
155 m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
156
157 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo = {
158 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
159 DE_NULL, // const void* pNext;
160 *m_cmdPool, // VkCommandPool commandPool;
161 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
162 1u, // uint32_t bufferCount;
163 };
164 m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, &cmdBufferAllocateInfo);
165
166 initRenderPass(device);
167 initFramebuffer(device);
168 initPipeline(device);
169 }
170
initRenderPass(const vk::VkDevice device)171 void DynamicStateBaseClass::initRenderPass(const vk::VkDevice device)
172 {
173 RenderPassCreateInfo renderPassCreateInfo;
174 renderPassCreateInfo.addAttachment(AttachmentDescription(
175 m_colorAttachmentFormat, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_ATTACHMENT_LOAD_OP_LOAD,
176 vk::VK_ATTACHMENT_STORE_OP_STORE, vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, vk::VK_ATTACHMENT_STORE_OP_STORE,
177 vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL));
178
179 const vk::VkAttachmentReference colorAttachmentReference = {0, vk::VK_IMAGE_LAYOUT_GENERAL};
180
181 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, DE_NULL, 1,
182 &colorAttachmentReference, DE_NULL, AttachmentReference(), 0,
183 DE_NULL));
184
185 m_renderPass = vk::RenderPassWrapper(m_pipelineConstructionType, m_vk, device, &renderPassCreateInfo);
186 }
187
initFramebuffer(const vk::VkDevice device)188 void DynamicStateBaseClass::initFramebuffer(const vk::VkDevice device)
189 {
190 std::vector<vk::VkImageView> colorAttachments(1);
191 colorAttachments[0] = *m_colorTargetView;
192
193 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
194
195 m_renderPass.createFramebuffer(m_vk, device, &framebufferCreateInfo, m_colorTargetImage->object());
196 }
197
initPipeline(const vk::VkDevice device)198 void DynamicStateBaseClass::initPipeline(const vk::VkDevice device)
199 {
200 const PipelineCreateInfo::ColorBlendState colorBlendState(1, &m_attachmentState);
201 const PipelineCreateInfo::RasterizerState rasterizerState;
202 const PipelineCreateInfo::DepthStencilState depthStencilState;
203 const PipelineCreateInfo::DynamicState dynamicState;
204 const PipelineCreateInfo::MultiSampleState multisampleState;
205
206 const auto &binaries = m_context.getBinaryCollection();
207 const vk::ShaderWrapper ms(m_isMesh ? vk::ShaderWrapper(m_vk, device, binaries.get(m_meshShaderName), 0) :
208 vk::ShaderWrapper());
209 const vk::ShaderWrapper vs(m_isMesh ? vk::ShaderWrapper() :
210 vk::ShaderWrapper(m_vk, device, binaries.get(m_vertexShaderName), 0));
211 const vk::ShaderWrapper fs(vk::ShaderWrapper(m_vk, device, binaries.get(m_fragmentShaderName), 0));
212 std::vector<vk::VkViewport> viewports{{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}};
213 std::vector<vk::VkRect2D> scissors{{{0u, 0u}, {0u, 0u}}};
214
215 m_pipeline.setDefaultTopology(m_topology)
216 .setDynamicState(static_cast<const vk::VkPipelineDynamicStateCreateInfo *>(&dynamicState));
217
218 #ifndef CTS_USES_VULKANSC
219 if (m_isMesh)
220 {
221 m_pipeline.setupPreRasterizationMeshShaderState(
222 viewports, scissors, m_pipelineLayout, *m_renderPass, 0u, vk::ShaderWrapper(), ms,
223 static_cast<const vk::VkPipelineRasterizationStateCreateInfo *>(&rasterizerState));
224 }
225 else
226 #endif // CTS_USES_VULKANSC
227 {
228 m_pipeline.setupVertexInputState(&m_vertexInputState)
229 .setupPreRasterizationShaderState(
230 viewports, scissors, m_pipelineLayout, *m_renderPass, 0u, vs,
231 static_cast<const vk::VkPipelineRasterizationStateCreateInfo *>(&rasterizerState));
232 }
233
234 m_pipeline
235 .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fs,
236 static_cast<const vk::VkPipelineDepthStencilStateCreateInfo *>(&depthStencilState),
237 &multisampleState)
238 .setupFragmentOutputState(*m_renderPass, 0u,
239 static_cast<const vk::VkPipelineColorBlendStateCreateInfo *>(&colorBlendState),
240 &multisampleState)
241 .setMonolithicPipelineLayout(m_pipelineLayout)
242 .buildPipeline();
243 }
244
iterate(void)245 tcu::TestStatus DynamicStateBaseClass::iterate(void)
246 {
247 DE_ASSERT(false);
248 return tcu::TestStatus::fail("Implement iterate() method!");
249 }
250
beginRenderPass(void)251 void DynamicStateBaseClass::beginRenderPass(void)
252 {
253 const vk::VkClearColorValue clearColor = {{0.0f, 0.0f, 0.0f, 1.0f}};
254 beginRenderPassWithClearColor(clearColor);
255 }
256
beginRenderPassWithClearColor(const vk::VkClearColorValue & clearColor,const bool skipBeginCmdBuffer,const bool previousTransfer)257 void DynamicStateBaseClass::beginRenderPassWithClearColor(const vk::VkClearColorValue &clearColor,
258 const bool skipBeginCmdBuffer, const bool previousTransfer)
259 {
260 if (!skipBeginCmdBuffer)
261 {
262 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
263 }
264
265 if (previousTransfer)
266 {
267 const auto transfer2Transfer = vk::makeMemoryBarrier(
268 vk::VK_ACCESS_TRANSFER_WRITE_BIT, (vk::VK_ACCESS_TRANSFER_WRITE_BIT | vk::VK_ACCESS_TRANSFER_READ_BIT));
269 vk::cmdPipelineMemoryBarrier(m_vk, *m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
270 vk::VK_PIPELINE_STAGE_TRANSFER_BIT, &transfer2Transfer);
271 }
272 else
273 {
274 initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
275 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
276 }
277
278 const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
279 m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1,
280 &subresourceRange);
281
282 const vk::VkMemoryBarrier memBarrier = {
283 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, vk::VK_ACCESS_TRANSFER_WRITE_BIT,
284 vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT};
285
286 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
287 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0,
288 DE_NULL);
289
290 m_renderPass.begin(m_vk, *m_cmdBuffer, vk::makeRect2D(0, 0, WIDTH, HEIGHT));
291 }
292
setDynamicViewportState(const uint32_t width,const uint32_t height)293 void DynamicStateBaseClass::setDynamicViewportState(const uint32_t width, const uint32_t height)
294 {
295 vk::VkViewport viewport = vk::makeViewport(tcu::UVec2(width, height));
296 vk::VkRect2D scissor = vk::makeRect2D(tcu::UVec2(width, height));
297 if (vk::isConstructionTypeShaderObject(m_pipelineConstructionType))
298 {
299 #ifndef CTS_USES_VULKANSC
300 m_vk.cmdSetViewportWithCount(*m_cmdBuffer, 1, &viewport);
301 m_vk.cmdSetScissorWithCount(*m_cmdBuffer, 1, &scissor);
302 #else
303 m_vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, 1, &viewport);
304 m_vk.cmdSetScissorWithCountEXT(*m_cmdBuffer, 1, &scissor);
305 #endif
306 }
307 else
308 {
309 m_vk.cmdSetViewport(*m_cmdBuffer, 0, 1, &viewport);
310 m_vk.cmdSetScissor(*m_cmdBuffer, 0, 1, &scissor);
311 }
312 }
313
setDynamicViewportState(uint32_t viewportCount,const vk::VkViewport * pViewports,const vk::VkRect2D * pScissors)314 void DynamicStateBaseClass::setDynamicViewportState(uint32_t viewportCount, const vk::VkViewport *pViewports,
315 const vk::VkRect2D *pScissors)
316 {
317 if (vk::isConstructionTypeShaderObject(m_pipelineConstructionType))
318 {
319 #ifndef CTS_USES_VULKANSC
320 m_vk.cmdSetViewportWithCount(*m_cmdBuffer, viewportCount, pViewports);
321 m_vk.cmdSetScissorWithCount(*m_cmdBuffer, viewportCount, pScissors);
322 #else
323 m_vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, viewportCount, pViewports);
324 m_vk.cmdSetScissorWithCountEXT(*m_cmdBuffer, viewportCount, pScissors);
325 #endif
326 }
327 else
328 {
329 m_vk.cmdSetViewport(*m_cmdBuffer, 0, viewportCount, pViewports);
330 m_vk.cmdSetScissor(*m_cmdBuffer, 0, viewportCount, pScissors);
331 }
332 }
333
setDynamicRasterizationState(const float lineWidth,const float depthBiasConstantFactor,const float depthBiasClamp,const float depthBiasSlopeFactor)334 void DynamicStateBaseClass::setDynamicRasterizationState(const float lineWidth, const float depthBiasConstantFactor,
335 const float depthBiasClamp, const float depthBiasSlopeFactor)
336 {
337 m_vk.cmdSetLineWidth(*m_cmdBuffer, lineWidth);
338 m_vk.cmdSetDepthBias(*m_cmdBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
339 }
340
setDynamicBlendState(const float const1,const float const2,const float const3,const float const4)341 void DynamicStateBaseClass::setDynamicBlendState(const float const1, const float const2, const float const3,
342 const float const4)
343 {
344 float blendConstantsants[4] = {const1, const2, const3, const4};
345 m_vk.cmdSetBlendConstants(*m_cmdBuffer, blendConstantsants);
346 }
347
setDynamicDepthStencilState(const float minDepthBounds,const float maxDepthBounds,const uint32_t stencilFrontCompareMask,const uint32_t stencilFrontWriteMask,const uint32_t stencilFrontReference,const uint32_t stencilBackCompareMask,const uint32_t stencilBackWriteMask,const uint32_t stencilBackReference)348 void DynamicStateBaseClass::setDynamicDepthStencilState(
349 const float minDepthBounds, const float maxDepthBounds, const uint32_t stencilFrontCompareMask,
350 const uint32_t stencilFrontWriteMask, const uint32_t stencilFrontReference, const uint32_t stencilBackCompareMask,
351 const uint32_t stencilBackWriteMask, const uint32_t stencilBackReference)
352 {
353 m_vk.cmdSetDepthBounds(*m_cmdBuffer, minDepthBounds, maxDepthBounds);
354 m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontCompareMask);
355 m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontWriteMask);
356 m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontReference);
357 m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackCompareMask);
358 m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackWriteMask);
359 m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackReference);
360 }
361
362 #ifndef CTS_USES_VULKANSC
pushVertexOffset(const uint32_t vertexOffset,const vk::VkPipelineLayout pipelineLayout,const vk::VkShaderStageFlags stageFlags)363 void DynamicStateBaseClass::pushVertexOffset(const uint32_t vertexOffset, const vk::VkPipelineLayout pipelineLayout,
364 const vk::VkShaderStageFlags stageFlags)
365 {
366 m_vk.cmdPushConstants(*m_cmdBuffer, pipelineLayout, stageFlags, 0u, static_cast<uint32_t>(sizeof(uint32_t)),
367 &vertexOffset);
368 }
369 #endif // CTS_USES_VULKANSC
370
371 } // namespace DynamicState
372 } // namespace vkt
373