You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
331 lines
9.6 KiB
331 lines
9.6 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL ES 3.1 Module
|
|
* -------------------------------------------------
|
|
*
|
|
* Copyright 2016 The Android Open Source Project
|
|
*
|
|
* 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 Negative Shader Storage Tests
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "es31fNegativeShaderStorageTests.hpp"
|
|
|
|
#include "gluShaderProgram.hpp"
|
|
#include "glwDefs.hpp"
|
|
#include "glwEnums.hpp"
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gles31
|
|
{
|
|
namespace Functional
|
|
{
|
|
namespace NegativeTestShared
|
|
{
|
|
namespace
|
|
{
|
|
|
|
void verifyProgram(NegativeTestContext& ctx, glu::ProgramSources sources)
|
|
{
|
|
tcu::TestLog& log = ctx.getLog();
|
|
const glu::ShaderProgram program (ctx.getRenderContext(), sources);
|
|
bool testFailed = false;
|
|
|
|
log << program;
|
|
|
|
testFailed = program.getProgramInfo().linkOk;
|
|
|
|
if (testFailed)
|
|
{
|
|
const char* const message("Program was not expected to link.");
|
|
log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
|
|
ctx.fail(message);
|
|
}
|
|
}
|
|
|
|
const char* getShaderExtensionDeclaration (glw::GLenum glShaderType)
|
|
{
|
|
switch (glShaderType)
|
|
{
|
|
case GL_TESS_CONTROL_SHADER:
|
|
case GL_TESS_EVALUATION_SHADER: return "#extension GL_EXT_tessellation_shader : require\n";
|
|
case GL_GEOMETRY_SHADER: return "#extension GL_EXT_geometry_shader : require\n";
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
glu::ShaderType getGLUShaderType (glw::GLenum glShaderType)
|
|
{
|
|
switch (glShaderType)
|
|
{
|
|
case GL_VERTEX_SHADER: return glu::SHADERTYPE_VERTEX;
|
|
case GL_FRAGMENT_SHADER: return glu::SHADERTYPE_FRAGMENT;
|
|
case GL_TESS_CONTROL_SHADER: return glu::SHADERTYPE_TESSELLATION_CONTROL;
|
|
case GL_TESS_EVALUATION_SHADER: return glu::SHADERTYPE_TESSELLATION_EVALUATION;
|
|
case GL_GEOMETRY_SHADER: return glu::SHADERTYPE_GEOMETRY;
|
|
case GL_COMPUTE_SHADER: return glu::SHADERTYPE_COMPUTE;
|
|
default:
|
|
DE_FATAL("Unknown shader type");
|
|
return glu::SHADERTYPE_LAST;
|
|
}
|
|
}
|
|
|
|
glw::GLenum getMaxSSBlockSizeEnum (glw::GLenum glShaderType)
|
|
{
|
|
switch (glShaderType)
|
|
{
|
|
case GL_VERTEX_SHADER: return GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
|
|
case GL_FRAGMENT_SHADER: return GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
|
|
case GL_TESS_CONTROL_SHADER: return GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
|
|
case GL_TESS_EVALUATION_SHADER: return GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
|
|
case GL_GEOMETRY_SHADER: return GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
|
|
case GL_COMPUTE_SHADER: return GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
|
|
default:
|
|
DE_FATAL("Unknown shader type");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int getMaxSSBlockSize (NegativeTestContext& ctx, glw::GLenum glShaderType)
|
|
{
|
|
int maxSSBlocks = 0;
|
|
ctx.glGetIntegerv(getMaxSSBlockSizeEnum(glShaderType), &maxSSBlocks);
|
|
|
|
return maxSSBlocks;
|
|
}
|
|
|
|
std::string genBlockSource (NegativeTestContext& ctx, deInt64 numSSBlocks, glw::GLenum shaderType)
|
|
{
|
|
const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
|
|
const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
|
|
std::ostringstream source;
|
|
|
|
source << glu::getGLSLVersionDeclaration(version) << "\n"
|
|
<< ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
|
|
|
|
switch (shaderType)
|
|
{
|
|
case GL_VERTEX_SHADER:
|
|
case GL_FRAGMENT_SHADER:
|
|
break;
|
|
|
|
case GL_COMPUTE_SHADER:
|
|
source << "layout (local_size_x = 1) in;\n";
|
|
break;
|
|
|
|
case GL_GEOMETRY_SHADER:
|
|
source << "layout(points) in;\n"
|
|
<< "layout(line_strip, max_vertices = 3) out;\n";
|
|
break;
|
|
|
|
case GL_TESS_CONTROL_SHADER:
|
|
source << "layout(vertices = 10) out;\n";
|
|
break;
|
|
|
|
case GL_TESS_EVALUATION_SHADER:
|
|
source << "layout(triangles) in;\n";
|
|
break;
|
|
|
|
default:
|
|
DE_FATAL("Unknown shader type");
|
|
break;
|
|
}
|
|
|
|
source << "\n"
|
|
<< "layout(std430, binding = 0) buffer Block {\n"
|
|
<< " int value;\n"
|
|
<< "} sb_in[" << numSSBlocks << "];\n"
|
|
<< "void main(void) { sb_in[0].value = 1; }\n";
|
|
|
|
return source.str();
|
|
}
|
|
|
|
std::string genCommonSource (NegativeTestContext& ctx, glw::GLenum shaderType)
|
|
{
|
|
const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
|
|
const glu::GLSLVersion version = isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
|
|
std::ostringstream source;
|
|
|
|
source << glu::getGLSLVersionDeclaration(version) << "\n"
|
|
<< ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
|
|
|
|
switch (shaderType)
|
|
{
|
|
case GL_TESS_CONTROL_SHADER:
|
|
source << "layout(vertices = 3) out;\n"
|
|
<< "void main() {}\n";
|
|
break;
|
|
|
|
case GL_TESS_EVALUATION_SHADER:
|
|
source << "layout(triangles, equal_spacing, cw) in;\n"
|
|
<< "void main() {}\n";
|
|
break;
|
|
|
|
default:
|
|
source << "void main() {}\n";
|
|
break;
|
|
}
|
|
|
|
return source.str();
|
|
}
|
|
|
|
int genMaxSSBlocksSource (NegativeTestContext& ctx, glw::GLenum glShaderType, glu::ProgramSources& sources)
|
|
{
|
|
int maxSSBlocks = getMaxSSBlockSize(ctx, glShaderType);
|
|
const std::string shaderSrc = genBlockSource(ctx, (maxSSBlocks), glShaderType);
|
|
|
|
sources.sources[getGLUShaderType(glShaderType)].push_back(shaderSrc);
|
|
|
|
return maxSSBlocks;
|
|
}
|
|
|
|
void block_number_limits (NegativeTestContext& ctx)
|
|
{
|
|
const glw::GLenum glShaderTypes[] =
|
|
{
|
|
GL_VERTEX_SHADER,
|
|
GL_FRAGMENT_SHADER,
|
|
GL_TESS_CONTROL_SHADER,
|
|
GL_TESS_EVALUATION_SHADER,
|
|
GL_GEOMETRY_SHADER,
|
|
GL_COMPUTE_SHADER,
|
|
};
|
|
|
|
const std::string vertSource = genCommonSource(ctx, GL_VERTEX_SHADER);
|
|
const std::string fragSource = genCommonSource(ctx, GL_FRAGMENT_SHADER);
|
|
const std::string tessControlSource = genCommonSource(ctx, GL_TESS_CONTROL_SHADER);
|
|
const std::string tessEvalSource = genCommonSource(ctx, GL_TESS_EVALUATION_SHADER);
|
|
|
|
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(glShaderTypes); ndx++)
|
|
{
|
|
ctx.beginSection("maxShaderStorageBlocks: Exceed limits");
|
|
|
|
if (!ctx.isShaderSupported(static_cast<glu::ShaderType>(getGLUShaderType(glShaderTypes[ndx]))))
|
|
{
|
|
ctx.endSection();
|
|
continue;
|
|
}
|
|
|
|
int maxSSBlocks = getMaxSSBlockSize(ctx, glShaderTypes[ndx]);
|
|
std::string source = genBlockSource(ctx, maxSSBlocks+1, glShaderTypes[ndx]);
|
|
|
|
glu::ProgramSources sources;
|
|
|
|
if (maxSSBlocks == 0)
|
|
{
|
|
ctx.endSection();
|
|
continue;
|
|
}
|
|
|
|
switch (glShaderTypes[ndx])
|
|
{
|
|
case GL_VERTEX_SHADER:
|
|
sources << glu::VertexSource(source)
|
|
<< glu::FragmentSource(fragSource);
|
|
break;
|
|
|
|
case GL_FRAGMENT_SHADER:
|
|
sources << glu::VertexSource(vertSource)
|
|
<< glu::FragmentSource(source);
|
|
break;
|
|
|
|
case GL_TESS_CONTROL_SHADER:
|
|
sources << glu::VertexSource(vertSource)
|
|
<< glu::FragmentSource(fragSource)
|
|
<< glu::TessellationControlSource(source)
|
|
<< glu::TessellationEvaluationSource(tessEvalSource);
|
|
break;
|
|
|
|
case GL_TESS_EVALUATION_SHADER:
|
|
sources << glu::VertexSource(vertSource)
|
|
<< glu::FragmentSource(fragSource)
|
|
<< glu::TessellationControlSource(tessControlSource)
|
|
<< glu::TessellationEvaluationSource(source);
|
|
break;
|
|
|
|
case GL_GEOMETRY_SHADER:
|
|
sources << glu::VertexSource(vertSource)
|
|
<< glu::FragmentSource(fragSource)
|
|
<< glu::GeometrySource(source);
|
|
break;
|
|
|
|
case GL_COMPUTE_SHADER:
|
|
sources << glu::ComputeSource(source);
|
|
break;
|
|
|
|
default:
|
|
DE_FATAL("Unknown shader type");
|
|
break;
|
|
}
|
|
|
|
verifyProgram(ctx, sources);
|
|
ctx.endSection();
|
|
}
|
|
}
|
|
|
|
void max_combined_block_number_limit (NegativeTestContext& ctx)
|
|
{
|
|
ctx.beginSection("maxCombinedShaderStorageBlocks: Exceed limits");
|
|
|
|
glu::ProgramSources sources;
|
|
|
|
int combinedSSBlocks = 0;
|
|
int maxCombinedSSBlocks = 0;
|
|
|
|
combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_VERTEX_SHADER, sources);
|
|
combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_FRAGMENT_SHADER, sources);
|
|
|
|
if ((ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_CONTROL)) && (ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_EVALUATION)))
|
|
{
|
|
combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_CONTROL_SHADER, sources);
|
|
combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_EVALUATION_SHADER, sources);
|
|
}
|
|
|
|
if (ctx.isShaderSupported(glu::SHADERTYPE_GEOMETRY))
|
|
combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_GEOMETRY_SHADER, sources);
|
|
|
|
ctx.glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedSSBlocks);
|
|
|
|
ctx.getLog() << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << maxCombinedSSBlocks << tcu::TestLog::EndMessage;
|
|
ctx.getLog() << tcu::TestLog::Message << "Combined shader storage blocks: " << combinedSSBlocks << tcu::TestLog::EndMessage;
|
|
|
|
if (combinedSSBlocks > maxCombinedSSBlocks)
|
|
verifyProgram(ctx, sources);
|
|
else
|
|
ctx.getLog() << tcu::TestLog::Message << "Test skipped: Combined shader storage blocks < GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << tcu::TestLog::EndMessage;
|
|
|
|
ctx.endSection();
|
|
}
|
|
|
|
} // anonymous
|
|
|
|
std::vector<FunctionContainer> getNegativeShaderStorageTestFunctions ()
|
|
{
|
|
const FunctionContainer funcs[] =
|
|
{
|
|
{ block_number_limits, "block_number_limits", "Invalid shader linkage" },
|
|
{ max_combined_block_number_limit, "max_combined_block_number_limit", "Invalid shader linkage" },
|
|
};
|
|
|
|
return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
|
|
}
|
|
|
|
} // NegativeTestShared
|
|
} // Functional
|
|
} // gles31
|
|
} // deqp
|