bluenoise-raytracer/raytracer/nvpro_core/nvgl/programmanager_gl.hpp
2024-05-25 11:53:25 +02:00

162 lines
4.4 KiB
C++

/*
* Copyright (c) 2014-2021, NVIDIA CORPORATION. All rights reserved.
*
* 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.
*
* SPDX-FileCopyrightText: Copyright (c) 2014-2021 NVIDIA CORPORATION
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef NV_PROGRAMMANAGER_INCLUDED
#define NV_PROGRAMMANAGER_INCLUDED
#include "extensions_gl.hpp"
#include <stdio.h>
#include <string>
#include <vector>
#include <nvh/nvprint.hpp>
#include <nvh/shaderfilemanager.hpp>
namespace nvgl {
//////////////////////////////////////////////////////////////////////////
/** @DOC_START
# class nvgl::ProgramManager
The nvgl::ProgramManager manages OpenGL programs generated from shader files (GLSL)
Using ShaderFileManager it will find the files and resolve #include for GLSL.
You must add include directories to the base-class for this.
It also comes with some convenience functions to reload shaders etc.
That is why we pass out the ProgramID rather than a GLuint directly.
Example:
```cpp
ProgramManager mgr;
// derived from ShaderFileManager
mgr.addDirectory("/shaders/")
// injected after #version directive
mgr.m_prepend = "#define USE_NOISE 1\n";
id = mgr.createProgram({{GL_VERTEX_SHADER, "object.vert.glsl"},{GL_FRAGMENT_SHADER, "object.frag.glsl"}}):
glUseProgram(mgr.get(id));
```
@DOC_END */
class ProgramID
{
public:
size_t m_value;
ProgramID()
: m_value(size_t(~0))
{
}
ProgramID(size_t b)
: m_value(b)
{
}
ProgramID& operator=(size_t b)
{
m_value = b;
return *this;
}
bool isValid() const { return m_value != size_t(~0); }
operator bool() const { return isValid(); }
operator size_t() const { return m_value; }
friend bool operator==(const ProgramID& lhs, const ProgramID& rhs) { return rhs.m_value == lhs.m_value; }
};
class ProgramManager : public nvh::ShaderFileManager
{
public:
static const uint32_t PREPROCESS_ONLY_PROGRAM = ~0;
struct Program
{
Program()
: program(0)
{
}
uint32_t program;
std::vector<Definition> definitions;
};
ProgramID createProgram(const std::vector<Definition>& definitions);
ProgramID createProgram(const Definition& def0,
const Definition& def1 = Definition(),
const Definition& def2 = Definition(),
const Definition& def3 = Definition(),
const Definition& def4 = Definition());
void destroyProgram(ProgramID idx);
void reloadProgram(ProgramID idx);
void reloadPrograms();
void deletePrograms();
bool areProgramsValid();
bool isValid(ProgramID idx) const;
unsigned int get(ProgramID idx) const;
//////////////////////////////////////////////////////////////////////////
// special purpose use, normally not required to touch
// if not empty then we will store program binaries in files that use the cachefile as prefix
// m_useCacheFile + "_"... implementation dependent
std::string m_useCacheFile;
// look for cachefiles first, otherwise look for original glsl files
bool m_preferCache;
// don't create actual program, only preprocess definition strings
bool m_preprocessOnly;
// don't create actual program, treat filename as raw
bool m_rawOnly;
ProgramManager(ProgramManager const&) = delete;
ProgramManager& operator=(ProgramManager const&) = delete;
ProgramManager()
: m_preprocessOnly(false)
, m_preferCache(false)
, m_rawOnly(false)
{
m_filetype = FILETYPE_GLSL;
}
private:
bool setupProgram(Program& prog);
bool loadBinary(GLuint program, const std::string& combinedPrepend, const std::string& combinedFilenames);
void saveBinary(GLuint program, const std::string& combinedPrepend, const std::string& combinedFilenames);
std::string binaryName(const std::string& combinedPrepend, const std::string& combinedFilenames);
std::vector<Program> m_programs;
};
} // namespace nvgl
#endif