// 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 #include #include #include 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 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 infoLog(infoLogLength + 1, 0); gl->glGetProgramInfoLog(program, infoLogLength, nullptr, &infoLog[0]); E("failed to link. infolog: %s", &infoLog[0]); } return program; } // static Optional 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 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 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 > 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 buffer(fileSize); // // in.seekg(0); // in.read(buffer.data(), fileSize); // // return buffer; // } } // namespace gfxstream