884 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			884 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
//
 | 
						|
// Copyright 2014 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 "util/shader_utils.h"
 | 
						|
 | 
						|
#include <cstring>
 | 
						|
#include <fstream>
 | 
						|
#include <iostream>
 | 
						|
#include <vector>
 | 
						|
 | 
						|
#include "common/utilities.h"
 | 
						|
#include "util/test_utils.h"
 | 
						|
 | 
						|
namespace
 | 
						|
{
 | 
						|
bool ReadEntireFile(const std::string &filePath, std::string *contentsOut)
 | 
						|
{
 | 
						|
    constexpr uint32_t kMaxBufferSize = 2000;
 | 
						|
    char buffer[kMaxBufferSize]       = {};
 | 
						|
    if (!angle::ReadEntireFileToString(filePath.c_str(), buffer, kMaxBufferSize) ||
 | 
						|
        strlen(buffer) == 0)
 | 
						|
        return false;
 | 
						|
    *contentsOut = buffer;
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
GLuint CompileProgramInternal(const char *vsSource,
 | 
						|
                              const char *tcsSource,
 | 
						|
                              const char *tesSource,
 | 
						|
                              const char *gsSource,
 | 
						|
                              const char *fsSource,
 | 
						|
                              const std::function<void(GLuint)> &preLinkCallback)
 | 
						|
{
 | 
						|
    GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
 | 
						|
    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
 | 
						|
 | 
						|
    if (vs == 0 || fs == 0)
 | 
						|
    {
 | 
						|
        glDeleteShader(fs);
 | 
						|
        glDeleteShader(vs);
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    GLuint program = glCreateProgram();
 | 
						|
 | 
						|
    glAttachShader(program, vs);
 | 
						|
    glDeleteShader(vs);
 | 
						|
 | 
						|
    glAttachShader(program, fs);
 | 
						|
    glDeleteShader(fs);
 | 
						|
 | 
						|
    GLuint tcs = 0;
 | 
						|
    GLuint tes = 0;
 | 
						|
    GLuint gs  = 0;
 | 
						|
 | 
						|
    if (strlen(tcsSource) > 0)
 | 
						|
    {
 | 
						|
        tcs = CompileShader(GL_TESS_CONTROL_SHADER_EXT, tcsSource);
 | 
						|
        if (tcs == 0)
 | 
						|
        {
 | 
						|
            glDeleteShader(vs);
 | 
						|
            glDeleteShader(fs);
 | 
						|
            glDeleteProgram(program);
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
 | 
						|
        glAttachShader(program, tcs);
 | 
						|
        glDeleteShader(tcs);
 | 
						|
    }
 | 
						|
 | 
						|
    if (strlen(tesSource) > 0)
 | 
						|
    {
 | 
						|
        tes = CompileShader(GL_TESS_EVALUATION_SHADER_EXT, tesSource);
 | 
						|
        if (tes == 0)
 | 
						|
        {
 | 
						|
            glDeleteShader(vs);
 | 
						|
            glDeleteShader(fs);
 | 
						|
            glDeleteShader(tcs);
 | 
						|
            glDeleteProgram(program);
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
 | 
						|
        glAttachShader(program, tes);
 | 
						|
        glDeleteShader(tes);
 | 
						|
    }
 | 
						|
 | 
						|
    if (strlen(gsSource) > 0)
 | 
						|
    {
 | 
						|
        gs = CompileShader(GL_GEOMETRY_SHADER_EXT, gsSource);
 | 
						|
        if (gs == 0)
 | 
						|
        {
 | 
						|
            glDeleteShader(vs);
 | 
						|
            glDeleteShader(fs);
 | 
						|
            glDeleteShader(tcs);
 | 
						|
            glDeleteShader(tes);
 | 
						|
            glDeleteProgram(program);
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
 | 
						|
        glAttachShader(program, gs);
 | 
						|
        glDeleteShader(gs);
 | 
						|
    }
 | 
						|
 | 
						|
    if (preLinkCallback)
 | 
						|
    {
 | 
						|
        preLinkCallback(program);
 | 
						|
    }
 | 
						|
 | 
						|
    glLinkProgram(program);
 | 
						|
 | 
						|
    return CheckLinkStatusAndReturnProgram(program, true);
 | 
						|
}
 | 
						|
 | 
						|
const void *gCallbackChainUserParam;
 | 
						|
 | 
						|
void KHRONOS_APIENTRY DebugMessageCallback(GLenum source,
 | 
						|
                                           GLenum type,
 | 
						|
                                           GLuint id,
 | 
						|
                                           GLenum severity,
 | 
						|
                                           GLsizei length,
 | 
						|
                                           const GLchar *message,
 | 
						|
                                           const void *userParam)
 | 
						|
{
 | 
						|
    std::string sourceText   = gl::GetDebugMessageSourceString(source);
 | 
						|
    std::string typeText     = gl::GetDebugMessageTypeString(type);
 | 
						|
    std::string severityText = gl::GetDebugMessageSeverityString(severity);
 | 
						|
    std::cerr << sourceText << ", " << typeText << ", " << severityText << ": " << message << "\n";
 | 
						|
 | 
						|
    GLDEBUGPROC callbackChain = reinterpret_cast<GLDEBUGPROC>(const_cast<void *>(userParam));
 | 
						|
    if (callbackChain)
 | 
						|
    {
 | 
						|
        callbackChain(source, type, id, severity, length, message, gCallbackChainUserParam);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void GetPerfCounterValue(const CounterNameToIndexMap &counterIndexMap,
 | 
						|
                         std::vector<angle::PerfMonitorTriplet> &triplets,
 | 
						|
                         const char *name,
 | 
						|
                         GLuint *counterOut)
 | 
						|
{
 | 
						|
    auto iter = counterIndexMap.find(name);
 | 
						|
    ASSERT(iter != counterIndexMap.end());
 | 
						|
    GLuint counterIndex = iter->second;
 | 
						|
 | 
						|
    for (const angle::PerfMonitorTriplet &triplet : triplets)
 | 
						|
    {
 | 
						|
        ASSERT(triplet.group == 0);
 | 
						|
        if (triplet.counter == counterIndex)
 | 
						|
        {
 | 
						|
            *counterOut = triplet.value;
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    UNREACHABLE();
 | 
						|
}
 | 
						|
}  // namespace
 | 
						|
 | 
						|
GLuint CompileShader(GLenum type, const char *source)
 | 
						|
{
 | 
						|
    GLuint shader = glCreateShader(type);
 | 
						|
 | 
						|
    const char *sourceArray[1] = {source};
 | 
						|
    glShaderSource(shader, 1, sourceArray, nullptr);
 | 
						|
    glCompileShader(shader);
 | 
						|
 | 
						|
    GLint compileResult;
 | 
						|
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
 | 
						|
 | 
						|
    if (compileResult == 0)
 | 
						|
    {
 | 
						|
        GLint infoLogLength;
 | 
						|
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
 | 
						|
 | 
						|
        // Info log length includes the null terminator, so 1 means that the info log is an empty
 | 
						|
        // string.
 | 
						|
        if (infoLogLength > 1)
 | 
						|
        {
 | 
						|
            std::vector<GLchar> infoLog(infoLogLength);
 | 
						|
            glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr, &infoLog[0]);
 | 
						|
            std::cerr << "shader compilation failed: " << &infoLog[0];
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            std::cerr << "shader compilation failed. <Empty log message>";
 | 
						|
        }
 | 
						|
 | 
						|
        std::cerr << std::endl;
 | 
						|
 | 
						|
        glDeleteShader(shader);
 | 
						|
        shader = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return shader;
 | 
						|
}
 | 
						|
 | 
						|
GLuint CompileShaderFromFile(GLenum type, const std::string &sourcePath)
 | 
						|
{
 | 
						|
    std::string source;
 | 
						|
    if (!ReadEntireFile(sourcePath, &source))
 | 
						|
    {
 | 
						|
        std::cerr << "Error reading shader file: " << sourcePath << "\n";
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return CompileShader(type, source.c_str());
 | 
						|
}
 | 
						|
 | 
						|
GLuint CheckLinkStatusAndReturnProgram(GLuint program, bool outputErrorMessages)
 | 
						|
{
 | 
						|
    if (glGetError() != GL_NO_ERROR)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    GLint linkStatus;
 | 
						|
    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
 | 
						|
    if (linkStatus == 0)
 | 
						|
    {
 | 
						|
        if (outputErrorMessages)
 | 
						|
        {
 | 
						|
            GLint infoLogLength;
 | 
						|
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
 | 
						|
 | 
						|
            // Info log length includes the null terminator, so 1 means that the info log is an
 | 
						|
            // empty string.
 | 
						|
            if (infoLogLength > 1)
 | 
						|
            {
 | 
						|
                std::vector<GLchar> infoLog(infoLogLength);
 | 
						|
                glGetProgramInfoLog(program, static_cast<GLsizei>(infoLog.size()), nullptr,
 | 
						|
                                    &infoLog[0]);
 | 
						|
 | 
						|
                std::cerr << "program link failed: " << &infoLog[0];
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                std::cerr << "program link failed. <Empty log message>";
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        glDeleteProgram(program);
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return program;
 | 
						|
}
 | 
						|
 | 
						|
GLuint GetProgramShader(GLuint program, GLint requestedType)
 | 
						|
{
 | 
						|
    static constexpr GLsizei kMaxShaderCount = 16;
 | 
						|
    GLuint attachedShaders[kMaxShaderCount]  = {0u};
 | 
						|
    GLsizei count                            = 0;
 | 
						|
    glGetAttachedShaders(program, kMaxShaderCount, &count, attachedShaders);
 | 
						|
    for (int i = 0; i < count; ++i)
 | 
						|
    {
 | 
						|
        GLint type = 0;
 | 
						|
        glGetShaderiv(attachedShaders[i], GL_SHADER_TYPE, &type);
 | 
						|
        if (type == requestedType)
 | 
						|
        {
 | 
						|
            return attachedShaders[i];
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
GLuint CompileProgramWithTransformFeedback(
 | 
						|
    const char *vsSource,
 | 
						|
    const char *fsSource,
 | 
						|
    const std::vector<std::string> &transformFeedbackVaryings,
 | 
						|
    GLenum bufferMode)
 | 
						|
{
 | 
						|
    auto preLink = [&](GLuint program) {
 | 
						|
        if (transformFeedbackVaryings.size() > 0)
 | 
						|
        {
 | 
						|
            std::vector<const char *> constCharTFVaryings;
 | 
						|
 | 
						|
            for (const std::string &transformFeedbackVarying : transformFeedbackVaryings)
 | 
						|
            {
 | 
						|
                constCharTFVaryings.push_back(transformFeedbackVarying.c_str());
 | 
						|
            }
 | 
						|
 | 
						|
            glTransformFeedbackVaryings(program,
 | 
						|
                                        static_cast<GLsizei>(transformFeedbackVaryings.size()),
 | 
						|
                                        &constCharTFVaryings[0], bufferMode);
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    return CompileProgramInternal(vsSource, "", "", "", fsSource, preLink);
 | 
						|
}
 | 
						|
 | 
						|
GLuint CompileProgram(const char *vsSource, const char *fsSource)
 | 
						|
{
 | 
						|
    return CompileProgramInternal(vsSource, "", "", "", fsSource, nullptr);
 | 
						|
}
 | 
						|
 | 
						|
GLuint CompileProgram(const char *vsSource,
 | 
						|
                      const char *fsSource,
 | 
						|
                      const std::function<void(GLuint)> &preLinkCallback)
 | 
						|
{
 | 
						|
    return CompileProgramInternal(vsSource, "", "", "", fsSource, preLinkCallback);
 | 
						|
}
 | 
						|
 | 
						|
GLuint CompileProgramWithGS(const char *vsSource, const char *gsSource, const char *fsSource)
 | 
						|
{
 | 
						|
    return CompileProgramInternal(vsSource, "", "", gsSource, fsSource, nullptr);
 | 
						|
}
 | 
						|
 | 
						|
GLuint CompileProgramWithTESS(const char *vsSource,
 | 
						|
                              const char *tcsSource,
 | 
						|
                              const char *tesSource,
 | 
						|
                              const char *fsSource)
 | 
						|
{
 | 
						|
    return CompileProgramInternal(vsSource, tcsSource, tesSource, "", fsSource, nullptr);
 | 
						|
}
 | 
						|
 | 
						|
GLuint CompileProgramFromFiles(const std::string &vsPath, const std::string &fsPath)
 | 
						|
{
 | 
						|
    std::string vsSource;
 | 
						|
    if (!ReadEntireFile(vsPath, &vsSource))
 | 
						|
    {
 | 
						|
        std::cerr << "Error reading shader: " << vsPath << "\n";
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    std::string fsSource;
 | 
						|
    if (!ReadEntireFile(fsPath, &fsSource))
 | 
						|
    {
 | 
						|
        std::cerr << "Error reading shader: " << fsPath << "\n";
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return CompileProgram(vsSource.c_str(), fsSource.c_str());
 | 
						|
}
 | 
						|
 | 
						|
GLuint CompileComputeProgram(const char *csSource, bool outputErrorMessages)
 | 
						|
{
 | 
						|
    GLuint program = glCreateProgram();
 | 
						|
 | 
						|
    GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
 | 
						|
    if (cs == 0)
 | 
						|
    {
 | 
						|
        glDeleteProgram(program);
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    glAttachShader(program, cs);
 | 
						|
 | 
						|
    glLinkProgram(program);
 | 
						|
 | 
						|
    return CheckLinkStatusAndReturnProgram(program, outputErrorMessages);
 | 
						|
}
 | 
						|
 | 
						|
GLuint LoadBinaryProgramOES(const std::vector<uint8_t> &binary, GLenum binaryFormat)
 | 
						|
{
 | 
						|
    GLuint program = glCreateProgram();
 | 
						|
    glProgramBinaryOES(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
 | 
						|
    return CheckLinkStatusAndReturnProgram(program, true);
 | 
						|
}
 | 
						|
 | 
						|
GLuint LoadBinaryProgramES3(const std::vector<uint8_t> &binary, GLenum binaryFormat)
 | 
						|
{
 | 
						|
    GLuint program = glCreateProgram();
 | 
						|
    glProgramBinary(program, binaryFormat, binary.data(), static_cast<GLint>(binary.size()));
 | 
						|
    return CheckLinkStatusAndReturnProgram(program, true);
 | 
						|
}
 | 
						|
 | 
						|
bool LinkAttachedProgram(GLuint program)
 | 
						|
{
 | 
						|
    glLinkProgram(program);
 | 
						|
    return (CheckLinkStatusAndReturnProgram(program, true) != 0);
 | 
						|
}
 | 
						|
 | 
						|
void EnableDebugCallback(GLDEBUGPROC callbackChain, const void *userParam)
 | 
						|
{
 | 
						|
    gCallbackChainUserParam = userParam;
 | 
						|
 | 
						|
    glEnable(GL_DEBUG_OUTPUT);
 | 
						|
    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
 | 
						|
    // Enable medium and high priority messages.
 | 
						|
    glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr,
 | 
						|
                             GL_TRUE);
 | 
						|
    glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr,
 | 
						|
                             GL_TRUE);
 | 
						|
    // Disable low and notification priority messages.
 | 
						|
    glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0, nullptr,
 | 
						|
                             GL_FALSE);
 | 
						|
    glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr,
 | 
						|
                             GL_FALSE);
 | 
						|
    // Disable performance messages to reduce spam.
 | 
						|
    glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE, GL_DONT_CARE, 0, nullptr,
 | 
						|
                             GL_FALSE);
 | 
						|
    glDebugMessageCallbackKHR(DebugMessageCallback, reinterpret_cast<const void *>(callbackChain));
 | 
						|
}
 | 
						|
 | 
						|
CounterNameToIndexMap BuildCounterNameToIndexMap()
 | 
						|
{
 | 
						|
    GLint numCounters = 0;
 | 
						|
    glGetPerfMonitorCountersAMD(0, &numCounters, nullptr, 0, nullptr);
 | 
						|
    if (glGetError() != GL_NO_ERROR)
 | 
						|
    {
 | 
						|
        return {};
 | 
						|
    }
 | 
						|
 | 
						|
    std::vector<GLuint> counterIndexes(numCounters, 0);
 | 
						|
    glGetPerfMonitorCountersAMD(0, nullptr, nullptr, numCounters, counterIndexes.data());
 | 
						|
    if (glGetError() != GL_NO_ERROR)
 | 
						|
    {
 | 
						|
        return {};
 | 
						|
    }
 | 
						|
 | 
						|
    CounterNameToIndexMap indexMap;
 | 
						|
 | 
						|
    for (GLuint counterIndex : counterIndexes)
 | 
						|
    {
 | 
						|
        static constexpr size_t kBufSize = 1000;
 | 
						|
        char buffer[kBufSize]            = {};
 | 
						|
        glGetPerfMonitorCounterStringAMD(0, counterIndex, kBufSize, nullptr, buffer);
 | 
						|
        if (glGetError() != GL_NO_ERROR)
 | 
						|
        {
 | 
						|
            return {};
 | 
						|
        }
 | 
						|
 | 
						|
        indexMap[buffer] = counterIndex;
 | 
						|
    }
 | 
						|
 | 
						|
    return indexMap;
 | 
						|
}
 | 
						|
 | 
						|
std::vector<angle::PerfMonitorTriplet> GetPerfMonitorTriplets()
 | 
						|
{
 | 
						|
    GLuint resultSize = 0;
 | 
						|
    glGetPerfMonitorCounterDataAMD(0, GL_PERFMON_RESULT_SIZE_AMD, sizeof(GLuint), &resultSize,
 | 
						|
                                   nullptr);
 | 
						|
    if (glGetError() != GL_NO_ERROR || resultSize == 0)
 | 
						|
    {
 | 
						|
        return {};
 | 
						|
    }
 | 
						|
 | 
						|
    std::vector<angle::PerfMonitorTriplet> perfResults(resultSize /
 | 
						|
                                                       sizeof(angle::PerfMonitorTriplet));
 | 
						|
    glGetPerfMonitorCounterDataAMD(
 | 
						|
        0, GL_PERFMON_RESULT_AMD, static_cast<GLsizei>(perfResults.size() * sizeof(perfResults[0])),
 | 
						|
        &perfResults.data()->group, nullptr);
 | 
						|
 | 
						|
    if (glGetError() != GL_NO_ERROR)
 | 
						|
    {
 | 
						|
        return {};
 | 
						|
    }
 | 
						|
 | 
						|
    return perfResults;
 | 
						|
}
 | 
						|
 | 
						|
angle::VulkanPerfCounters GetPerfCounters(const CounterNameToIndexMap &indexMap)
 | 
						|
{
 | 
						|
    std::vector<angle::PerfMonitorTriplet> perfResults = GetPerfMonitorTriplets();
 | 
						|
 | 
						|
    angle::VulkanPerfCounters counters;
 | 
						|
 | 
						|
#define ANGLE_UNPACK_PERF_COUNTER(COUNTER) \
 | 
						|
    GetPerfCounterValue(indexMap, perfResults, #COUNTER, &counters.COUNTER);
 | 
						|
 | 
						|
    ANGLE_VK_PERF_COUNTERS_X(ANGLE_UNPACK_PERF_COUNTER)
 | 
						|
 | 
						|
#undef ANGLE_UNPACK_PERF_COUNTER
 | 
						|
 | 
						|
    return counters;
 | 
						|
}
 | 
						|
 | 
						|
CounterNameToIndexMap BuildCounterNameToValueMap()
 | 
						|
{
 | 
						|
    CounterNameToIndexMap indexMap                     = BuildCounterNameToIndexMap();
 | 
						|
    std::vector<angle::PerfMonitorTriplet> perfResults = GetPerfMonitorTriplets();
 | 
						|
 | 
						|
    CounterNameToValueMap valueMap;
 | 
						|
 | 
						|
    for (const auto &iter : indexMap)
 | 
						|
    {
 | 
						|
        const std::string &name = iter.first;
 | 
						|
        GLuint index            = iter.second;
 | 
						|
 | 
						|
        valueMap[name] = perfResults[index].value;
 | 
						|
    }
 | 
						|
 | 
						|
    return valueMap;
 | 
						|
}
 | 
						|
 | 
						|
namespace angle
 | 
						|
{
 | 
						|
 | 
						|
namespace essl1_shaders
 | 
						|
{
 | 
						|
 | 
						|
const char *PositionAttrib()
 | 
						|
{
 | 
						|
    return "a_position";
 | 
						|
}
 | 
						|
const char *ColorUniform()
 | 
						|
{
 | 
						|
    return "u_color";
 | 
						|
}
 | 
						|
 | 
						|
const char *Texture2DUniform()
 | 
						|
{
 | 
						|
    return "u_tex2D";
 | 
						|
}
 | 
						|
 | 
						|
namespace vs
 | 
						|
{
 | 
						|
 | 
						|
// A shader that sets gl_Position to zero.
 | 
						|
const char *Zero()
 | 
						|
{
 | 
						|
    return R"(void main()
 | 
						|
{
 | 
						|
    gl_Position = vec4(0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that sets gl_Position to attribute a_position.
 | 
						|
const char *Simple()
 | 
						|
{
 | 
						|
    return R"(precision highp float;
 | 
						|
attribute vec4 a_position;
 | 
						|
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_Position = a_position;
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
 | 
						|
// v_position.
 | 
						|
const char *Passthrough()
 | 
						|
{
 | 
						|
    return R"(precision highp float;
 | 
						|
attribute vec4 a_position;
 | 
						|
varying vec4 v_position;
 | 
						|
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_Position = a_position;
 | 
						|
    v_position = a_position;
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
 | 
						|
// texcoord.
 | 
						|
const char *Texture2D()
 | 
						|
{
 | 
						|
    return R"(precision highp float;
 | 
						|
attribute vec4 a_position;
 | 
						|
varying vec2 v_texCoord;
 | 
						|
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_Position = vec4(a_position.xy, 0.0, 1.0);
 | 
						|
    v_texCoord = a_position.xy * 0.5 + vec2(0.5);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace vs
 | 
						|
 | 
						|
namespace fs
 | 
						|
{
 | 
						|
 | 
						|
// A shader that renders a simple checker pattern of red and green. X axis and y axis separate the
 | 
						|
// different colors. Needs varying v_position.
 | 
						|
const char *Checkered()
 | 
						|
{
 | 
						|
    return R"(precision highp float;
 | 
						|
varying vec4 v_position;
 | 
						|
 | 
						|
void main()
 | 
						|
{
 | 
						|
    bool isLeft = v_position.x < 0.0;
 | 
						|
    bool isTop = v_position.y < 0.0;
 | 
						|
    if (isLeft)
 | 
						|
    {
 | 
						|
        if (isTop)
 | 
						|
        {
 | 
						|
            gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        if (isTop)
 | 
						|
        {
 | 
						|
            gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
 | 
						|
        }
 | 
						|
    }
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that fills with color taken from uniform named "color".
 | 
						|
const char *UniformColor()
 | 
						|
{
 | 
						|
    return R"(uniform mediump vec4 u_color;
 | 
						|
void main(void)
 | 
						|
{
 | 
						|
    gl_FragColor = u_color;
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that fills with 100% opaque red.
 | 
						|
const char *Red()
 | 
						|
{
 | 
						|
    return R"(precision mediump float;
 | 
						|
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that fills with 100% opaque green.
 | 
						|
const char *Green()
 | 
						|
{
 | 
						|
    return R"(precision mediump float;
 | 
						|
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that fills with 100% opaque blue.
 | 
						|
const char *Blue()
 | 
						|
{
 | 
						|
    return R"(precision mediump float;
 | 
						|
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that samples the texture.
 | 
						|
const char *Texture2D()
 | 
						|
{
 | 
						|
    return R"(precision mediump float;
 | 
						|
uniform sampler2D u_tex2D;
 | 
						|
varying vec2 v_texCoord;
 | 
						|
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_FragColor = texture2D(u_tex2D, v_texCoord);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace fs
 | 
						|
}  // namespace essl1_shaders
 | 
						|
 | 
						|
namespace essl3_shaders
 | 
						|
{
 | 
						|
 | 
						|
const char *PositionAttrib()
 | 
						|
{
 | 
						|
    return "a_position";
 | 
						|
}
 | 
						|
const char *Texture2DUniform()
 | 
						|
{
 | 
						|
    return "u_tex2D";
 | 
						|
}
 | 
						|
const char *LodUniform()
 | 
						|
{
 | 
						|
    return "u_lod";
 | 
						|
}
 | 
						|
 | 
						|
namespace vs
 | 
						|
{
 | 
						|
 | 
						|
// A shader that sets gl_Position to zero.
 | 
						|
const char *Zero()
 | 
						|
{
 | 
						|
    return R"(#version 300 es
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_Position = vec4(0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that sets gl_Position to attribute a_position.
 | 
						|
const char *Simple()
 | 
						|
{
 | 
						|
    return R"(#version 300 es
 | 
						|
in vec4 a_position;
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_Position = a_position;
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
 | 
						|
// v_position.
 | 
						|
const char *Passthrough()
 | 
						|
{
 | 
						|
    return R"(#version 300 es
 | 
						|
in vec4 a_position;
 | 
						|
out vec4 v_position;
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_Position = a_position;
 | 
						|
    v_position = a_position;
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
 | 
						|
// texcoord.
 | 
						|
const char *Texture2DLod()
 | 
						|
{
 | 
						|
    return R"(#version 300 es
 | 
						|
in vec4 a_position;
 | 
						|
out vec2 v_texCoord;
 | 
						|
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_Position = vec4(a_position.xy, 0.0, 1.0);
 | 
						|
    v_texCoord = a_position.xy * 0.5 + vec2(0.5);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace vs
 | 
						|
 | 
						|
namespace fs
 | 
						|
{
 | 
						|
 | 
						|
// A shader that fills with 100% opaque red.
 | 
						|
const char *Red()
 | 
						|
{
 | 
						|
    return R"(#version 300 es
 | 
						|
precision highp float;
 | 
						|
out vec4 my_FragColor;
 | 
						|
void main()
 | 
						|
{
 | 
						|
    my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that fills with 100% opaque green.
 | 
						|
const char *Green()
 | 
						|
{
 | 
						|
    return R"(#version 300 es
 | 
						|
precision highp float;
 | 
						|
out vec4 my_FragColor;
 | 
						|
void main()
 | 
						|
{
 | 
						|
    my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that fills with 100% opaque blue.
 | 
						|
const char *Blue()
 | 
						|
{
 | 
						|
    return R"(#version 300 es
 | 
						|
precision highp float;
 | 
						|
out vec4 my_FragColor;
 | 
						|
void main()
 | 
						|
{
 | 
						|
    my_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that samples the texture at a given lod.
 | 
						|
const char *Texture2DLod()
 | 
						|
{
 | 
						|
    return R"(#version 300 es
 | 
						|
precision mediump float;
 | 
						|
uniform sampler2D u_tex2D;
 | 
						|
uniform float u_lod;
 | 
						|
in vec2 v_texCoord;
 | 
						|
out vec4 my_FragColor;
 | 
						|
 | 
						|
void main()
 | 
						|
{
 | 
						|
    my_FragColor = textureLod(u_tex2D, v_texCoord, u_lod);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace fs
 | 
						|
}  // namespace essl3_shaders
 | 
						|
 | 
						|
namespace essl31_shaders
 | 
						|
{
 | 
						|
 | 
						|
const char *PositionAttrib()
 | 
						|
{
 | 
						|
    return "a_position";
 | 
						|
}
 | 
						|
 | 
						|
namespace vs
 | 
						|
{
 | 
						|
 | 
						|
// A shader that sets gl_Position to zero.
 | 
						|
const char *Zero()
 | 
						|
{
 | 
						|
    return R"(#version 310 es
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_Position = vec4(0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that sets gl_Position to attribute a_position.
 | 
						|
const char *Simple()
 | 
						|
{
 | 
						|
    return R"(#version 310 es
 | 
						|
in vec4 a_position;
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_Position = a_position;
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
 | 
						|
// v_position.
 | 
						|
const char *Passthrough()
 | 
						|
{
 | 
						|
    return R"(#version 310 es
 | 
						|
in vec4 a_position;
 | 
						|
out vec4 v_position;
 | 
						|
void main()
 | 
						|
{
 | 
						|
    gl_Position = a_position;
 | 
						|
    v_position = a_position;
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace vs
 | 
						|
 | 
						|
namespace fs
 | 
						|
{
 | 
						|
 | 
						|
// A shader that fills with 100% opaque red.
 | 
						|
const char *Red()
 | 
						|
{
 | 
						|
    return R"(#version 310 es
 | 
						|
precision highp float;
 | 
						|
out vec4 my_FragColor;
 | 
						|
void main()
 | 
						|
{
 | 
						|
    my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that fills with 100% opaque green.
 | 
						|
const char *Green()
 | 
						|
{
 | 
						|
    return R"(#version 310 es
 | 
						|
precision highp float;
 | 
						|
out vec4 my_FragColor;
 | 
						|
void main()
 | 
						|
{
 | 
						|
    my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
// A shader that renders a simple gradient of red to green. Needs varying v_position.
 | 
						|
const char *RedGreenGradient()
 | 
						|
{
 | 
						|
    return R"(#version 310 es
 | 
						|
precision highp float;
 | 
						|
in vec4 v_position;
 | 
						|
out vec4 my_FragColor;
 | 
						|
 | 
						|
void main()
 | 
						|
{
 | 
						|
    my_FragColor = vec4(v_position.xy * 0.5 + vec2(0.5), 0.0, 1.0);
 | 
						|
})";
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace fs
 | 
						|
}  // namespace essl31_shaders
 | 
						|
}  // namespace angle
 |