Write gl_PointSize value when it is undefined
authorIago Toral Quiroga <itoral@igalia.com>
Fri, 10 Feb 2017 10:35:52 +0000 (11:35 +0100)
committerIago Toral Quiroga <itoral@igalia.com>
Mon, 13 Feb 2017 10:13:28 +0000 (11:13 +0100)
gl_PointSize is undefined unless expicitly written to. The only
exception to this rule is the case when
shaderTessellationAndGeometryPointSize is disabled, in which case it
defaults to 1.0 for these stages.

Since we don't have access to the physical device features at shader
compile time, implement two variants of the tessellation evaluation
shader when point mode is enabled, one that writes gl_PointSize and
one that doesn't and decide the one we need at run time based on
whether the feature is enabled or not.

Components: Vulkan
Fixes VK-GL-CTS issue: 159

Affects:
dEQP-VK.tessellation.primitive_discard.*point_mode

Change-Id: Idadbc70a704f00ed601ff65afeb2a3edfbeb3f19

external/vulkancts/modules/vulkan/tessellation/vktTessellationPrimitiveDiscardTests.cpp

index a0992b4..bd77bbf 100644 (file)
@@ -301,31 +301,50 @@ void initPrograms (vk::SourceCollections& programCollection, const CaseDefinitio
        }
 
        // Tessellation evaluation shader
+       // When using point mode we need two variants of the shader, one for the case where
+       // shaderTessellationAndGeometryPointSize is enabled (in which the tessellation evaluation
+       // shader needs to write to gl_PointSize for it to be defined) and one for the case where
+       // it is disabled, in which we can't write to gl_PointSize but it has a default value
+       // of 1.0
        {
-               std::ostringstream src;
-               src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
-                       << "#extension GL_EXT_tessellation_shader : require\n"
-                       << "\n"
-                       << "layout(" << getTessPrimitiveTypeShaderName(caseDef.primitiveType) << ", "
-                                                << getSpacingModeShaderName(caseDef.spacingMode) << ", "
-                                                << getWindingShaderName(caseDef.winding)
-                                                << (caseDef.usePointMode ? ", point_mode" : "") << ") in;\n"
-                       << "\n"
-                       << "layout(location = 0) patch in highp vec2 in_te_positionScale;\n"
-                       << "layout(location = 1) patch in highp vec2 in_te_positionOffset;\n"
-                       << "\n"
-                       << "layout(set = 0, binding = 0, std430) coherent restrict buffer Output {\n"
-                       << "    int  numInvocations;\n"
-                       << "} sb_out;\n"
-                       << "\n"
-                       << "void main (void)\n"
-                       << "{\n"
-                       << "    atomicAdd(sb_out.numInvocations, 1);\n"
-                       << "\n"
-                       << "    gl_Position = vec4(gl_TessCoord.xy*in_te_positionScale + in_te_positionOffset, 0.0, 1.0);\n"
-                       << "}\n";
+               const deUint32  numVariants                     = caseDef.usePointMode ? 2 : 1;
+               for (deUint32 variant = 0; variant < numVariants; variant++)
+               {
+                       const bool      needPointSizeWrite      = caseDef.usePointMode && variant == 1;
 
-               programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
+                       std::ostringstream src;
+                       src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
+                               << "#extension GL_EXT_tessellation_shader : require\n";
+                       if (needPointSizeWrite)
+                       {
+                               src << "#extension GL_EXT_tessellation_point_size : require\n";
+                       }
+                       src << "\n"
+                               << "layout(" << getTessPrimitiveTypeShaderName(caseDef.primitiveType) << ", "
+                                                        << getSpacingModeShaderName(caseDef.spacingMode) << ", "
+                                                        << getWindingShaderName(caseDef.winding)
+                                                        << (caseDef.usePointMode ? ", point_mode" : "") << ") in;\n"
+                               << "\n"
+                               << "layout(location = 0) patch in highp vec2 in_te_positionScale;\n"
+                               << "layout(location = 1) patch in highp vec2 in_te_positionOffset;\n"
+                               << "\n"
+                               << "layout(set = 0, binding = 0, std430) coherent restrict buffer Output {\n"
+                               << "    int  numInvocations;\n"
+                               << "} sb_out;\n"
+                               << "\n"
+                               << "void main (void)\n"
+                               << "{\n"
+                               << "    atomicAdd(sb_out.numInvocations, 1);\n"
+                               << "\n"
+                               << "    gl_Position = vec4(gl_TessCoord.xy*in_te_positionScale + in_te_positionOffset, 0.0, 1.0);\n";
+                       if (needPointSizeWrite)
+                       {
+                               src << "    gl_PointSize = 1.0;\n";
+                       }
+                       src << "}\n";
+
+                       programCollection.glslSources.add(needPointSizeWrite ? "tese_psw" : "tese") << glu::TessellationEvaluationSource(src.str());
+               }
        }
 
        // Fragment shader
@@ -449,6 +468,7 @@ tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
        const Unique<VkPipelineLayout> pipelineLayout     (makePipelineLayout(vk, device, *descriptorSetLayout));
        const Unique<VkCommandPool>        cmdPool                        (makeCommandPool       (vk, device, queueFamilyIndex));
        const Unique<VkCommandBuffer>  cmdBuffer                  (makeCommandBuffer (vk, device, *cmdPool));
+       const bool                                         needPointSizeWrite = getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice()).shaderTessellationAndGeometryPointSize && caseDef.usePointMode;
 
        const Unique<VkPipeline> pipeline(GraphicsPipelineBuilder()
                .setRenderSize                            (renderSize)
@@ -456,7 +476,7 @@ tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
                .setVertexInputSingleAttribute(vertexFormat, vertexStride)
                .setShader                                        (vk, device, VK_SHADER_STAGE_VERTEX_BIT,                                      context.getBinaryCollection().get("vert"), DE_NULL)
                .setShader                                        (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,        context.getBinaryCollection().get("tesc"), DE_NULL)
-               .setShader                                        (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, context.getBinaryCollection().get("tese"), DE_NULL)
+               .setShader                                        (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, context.getBinaryCollection().get(needPointSizeWrite ? "tese_psw" : "tese"), DE_NULL)
                .setShader                                        (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,                            context.getBinaryCollection().get("frag"), DE_NULL)
                .build                                            (vk, device, *pipelineLayout, *renderPass));