1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2017 The Khronos Group Inc. 6 * Copyright (c) 2017 Google Inc. 7 * Copyright (c) 2017 Samsung Electronics Co., Ltd. 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 *//*! 22 * \file 23 * \brief Differing iterpolation decorations tests 24 *//*--------------------------------------------------------------------*/ 25 26 #include "vktDrawDifferingInterpolationTests.hpp" 27 28 #include "vktDrawBaseClass.hpp" 29 #include "vkQueryUtil.hpp" 30 #include "vkCmdUtil.hpp" 31 #include "vkTypeUtil.hpp" 32 #include "vktTestGroupUtil.hpp" 33 34 #include "deDefs.h" 35 #include "deRandom.hpp" 36 #include "deString.h" 37 38 #include "tcuTestCase.hpp" 39 #include "tcuRGBA.hpp" 40 #include "tcuTextureUtil.hpp" 41 #include "tcuImageCompare.hpp" 42 #include "tcuStringTemplate.hpp" 43 44 #include "rrRenderer.hpp" 45 46 #include <string> 47 #include <sstream> 48 49 namespace vkt 50 { 51 namespace Draw 52 { 53 namespace 54 { 55 using namespace vk; 56 using namespace std; 57 58 struct DrawParams 59 { 60 string vertShader; 61 string fragShader; 62 string refVertShader; 63 string refFragShader; 64 }; 65 66 class DrawTestInstance : public TestInstance 67 { 68 public: 69 DrawTestInstance (Context& context, const DrawParams& data); 70 ~DrawTestInstance (void); 71 tcu::TestStatus iterate (void); 72 private: 73 DrawParams m_data; 74 75 enum 76 { 77 WIDTH = 256, 78 HEIGHT = 256 79 }; 80 }; 81 DrawTestInstance(Context & context,const DrawParams & data)82 DrawTestInstance::DrawTestInstance (Context& context, const DrawParams& data) 83 : vkt::TestInstance (context) 84 , m_data (data) 85 { 86 } 87 ~DrawTestInstance(void)88 DrawTestInstance::~DrawTestInstance (void) 89 { 90 } 91 92 class DrawTestCase : public TestCase 93 { 94 public: 95 DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data); 96 ~DrawTestCase (void); 97 virtual void initPrograms (SourceCollections& programCollection) const; 98 virtual TestInstance* createInstance (Context& context) const; 99 100 private: 101 DrawParams m_data; 102 }; 103 DrawTestCase(tcu::TestContext & context,const char * name,const char * desc,const DrawParams data)104 DrawTestCase::DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const DrawParams data) 105 : vkt::TestCase (context, name, desc) 106 , m_data (data) 107 { 108 } 109 ~DrawTestCase(void)110 DrawTestCase::~DrawTestCase (void) 111 { 112 } 113 initPrograms(SourceCollections & programCollection) const114 void DrawTestCase::initPrograms (SourceCollections& programCollection) const 115 { 116 const tcu::StringTemplate vertShader (string( 117 "#version 430\n" 118 "layout(location = 0) in vec4 in_position;\n" 119 "layout(location = 1) in vec4 in_color;\n" 120 "layout(location = 0) ${qualifier:opt} out vec4 out_color;\n" 121 "out gl_PerVertex {\n" 122 " vec4 gl_Position;\n" 123 " float gl_PointSize;\n" 124 "};\n" 125 "void main() {\n" 126 " gl_PointSize = 1.0;\n" 127 " gl_Position = in_position;\n" 128 " out_color = in_color;\n" 129 "}\n")); 130 131 const tcu::StringTemplate fragShader (string( 132 "#version 430\n" 133 "layout(location = 0) ${qualifier:opt} in vec4 in_color;\n" 134 "layout(location = 0) out vec4 out_color;\n" 135 "void main()\n" 136 "{\n" 137 " out_color = in_color;\n" 138 "}\n")); 139 140 map<string, string> empty; 141 map<string, string> flat; 142 flat["qualifier"] = "flat"; 143 map<string, string> noPerspective; 144 noPerspective["qualifier"] = "noperspective"; 145 146 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(empty)); 147 programCollection.glslSources.add("vertFlatColor") << glu::VertexSource(vertShader.specialize(flat)); 148 programCollection.glslSources.add("vertNoPerspective") << glu::VertexSource(vertShader.specialize(noPerspective)); 149 programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(empty)); 150 programCollection.glslSources.add("fragFlatColor") << glu::FragmentSource(fragShader.specialize(flat)); 151 programCollection.glslSources.add("fragNoPerspective") << glu::FragmentSource(fragShader.specialize(noPerspective)); 152 } 153 createInstance(Context & context) const154 TestInstance* DrawTestCase::createInstance (Context& context) const 155 { 156 return new DrawTestInstance(context, m_data); 157 } 158 iterate(void)159 tcu::TestStatus DrawTestInstance::iterate (void) 160 { 161 tcu::ConstPixelBufferAccess frames[2]; 162 de::SharedPtr<Image> colorTargetImages[2]; 163 const string vertShaderNames[2] = { m_data.vertShader, m_data.refVertShader }; 164 const string fragShaderNames[2] = { m_data.fragShader, m_data.refFragShader }; 165 tcu::TestLog &log = m_context.getTestContext().getLog(); 166 167 // Run two iterations with shaders that have different interpolation decorations. Images should still match. 168 for (deUint32 frameIdx = 0; frameIdx < DE_LENGTH_OF_ARRAY(frames); frameIdx++) 169 { 170 const DeviceInterface& vk = m_context.getDeviceInterface(); 171 const VkDevice device = m_context.getDevice(); 172 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex()); 173 Move<VkCommandPool> cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo); 174 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 175 const Unique<VkShaderModule> vs (createShaderModule(vk, device, m_context.getBinaryCollection().get(vertShaderNames[frameIdx].c_str()), 0)); 176 const Unique<VkShaderModule> fs (createShaderModule(vk, device, m_context.getBinaryCollection().get(fragShaderNames[frameIdx].c_str()), 0)); 177 de::SharedPtr<Buffer> vertexBuffer; 178 Move<VkRenderPass> renderPass; 179 Move<VkImageView> colorTargetView; 180 Move<VkFramebuffer> framebuffer; 181 Move<VkPipeline> pipeline; 182 183 // Create color buffer image. 184 { 185 const VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 }; 186 const ImageCreateInfo targetImageCreateInfo (VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT, 187 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); 188 colorTargetImages[frameIdx] = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex()); 189 } 190 191 // Create render pass and frame buffer. 192 { 193 const ImageViewCreateInfo colorTargetViewInfo (colorTargetImages[frameIdx]->object(), VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM); 194 colorTargetView = createImageView(vk, device, &colorTargetViewInfo); 195 196 RenderPassCreateInfo renderPassCreateInfo; 197 renderPassCreateInfo.addAttachment(AttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, 198 VK_SAMPLE_COUNT_1_BIT, 199 VK_ATTACHMENT_LOAD_OP_LOAD, 200 VK_ATTACHMENT_STORE_OP_STORE, 201 VK_ATTACHMENT_LOAD_OP_DONT_CARE, 202 VK_ATTACHMENT_STORE_OP_STORE, 203 VK_IMAGE_LAYOUT_GENERAL, 204 VK_IMAGE_LAYOUT_GENERAL)); 205 206 const VkAttachmentReference colorAttachmentRef = { 0, VK_IMAGE_LAYOUT_GENERAL }; 207 renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS, 208 0, 209 0, 210 DE_NULL, 211 1, 212 &colorAttachmentRef, 213 DE_NULL, 214 AttachmentReference(), 215 0, 216 DE_NULL)); 217 218 vector<VkImageView> colorAttachments (1); 219 220 renderPass = createRenderPass(vk, device, &renderPassCreateInfo); 221 colorAttachments[0] = *colorTargetView; 222 223 const FramebufferCreateInfo framebufferCreateInfo (*renderPass, colorAttachments, WIDTH, HEIGHT, 1); 224 225 framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo); 226 } 227 228 // Create vertex buffer. 229 { 230 const PositionColorVertex vertices[] = 231 { 232 PositionColorVertex( 233 tcu::Vec4(-0.8f, -0.7f, 1.0f, 1.0f), // Coord 234 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)), // Color 235 236 PositionColorVertex( 237 tcu::Vec4(0.0f, 0.4f, 0.5f, 0.5f), // Coord 238 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)), // Color 239 240 PositionColorVertex( 241 tcu::Vec4(0.8f, -0.5f, 1.0f, 1.0f), // Coord 242 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f)) // Color 243 }; 244 245 const VkDeviceSize dataSize = DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionColorVertex); 246 vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible); 247 deUint8* ptr = reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr()); 248 249 deMemcpy(ptr, vertices, static_cast<size_t>(dataSize)); 250 flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE); 251 } 252 253 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo; 254 Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo); 255 256 // Create pipeline 257 { 258 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState; 259 260 VkViewport viewport = makeViewport(WIDTH, HEIGHT); 261 VkRect2D scissor = makeRect2D(WIDTH, HEIGHT); 262 263 const VkVertexInputBindingDescription vertexInputBindingDescription = { 0, (deUint32)sizeof(tcu::Vec4) * 2, VK_VERTEX_INPUT_RATE_VERTEX }; 264 265 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = 266 { 267 { 0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u }, 268 { 1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(sizeof(float)* 4) } 269 }; 270 271 PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions); 272 273 PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0); 274 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT)); 275 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT)); 276 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState)); 277 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)); 278 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState)); 279 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor))); 280 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState()); 281 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState()); 282 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState()); 283 284 pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo); 285 } 286 287 // Queue draw and read results. 288 { 289 const VkQueue queue = m_context.getUniversalQueue(); 290 const VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } }; 291 const ImageSubresourceRange subresourceRange (VK_IMAGE_ASPECT_COLOR_BIT); 292 const VkMemoryBarrier memBarrier = 293 { 294 VK_STRUCTURE_TYPE_MEMORY_BARRIER, 295 DE_NULL, 296 VK_ACCESS_TRANSFER_WRITE_BIT, 297 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT 298 }; 299 const VkRect2D renderArea = makeRect2D(WIDTH, HEIGHT); 300 const VkDeviceSize vertexBufferOffset = 0; 301 const VkBuffer buffer = vertexBuffer->object(); 302 const VkOffset3D zeroOffset = { 0, 0, 0 }; 303 304 beginCommandBuffer(vk, *cmdBuffer, 0u); 305 306 initialTransitionColor2DImage(vk, *cmdBuffer, colorTargetImages[frameIdx]->object(), VK_IMAGE_LAYOUT_GENERAL, 307 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT); 308 309 vk.cmdClearColorImage(*cmdBuffer, colorTargetImages[frameIdx]->object(), 310 VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange); 311 312 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, 313 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 314 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL); 315 316 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea); 317 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset); 318 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 319 vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u); 320 endRenderPass(vk, *cmdBuffer); 321 endCommandBuffer(vk, *cmdBuffer); 322 323 submitCommandsAndWait(vk, device, queue, cmdBuffer.get()); 324 325 frames[frameIdx] = colorTargetImages[frameIdx]->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT); 326 } 327 } 328 329 qpTestResult res = QP_TEST_RESULT_PASS; 330 331 if (!tcu::intThresholdCompare(log, "Result", "Image comparison result", frames[0], frames[1], tcu::UVec4(0), tcu::COMPARE_LOG_RESULT)) 332 res = QP_TEST_RESULT_FAIL; 333 334 return tcu::TestStatus(res, qpGetTestResultName(res)); 335 } 336 createTests(tcu::TestCaseGroup * testGroup)337 void createTests (tcu::TestCaseGroup* testGroup) 338 { 339 tcu::TestContext& testCtx = testGroup->getTestContext(); 340 const DrawParams paramsFlat0 = { "vert", "fragFlatColor", "vertFlatColor", "fragFlatColor" }; 341 const DrawParams paramsFlat1 = { "vertFlatColor", "frag", "vert", "frag" }; 342 343 const DrawParams paramsNoPerspective0 = { "vert", "fragNoPerspective", "vertNoPerspective", "fragNoPerspective" }; 344 const DrawParams paramsNoPerspective1 = { "vertNoPerspective", "frag", "vert", "frag" }; 345 346 testGroup->addChild(new DrawTestCase(testCtx, "flat_0", "Mismatching flat interpolation testcase 0.", paramsFlat0)); 347 testGroup->addChild(new DrawTestCase(testCtx, "flat_1", "Mismatching flat interpolation testcase 1.", paramsFlat1)); 348 349 testGroup->addChild(new DrawTestCase(testCtx, "noperspective_0", "Mismatching noperspective interpolation testcase 0.", paramsNoPerspective0)); 350 testGroup->addChild(new DrawTestCase(testCtx, "noperspective_1", "Mismatching noperspective interpolation testcase 1.", paramsNoPerspective1)); 351 } 352 353 } // anonymous 354 createDifferingInterpolationTests(tcu::TestContext & testCtx)355 tcu::TestCaseGroup* createDifferingInterpolationTests (tcu::TestContext& testCtx) 356 { 357 return createTestGroup(testCtx, "differing_interpolation", "Tests for mismatched interpolation decorations.", createTests); 358 } 359 360 } // Draw 361 } // vkt 362