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