blob: ddb7791e2a1643e48045b4e6157da64f2f4546cf [file] [log] [blame]
/*-------------------------------------------------------------------------
* OpenGL Conformance Test Suite
* -----------------------------
*
* Copyright (c) 2016-2017 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
* \brief
*/ /*-------------------------------------------------------------------*/
/**
*/ /*!
* \file glcParallelShaderCompileTests.cpp
* \brief Conformance tests for the GL_KHR_parallel_shader_compile functionality.
*/ /*-------------------------------------------------------------------*/
#include "glcParallelShaderCompileTests.hpp"
#include "deClock.h"
#include "gluContextInfo.hpp"
#include "gluDefs.hpp"
#include "gluShaderProgram.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuTestLog.hpp"
using namespace glu;
using namespace glw;
namespace glcts
{
static const char* shaderVersionES = "#version 300 es\n";
static const char* shaderVersionGL = "#version 450\n";
static const char* vShader = "\n"
"in vec3 vertex;\n"
"\n"
"void main() {\n"
" gl_Position = vec4(vertex, 1);\n"
"}\n";
static const char* fShader = "\n"
"out vec4 fragColor;\n"
"\n"
"void main() {\n"
" fragColor = vec4(1, 1, 1, 1);\n"
"}\n";
/** Constructor.
*
* @param context Rendering context
* @param name Test name
* @param description Test description
*/
SimpleQueriesTest::SimpleQueriesTest(deqp::Context& context)
: TestCase(context, "simple_queries",
"Tests verifies if simple queries works as expected for MAX_SHADER_COMPILER_THREADS_KHR <pname>")
{
/* Left blank intentionally */
}
/** Executes test iteration.
*
* @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
*/
tcu::TestNode::IterateResult SimpleQueriesTest::iterate()
{
const glu::ContextInfo& contextInfo = m_context.getContextInfo();
const glu::ContextType& contextType = m_context.getRenderContext().getType();
const bool isGL = glu::isContextTypeGLCore(contextType);
const bool supportParallel = (isGL && contextInfo.isExtensionSupported("GL_ARB_parallel_shader_compile")) ||
contextInfo.isExtensionSupported("GL_KHR_parallel_shader_compile");
if (!supportParallel)
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
return STOP;
}
const Functions& gl = m_context.getRenderContext().getFunctions();
GLboolean boolValue;
GLint intValue;
GLint64 int64Value;
GLfloat floatValue;
GLdouble doubleValue;
bool supportsInt64 = isGL || glu::contextSupports(contextType, glu::ApiType::es(3, 0));
bool supportsDouble = isGL;
gl.getBooleanv(GL_MAX_SHADER_COMPILER_THREADS_KHR, &boolValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv");
gl.getIntegerv(GL_MAX_SHADER_COMPILER_THREADS_KHR, &intValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
if (supportsInt64)
{
gl.getInteger64v(GL_MAX_SHADER_COMPILER_THREADS_KHR, &int64Value);
GLU_EXPECT_NO_ERROR(gl.getError(), "getInteger64v");
}
gl.getFloatv(GL_MAX_SHADER_COMPILER_THREADS_KHR, &floatValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv");
if (supportsDouble)
{
gl.getDoublev(GL_MAX_SHADER_COMPILER_THREADS_KHR, &doubleValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getDoublev");
}
if (boolValue != (intValue != 0) || intValue != (GLint)floatValue ||
(supportsInt64 && intValue != (GLint)int64Value) || (supportsDouble && intValue != (GLint)doubleValue))
{
tcu::MessageBuilder message = m_testCtx.getLog() << tcu::TestLog::Message;
message << "Simple queries returned different values: "
<< "bool(" << (int)boolValue << "), "
<< "int(" << intValue << "), ";
if (supportsInt64)
message << "int64(" << int64Value << "), ";
message << "float(" << floatValue << ")";
if (supportsDouble)
message << ", double(" << doubleValue << ")";
message << tcu::TestLog::EndMessage;
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
return STOP;
}
/** Constructor.
*
* @param context Rendering context
* @param name Test name
* @param description Test description
*/
MaxShaderCompileThreadsTest::MaxShaderCompileThreadsTest(deqp::Context& context)
: TestCase(context, "max_shader_compile_threads",
"Tests verifies if MaxShaderCompileThreadsKHR function works as expected")
{
/* Left blank intentionally */
}
/** Executes test iteration.
*
* @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
*/
tcu::TestNode::IterateResult MaxShaderCompileThreadsTest::iterate()
{
const glu::ContextInfo& contextInfo = m_context.getContextInfo();
const glu::ContextType& contextType = m_context.getRenderContext().getType();
const bool isGL = glu::isContextTypeGLCore(contextType);
const bool supportParallel = (isGL && contextInfo.isExtensionSupported("GL_ARB_parallel_shader_compile")) ||
contextInfo.isExtensionSupported("GL_KHR_parallel_shader_compile");
if (!supportParallel)
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
return STOP;
}
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
GLint intValue;
gl.maxShaderCompilerThreadsKHR(0);
GLU_EXPECT_NO_ERROR(gl.getError(), "maxShaderCompilerThreadsKHR");
gl.getIntegerv(GL_MAX_SHADER_COMPILER_THREADS_KHR, &intValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
if (intValue != 0)
{
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Failed to disable parallel shader compilation.");
return STOP;
}
gl.maxShaderCompilerThreadsKHR(0xFFFFFFFF);
GLU_EXPECT_NO_ERROR(gl.getError(), "maxShaderCompilerThreadsKHR");
gl.getIntegerv(GL_MAX_SHADER_COMPILER_THREADS_KHR, &intValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
if (intValue != GLint(0xFFFFFFFF))
{
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Failed to set maximum shader compiler threads.");
return STOP;
}
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
return STOP;
}
/** Constructor.
*
* @param context Rendering context
* @param name Test name
* @param description Test description
*/
CompilationCompletionParallelTest::CompilationCompletionParallelTest(deqp::Context& context)
: TestCase(context, "compilation_completion_parallel",
"Tests verifies if shader COMPLETION_STATUS query works as expected for parallel compilation")
{
/* Left blank intentionally */
}
/** Executes test iteration.
*
* @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
*/
tcu::TestNode::IterateResult CompilationCompletionParallelTest::iterate()
{
const glu::ContextInfo& contextInfo = m_context.getContextInfo();
const glu::ContextType& contextType = m_context.getRenderContext().getType();
const bool isGL = glu::isContextTypeGLCore(contextType);
const bool supportParallel = (isGL && contextInfo.isExtensionSupported("GL_ARB_parallel_shader_compile")) ||
contextInfo.isExtensionSupported("GL_KHR_parallel_shader_compile");
if (!supportParallel)
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
return STOP;
}
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
GLint completionStatus;
gl.maxShaderCompilerThreadsKHR(8);
GLU_EXPECT_NO_ERROR(gl.getError(), "maxShaderCompilerThreadsKHR");
{
Shader vertexShader(gl, SHADERTYPE_VERTEX);
deUint32 fragmentShader[8];
deUint32 program[8];
bool isContextES = (glu::isContextTypeES(m_context.getRenderContext().getType()));
const char* shaderVersion = isContextES ? shaderVersionES : shaderVersionGL;
for (int i = 0; i < 8; ++i)
{
fragmentShader[i] = gl.createShader(GL_FRAGMENT_SHADER);
program[i] = gl.createProgram();
}
const char* vSources[] = { shaderVersion, vShader };
const int vLengths[] = { int(strlen(shaderVersion)), int(strlen(vShader)) };
vertexShader.setSources(2, vSources, vLengths);
//Compilation test
for (int i = 0; i < 8; ++i)
{
const char* fSources[] = { shaderVersion, fShader };
const int fLengths[] = { int(strlen(shaderVersion)), int(strlen(fShader)) };
gl.shaderSource(fragmentShader[i], 2, fSources, fLengths);
}
gl.compileShader(vertexShader.getShader());
GLU_EXPECT_NO_ERROR(gl.getError(), "compileShader");
for (int i = 0; i < 8; ++i)
{
gl.compileShader(fragmentShader[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "compileShader");
}
{
int completion = 0;
deUint64 shLoopStart = deGetMicroseconds();
while (completion != 8 && deGetMicroseconds() < shLoopStart + 1000000)
{
completion = 0;
for (int i = 0; i < 8; ++i)
{
gl.getShaderiv(fragmentShader[i], GL_COMPLETION_STATUS_KHR, &completionStatus);
GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv");
if (completionStatus)
completion++;
}
}
if (completion != 8)
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL,
"Failed reading completion status for parallel shader compiling");
for (int i = 0; i < 8; ++i)
{
gl.deleteProgram(program[i]);
gl.deleteShader(fragmentShader[i]);
}
return STOP;
}
}
for (int i = 0; i < 8; ++i)
{
gl.attachShader(program[i], vertexShader.getShader());
GLU_EXPECT_NO_ERROR(gl.getError(), "attachShader");
gl.attachShader(program[i], fragmentShader[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "attachShader");
}
//Linking test
for (int i = 0; i < 8; ++i)
{
gl.linkProgram(program[i]);
GLU_EXPECT_NO_ERROR(gl.getError(), "linkProgram");
}
{
int completion = 0;
deUint64 prLoopStart = deGetMicroseconds();
while (completion != 8 && deGetMicroseconds() < prLoopStart + 1000000)
{
completion = 0;
for (int i = 0; i < 8; ++i)
{
gl.getProgramiv(program[i], GL_COMPLETION_STATUS_KHR, &completionStatus);
GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
if (completionStatus)
completion++;
}
}
if (completion != 8)
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL,
"Failed reading completion status for parallel program linking");
for (int i = 0; i < 8; ++i)
{
gl.deleteProgram(program[i]);
gl.deleteShader(fragmentShader[i]);
}
return STOP;
}
}
}
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
return STOP;
}
/** Constructor.
*
* @param context Rendering context.
*/
ParallelShaderCompileTests::ParallelShaderCompileTests(deqp::Context& context)
: TestCaseGroup(context, "parallel_shader_compile",
"Verify conformance of KHR_parallel_shader_compile implementation")
{
}
/** Initializes the test group contents. */
void ParallelShaderCompileTests::init()
{
addChild(new SimpleQueriesTest(m_context));
addChild(new MaxShaderCompileThreadsTest(m_context));
addChild(new CompilationCompletionParallelTest(m_context));
}
} /* glcts namespace */