| // Copyright (C) 2018 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. |
| |
| #include "ShaderUtils.h" |
| |
| #include "aemu/base/files/PathUtils.h" |
| #include "aemu/base/Optional.h" |
| #include "aemu/base/system/System.h" |
| |
| #include "OpenGLESDispatch/OpenGLDispatchLoader.h" |
| |
| #include <fstream> |
| #include <vector> |
| |
| #include <fcntl.h> |
| #include <stdio.h> |
| |
| using android::base::Optional; |
| using android::base::pj; |
| |
| #define DEBUG 0 |
| |
| #if DEBUG |
| #define D(fmt,...) fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__); |
| #else |
| #define D(fmt,...) |
| #endif |
| |
| #define E(fmt,...) fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__); |
| |
| namespace gfxstream { |
| |
| GLuint compileShader(GLenum shaderType, const char* src) { |
| auto gl = gl::LazyLoadedGLESv2Dispatch::get(); |
| |
| GLuint shader = gl->glCreateShader(shaderType); |
| gl->glShaderSource(shader, 1, (const GLchar* const*)&src, nullptr); |
| gl->glCompileShader(shader); |
| |
| GLint compileStatus; |
| gl->glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); |
| |
| if (compileStatus != GL_TRUE) { |
| GLsizei infoLogLength = 0; |
| gl->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); |
| std::vector<char> infoLog(infoLogLength + 1, 0); |
| gl->glGetShaderInfoLog(shader, infoLogLength, nullptr, &infoLog[0]); |
| E("fail to compile. infolog: %s", &infoLog[0]); |
| } |
| |
| return shader; |
| } |
| |
| GLint compileAndLinkShaderProgram(const char* vshaderSrc, const char* fshaderSrc) { |
| auto gl = gl::LazyLoadedGLESv2Dispatch::get(); |
| |
| GLuint vshader = compileShader(GL_VERTEX_SHADER, vshaderSrc); |
| GLuint fshader = compileShader(GL_FRAGMENT_SHADER, fshaderSrc); |
| |
| GLuint program = gl->glCreateProgram(); |
| gl->glAttachShader(program, vshader); |
| gl->glAttachShader(program, fshader); |
| gl->glLinkProgram(program); |
| |
| GLint linkStatus; |
| gl->glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); |
| |
| gl->glClearColor(0.0f, 0.0f, 1.0f, 0.0f); |
| |
| if (linkStatus != GL_TRUE) { |
| GLsizei infoLogLength = 0; |
| gl->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); |
| std::vector<char> infoLog(infoLogLength + 1, 0); |
| gl->glGetProgramInfoLog(program, infoLogLength, nullptr, &infoLog[0]); |
| |
| E("failed to link. infolog: %s", &infoLog[0]); |
| } |
| |
| return program; |
| } |
| |
| // static Optional<std::string> getSpirvCompilerPath() { |
| // #ifdef _WIN32 |
| // std::string programName = "glslangValidator.exe"; |
| // #else |
| // std::string programName = "glslangValidator"; |
| // #endif |
| // |
| // auto programDirRelativePath = |
| // pj(android::base::getProgramDirectory(), |
| // "lib64", "vulkan", "tools", programName); |
| // |
| // if (path_exists(programDirRelativePath.c_str())) { |
| // return programDirRelativePath; |
| // } |
| // |
| // auto launcherDirRelativePath = |
| // pj(android::base::getLauncherDirectory(), |
| // "lib64", "vulkan", programName); |
| // |
| // if (path_exists(launcherDirRelativePath.c_str())) { |
| // return launcherDirRelativePath; |
| // } |
| // |
| // E("spirv compiler does not exist"); |
| // return {}; |
| // } |
| |
| // Optional<std::string> compileSpirvFromGLSL(const std::string& shaderType, |
| // const std::string& src) { |
| // auto spvCompilerPath = getSpirvCompilerPath(); |
| // |
| // if (!spvCompilerPath) return {}; |
| // |
| // const auto glslFile = android::base::makeCustomScopedPtr( |
| // tempfile_create(), tempfile_unref_and_close_file); |
| // |
| // const auto spvFile = android::base::makeCustomScopedPtr( |
| // tempfile_create(), tempfile_unref_and_close_file); |
| // |
| // auto glslPath = tempfile_path(glslFile.get()); |
| // auto spvPath = tempfile_path(spvFile.get()); |
| // |
| // auto glslFd = android::base::ScopedFd(open(glslPath, O_RDWR)); |
| // if (!glslFd.valid()) { return {}; } |
| // |
| // android::writeStringToFile(glslFd.get(), src); |
| // glslFd.close(); |
| // |
| // std::vector<std::string> args = |
| // { *spvCompilerPath, glslPath, "-V", "-S", shaderType, "-o", spvPath }; |
| // |
| // auto runRes = System::get()->runCommandWithResult(args); |
| // |
| // if (!runRes) { |
| // E("failed to compile SPIRV from GLSL. args: %s %s -V -S %s -o %s", |
| // spvCompilerPath->c_str(), glslPath, shaderType.c_str(), spvPath); |
| // return {}; |
| // } |
| // |
| // D("Result of compiling SPIRV from GLSL. res: %s args: %s %s -V -S %s -o %s", |
| // runRes->c_str(), spvCompilerPath->c_str(), glslPath, shaderType.c_str(), |
| // spvPath); |
| // |
| // auto res = android::readFileIntoString(spvPath); |
| // |
| // if (res) { |
| // D("got %zu bytes:", res->size()); |
| // } else { |
| // E("failed to read SPIRV file %s into string", spvPath); |
| // } |
| // |
| // return res; |
| // } |
| // |
| // Optional<std::vector<char> > readSpirv(const char* path) { |
| // std::ifstream in(path, std::ios::ate | std::ios::binary); |
| // |
| // if (!in) return {}; |
| // |
| // size_t fileSize = (size_t)in.tellg(); |
| // std::vector<char> buffer(fileSize); |
| // |
| // in.seekg(0); |
| // in.read(buffer.data(), fileSize); |
| // |
| // return buffer; |
| // } |
| |
| } // namespace gfxstream |