blob: 775eb1fd51487ffb61e739c69cc6aebc0a26087c [file] [log] [blame] [edit]
//
// Copyright 2025 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "tests/test_utils/CompilerTest.h"
GLuint CompiledShader::compile(GLenum type, const char *source)
{
mShader = glCreateShader(type);
const char *sourceArray[1] = {source};
glShaderSource(mShader, 1, sourceArray, nullptr);
glCompileShader(mShader);
GLint compileResult;
glGetShaderiv(mShader, GL_COMPILE_STATUS, &compileResult);
GLint infoLogLength;
glGetShaderiv(mShader, GL_INFO_LOG_LENGTH, &infoLogLength);
mInfoLog.clear();
if (infoLogLength > 0)
{
std::vector<GLchar> infoLog(infoLogLength);
glGetShaderInfoLog(mShader, infoLogLength, nullptr, infoLog.data());
// Note: the info log is nul-terminated.
mInfoLog = infoLog.data();
}
if (compileResult == 0)
{
std::cerr << "shader compilation failed: "
<< (mInfoLog.empty() ? "<Empty message log>" : mInfoLog.data());
destroy();
}
else if (IsGLExtensionEnabled("GL_ANGLE_translated_shader_source"))
{
GLint translatedSourceLength;
glGetShaderiv(mShader, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, &translatedSourceLength);
if (translatedSourceLength > 0)
{
std::vector<GLchar> translatedSource(translatedSourceLength);
glGetTranslatedShaderSourceANGLE(mShader, translatedSourceLength, nullptr,
translatedSource.data());
// Note: the translatedSource is nul-terminated.
mTranslatedSource = translatedSource.data();
}
}
return mShader;
}
CompiledShader::~CompiledShader()
{
if (mShader != 0)
{
destroy();
}
}
void CompiledShader::destroy()
{
glDeleteShader(mShader);
ASSERT_GL_NO_ERROR();
mShader = 0;
mTranslatedSource.clear();
}
bool CompiledShader::hasInfoLog(const char *expect) const
{
return mInfoLog.find(expect) != std::string::npos;
}
bool CompiledShader::verifyInTranslatedSource(const char *expect) const
{
return mTranslatedSource.empty() || mTranslatedSource.find(expect) != std::string::npos;
}
bool CompiledShader::verifyNotInTranslatedSource(const char *expect) const
{
return mTranslatedSource.empty() || mTranslatedSource.find(expect) == std::string::npos;
}
bool CompiledShader::verifyCountInTranslatedSource(const char *expect, size_t expectCount) const
{
if (mTranslatedSource.empty())
{
return true;
}
size_t count = 0;
std::string::size_type pos = 0;
while (true)
{
pos = mTranslatedSource.find(expect, pos);
if (pos == std::string::npos)
{
break;
}
++count;
++pos;
}
return count == expectCount;
}
void CompilerTest::testSetUp() {}
void CompilerTest::testTearDown()
{
reset();
}
void CompilerTest::reset()
{
mVertexShader.destroy();
mTessellationControlShader.destroy();
mTessellationEvaluationShader.destroy();
mGeometryShader.destroy();
mFragmentShader.destroy();
mComputeShader.destroy();
glDeleteProgram(mProgram);
mProgram = 0;
}
const CompiledShader &CompilerTest::compile(GLenum type, const char *source)
{
CompiledShader &shader = getCompiledShader(type);
shader.compile(type, source);
return shader;
}
CompiledShader &CompilerTest::getCompiledShader(GLenum type)
{
switch (type)
{
case GL_VERTEX_SHADER:
return mVertexShader;
case GL_TESS_CONTROL_SHADER:
return mTessellationControlShader;
case GL_TESS_EVALUATION_SHADER:
return mTessellationEvaluationShader;
case GL_GEOMETRY_SHADER:
return mGeometryShader;
case GL_FRAGMENT_SHADER:
return mFragmentShader;
case GL_COMPUTE_SHADER:
return mComputeShader;
default:
// Unsupported type
ASSERT(false);
return mVertexShader;
}
}
GLuint CompilerTest::link()
{
mProgram = glCreateProgram();
if (mComputeShader.success())
{
glAttachShader(mProgram, mComputeShader.getShader());
}
else
{
if (mVertexShader.success())
{
glAttachShader(mProgram, mVertexShader.getShader());
}
if (mTessellationControlShader.success())
{
glAttachShader(mProgram, mTessellationControlShader.getShader());
}
if (mTessellationEvaluationShader.success())
{
glAttachShader(mProgram, mTessellationEvaluationShader.getShader());
}
if (mGeometryShader.success())
{
glAttachShader(mProgram, mGeometryShader.getShader());
}
if (mFragmentShader.success())
{
glAttachShader(mProgram, mFragmentShader.getShader());
}
}
glLinkProgram(mProgram);
EXPECT_GL_NO_ERROR();
GLint linkStatus;
glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
EXPECT_NE(linkStatus, 0);
return mProgram;
}