/*------------------------------------------------------------------------ * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2022 Google LLC. * * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Verify Depth/Stencil Write conditions *//*--------------------------------------------------------------------*/ #include "deUniquePtr.hpp" #include "../pipeline/vktPipelineImageUtil.hpp" #include "vktDrawImageObjectUtil.hpp" #include "vkImageUtil.hpp" #include "vkCmdUtil.hpp" #include "vkObjUtil.hpp" #include "vkTypeUtil.hpp" #include "vkImageWithMemory.hpp" #include "vktTestCaseUtil.hpp" #include using namespace vk; namespace vkt { namespace renderpass { namespace { using tcu::Vec4; using std::vector; using de::MovePtr; using tcu::TextureLevel; const int WIDTH = 64; const int HEIGHT = 64; enum DiscardType { KILL = 0, TERMINATE, DEMOTE }; enum BufferType { DEPTH = 0, STENCIL }; enum MutationMode { WRITE = 0, INITIALIZE, INITIALIZE_WRITE }; Move makeVertexBuffer (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex) { const VkBufferCreateInfo vertexBufferParams = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; 0u, // VkBufferCreateFlags flags; 1024u, // VkDeviceSize size; VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1u, // deUint32 queueFamilyIndexCount; &queueFamilyIndex // const deUint32* pQueueFamilyIndices; }; Move vertexBuffer = createBuffer(vk, device, &vertexBufferParams);; return vertexBuffer; } class DepthStencilWriteConditionsInstance : public TestInstance { public: DepthStencilWriteConditionsInstance (Context& context, const BufferType& bufferType, const VkFormat& m_bufferFormat); tcu::TestStatus iterate (void); private: BufferType m_bufferType; VkFormat m_bufferFormat; }; DepthStencilWriteConditionsInstance::DepthStencilWriteConditionsInstance (Context& context, const BufferType& bufferType, const VkFormat& bufferFormat) : TestInstance (context), m_bufferType(bufferType), m_bufferFormat(bufferFormat) { } template inline size_t sizeInBytes (const vector& vec) { return vec.size() * sizeof(vec[0]); } // A quad covering the whole framebuffer vector genFullQuadVertices (void) { vector vertices; vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f)); vertices.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f)); vertices.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f)); vertices.push_back(Vec4( 1.0f, -1.0f, 1.0f, 1.0f)); vertices.push_back(Vec4( 1.0f, 1.0f, 1.0f, 1.0f)); vertices.push_back(Vec4(-1.0f, 1.0f, 1.0f, 1.0f)); return vertices; } struct Vertex { Vertex(Vec4 vertices_) : vertices(vertices_) {} Vec4 vertices; static VkVertexInputBindingDescription getBindingDescription (void); static vector getAttributeDescriptions (void); }; VkVertexInputBindingDescription Vertex::getBindingDescription (void) { static const VkVertexInputBindingDescription desc = { 0u, // deUint32 binding; static_cast(sizeof(Vertex)), // deUint32 stride; VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; }; return desc; } vector Vertex::getAttributeDescriptions (void) { static const vector desc = { { 0u, // deUint32 location; 0u, // deUint32 binding; VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; static_cast(offsetof(Vertex, vertices)), // deUint32 offset; }, }; return desc; } tcu::TestStatus DepthStencilWriteConditionsInstance::iterate (void) { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); Allocator& allocator = m_context.getDefaultAllocator(); const VkQueue queue = m_context.getUniversalQueue(); const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); const VkDeviceSize bufferSize = 16 * 1024; const VkExtent2D renderSize = {deUint32(WIDTH), deUint32(HEIGHT)}; const VkRect2D renderArea = makeRect2D(makeExtent3D(WIDTH, HEIGHT, 1u)); const vector scissors (1u, renderArea); const vector viewports (1u, makeViewport(makeExtent3D(WIDTH, HEIGHT, 1u))); const vector vertices = genFullQuadVertices(); Move vertexBuffer = makeVertexBuffer(vk, device, queueFamilyIndex); MovePtr vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible); const VkDeviceSize vertexBufferOffset = 0ull; deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], sizeInBytes(vertices)); flushAlloc(vk, device, *vertexBufferAlloc); const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; const VkImageCreateInfo colorImageCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; 0, // VkImageCreateFlags flags; VK_IMAGE_TYPE_2D, // VkImageType imageType; VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; makeExtent3D(WIDTH, HEIGHT, 1u), // VkExtent3D extent; 1u, // deUint32 mipLevels; 1u, // deUint32 arrayLayers; VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; colorImageUsage, // VkImageUsageFlags usage; VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 0u, // deUint32 queueFamilyIndexCount; DE_NULL, // const deUint32* pQueueFamilyIndices; VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; }; const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1, 0, 1); const ImageWithMemory colorImage (vk, device, m_context.getDefaultAllocator(), colorImageCreateInfo, MemoryRequirement::Any); Move colorImageView = makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, colorSubresourceRange); // Depending on the type of the buffer, create a depth buffer or a stencil buffer. const VkImageUsageFlags depthStencilUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; const VkImageCreateInfo depthStencilBufferInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; nullptr, // const void* pNext; 0u, // VkImageCreateFlags flags; VK_IMAGE_TYPE_2D, // VkImageType imageType; m_bufferFormat, // VkFormat format; makeExtent3D(WIDTH, HEIGHT, 1u), // VkExtent3D extent; 1u, // deUint32 mipLevels; 1u, // deUint32 arrayLayers; VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; depthStencilUsage, // VkImageUsageFlags usage; VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 0u, // deUint32 queueFamilyIndexCount; nullptr, // const deUint32* pQueueFamilyIndices; VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; }; const de::SharedPtr depthStencilImage = Draw::Image::createAndAlloc(vk, device, depthStencilBufferInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex(), MemoryRequirement::Any); const VkImageAspectFlagBits imageAspectFlagBits = m_bufferType == BufferType::DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT; const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(imageAspectFlagBits, 0u, 1u, 0u, 1u); Move depthStencilImageView = makeImageView(vk, device, depthStencilImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_bufferFormat, subresourceRange); const Move cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex); const Move cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); const auto renderPass = makeRenderPass(vk, device,VK_FORMAT_R8G8B8A8_UNORM, m_bufferFormat, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); const vector attachments = {colorImageView.get(), depthStencilImageView.get()}; const auto framebuffer = makeFramebuffer(vk, device, renderPass.get(), static_cast(attachments.size()), de::dataOrNull(attachments), renderSize.width, renderSize.height); const Move vertexModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u); const Move fragmentModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u); const Move pipelineLayout = makePipelineLayout(vk, device, DE_NULL); const VkVertexInputBindingDescription vtxBindingDescription = Vertex::getBindingDescription(); const auto vtxAttrDescriptions = Vertex::getAttributeDescriptions(); const VkPipelineVertexInputStateCreateInfo vtxInputStateCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 1u, // deUint32 vertexBindingDescriptionCount; &vtxBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions static_cast(vtxAttrDescriptions.size()), // deUint32 vertexAttributeDescriptionCount vtxAttrDescriptions.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions }; // The value in the stencil buffer is replaced if the new value is greater than the previous value. const VkStencilOpState stencilOp = makeStencilOpState(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE, VK_COMPARE_OP_GREATER, 0xffu, 0xffu, 0u); const VkPipelineDepthStencilStateCreateInfo depthStencilCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType nullptr, // const void* pNext 0u, // VkPipelineDepthStencilStateCreateFlags flags m_bufferType == BufferType::DEPTH ? VK_TRUE : VK_FALSE, // VkBool32 depthTestEnable VK_TRUE, // VkBool32 depthWriteEnable VK_COMPARE_OP_GREATER, // VkCompareOp depthCompareOp VK_FALSE, // VkBool32 depthBoundsTestEnable m_bufferType == BufferType::STENCIL ? VK_TRUE : VK_FALSE, // VkBool32 stencilTestEnable stencilOp, // VkStencilOpState front stencilOp, // VkStencilOpState back 0.0f, // float minDepthBounds 1.0f, // float maxDepthBounds }; const Move graphicsPipeline = makeGraphicsPipeline(vk, device, pipelineLayout.get(), vertexModule.get(), DE_NULL, DE_NULL, DE_NULL, fragmentModule.get(), renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u, &vtxInputStateCreateInfo, DE_NULL, DE_NULL, &depthStencilCreateInfo, DE_NULL, DE_NULL); const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); Move resultBuffer = createBuffer(vk, device, &resultBufferCreateInfo); MovePtr resultBufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *resultBuffer), MemoryRequirement::HostVisible); VK_CHECK(vk.bindBufferMemory(device, *resultBuffer, resultBufferMemory->getMemory(), resultBufferMemory->getOffset())); const vector clearColors = { makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f), makeClearValueDepthStencil(.1f, 0u), }; beginCommandBuffer(vk, *cmdBuffer); vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline); beginRenderPass(vk, *cmdBuffer, renderPass.get(), framebuffer.get(), makeRect2D(0, 0, WIDTH, HEIGHT), static_cast(clearColors.size()), de::dataOrNull(clearColors), VK_SUBPASS_CONTENTS_INLINE, DE_NULL); vk.cmdDraw(*cmdBuffer, static_cast(vertices.size()), 1u, 0u, 0u); endRenderPass(vk, *cmdBuffer); endCommandBuffer(vk, *cmdBuffer); submitCommandsAndWait(vk, device, queue, *cmdBuffer); invalidateAlloc(vk, device, *resultBufferMemory); de::MovePtr attachment; if (m_bufferType == BufferType::DEPTH) attachment = pipeline::readDepthAttachment(vk, device, queue, queueFamilyIndex, allocator, depthStencilImage->object(), m_bufferFormat, tcu::UVec2(WIDTH, HEIGHT), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); else attachment = pipeline::readStencilAttachment(vk, device, queue, queueFamilyIndex, allocator, depthStencilImage->object(), m_bufferFormat, tcu::UVec2(WIDTH, HEIGHT), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); bool result = true; for (deUint32 y = 0; y < HEIGHT; y++) { for (deUint32 x = 0; x < WIDTH; x++) { if (m_bufferType == BufferType::STENCIL) { const auto stencilPixel = attachment->getAccess().getPixStencil(x, y, 0); if (static_cast(stencilPixel) != x % 2) result = false; } else { const auto depthPixel = attachment->getAccess().getPixDepth(x, y); if ((depthPixel < 0.09 || depthPixel > 0.11) && x % 2 == 0) result = false; if ((depthPixel < 0.19 || depthPixel > 0.21) && x % 2 == 1) result = false; } } } return result ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail"); } class DepthStencilWriteConditionsTest : public TestCase { public: DepthStencilWriteConditionsTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const BufferType bufferType, const DiscardType discardType, const MutationMode mutationMode, const VkFormat bufferFormat); virtual void checkSupport (Context& context) const; void initPrograms (SourceCollections& programCollection) const; TestInstance* createInstance (Context& context) const; private: BufferType m_bufferType; DiscardType m_discardType; MutationMode m_mutationMode; VkFormat m_bufferFormat; }; DepthStencilWriteConditionsTest::DepthStencilWriteConditionsTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const BufferType bufferType, const DiscardType discardType, const MutationMode mutationMode, const VkFormat bufferFormat) : TestCase (testCtx, name, description) , m_bufferType(bufferType) , m_discardType(discardType) , m_mutationMode(mutationMode) , m_bufferFormat(bufferFormat) { } void DepthStencilWriteConditionsTest::initPrograms (SourceCollections& programCollection) const { /* * The fragment shader has been compiled from the following GLSL shader: * * layout(location = 0) out vec4 outColor; * void main() { * if (int(gl_FragCoord.x) % 2 == 0) * discard; * outColor = vec4(1., 1., 1., 1.); * gl_FragDepth = 0.2; * } * * If a stencil buffer is enabled, the shader writes to gl_FragStencilRefARB * instead of gl_FragDepth. * * If the mutation mode is INITIALIZE or INITIALIZE_WRITE, the object that * is written to the buffer is allocated with an initial value. * * Demote and terminate commands are used instead of discard if a corresponding * DiscardType has been given. */ std::ostringstream vertexSrc; vertexSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" << "layout(location = 0) in highp vec4 a_position;\n" << "void main (void) {\n" << " gl_Position = a_position;\n" << "}\n"; std::string discardCommand = "OpKill\n"; std::string extensions = ""; std::string capabilities = ""; if (m_discardType == DiscardType::TERMINATE) { extensions = "OpExtension \"SPV_KHR_terminate_invocation\"\n"; discardCommand = "OpTerminateInvocation\n"; } else if (m_discardType == DiscardType::DEMOTE) { capabilities = "OpCapability DemoteToHelperInvocationEXT\n"; extensions = "OpExtension \"SPV_EXT_demote_to_helper_invocation\"\n"; discardCommand = "OpDemoteToHelperInvocationEXT\n"; } if (m_bufferType == BufferType::STENCIL) { capabilities += "OpCapability StencilExportEXT\n"; extensions += "OpExtension \"SPV_EXT_shader_stencil_export\"\n"; } std::ostringstream fragmentSrc; fragmentSrc << "OpCapability Shader\n" << capabilities << extensions << "%1 = OpExtInstImport \"GLSL.std.450\"\n" << "OpMemoryModel Logical GLSL450\n"; fragmentSrc << "OpEntryPoint Fragment %4 \"main\" %9 %26 %30\n" << "OpExecutionMode %4 OriginUpperLeft\n"; if (m_bufferType == BufferType::DEPTH) fragmentSrc << "OpExecutionMode %4 DepthReplacing\n"; fragmentSrc << "OpDecorate %9 BuiltIn FragCoord\n" << "OpDecorate %26 Location 0\n"; if (m_bufferType == BufferType::DEPTH) fragmentSrc << "OpDecorate %30 BuiltIn FragDepth\n"; else fragmentSrc << "OpDecorate %30 BuiltIn FragStencilRefEXT\n"; fragmentSrc << "%2 = OpTypeVoid\n" << "%3 = OpTypeFunction %2\n" << "%6 = OpTypeFloat 32\n" << "%7 = OpTypeVector %6 4\n" << "%8 = OpTypePointer Input %7\n" << "%9 = OpVariable %8 Input\n" << "%10 = OpTypeInt 32 0\n" << "%11 = OpConstant %10 0\n" << "%12 = OpTypePointer Input %6\n" << "%15 = OpTypeInt 32 1\n" << "%17 = OpConstant %15 2\n" << "%19 = OpConstant %15 0\n" << "%20 = OpTypeBool\n" << "%25 = OpTypePointer Output %7\n" << "%26 = OpVariable %25 Output\n" << "%27 = OpConstant %6 1\n" << "%28 = OpConstantComposite %7 %27 %27 %27 %27\n"; if (m_bufferType == BufferType::DEPTH) { fragmentSrc << "%29 = OpTypePointer Output %6\n"; if (m_mutationMode == MutationMode::INITIALIZE || m_mutationMode == MutationMode::INITIALIZE_WRITE) { // The value the depth buffer is initialized with. fragmentSrc << "%const_f32_02 = OpConstant %6 0.2\n"; fragmentSrc << "%30 = OpVariable %29 Output %const_f32_02\n"; } else fragmentSrc << "%30 = OpVariable %29 Output\n"; // The value written to the depth buffer. fragmentSrc << "%31 = OpConstant %6 0.2\n"; } else { fragmentSrc << "%29 = OpTypePointer Output %15\n"; if (m_mutationMode == MutationMode::INITIALIZE || m_mutationMode == MutationMode::INITIALIZE_WRITE) { // The value the stencil buffer is initialized with. fragmentSrc << "%const_int_1 = OpConstant %15 1\n"; fragmentSrc << "%30 = OpVariable %29 Output %const_int_1\n"; } else fragmentSrc << "%30 = OpVariable %29 Output\n"; // The value written to the stencil buffer. fragmentSrc << "%31 = OpConstant %15 1\n"; } fragmentSrc << "%4 = OpFunction %2 None %3\n" << "%5 = OpLabel\n" << "%13 = OpAccessChain %12 %9 %11\n" << "%14 = OpLoad %6 %13\n" << "%16 = OpConvertFToS %15 %14\n" << "%18 = OpSMod %15 %16 %17\n" << "%21 = OpIEqual %20 %18 %19\n" << "OpSelectionMerge %23 None\n" << "OpBranchConditional %21 %22 %23\n" << "%22 = OpLabel\n" << discardCommand; if (m_discardType == DiscardType::DEMOTE) fragmentSrc << "OpBranch %23\n"; fragmentSrc << "%23 = OpLabel\n" << "OpStore %26 %28\n"; if (m_mutationMode == MutationMode::WRITE || m_mutationMode == MutationMode::INITIALIZE_WRITE) fragmentSrc << "OpStore %30 %31\n"; fragmentSrc << "OpReturn\n" << "OpFunctionEnd\n"; programCollection.spirvAsmSources.add("frag") << fragmentSrc.str().c_str(); programCollection.glslSources.add("vert") << glu::VertexSource(vertexSrc.str()); } void DepthStencilWriteConditionsTest::checkSupport (Context& context) const { if (m_discardType == DiscardType::DEMOTE) context.requireDeviceFunctionality("VK_EXT_shader_demote_to_helper_invocation"); if (m_discardType == DiscardType::TERMINATE) context.requireDeviceFunctionality("VK_KHR_shader_terminate_invocation"); if (m_bufferType == BufferType::STENCIL) context.requireDeviceFunctionality("VK_EXT_shader_stencil_export"); std::string formatName = "VK_FORMAT_D32_SFLOAT_S8_UINT"; if (m_bufferFormat == VK_FORMAT_D24_UNORM_S8_UINT) formatName = "VK_FORMAT_D24_UNORM_S8_UINT"; if (m_bufferFormat == VK_FORMAT_X8_D24_UNORM_PACK32) formatName = "VK_FORMAT_X8_D24_UNORM_PACK32"; if (m_bufferFormat == VK_FORMAT_D32_SFLOAT) formatName = "VK_FORMAT_D32_SFLOAT"; const auto& vki = context.getInstanceInterface(); const auto physicalDevice = context.getPhysicalDevice(); const VkImageUsageFlags depthStencilUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; VkImageFormatProperties imageFormatProperties; if (vki.getPhysicalDeviceImageFormatProperties(physicalDevice, m_bufferFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, depthStencilUsage, (VkImageCreateFlags)0, &imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED) TCU_THROW(NotSupportedError, formatName + " not supported."); } TestInstance* DepthStencilWriteConditionsTest::createInstance (Context& context) const { return new DepthStencilWriteConditionsInstance(context, m_bufferType, m_bufferFormat); } } // anonymous ns tcu::TestCaseGroup* createDepthStencilWriteConditionsTests (tcu::TestContext& testCtx) { de::MovePtr testGroup(new tcu::TestCaseGroup(testCtx, "depth_stencil_write_conditions", "Depth/Stencil Write conditions tests")); const VkFormat depthFormats[4] = {VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT}; const VkFormat stencilFormats[2] = {VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}; for (int i = 0; i < 4; i++) { VkFormat format = depthFormats[i]; std::string postfix = "_d32sf_s8ui"; if (format == VK_FORMAT_D24_UNORM_S8_UINT) postfix = "_d24unorm_s8ui"; if (format == VK_FORMAT_X8_D24_UNORM_PACK32) postfix = "_d24_unorm"; if (format == VK_FORMAT_D32_SFLOAT) postfix = "_d32sf"; testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "depth_kill_write" + postfix, "", BufferType::DEPTH, DiscardType::KILL, MutationMode::WRITE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "depth_kill_initialize" + postfix, "", BufferType::DEPTH, DiscardType::KILL, MutationMode::INITIALIZE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "depth_kill_write_initialize" + postfix, "", BufferType::DEPTH, DiscardType::KILL, MutationMode::INITIALIZE_WRITE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "depth_terminate_write" + postfix, "", BufferType::DEPTH, DiscardType::TERMINATE, MutationMode::WRITE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "depth_terminate_initialize" + postfix, "", BufferType::DEPTH, DiscardType::TERMINATE, MutationMode::INITIALIZE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "depth_terminate_write_initialize" + postfix, "", BufferType::DEPTH, DiscardType::TERMINATE, MutationMode::INITIALIZE_WRITE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "depth_demote_write" + postfix, "", BufferType::DEPTH, DiscardType::DEMOTE, MutationMode::WRITE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "depth_demote_initialize" + postfix, "", BufferType::DEPTH, DiscardType::DEMOTE, MutationMode::INITIALIZE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "depth_demote_write_initialize" + postfix, "", BufferType::DEPTH, DiscardType::DEMOTE, MutationMode::INITIALIZE_WRITE, format)); } for (int i = 0; i < 2; i++) { VkFormat format = stencilFormats[i]; std::string postfix = "_d32sf_s8ui"; if (format == VK_FORMAT_D24_UNORM_S8_UINT) postfix = "_d24unorm_s8ui"; testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "stencil_kill_write" + postfix, "", BufferType::STENCIL, DiscardType::KILL, MutationMode::WRITE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "stencil_kill_initialize" + postfix, "", BufferType::STENCIL, DiscardType::KILL, MutationMode::INITIALIZE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "stencil_kill_write_initialize" + postfix, "", BufferType::STENCIL, DiscardType::KILL, MutationMode::INITIALIZE_WRITE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "stencil_terminate_write" + postfix, "", BufferType::STENCIL, DiscardType::TERMINATE, MutationMode::WRITE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "stencil_terminate_initialize" + postfix, "", BufferType::STENCIL, DiscardType::TERMINATE, MutationMode::INITIALIZE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "stencil_terminate_write_initialize" + postfix, "", BufferType::STENCIL, DiscardType::TERMINATE, MutationMode::INITIALIZE_WRITE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "stencil_demote_write" + postfix, "", BufferType::STENCIL, DiscardType::DEMOTE, MutationMode::WRITE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "stencil_demote_initialize" + postfix, "", BufferType::STENCIL, DiscardType::DEMOTE, MutationMode::INITIALIZE, format)); testGroup->addChild(new DepthStencilWriteConditionsTest(testCtx, "stencil_demote_write_initialize" + postfix, "", BufferType::STENCIL, DiscardType::DEMOTE, MutationMode::INITIALIZE_WRITE, format)); } return testGroup.release(); } } // renderpass } // vkt