| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2016 The Khronos Group Inc. |
| * |
| * 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 vktSparseResourcesShaderIntrinsicsSampled.cpp |
| * \brief Sparse Resources Shader Intrinsics for sampled images |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktSparseResourcesShaderIntrinsicsSampled.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkObjUtil.hpp" |
| #include "vkBarrierUtil.hpp" |
| #include "vkBufferWithMemory.hpp" |
| |
| using namespace vk; |
| |
| namespace vkt |
| { |
| namespace sparse |
| { |
| namespace |
| { |
| |
| Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk, |
| const VkDevice device, |
| const VkPipelineLayout pipelineLayout, |
| const VkRenderPass renderPass, |
| const VkShaderModule vertexModule, |
| const VkShaderModule fragmentModule, |
| const VkShaderModule geometryModule) |
| { |
| const std::vector<VkViewport> noViewports; |
| const std::vector<VkRect2D> noScissors; |
| |
| const VkFormat format = VK_FORMAT_R32G32_SFLOAT; |
| const deUint32 size = tcu::getPixelSize(mapVkFormat(format)); |
| |
| const VkVertexInputBindingDescription vertexBinding = |
| { |
| 0u, // deUint32 binding; |
| size * 2, // deUint32 stride; |
| VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate; |
| }; |
| |
| const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = |
| { |
| // position |
| { |
| 0u, // deUint32 location; |
| 0u, // deUint32 binding; |
| format, // VkFormat format; |
| 0u // deUint32 offset; |
| }, |
| // texture coordinates |
| { |
| 1u, // deUint32 location; |
| 0u, // deUint32 binding; |
| format, // VkFormat format; |
| size // deUint32 offset; |
| }, |
| }; |
| |
| const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; |
| 1u, // deUint32 vertexBindingDescriptionCount; |
| &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; |
| 2u, // deUint32 vertexAttributeDescriptionCount; |
| vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; |
| }; |
| |
| const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; |
| const VkPipelineColorBlendAttachmentState defaultColorBlendAttachmentState = |
| { |
| VK_FALSE, // VkBool32 blendEnable; |
| VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; |
| VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; |
| VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; |
| VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; |
| VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; |
| VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; |
| colorComponentsAll // VkColorComponentFlags colorWriteMask; |
| }; |
| |
| const VkPipelineColorBlendAttachmentState colorBlendAttachmentStates[] = |
| { |
| defaultColorBlendAttachmentState, |
| defaultColorBlendAttachmentState |
| }; |
| |
| const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; |
| VK_FALSE, // VkBool32 logicOpEnable; |
| VK_LOGIC_OP_COPY, // VkLogicOp logicOp; |
| DE_LENGTH_OF_ARRAY(colorBlendAttachmentStates), // deUint32 attachmentCount; |
| colorBlendAttachmentStates, // const VkPipelineColorBlendAttachmentState* pAttachments; |
| { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]; |
| }; |
| |
| return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk |
| device, // const VkDevice device |
| pipelineLayout, // const VkPipelineLayout pipelineLayout |
| vertexModule, // const VkShaderModule vertexShaderModule |
| DE_NULL, // const VkShaderModule tessellationControlModule |
| DE_NULL, // const VkShaderModule tessellationEvalModule |
| geometryModule, // const VkShaderModule geometryShaderModule |
| fragmentModule, // const VkShaderModule fragmentShaderModule |
| renderPass, // const VkRenderPass renderPass |
| noViewports, // const std::vector<VkViewport>& viewports |
| noScissors, // const std::vector<VkRect2D>& scissors |
| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // const VkPrimitiveTopology topology |
| 0u, // const deUint32 subpass |
| 0u, // const deUint32 patchControlPoints |
| &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo |
| DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo |
| DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo |
| DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo |
| &pipelineColorBlendStateInfo); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo |
| } |
| |
| } // anonymous |
| |
| void SparseShaderIntrinsicsCaseSampledBase::initPrograms (vk::SourceCollections& programCollection) const |
| { |
| const PlanarFormatDescription formatDescription = getPlanarFormatDescription(m_format); |
| const deUint32 numLayers = getNumLayers(m_imageType, m_imageSize); |
| const std::string coordString = getShaderImageCoordinates(m_imageType, "%local_texCoord_x", "%local_texCoord_xy", "%local_texCoord_xyz"); |
| |
| // Create vertex shader |
| std::ostringstream vs; |
| |
| vs << "#version 440\n" |
| << "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n" |
| << "#extension GL_EXT_shader_image_int64 : require\n" |
| << "layout(location = 0) in highp vec2 vs_in_position;\n" |
| << "layout(location = 1) in highp vec2 vs_in_texCoord;\n" |
| << "\n" |
| << "layout(location = 0) out highp vec3 vs_out_texCoord;\n" |
| << "\n" |
| << "out gl_PerVertex {\n" |
| << " vec4 gl_Position;\n" |
| << "};\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " gl_Position = vec4(vs_in_position, 0.0f, 1.0f);\n" |
| << " vs_out_texCoord = vec3(vs_in_texCoord, 0.0f);\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); |
| |
| if (numLayers > 1u) |
| { |
| const deInt32 maxVertices = 3u * numLayers; |
| |
| // Create geometry shader |
| std::ostringstream gs; |
| |
| gs << "#version 440\n" |
| << "layout(triangles) in;\n" |
| << "layout(triangle_strip, max_vertices = " << static_cast<deInt32>(maxVertices) << ") out;\n" |
| << "\n" |
| << "in gl_PerVertex {\n" |
| << " vec4 gl_Position;\n" |
| << "} gl_in[];\n" |
| << "out gl_PerVertex {\n" |
| << " vec4 gl_Position;\n" |
| << "};\n" |
| << "layout(location = 0) in highp vec3 gs_in_texCoord[];\n" |
| << "\n" |
| << "layout(location = 0) out highp vec3 gs_out_texCoord;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " for (int layerNdx = 0; layerNdx < " << static_cast<deInt32>(numLayers) << "; ++layerNdx)\n" |
| << " {\n" |
| << " for (int vertexNdx = 0; vertexNdx < gl_in.length(); ++vertexNdx)\n" |
| << " {\n" |
| << " gl_Layer = layerNdx;\n" |
| << " gl_Position = gl_in[vertexNdx].gl_Position;\n" |
| << " gs_out_texCoord = vec3(gs_in_texCoord[vertexNdx].xy, float(layerNdx));\n" |
| << " EmitVertex();\n" |
| << " }\n" |
| << " EndPrimitive();\n" |
| << " }\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("geometry_shader") << glu::GeometrySource(gs.str()); |
| } |
| |
| // Create fragment shader |
| std::ostringstream fs; |
| |
| const std::string typeImgComp = getImageComponentTypeName(formatDescription); |
| const std::string typeImgCompVec4 = getImageComponentVec4TypeName(formatDescription); |
| |
| SpirvVersion spirvVersion = SPIRV_VERSION_1_0; |
| std::string interfaceList = ""; |
| |
| if (m_operand.find("Nontemporal") != std::string::npos) |
| { |
| spirvVersion = SPIRV_VERSION_1_6; |
| interfaceList = " %uniformconst_image_sparse %uniformblock_instance"; |
| } |
| |
| fs << "OpCapability Shader\n" |
| << "OpCapability SampledCubeArray\n" |
| << "OpCapability ImageCubeArray\n" |
| << "OpCapability SparseResidency\n" |
| << "OpCapability StorageImageExtendedFormats\n"; |
| |
| if (formatIsR64(m_format)) |
| { |
| fs << "OpCapability Int64\n" |
| << "OpCapability Int64ImageEXT\n" |
| << "OpExtension \"SPV_EXT_shader_image_int64\"\n"; |
| } |
| |
| fs << "%ext_import = OpExtInstImport \"GLSL.std.450\"\n" |
| << "OpMemoryModel Logical GLSL450\n" |
| << "OpEntryPoint Fragment %func_main \"main\" %varying_texCoord %output_texel %output_residency " << interfaceList << "\n" |
| << "OpExecutionMode %func_main OriginUpperLeft\n" |
| << "OpSource GLSL 440\n" |
| |
| << "OpName %func_main \"main\"\n" |
| |
| << "OpName %varying_texCoord \"varying_texCoord\"\n" |
| |
| << "OpName %output_texel \"out_texel\"\n" |
| << "OpName %output_residency \"out_residency\"\n" |
| |
| << "OpName %type_uniformblock \"LodBlock\"\n" |
| << "OpMemberName %type_uniformblock 0 \"lod\"\n" |
| << "OpMemberName %type_uniformblock 1 \"size\"\n" |
| << "OpName %uniformblock_instance \"lodInstance\"\n" |
| |
| << "OpName %uniformconst_image_sparse \"u_imageSparse\"\n" |
| |
| << "OpDecorate %varying_texCoord Location 0\n" |
| |
| << "OpDecorate %output_texel Location 0\n" |
| << "OpDecorate %output_residency Location 1\n" |
| |
| << "OpDecorate %type_uniformblock Block\n" |
| << "OpMemberDecorate %type_uniformblock 0 Offset 0\n" |
| << "OpMemberDecorate %type_uniformblock 1 Offset 8\n" |
| |
| << "OpDecorate %uniformconst_image_sparse DescriptorSet 0\n" |
| << "OpDecorate %uniformconst_image_sparse Binding " << BINDING_IMAGE_SPARSE << "\n" |
| |
| << "%type_void = OpTypeVoid\n" |
| << "%type_void_func = OpTypeFunction %type_void\n" |
| |
| << "%type_bool = OpTypeBool\n" |
| << "%type_int = OpTypeInt 32 1\n" |
| << "%type_uint = OpTypeInt 32 0\n" |
| << "%type_float = OpTypeFloat 32\n" |
| << "%type_vec2 = OpTypeVector %type_float 2\n" |
| << "%type_vec3 = OpTypeVector %type_float 3\n" |
| << "%type_vec4 = OpTypeVector %type_float 4\n" |
| << "%type_ivec4 = OpTypeVector %type_int 4\n" |
| << "%type_uvec4 = OpTypeVector %type_uint 4\n" |
| << "%type_uniformblock = OpTypeStruct %type_uint %type_vec2\n"; |
| |
| if (formatIsR64(m_format)) |
| { |
| fs << "%type_int64 = OpTypeInt 64 1\n" |
| << "%type_uint64 = OpTypeInt 64 0\n" |
| << "%type_i64vec2 = OpTypeVector %type_int64 2\n" |
| << "%type_i64vec3 = OpTypeVector %type_int64 3\n" |
| << "%type_i64vec4 = OpTypeVector %type_int64 4\n" |
| << "%type_u64vec3 = OpTypeVector %type_uint64 3\n" |
| << "%type_u64vec4 = OpTypeVector %type_uint64 4\n"; |
| } |
| |
| fs << "%type_struct_int_img_comp_vec4 = OpTypeStruct %type_int "<< typeImgCompVec4 << "\n" |
| << "%type_input_vec3 = OpTypePointer Input %type_vec3\n" |
| << "%type_input_float = OpTypePointer Input %type_float\n"; |
| |
| if (formatIsR64(m_format)) |
| fs << "%type_output_img_comp_vec4 = OpTypePointer Output " << "%type_ivec4" << "\n"; |
| else |
| fs << "%type_output_img_comp_vec4 = OpTypePointer Output " << typeImgCompVec4 << "\n"; |
| |
| fs << "%type_output_uint = OpTypePointer Output %type_uint\n" |
| |
| << "%type_function_int = OpTypePointer Function %type_int\n" |
| << "%type_function_img_comp_vec4 = OpTypePointer Function " << typeImgCompVec4 << "\n" |
| << "%type_function_int_img_comp_vec4 = OpTypePointer Function %type_struct_int_img_comp_vec4\n" |
| |
| << "%type_pushconstant_uniformblock = OpTypePointer PushConstant %type_uniformblock\n" |
| << "%type_pushconstant_uniformblock_member_lod = OpTypePointer PushConstant %type_uint\n" |
| << "%type_pushconstant_uniformblock_member_size = OpTypePointer PushConstant %type_vec2\n" |
| |
| << "%type_image_sparse = " << getOpTypeImageSparse(m_imageType, m_format, typeImgComp, true) << "\n" |
| << "%type_sampled_image_sparse = OpTypeSampledImage %type_image_sparse\n" |
| << "%type_uniformconst_image_sparse = OpTypePointer UniformConstant %type_sampled_image_sparse\n" |
| |
| << "%varying_texCoord = OpVariable %type_input_vec3 Input\n" |
| |
| << "%output_texel = OpVariable %type_output_img_comp_vec4 Output\n" |
| << "%output_residency = OpVariable %type_output_uint Output\n" |
| |
| << "%uniformconst_image_sparse = OpVariable %type_uniformconst_image_sparse UniformConstant\n" |
| |
| << "%uniformblock_instance = OpVariable %type_pushconstant_uniformblock PushConstant\n" |
| |
| // Declare constants |
| << "%constant_uint_0 = OpConstant %type_uint 0\n" |
| << "%constant_uint_1 = OpConstant %type_uint 1\n" |
| << "%constant_uint_2 = OpConstant %type_uint 2\n" |
| << "%constant_uint_3 = OpConstant %type_uint 3\n" |
| << "%constant_int_0 = OpConstant %type_int 0\n" |
| << "%constant_int_1 = OpConstant %type_int 1\n" |
| << "%constant_int_2 = OpConstant %type_int 2\n" |
| << "%constant_int_3 = OpConstant %type_int 3\n" |
| << "%constant_float_0 = OpConstant %type_float 0.0\n" |
| << "%constant_float_half = OpConstant %type_float 0.5\n" |
| << "%constant_texel_resident = OpConstant %type_uint " << MEMORY_BLOCK_BOUND_VALUE << "\n" |
| << "%constant_texel_not_resident = OpConstant %type_uint " << MEMORY_BLOCK_NOT_BOUND_VALUE << "\n" |
| |
| // Call main function |
| << "%func_main = OpFunction %type_void None %type_void_func\n" |
| << "%label_func_main = OpLabel\n" |
| |
| << "%local_image_sparse = OpLoad %type_sampled_image_sparse %uniformconst_image_sparse\n" |
| |
| << "%texCoord = OpLoad %type_vec3 %varying_texCoord\n" |
| |
| << "%local_texCoord_x = OpCompositeExtract %type_float %texCoord 0\n" |
| << "%local_texCoord_y = OpCompositeExtract %type_float %texCoord 1\n" |
| << "%local_texCoord_z = OpCompositeExtract %type_float %texCoord 2\n" |
| |
| << "%local_texCoord_xy = OpCompositeConstruct %type_vec2 %local_texCoord_x %local_texCoord_y\n" |
| << "%local_texCoord_xyz = OpCompositeConstruct %type_vec3 %local_texCoord_x %local_texCoord_y %local_texCoord_z\n" |
| |
| << "%access_uniformblock_member_uint_lod = OpAccessChain %type_pushconstant_uniformblock_member_lod %uniformblock_instance %constant_int_0\n" |
| << "%local_uniformblock_member_uint_lod = OpLoad %type_uint %access_uniformblock_member_uint_lod\n" |
| << "%local_uniformblock_member_float_lod = OpConvertUToF %type_float %local_uniformblock_member_uint_lod\n" |
| << "%access_uniformblock_member_size = OpAccessChain %type_pushconstant_uniformblock_member_size %uniformblock_instance %constant_int_1\n" |
| << "%local_uniformblock_member_size = OpLoad %type_vec2 %access_uniformblock_member_size\n" |
| |
| << sparseImageOpString("%local_sparse_op_result", "%type_struct_int_img_comp_vec4", "%local_image_sparse", coordString, "%local_uniformblock_member_float_lod") << "\n" |
| |
| // Load texel value |
| << "%local_img_comp_vec4 = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_op_result 1\n"; |
| |
| if (formatIsR64(m_format)) |
| { |
| fs << "%local_img_comp32b = OpSConvert %type_ivec4 %local_img_comp_vec4\n" |
| << "OpStore %output_texel %local_img_comp32b\n"; |
| } |
| else |
| { |
| fs << "OpStore %output_texel %local_img_comp_vec4\n"; |
| } |
| |
| // Load residency code |
| fs << "%local_residency_code = OpCompositeExtract %type_int %local_sparse_op_result 0\n" |
| |
| // Check if loaded texel is placed in resident memory |
| << "%local_texel_resident = OpImageSparseTexelsResident %type_bool %local_residency_code\n" |
| << "OpSelectionMerge %branch_texel_resident None\n" |
| << "OpBranchConditional %local_texel_resident %label_texel_resident %label_texel_not_resident\n" |
| << "%label_texel_resident = OpLabel\n" |
| |
| // Loaded texel is in resident memory |
| << "OpStore %output_residency %constant_texel_resident\n" |
| |
| << "OpBranch %branch_texel_resident\n" |
| << "%label_texel_not_resident = OpLabel\n" |
| |
| // Loaded texel is not in resident memory |
| << "OpStore %output_residency %constant_texel_not_resident\n" |
| |
| << "OpBranch %branch_texel_resident\n" |
| << "%branch_texel_resident = OpLabel\n" |
| |
| << "OpReturn\n" |
| << "OpFunctionEnd\n"; |
| |
| programCollection.spirvAsmSources.add("fragment_shader") << fs.str() |
| << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, spirvVersion); |
| |
| } |
| |
| std::string SparseCaseOpImageSparseSampleExplicitLod::sparseImageOpString (const std::string& resultVariable, |
| const std::string& resultType, |
| const std::string& image, |
| const std::string& coord, |
| const std::string& miplevel) const |
| { |
| std::ostringstream src; |
| std::string additionalOperand = (m_operand.empty() ? " " : (std::string("|") + m_operand + " ")); |
| |
| src << resultVariable << " = OpImageSparseSampleExplicitLod " << resultType << " " << image << " " << coord << " Lod" << additionalOperand << miplevel << "\n"; |
| |
| return src.str(); |
| } |
| |
| std::string SparseCaseOpImageSparseSampleImplicitLod::sparseImageOpString (const std::string& resultVariable, |
| const std::string& resultType, |
| const std::string& image, |
| const std::string& coord, |
| const std::string& miplevel) const |
| { |
| DE_UNREF(miplevel); |
| |
| std::ostringstream src; |
| |
| src << resultVariable << " = OpImageSparseSampleImplicitLod " << resultType << " " << image << " " << coord << " " << m_operand << "\n"; |
| |
| return src.str(); |
| } |
| |
| std::string SparseCaseOpImageSparseGather::sparseImageOpString (const std::string& resultVariable, |
| const std::string& resultType, |
| const std::string& image, |
| const std::string& coord, |
| const std::string& miplevel) const |
| { |
| DE_UNREF(miplevel); |
| |
| std::ostringstream src; |
| |
| const PlanarFormatDescription formatDescription = getPlanarFormatDescription(m_format); |
| const std::string typeImgComp = getImageComponentTypeName(formatDescription); |
| const std::string typeImgCompVec4 = getImageComponentVec4TypeName(formatDescription); |
| |
| // Bias the coord value by half a texel, so we sample from center of 2x2 gather rectangle |
| |
| src << "%local_image_width = OpCompositeExtract %type_float %local_uniformblock_member_size 0\n"; |
| src << "%local_image_height = OpCompositeExtract %type_float %local_uniformblock_member_size 1\n"; |
| src << "%local_coord_x_bias = OpFDiv %type_float %constant_float_half %local_image_width\n"; |
| src << "%local_coord_y_bias = OpFDiv %type_float %constant_float_half %local_image_height\n"; |
| |
| switch (m_imageType) |
| { |
| case IMAGE_TYPE_2D: |
| { |
| src << "%local_coord_bias = OpCompositeConstruct %type_vec2 %local_coord_x_bias %local_coord_y_bias\n"; |
| src << "%local_coord_biased = OpFAdd %type_vec2 " << coord << " %local_coord_bias\n"; |
| |
| break; |
| } |
| |
| case IMAGE_TYPE_2D_ARRAY: |
| case IMAGE_TYPE_3D: |
| { |
| src << "%local_coord_bias = OpCompositeConstruct %type_vec3 %local_coord_x_bias %local_coord_y_bias %constant_float_0\n"; |
| src << "%local_coord_biased = OpFAdd %type_vec3 " << coord << " %local_coord_bias\n"; |
| |
| break; |
| } |
| |
| default: |
| { |
| DE_FATAL("Unexpected image type"); |
| } |
| } |
| |
| src << "%local_sparse_gather_result_x = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_0 " + m_operand + "\n"; |
| src << "%local_sparse_gather_result_y = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_1 " + m_operand + "\n"; |
| src << "%local_sparse_gather_result_z = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_2 " + m_operand + "\n"; |
| src << "%local_sparse_gather_result_w = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_3 " + m_operand + "\n"; |
| |
| src << "%local_gather_residency_code = OpCompositeExtract %type_int %local_sparse_gather_result_x 0\n"; |
| |
| src << "%local_gather_texels_x = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_x 1\n"; |
| src << "%local_gather_texels_y = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_y 1\n"; |
| src << "%local_gather_texels_z = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_z 1\n"; |
| src << "%local_gather_texels_w = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_w 1\n"; |
| |
| src << "%local_gather_primary_texel_x = OpCompositeExtract " << typeImgComp << " %local_gather_texels_x 3\n"; |
| src << "%local_gather_primary_texel_y = OpCompositeExtract " << typeImgComp << " %local_gather_texels_y 3\n"; |
| src << "%local_gather_primary_texel_z = OpCompositeExtract " << typeImgComp << " %local_gather_texels_z 3\n"; |
| src << "%local_gather_primary_texel_w = OpCompositeExtract " << typeImgComp << " %local_gather_texels_w 3\n"; |
| |
| src << "%local_gather_primary_texel = OpCompositeConstruct " << typeImgCompVec4 << " %local_gather_primary_texel_x %local_gather_primary_texel_y %local_gather_primary_texel_z %local_gather_primary_texel_w\n"; |
| src << resultVariable << " = OpCompositeConstruct " << resultType << " %local_gather_residency_code %local_gather_primary_texel\n"; |
| |
| return src.str(); |
| } |
| |
| class SparseShaderIntrinsicsInstanceSampledBase : public SparseShaderIntrinsicsInstanceBase |
| { |
| public: |
| SparseShaderIntrinsicsInstanceSampledBase (Context& context, |
| const SpirVFunction function, |
| const ImageType imageType, |
| const tcu::UVec3& imageSize, |
| const VkFormat format) |
| : SparseShaderIntrinsicsInstanceBase(context, function, imageType, imageSize, format) {} |
| |
| VkImageUsageFlags imageSparseUsageFlags (void) const; |
| VkImageUsageFlags imageOutputUsageFlags (void) const; |
| |
| VkQueueFlags getQueueFlags (void) const; |
| |
| void recordCommands (const VkCommandBuffer commandBuffer, |
| const VkImageCreateInfo& imageSparseInfo, |
| const VkImage imageSparse, |
| const VkImage imageTexels, |
| const VkImage imageResidency); |
| |
| virtual void checkSupport (VkImageCreateInfo imageSparseInfo) const; |
| |
| virtual VkImageSubresourceRange sampledImageRangeToBind(const VkImageCreateInfo& imageSparseInfo, const deUint32 mipLevel) const = 0; |
| |
| private: |
| typedef de::SharedPtr< vk::Unique<VkFramebuffer> > VkFramebufferSp; |
| |
| Move<VkBuffer> m_vertexBuffer; |
| de::MovePtr<Allocation> m_vertexBufferAlloc; |
| std::vector<VkFramebufferSp> m_framebuffers; |
| Move<VkRenderPass> m_renderPass; |
| Move<VkSampler> m_sampler; |
| }; |
| |
| VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageSparseUsageFlags (void) const |
| { |
| return VK_IMAGE_USAGE_SAMPLED_BIT; |
| } |
| |
| VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageOutputUsageFlags (void) const |
| { |
| return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| } |
| |
| VkQueueFlags SparseShaderIntrinsicsInstanceSampledBase::getQueueFlags (void) const |
| { |
| return VK_QUEUE_GRAPHICS_BIT; |
| } |
| |
| void SparseShaderIntrinsicsInstanceSampledBase::checkSupport(VkImageCreateInfo imageSparseInfo) const |
| { |
| const InstanceInterface& instance = m_context.getInstanceInterface(); |
| const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); |
| const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice); |
| |
| SparseShaderIntrinsicsInstanceBase::checkSupport(imageSparseInfo); |
| |
| if (imageSparseInfo.extent.width > deviceProperties.limits.maxFramebufferWidth || |
| imageSparseInfo.extent.height > deviceProperties.limits.maxFramebufferHeight || |
| imageSparseInfo.arrayLayers > deviceProperties.limits.maxFramebufferLayers) |
| { |
| TCU_THROW(NotSupportedError, "Image size exceeds allowed framebuffer dimensions"); |
| } |
| |
| // Check if device supports image format for sampled images |
| if (!checkImageFormatFeatureSupport(instance, physicalDevice, imageSparseInfo.format, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) |
| TCU_THROW(NotSupportedError, "Device does not support image format for sampled images"); |
| |
| // Check if device supports image format for color attachment |
| if (!checkImageFormatFeatureSupport(instance, physicalDevice, imageSparseInfo.format, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) |
| TCU_THROW(NotSupportedError, "Device does not support image format for color attachment"); |
| |
| // Make sure device supports VK_FORMAT_R32_UINT format for color attachment |
| if (!checkImageFormatFeatureSupport(instance, physicalDevice, mapTextureFormat(m_residencyFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) |
| TCU_THROW(TestError, "Device does not support VK_FORMAT_R32_UINT format for color attachment"); |
| } |
| |
| void SparseShaderIntrinsicsInstanceSampledBase::recordCommands (const VkCommandBuffer commandBuffer, |
| const VkImageCreateInfo& imageSparseInfo, |
| const VkImage imageSparse, |
| const VkImage imageTexels, |
| const VkImage imageResidency) |
| { |
| const InstanceInterface& instance = m_context.getInstanceInterface(); |
| const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); |
| const DeviceInterface& deviceInterface = getDeviceInterface(); |
| |
| // Create buffer storing vertex data |
| std::vector<tcu::Vec2> vertexData; |
| |
| vertexData.push_back(tcu::Vec2(-1.0f,-1.0f)); |
| vertexData.push_back(tcu::Vec2( 0.0f, 0.0f)); |
| |
| vertexData.push_back(tcu::Vec2(-1.0f, 1.0f)); |
| vertexData.push_back(tcu::Vec2( 0.0f, 1.0f)); |
| |
| vertexData.push_back(tcu::Vec2( 1.0f,-1.0f)); |
| vertexData.push_back(tcu::Vec2( 1.0f, 0.0f)); |
| |
| vertexData.push_back(tcu::Vec2( 1.0f, 1.0f)); |
| vertexData.push_back(tcu::Vec2( 1.0f, 1.0f)); |
| |
| const VkDeviceSize vertexDataSizeInBytes = sizeInBytes(vertexData); |
| const VkBufferCreateInfo vertexBufferCreateInfo = makeBufferCreateInfo(vertexDataSizeInBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); |
| |
| m_vertexBuffer = createBuffer(deviceInterface, getDevice(), &vertexBufferCreateInfo); |
| m_vertexBufferAlloc = bindBuffer(deviceInterface, getDevice(), getAllocator(), *m_vertexBuffer, MemoryRequirement::HostVisible); |
| |
| deMemcpy(m_vertexBufferAlloc->getHostPtr(), &vertexData[0], static_cast<std::size_t>(vertexDataSizeInBytes)); |
| flushAlloc(deviceInterface, getDevice(), *m_vertexBufferAlloc); |
| |
| // Create render pass |
| const VkAttachmentDescription texelsAttachmentDescription = |
| { |
| (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; |
| imageSparseInfo.format, // VkFormat format; |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; |
| VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; |
| }; |
| |
| const VkAttachmentDescription residencyAttachmentDescription = |
| { |
| (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; |
| mapTextureFormat(m_residencyFormat), // VkFormat format; |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; |
| VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; |
| }; |
| |
| const VkAttachmentDescription colorAttachmentsDescription[] = { texelsAttachmentDescription, residencyAttachmentDescription }; |
| |
| const VkAttachmentReference texelsAttachmentReference = |
| { |
| 0u, // deUint32 attachment; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; |
| }; |
| |
| const VkAttachmentReference residencyAttachmentReference = |
| { |
| 1u, // deUint32 attachment; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; |
| }; |
| |
| const VkAttachmentReference colorAttachmentsReference[] = { texelsAttachmentReference, residencyAttachmentReference }; |
| |
| const VkAttachmentReference depthAttachmentReference = |
| { |
| VK_ATTACHMENT_UNUSED, // deUint32 attachment; |
| VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout; |
| }; |
| |
| const VkSubpassDescription subpassDescription = |
| { |
| (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; |
| VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; |
| 0u, // deUint32 inputAttachmentCount; |
| DE_NULL, // const VkAttachmentReference* pInputAttachments; |
| 2u, // deUint32 colorAttachmentCount; |
| colorAttachmentsReference, // const VkAttachmentReference* pColorAttachments; |
| DE_NULL, // const VkAttachmentReference* pResolveAttachments; |
| &depthAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment; |
| 0u, // deUint32 preserveAttachmentCount; |
| DE_NULL // const deUint32* pPreserveAttachments; |
| }; |
| |
| const VkRenderPassCreateInfo renderPassInfo = |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; |
| 2u, // deUint32 attachmentCount; |
| colorAttachmentsDescription, // const VkAttachmentDescription* pAttachments; |
| 1u, // deUint32 subpassCount; |
| &subpassDescription, // const VkSubpassDescription* pSubpasses; |
| 0u, // deUint32 dependencyCount; |
| DE_NULL // const VkSubpassDependency* pDependencies; |
| }; |
| |
| m_renderPass = createRenderPass(deviceInterface, getDevice(), &renderPassInfo); |
| |
| // Create descriptor set layout |
| DescriptorSetLayoutBuilder descriptorLayerBuilder; |
| |
| descriptorLayerBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| const Unique<VkDescriptorSetLayout> descriptorSetLayout(descriptorLayerBuilder.build(deviceInterface, getDevice())); |
| |
| // Create descriptor pool |
| DescriptorPoolBuilder descriptorPoolBuilder; |
| |
| descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageSparseInfo.mipLevels); |
| |
| descriptorPool = descriptorPoolBuilder.build(deviceInterface, getDevice(), VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, imageSparseInfo.mipLevels); |
| |
| VkSamplerCreateInfo samplerCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, |
| DE_NULL, |
| (VkSamplerCreateFlags)0, |
| mapFilterMode(tcu::Sampler::NEAREST), // magFilter |
| mapFilterMode(tcu::Sampler::NEAREST_MIPMAP_NEAREST), // minFilter |
| mapMipmapMode(tcu::Sampler::NEAREST_MIPMAP_NEAREST), // mipMode |
| mapWrapMode(tcu::Sampler::REPEAT_GL), // addressU |
| mapWrapMode(tcu::Sampler::REPEAT_GL), // addressV |
| mapWrapMode(tcu::Sampler::REPEAT_GL), // addressW |
| 0.0f, // mipLodBias |
| VK_FALSE, // anisotropyEnable |
| 1.0f, // maxAnisotropy |
| VK_FALSE, // compareEnable |
| mapCompareMode(tcu::Sampler::COMPAREMODE_ALWAYS), // compareOp |
| 0.0f, // minLod |
| 1000.0f, // maxLod |
| VK_BORDER_COLOR_INT_TRANSPARENT_BLACK, // borderColor |
| VK_FALSE, // unnormalizedCoords |
| }; |
| m_sampler = createSampler(deviceInterface, getDevice(), &samplerCreateInfo); |
| |
| struct PushConstants |
| { |
| deUint32 lod; |
| deUint32 padding; // padding needed to satisfy std430 rules |
| float lodWidth; |
| float lodHeight; |
| }; |
| |
| // Create pipeline layout |
| const VkPushConstantRange lodConstantRange = |
| { |
| VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags; |
| 0u, // deUint32 offset; |
| sizeof(PushConstants), // deUint32 size; |
| }; |
| |
| const VkPipelineLayoutCreateInfo pipelineLayoutParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineLayoutCreateFlags flags; |
| 1u, // deUint32 setLayoutCount; |
| &descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts; |
| 1u, // deUint32 pushConstantRangeCount; |
| &lodConstantRange, // const VkPushConstantRange* pPushConstantRanges; |
| }; |
| |
| pipelineLayout = createPipelineLayout(deviceInterface, getDevice(), &pipelineLayoutParams); |
| |
| // Create graphics pipeline |
| { |
| Move<VkShaderModule> vertexModule = createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0); |
| Move<VkShaderModule> fragmentModule = createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0); |
| Move<VkShaderModule> geometryModule; |
| |
| if (imageSparseInfo.arrayLayers > 1u) |
| { |
| requireFeatures(instance, physicalDevice, FEATURE_GEOMETRY_SHADER); |
| geometryModule = createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("geometry_shader"), (VkShaderModuleCreateFlags)0); |
| } |
| |
| pipelines.push_back(makeVkSharedPtr(makeGraphicsPipeline( |
| deviceInterface, getDevice(), *pipelineLayout, *m_renderPass, *vertexModule, *fragmentModule, *geometryModule))); |
| } |
| |
| const VkPipeline graphicsPipeline = **pipelines[0]; |
| |
| { |
| const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers); |
| |
| VkImageMemoryBarrier imageShaderAccessBarriers[3]; |
| |
| imageShaderAccessBarriers[0] = makeImageMemoryBarrier |
| ( |
| VK_ACCESS_TRANSFER_WRITE_BIT, |
| VK_ACCESS_SHADER_READ_BIT, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, |
| imageSparse, |
| fullImageSubresourceRange |
| ); |
| |
| imageShaderAccessBarriers[1] = makeImageMemoryBarrier |
| ( |
| 0u, |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| VK_IMAGE_LAYOUT_UNDEFINED, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| imageTexels, |
| fullImageSubresourceRange |
| ); |
| |
| imageShaderAccessBarriers[2] = makeImageMemoryBarrier |
| ( |
| 0u, |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| VK_IMAGE_LAYOUT_UNDEFINED, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| imageResidency, |
| fullImageSubresourceRange |
| ); |
| |
| deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 3u, imageShaderAccessBarriers); |
| } |
| |
| imageSparseViews.resize(imageSparseInfo.mipLevels); |
| imageTexelsViews.resize(imageSparseInfo.mipLevels); |
| imageResidencyViews.resize(imageSparseInfo.mipLevels); |
| m_framebuffers.resize(imageSparseInfo.mipLevels); |
| descriptorSets.resize(imageSparseInfo.mipLevels); |
| |
| std::vector<VkClearValue> clearValues; |
| clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))); |
| clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f))); |
| |
| for (deUint32 mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx) |
| { |
| const VkExtent3D mipLevelSize = mipLevelExtents(imageSparseInfo.extent, mipLevelNdx); |
| const VkRect2D renderArea = makeRect2D(mipLevelSize); |
| const VkViewport viewport = makeViewport(mipLevelSize); |
| const VkImageSubresourceRange mipLevelRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevelNdx, 1u, 0u, imageSparseInfo.arrayLayers); |
| |
| // Create color attachments image views |
| imageTexelsViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageTexels, mapImageViewType(m_imageType), imageSparseInfo.format, mipLevelRange)); |
| imageResidencyViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageResidency, mapImageViewType(m_imageType), mapTextureFormat(m_residencyFormat), mipLevelRange)); |
| |
| const VkImageView attachmentsViews[] = { **imageTexelsViews[mipLevelNdx], **imageResidencyViews[mipLevelNdx] }; |
| |
| // Create framebuffer |
| const VkFramebufferCreateInfo framebufferInfo = |
| { |
| VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags; |
| *m_renderPass, // VkRenderPass renderPass; |
| 2u, // uint32_t attachmentCount; |
| attachmentsViews, // const VkImageView* pAttachments; |
| mipLevelSize.width, // uint32_t width; |
| mipLevelSize.height, // uint32_t height; |
| imageSparseInfo.arrayLayers, // uint32_t layers; |
| }; |
| |
| m_framebuffers[mipLevelNdx] = makeVkSharedPtr(createFramebuffer(deviceInterface, getDevice(), &framebufferInfo)); |
| |
| // Create descriptor set |
| descriptorSets[mipLevelNdx] = makeVkSharedPtr(makeDescriptorSet(deviceInterface, getDevice(), *descriptorPool, *descriptorSetLayout)); |
| const VkDescriptorSet descriptorSet = **descriptorSets[mipLevelNdx]; |
| |
| // Update descriptor set |
| const VkImageSubresourceRange sparseImageSubresourceRange = sampledImageRangeToBind(imageSparseInfo, mipLevelNdx); |
| |
| imageSparseViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageSparse, mapImageViewType(m_imageType), imageSparseInfo.format, sparseImageSubresourceRange)); |
| |
| const VkDescriptorImageInfo imageSparseDescInfo = makeDescriptorImageInfo(*m_sampler, **imageSparseViews[mipLevelNdx], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); |
| |
| DescriptorSetUpdateBuilder descriptorUpdateBuilder; |
| |
| descriptorUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(BINDING_IMAGE_SPARSE), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSparseDescInfo); |
| descriptorUpdateBuilder.update(deviceInterface, getDevice()); |
| |
| beginRenderPass(deviceInterface, commandBuffer, *m_renderPass, **m_framebuffers[mipLevelNdx], renderArea, (deUint32)clearValues.size(), &clearValues[0]); |
| |
| // Bind graphics pipeline |
| deviceInterface.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); |
| |
| // Bind descriptor set |
| deviceInterface.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL); |
| |
| // Bind vertex buffer |
| { |
| const VkDeviceSize offset = 0ull; |
| deviceInterface.cmdBindVertexBuffers(commandBuffer, 0u, 1u, &m_vertexBuffer.get(), &offset); |
| } |
| |
| // Bind Viewport |
| deviceInterface.cmdSetViewport(commandBuffer, 0u, 1u, &viewport); |
| |
| // Bind Scissor Rectangle |
| deviceInterface.cmdSetScissor(commandBuffer, 0u, 1u, &renderArea); |
| |
| const PushConstants pushConstants = |
| { |
| mipLevelNdx, |
| 0u, // padding |
| static_cast<float>(mipLevelSize.width), |
| static_cast<float>(mipLevelSize.height) |
| }; |
| |
| // Update push constants |
| deviceInterface.cmdPushConstants(commandBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(PushConstants), &pushConstants); |
| |
| // Draw full screen quad |
| deviceInterface.cmdDraw(commandBuffer, 4u, 1u, 0u, 0u); |
| |
| // End render pass |
| endRenderPass(deviceInterface, commandBuffer); |
| } |
| |
| { |
| const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers); |
| |
| VkImageMemoryBarrier imageOutputTransferSrcBarriers[2]; |
| |
| imageOutputTransferSrcBarriers[0] = makeImageMemoryBarrier |
| ( |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| VK_ACCESS_TRANSFER_READ_BIT, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| imageTexels, |
| fullImageSubresourceRange |
| ); |
| |
| imageOutputTransferSrcBarriers[1] = makeImageMemoryBarrier |
| ( |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| VK_ACCESS_TRANSFER_READ_BIT, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| imageResidency, |
| fullImageSubresourceRange |
| ); |
| |
| deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputTransferSrcBarriers); |
| } |
| } |
| |
| class SparseShaderIntrinsicsInstanceSampledExplicit : public SparseShaderIntrinsicsInstanceSampledBase |
| { |
| public: |
| SparseShaderIntrinsicsInstanceSampledExplicit (Context& context, |
| const SpirVFunction function, |
| const ImageType imageType, |
| const tcu::UVec3& imageSize, |
| const VkFormat format) |
| : SparseShaderIntrinsicsInstanceSampledBase(context, function, imageType, imageSize, format) {} |
| |
| VkImageSubresourceRange sampledImageRangeToBind (const VkImageCreateInfo& imageSparseInfo, |
| const deUint32 mipLevel) const |
| { |
| DE_UNREF(mipLevel); |
| return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers); |
| } |
| }; |
| |
| TestInstance* SparseShaderIntrinsicsCaseSampledExplicit::createInstance (Context& context) const |
| { |
| return new SparseShaderIntrinsicsInstanceSampledExplicit(context, m_function, m_imageType, m_imageSize, m_format); |
| } |
| |
| class SparseShaderIntrinsicsInstanceSampledImplicit : public SparseShaderIntrinsicsInstanceSampledBase |
| { |
| public: |
| SparseShaderIntrinsicsInstanceSampledImplicit (Context& context, |
| const SpirVFunction function, |
| const ImageType imageType, |
| const tcu::UVec3& imageSize, |
| const VkFormat format) |
| : SparseShaderIntrinsicsInstanceSampledBase(context, function, imageType, imageSize, format) {} |
| |
| VkImageSubresourceRange sampledImageRangeToBind (const VkImageCreateInfo& imageSparseInfo, |
| const deUint32 mipLevel) const |
| { |
| return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, 0u, imageSparseInfo.arrayLayers); |
| } |
| }; |
| |
| TestInstance* SparseShaderIntrinsicsCaseSampledImplicit::createInstance (Context& context) const |
| { |
| return new SparseShaderIntrinsicsInstanceSampledImplicit(context, m_function, m_imageType, m_imageSize, m_format); |
| } |
| |
| } // sparse |
| } // vkt |