1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "ShaderUtils.h"
16
17 #include "aemu/base/files/PathUtils.h"
18 #include "aemu/base/Optional.h"
19 #include "aemu/base/system/System.h"
20
21 #include "OpenGLESDispatch/OpenGLDispatchLoader.h"
22
23 #include <fstream>
24 #include <vector>
25
26 #include <fcntl.h>
27 #include <stdio.h>
28
29 using android::base::Optional;
30 using android::base::pj;
31
32 #define DEBUG 0
33
34 #if DEBUG
35 #define D(fmt,...) fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__);
36 #else
37 #define D(fmt,...)
38 #endif
39
40 #define E(fmt,...) fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__);
41
42 namespace gfxstream {
43
compileShader(GLenum shaderType,const char * src)44 GLuint compileShader(GLenum shaderType, const char* src) {
45 auto gl = gl::LazyLoadedGLESv2Dispatch::get();
46
47 GLuint shader = gl->glCreateShader(shaderType);
48 gl->glShaderSource(shader, 1, (const GLchar* const*)&src, nullptr);
49 gl->glCompileShader(shader);
50
51 GLint compileStatus;
52 gl->glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
53
54 if (compileStatus != GL_TRUE) {
55 GLsizei infoLogLength = 0;
56 gl->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
57 std::vector<char> infoLog(infoLogLength + 1, 0);
58 gl->glGetShaderInfoLog(shader, infoLogLength, nullptr, &infoLog[0]);
59 E("fail to compile. infolog: %s", &infoLog[0]);
60 }
61
62 return shader;
63 }
64
compileAndLinkShaderProgram(const char * vshaderSrc,const char * fshaderSrc)65 GLint compileAndLinkShaderProgram(const char* vshaderSrc, const char* fshaderSrc) {
66 auto gl = gl::LazyLoadedGLESv2Dispatch::get();
67
68 GLuint vshader = compileShader(GL_VERTEX_SHADER, vshaderSrc);
69 GLuint fshader = compileShader(GL_FRAGMENT_SHADER, fshaderSrc);
70
71 GLuint program = gl->glCreateProgram();
72 gl->glAttachShader(program, vshader);
73 gl->glAttachShader(program, fshader);
74 gl->glLinkProgram(program);
75
76 GLint linkStatus;
77 gl->glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
78
79 gl->glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
80
81 if (linkStatus != GL_TRUE) {
82 GLsizei infoLogLength = 0;
83 gl->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
84 std::vector<char> infoLog(infoLogLength + 1, 0);
85 gl->glGetProgramInfoLog(program, infoLogLength, nullptr, &infoLog[0]);
86
87 E("failed to link. infolog: %s", &infoLog[0]);
88 }
89
90 return program;
91 }
92
93 // static Optional<std::string> getSpirvCompilerPath() {
94 // #ifdef _WIN32
95 // std::string programName = "glslangValidator.exe";
96 // #else
97 // std::string programName = "glslangValidator";
98 // #endif
99 //
100 // auto programDirRelativePath =
101 // pj(android::base::getProgramDirectory(),
102 // "lib64", "vulkan", "tools", programName);
103 //
104 // if (path_exists(programDirRelativePath.c_str())) {
105 // return programDirRelativePath;
106 // }
107 //
108 // auto launcherDirRelativePath =
109 // pj(android::base::getLauncherDirectory(),
110 // "lib64", "vulkan", programName);
111 //
112 // if (path_exists(launcherDirRelativePath.c_str())) {
113 // return launcherDirRelativePath;
114 // }
115 //
116 // E("spirv compiler does not exist");
117 // return {};
118 // }
119
120 // Optional<std::string> compileSpirvFromGLSL(const std::string& shaderType,
121 // const std::string& src) {
122 // auto spvCompilerPath = getSpirvCompilerPath();
123 //
124 // if (!spvCompilerPath) return {};
125 //
126 // const auto glslFile = android::base::makeCustomScopedPtr(
127 // tempfile_create(), tempfile_unref_and_close_file);
128 //
129 // const auto spvFile = android::base::makeCustomScopedPtr(
130 // tempfile_create(), tempfile_unref_and_close_file);
131 //
132 // auto glslPath = tempfile_path(glslFile.get());
133 // auto spvPath = tempfile_path(spvFile.get());
134 //
135 // auto glslFd = android::base::ScopedFd(open(glslPath, O_RDWR));
136 // if (!glslFd.valid()) { return {}; }
137 //
138 // android::writeStringToFile(glslFd.get(), src);
139 // glslFd.close();
140 //
141 // std::vector<std::string> args =
142 // { *spvCompilerPath, glslPath, "-V", "-S", shaderType, "-o", spvPath };
143 //
144 // auto runRes = System::get()->runCommandWithResult(args);
145 //
146 // if (!runRes) {
147 // E("failed to compile SPIRV from GLSL. args: %s %s -V -S %s -o %s",
148 // spvCompilerPath->c_str(), glslPath, shaderType.c_str(), spvPath);
149 // return {};
150 // }
151 //
152 // D("Result of compiling SPIRV from GLSL. res: %s args: %s %s -V -S %s -o %s",
153 // runRes->c_str(), spvCompilerPath->c_str(), glslPath, shaderType.c_str(),
154 // spvPath);
155 //
156 // auto res = android::readFileIntoString(spvPath);
157 //
158 // if (res) {
159 // D("got %zu bytes:", res->size());
160 // } else {
161 // E("failed to read SPIRV file %s into string", spvPath);
162 // }
163 //
164 // return res;
165 // }
166 //
167 // Optional<std::vector<char> > readSpirv(const char* path) {
168 // std::ifstream in(path, std::ios::ate | std::ios::binary);
169 //
170 // if (!in) return {};
171 //
172 // size_t fileSize = (size_t)in.tellg();
173 // std::vector<char> buffer(fileSize);
174 //
175 // in.seekg(0);
176 // in.read(buffer.data(), fileSize);
177 //
178 // return buffer;
179 // }
180
181 } // namespace gfxstream
182