cleanup and refactoring
This commit is contained in:
parent
2302158928
commit
76f6bf62a4
1285 changed files with 757994 additions and 8 deletions
98
raytracer/nvpro_core/nvgl/README.md
Normal file
98
raytracer/nvpro_core/nvgl/README.md
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
## Table of Contents
|
||||
- [appwindowprofiler_gl.hpp](#appwindowprofiler_glhpp)
|
||||
- [contextwindow_gl.hpp](#contextwindow_glhpp)
|
||||
- [error_gl.hpp](#error_glhpp)
|
||||
- [extensions_gl.hpp](#extensions_glhpp)
|
||||
- [profiler_gl.hpp](#profiler_glhpp)
|
||||
- [programmanager_gl.hpp](#programmanager_glhpp)
|
||||
|
||||
## appwindowprofiler_gl.hpp
|
||||
### class nvgl::AppWindowProfilerGL
|
||||
|
||||
|
||||
nvgl::AppWindowProfilerGL derives from nvh::AppWindowProfiler
|
||||
and overrides the context and swapbuffer functions.
|
||||
|
||||
To influence the context creation modify
|
||||
`m_contextInfo` prior running AppWindowProfiler::run,
|
||||
which triggers window, and context creation etc.
|
||||
|
||||
The class comes with a nvgl::ProfilerGL instance that references the
|
||||
AppWindowProfiler::m_profiler's data.
|
||||
|
||||
## contextwindow_gl.hpp
|
||||
### struct nvgl::ContextWindowCreateInfo
|
||||
|
||||
|
||||
Set up the context properties for a OpenGL ContextWindow.
|
||||
e.g. version, core/compatibiltiy etc.
|
||||
### class nvgl::ContextWindow
|
||||
|
||||
|
||||
nvgl::ContextWindow sets up an OpenGL context from a provided `GLFWwindow`.
|
||||
Makes use of `glDebugMessageCallback` to hook up an error callback
|
||||
and loads all extensions provided by `extensions_gl.hpp`
|
||||
|
||||
## error_gl.hpp
|
||||
### functions in nvgl
|
||||
|
||||
|
||||
Several utility functions that aid debugging. Check if all bindings
|
||||
are cleared, framebuffer complete etc.
|
||||
### template class nvgl::CheckBufferContent
|
||||
|
||||
Utility wrapper to downlad buffer data into a temp vector for debugging
|
||||
### class nvgl::CheckBufferResidency
|
||||
|
||||
nvgl::CheckBufferResidency utility class to test if a certain gpu address is coming from
|
||||
a resident buffer. Register the address of buffers in advance.
|
||||
|
||||
## extensions_gl.hpp
|
||||
### function load_GL
|
||||
|
||||
> An OpenGL Extension loader
|
||||
|
||||
Provides a subset of OpenGL Extensions generated by `extensions_gl.lua`.
|
||||
The framework uses a sanitized OpenGL header that is mostly core functionality.
|
||||
`GL/glsubset.h` is generated using a enablelist by the lua script
|
||||
from `GL/glcustom.h` (which is mostly based on `glcorearb.h` with some
|
||||
additional extensions and features)
|
||||
|
||||
## profiler_gl.hpp
|
||||
### class nvgl::ProfilerGL
|
||||
|
||||
|
||||
nvgl::ProfilerGL extends Profiler and uses `glQueryCounter(... GL_TIMESTAMP)`
|
||||
to compute the GPU time of a section.
|
||||
`glPushDebugGroup` and `glPopDebugGroup` are used within each timed
|
||||
section, so that the section names can show up in NSightGraphics,
|
||||
renderdoc or comparable tools.
|
||||
|
||||
|
||||
## programmanager_gl.hpp
|
||||
### 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));
|
||||
```
|
||||
43
raytracer/nvpro_core/nvgl/appwindowprofiler_gl.cpp
Normal file
43
raytracer/nvpro_core/nvgl/appwindowprofiler_gl.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
||||
#include "appwindowprofiler_gl.hpp"
|
||||
|
||||
#include <nvh/misc.hpp>
|
||||
|
||||
namespace nvgl {
|
||||
void AppWindowProfilerGL::contextInit()
|
||||
{
|
||||
// create OpenGL stuff at last
|
||||
m_contextWindow.init(&m_contextInfo, m_internal, m_windowName.c_str());
|
||||
// create other additional OpenGL tools
|
||||
m_profilerGL.init();
|
||||
|
||||
m_windowState.m_swapSize[0] = NVPWindow::getWidth();
|
||||
m_windowState.m_swapSize[1] = NVPWindow::getHeight();
|
||||
}
|
||||
|
||||
void AppWindowProfilerGL::contextDeinit()
|
||||
{
|
||||
m_profilerGL.deinit();
|
||||
m_contextWindow.deinit();
|
||||
}
|
||||
|
||||
} // namespace nvgl
|
||||
94
raytracer/nvpro_core/nvgl/appwindowprofiler_gl.hpp
Normal file
94
raytracer/nvpro_core/nvgl/appwindowprofiler_gl.hpp
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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_WINDOWPROFILER_GL_INCLUDED
|
||||
#define NV_WINDOWPROFILER_GL_INCLUDED
|
||||
|
||||
#include "contextwindow_gl.hpp"
|
||||
#include "profiler_gl.hpp"
|
||||
#include <nvh/appwindowprofiler.hpp>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/** @DOC_START
|
||||
# class nvgl::AppWindowProfilerGL
|
||||
|
||||
nvgl::AppWindowProfilerGL derives from nvh::AppWindowProfiler
|
||||
and overrides the context and swapbuffer functions.
|
||||
|
||||
To influence the context creation modify
|
||||
`m_contextInfo` prior running AppWindowProfiler::run,
|
||||
which triggers window, and context creation etc.
|
||||
|
||||
The class comes with a nvgl::ProfilerGL instance that references the
|
||||
AppWindowProfiler::m_profiler's data.
|
||||
@DOC_END */
|
||||
|
||||
namespace nvgl {
|
||||
|
||||
#define NV_PROFILE_GL_SECTION(name) nvgl::ProfilerGL::Section _tempTimer(m_profilerGL, name)
|
||||
#define NV_PROFILE_GL_SPLIT() m_profilerGL.accumulationSplit()
|
||||
|
||||
class AppWindowProfilerGL : public nvh::AppWindowProfiler
|
||||
{
|
||||
public:
|
||||
AppWindowProfilerGL(bool singleThreaded = true)
|
||||
: nvh::AppWindowProfiler(singleThreaded)
|
||||
, m_profilerGL(&m_profiler)
|
||||
{
|
||||
m_contextInfo.robust = false;
|
||||
m_contextInfo.core = false;
|
||||
#ifdef NDEBUG
|
||||
m_contextInfo.debug = false;
|
||||
#else
|
||||
m_contextInfo.debug = true;
|
||||
#endif
|
||||
m_contextInfo.share = NULL;
|
||||
m_contextInfo.major = 4;
|
||||
m_contextInfo.minor = 5;
|
||||
}
|
||||
|
||||
nvgl::ContextWindowCreateInfo m_contextInfo;
|
||||
ContextWindow m_contextWindow;
|
||||
|
||||
nvgl::ProfilerGL m_profilerGL;
|
||||
|
||||
|
||||
int run(const std::string& name, int argc, const char** argv, int width, int height)
|
||||
{
|
||||
return AppWindowProfiler::run(name, argc, argv, width, height, true);
|
||||
}
|
||||
|
||||
virtual void contextInit() override;
|
||||
virtual void contextDeinit() override;
|
||||
|
||||
virtual void swapResize(int width, int height) override
|
||||
{
|
||||
m_windowState.m_swapSize[0] = width;
|
||||
m_windowState.m_swapSize[1] = height;
|
||||
}
|
||||
virtual void swapPrepare() override {}
|
||||
virtual void swapBuffers() override { m_contextWindow.swapBuffers(); }
|
||||
virtual void swapVsync(bool state) override { m_contextWindow.swapInterval(state ? 1 : 0); }
|
||||
virtual const char* contextGetDeviceName() override { return m_contextWindow.m_deviceName.c_str(); }
|
||||
};
|
||||
} // namespace nvgl
|
||||
|
||||
|
||||
#endif
|
||||
288
raytracer/nvpro_core/nvgl/base_gl.hpp
Normal file
288
raytracer/nvpro_core/nvgl/base_gl.hpp
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/// @DOC_SKIP (keyword to exclude this file from automatic README.md generation)
|
||||
|
||||
#ifndef NV_BASEGL_H_INCLUDED
|
||||
#define NV_BASEGL_H_INCLUDED
|
||||
|
||||
#include "extensions_gl.hpp"
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
#define NV_BUFFER_OFFSET(i) ((char*)NULL + (i))
|
||||
|
||||
namespace nvgl {
|
||||
/** @DOC_START
|
||||
# struct nvgl::BufferBinding
|
||||
Wraps buffer, offset, size, gpu address
|
||||
@DOC_END */
|
||||
|
||||
struct BufferBinding
|
||||
{
|
||||
GLuint buffer = 0;
|
||||
GLintptr offset = 0;
|
||||
GLsizeiptr size = 0;
|
||||
GLuint64 bufferADDR;
|
||||
|
||||
BufferBinding() {}
|
||||
BufferBinding(GLuint inBuffer, GLintptr inOffset, GLsizeiptr inSize, GLuint64 inBufferADDR)
|
||||
{
|
||||
buffer = inBuffer;
|
||||
size = inSize;
|
||||
offset = inOffset;
|
||||
bufferADDR = inBufferADDR + inOffset;
|
||||
}
|
||||
};
|
||||
|
||||
/** @DOC_START
|
||||
# struct nvgl::TextureBuffer
|
||||
A `GL_TEXTURE_BUFFER` that references the provided buffer.
|
||||
Wraps texture and bindless texture handle.
|
||||
@DOC_END */
|
||||
|
||||
struct TextureBuffer
|
||||
{
|
||||
GLuint tex = 0;
|
||||
GLuint64 texADDR = 0;
|
||||
|
||||
void create(GLuint buffer, GLintptr offset, GLsizeiptr sz, GLenum format)
|
||||
{
|
||||
glCreateTextures(GL_TEXTURE_BUFFER, 1, &tex);
|
||||
glTextureBufferRange(tex, format, buffer, offset, sz);
|
||||
if(has_GL_ARB_bindless_texture)
|
||||
{
|
||||
texADDR = glGetTextureHandleARB(tex);
|
||||
glMakeTextureHandleResidentARB(texADDR);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
if(texADDR)
|
||||
{
|
||||
glMakeTextureHandleNonResidentARB(texADDR);
|
||||
}
|
||||
glDeleteTextures(1, &tex);
|
||||
}
|
||||
};
|
||||
|
||||
/** @DOC_START
|
||||
# struct nvgl::Buffer
|
||||
Wraps buffer as well as optionally creates a `GL_TEXTURE_BUFFER` if
|
||||
a non-null `format` is provided. If bindless is available it will
|
||||
also create bindless handles for all resources and make them resident.
|
||||
|
||||
If the `flags` contain `GL_MAP_PERSISTENT_BIT` it will also map
|
||||
the buffer and keep the host pointer.
|
||||
@DOC_END */
|
||||
|
||||
struct Buffer
|
||||
{
|
||||
GLuint buffer = 0;
|
||||
GLuint tex = 0;
|
||||
GLuint64 bufferADDR = 0;
|
||||
GLuint64 texADDR = 0;
|
||||
GLsizeiptr size = 0;
|
||||
void* mapped = nullptr;
|
||||
|
||||
void create(GLsizeiptr sz, const void* data, GLuint flags, GLenum format)
|
||||
{
|
||||
size = sz;
|
||||
glCreateBuffers(1, &buffer);
|
||||
glNamedBufferStorage(buffer, sz, data, flags);
|
||||
if(has_GL_NV_shader_buffer_load)
|
||||
{
|
||||
glGetNamedBufferParameterui64vNV(buffer, GL_BUFFER_GPU_ADDRESS_NV, &bufferADDR);
|
||||
glMakeNamedBufferResidentNV(buffer, GL_READ_WRITE);
|
||||
}
|
||||
if(format)
|
||||
{
|
||||
glCreateTextures(GL_TEXTURE_BUFFER, 1, &tex);
|
||||
glTextureBuffer(tex, format, buffer);
|
||||
if(has_GL_ARB_bindless_texture)
|
||||
{
|
||||
texADDR = glGetTextureHandleARB(tex);
|
||||
glMakeTextureHandleResidentARB(texADDR);
|
||||
}
|
||||
}
|
||||
|
||||
if(flags & GL_MAP_PERSISTENT_BIT)
|
||||
{
|
||||
mapped = glMapNamedBufferRange(buffer, 0, sz,
|
||||
flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT));
|
||||
}
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
if(mapped)
|
||||
{
|
||||
glUnmapNamedBuffer(buffer);
|
||||
}
|
||||
if(tex)
|
||||
{
|
||||
if(texADDR)
|
||||
{
|
||||
glMakeTextureHandleNonResidentARB(texADDR);
|
||||
}
|
||||
glDeleteTextures(1, &tex);
|
||||
}
|
||||
if(bufferADDR)
|
||||
{
|
||||
glMakeNamedBufferNonResidentNV(buffer);
|
||||
}
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
|
||||
operator GLuint() const { return buffer; }
|
||||
};
|
||||
|
||||
inline size_t uboAligned(size_t size)
|
||||
{
|
||||
return ((size + 255) / 256) * 256;
|
||||
}
|
||||
|
||||
inline void bindMultiTexture(GLenum target, GLenum textarget, GLuint tex)
|
||||
{
|
||||
glActiveTexture(target);
|
||||
glBindTexture(textarget, tex);
|
||||
}
|
||||
|
||||
/** @DOC_START
|
||||
# nvgl resource functions
|
||||
|
||||
Functions that wrap glCreate/glDelete and operate on `GLuint& obj`.
|
||||
The "new" functions delete the existing object if non-null and create a new one.
|
||||
The "delete" functions delete non-null objects.
|
||||
|
||||
* newBuffer / deleteBuffer
|
||||
* newTextureView
|
||||
* newTexture / deleteTexture
|
||||
* newFramebuffer / deleteFramebuffer
|
||||
* newSampler / deleteSampler
|
||||
* newQuery / deleteQuery
|
||||
* newVertexArray / deleteVertexArray
|
||||
|
||||
```cpp
|
||||
// typical use-case
|
||||
FrameBuffer::resize(int with, int height){
|
||||
newFramebuffer(m_fbo);
|
||||
newTexture(m_color, GL_TEXTURE_2D);
|
||||
newTexture(m_depthStencil, GL_TEXTURE_2D);
|
||||
glTextureStorage2D(m_color, ...)
|
||||
glTextureStorage2D(m_depthStencil, ...)
|
||||
glNamedFramebufferTexture(m_fbo, GL_COLOR_ATTACHMENT0, m_color, 0);
|
||||
glNamedFramebufferTexture(m_fbo, GL_DEPTH_STENCIL_ATTACHMENT, m_depthStencil, 0);
|
||||
}
|
||||
```
|
||||
@DOC_END */
|
||||
|
||||
inline void newBuffer(GLuint& glid)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteBuffers(1, &glid);
|
||||
glCreateBuffers(1, &glid);
|
||||
}
|
||||
|
||||
inline void deleteBuffer(GLuint& glid)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteBuffers(1, &glid);
|
||||
glid = 0;
|
||||
}
|
||||
|
||||
inline void newTextureView(GLuint& glid)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteTextures(1, &glid);
|
||||
glGenTextures(1, &glid);
|
||||
}
|
||||
|
||||
inline void newTexture(GLuint& glid, GLenum target)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteTextures(1, &glid);
|
||||
glCreateTextures(target, 1, &glid);
|
||||
}
|
||||
|
||||
inline void deleteTexture(GLuint& glid)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteTextures(1, &glid);
|
||||
glid = 0;
|
||||
}
|
||||
|
||||
inline void newFramebuffer(GLuint& glid)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteFramebuffers(1, &glid);
|
||||
glCreateFramebuffers(1, &glid);
|
||||
}
|
||||
|
||||
inline void deleteFramebuffer(GLuint& glid)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteFramebuffers(1, &glid);
|
||||
glid = 0;
|
||||
}
|
||||
|
||||
inline void newSampler(GLuint& glid)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteSamplers(1, &glid);
|
||||
glCreateSamplers(1, &glid);
|
||||
}
|
||||
|
||||
inline void deleteSampler(GLuint& glid)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteSamplers(1, &glid);
|
||||
glid = 0;
|
||||
}
|
||||
|
||||
inline void newQuery(GLuint& glid, GLenum target)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteQueries(1, &glid);
|
||||
glCreateQueries(target, 1, &glid);
|
||||
}
|
||||
|
||||
inline void deleteQuery(GLuint& glid)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteQueries(1, &glid);
|
||||
glid = 0;
|
||||
}
|
||||
|
||||
inline void newVertexArray(GLuint& glid)
|
||||
{
|
||||
if(glid)
|
||||
glCreateVertexArrays(1, &glid);
|
||||
glGenVertexArrays(1, &glid);
|
||||
}
|
||||
|
||||
inline void deleteVertexArray(GLuint& glid)
|
||||
{
|
||||
if(glid)
|
||||
glDeleteVertexArrays(1, &glid);
|
||||
glid = 0;
|
||||
}
|
||||
} // namespace nvgl
|
||||
|
||||
#endif
|
||||
682
raytracer/nvpro_core/nvgl/contextwindow_gl.cpp
Normal file
682
raytracer/nvpro_core/nvgl/contextwindow_gl.cpp
Normal file
|
|
@ -0,0 +1,682 @@
|
|||
/*
|
||||
* Copyright (c) 2013-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) 2013-2021 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#include <nvgl/contextwindow_gl.hpp>
|
||||
#include <nvgl/error_gl.hpp>
|
||||
#include <nvgl/extensions_gl.hpp>
|
||||
|
||||
#ifdef WIN32
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#include <GLFW/glfw3native.h>
|
||||
|
||||
#include <GL/wgl.h>
|
||||
|
||||
#include "resources.h"
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#elif defined LINUX
|
||||
#define GLFW_EXPOSE_NATIVE_GLX
|
||||
#define GLFW_EXPOSE_NATIVE_X11
|
||||
#include <GL/glx.h>
|
||||
#include <GLFW/glfw3native.h>
|
||||
#endif
|
||||
|
||||
#include <fileformats/bmp.hpp>
|
||||
#include <nvh/nvprint.hpp>
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <fcntl.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace nvgl {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// OGL callback
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef NDEBUG
|
||||
static void APIENTRY myOpenGLCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const GLvoid* userParam)
|
||||
{
|
||||
|
||||
ContextWindow* window = (ContextWindow*)userParam;
|
||||
|
||||
GLenum filter = window->m_debugFilter;
|
||||
GLenum severitycmp = severity;
|
||||
// minor fixup for filtering so notification becomes lowest priority
|
||||
if(GL_DEBUG_SEVERITY_NOTIFICATION == filter)
|
||||
{
|
||||
filter = GL_DEBUG_SEVERITY_LOW_ARB + 1;
|
||||
}
|
||||
if(GL_DEBUG_SEVERITY_NOTIFICATION == severitycmp)
|
||||
{
|
||||
severitycmp = GL_DEBUG_SEVERITY_LOW_ARB + 1;
|
||||
}
|
||||
|
||||
if(!filter || severitycmp <= filter)
|
||||
{
|
||||
|
||||
//static std::map<GLuint, bool> ignoreMap;
|
||||
//if(ignoreMap[id] == true)
|
||||
// return;
|
||||
const char* strSource = "0";
|
||||
const char* strType = strSource;
|
||||
switch(source)
|
||||
{
|
||||
case GL_DEBUG_SOURCE_API_ARB:
|
||||
strSource = "API";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
|
||||
strSource = "WINDOWS";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
|
||||
strSource = "SHADER COMP.";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
|
||||
strSource = "3RD PARTY";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_APPLICATION_ARB:
|
||||
strSource = "APP";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_OTHER_ARB:
|
||||
strSource = "OTHER";
|
||||
break;
|
||||
}
|
||||
switch(type)
|
||||
{
|
||||
case GL_DEBUG_TYPE_ERROR_ARB:
|
||||
strType = "ERROR";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
|
||||
strType = "Deprecated";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
|
||||
strType = "Undefined";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_PORTABILITY_ARB:
|
||||
strType = "Portability";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_PERFORMANCE_ARB:
|
||||
strType = "Performance";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_OTHER_ARB:
|
||||
strType = "Other";
|
||||
break;
|
||||
}
|
||||
switch(severity)
|
||||
{
|
||||
case GL_DEBUG_SEVERITY_HIGH_ARB:
|
||||
LOGE("ARB_debug : %s High - %s - %s : %s\n", window->m_debugTitle.c_str(), strSource, strType, message);
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_MEDIUM_ARB:
|
||||
LOGW("ARB_debug : %s Medium - %s - %s : %s\n", window->m_debugTitle.c_str(), strSource, strType, message);
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_LOW_ARB:
|
||||
LOGI("ARB_debug : %s Low - %s - %s : %s\n", window->m_debugTitle.c_str(), strSource, strType, message);
|
||||
break;
|
||||
default:
|
||||
//LOGI("ARB_debug : comment - %s - %s : %s\n", strSource, strType, message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// from GLFW 3.0
|
||||
static int stringInExtensionString(const char* string, const char* exts)
|
||||
{
|
||||
const GLubyte* extensions = (const GLubyte*)exts;
|
||||
const GLubyte* start;
|
||||
GLubyte* where;
|
||||
GLubyte* terminator;
|
||||
|
||||
// It takes a bit of care to be fool-proof about parsing the
|
||||
// OpenGL extensions string. Don't be fooled by sub-strings,
|
||||
// etc.
|
||||
start = extensions;
|
||||
for(;;)
|
||||
{
|
||||
where = (GLubyte*)strstr((const char*)start, string);
|
||||
if(!where)
|
||||
return GL_FALSE;
|
||||
|
||||
terminator = where + strlen(string);
|
||||
if(where == start || *(where - 1) == ' ')
|
||||
{
|
||||
if(*terminator == ' ' || *terminator == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
start = terminator;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WIN 32
|
||||
|
||||
static HMODULE s_module = NULL;
|
||||
|
||||
struct ContextWindowInternalGL
|
||||
{
|
||||
HDC m_hDCaffinity = NULL;
|
||||
HDC m_hDC = NULL;
|
||||
HGLRC m_hRC = NULL;
|
||||
|
||||
PFNWGLSWAPINTERVALEXTPROC m_wglSwapIntervalEXT = NULL;
|
||||
PFNWGLGETEXTENSIONSSTRINGARBPROC m_wglGetExtensionsStringARB = NULL;
|
||||
PFNWGLDELETEDCNVPROC m_wglDeleteDCNV = NULL;
|
||||
|
||||
bool init(const ContextWindowCreateInfo& settings, GLFWwindow* sourcewindow, ContextWindow* ctxwindow)
|
||||
{
|
||||
GLuint PixelFormat;
|
||||
HWND hWnd = glfwGetWin32Window(sourcewindow);
|
||||
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||||
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
|
||||
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 32;
|
||||
pfd.cDepthBits = settings.depth;
|
||||
pfd.cStencilBits = settings.stencil;
|
||||
|
||||
if(settings.stereo)
|
||||
{
|
||||
pfd.dwFlags |= PFD_STEREO;
|
||||
}
|
||||
|
||||
if(settings.MSAA > 1)
|
||||
{
|
||||
HWND hWndDummy = CreateWindowEx(NULL, "Static", "Dummy", WS_OVERLAPPEDWINDOW, 0, 0, 10, 10, NULL, NULL, hInstance, NULL);
|
||||
|
||||
m_hDC = GetDC(hWndDummy);
|
||||
PixelFormat = ChoosePixelFormat(m_hDC, &pfd);
|
||||
SetPixelFormat(m_hDC, PixelFormat, &pfd);
|
||||
m_hRC = wglCreateContext(m_hDC);
|
||||
wglMakeCurrent(m_hDC, m_hRC);
|
||||
|
||||
PFNWGLCHOOSEPIXELFORMATARBPROC fn_wglChoosePixelFormatARB =
|
||||
(PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
|
||||
|
||||
ReleaseDC(hWndDummy, m_hDC);
|
||||
m_hDC = GetDC(hWnd);
|
||||
int attri[] = {WGL_DRAW_TO_WINDOW_ARB,
|
||||
true,
|
||||
WGL_PIXEL_TYPE_ARB,
|
||||
WGL_TYPE_RGBA_ARB,
|
||||
WGL_SUPPORT_OPENGL_ARB,
|
||||
true,
|
||||
WGL_ACCELERATION_ARB,
|
||||
WGL_FULL_ACCELERATION_ARB,
|
||||
WGL_DOUBLE_BUFFER_ARB,
|
||||
true,
|
||||
WGL_DEPTH_BITS_ARB,
|
||||
settings.depth,
|
||||
WGL_STENCIL_BITS_ARB,
|
||||
settings.stencil,
|
||||
WGL_SAMPLE_BUFFERS_ARB,
|
||||
1,
|
||||
WGL_SAMPLES_ARB,
|
||||
settings.MSAA,
|
||||
0,
|
||||
0};
|
||||
GLuint nfmts;
|
||||
int fmt;
|
||||
|
||||
if(!fn_wglChoosePixelFormatARB(m_hDC, attri, NULL, 1, &fmt, &nfmts))
|
||||
{
|
||||
wglDeleteContext(m_hRC);
|
||||
return false;
|
||||
}
|
||||
wglDeleteContext(m_hRC);
|
||||
DestroyWindow(hWndDummy);
|
||||
if(!SetPixelFormat(m_hDC, fmt, &pfd))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hDC = GetDC(hWnd);
|
||||
PixelFormat = ChoosePixelFormat(m_hDC, &pfd);
|
||||
SetPixelFormat(m_hDC, PixelFormat, &pfd);
|
||||
}
|
||||
m_hRC = wglCreateContext(m_hDC);
|
||||
wglMakeCurrent(m_hDC, m_hRC);
|
||||
|
||||
HDC hdcContext = m_hDC;
|
||||
|
||||
if(settings.device)
|
||||
{
|
||||
PFNWGLENUMGPUSNVPROC fn_wglEnumGpusNV = (PFNWGLENUMGPUSNVPROC)wglGetProcAddress("wglEnumGpusNV");
|
||||
PFNWGLENUMGPUDEVICESNVPROC fn_wglEnumGpuDevicesNV =
|
||||
(PFNWGLENUMGPUDEVICESNVPROC)wglGetProcAddress("wglEnumGpuDevicesNV");
|
||||
PFNWGLCREATEAFFINITYDCNVPROC fn_wglCreateAffinityDCNV =
|
||||
(PFNWGLCREATEAFFINITYDCNVPROC)wglGetProcAddress("wglCreateAffinityDCNV");
|
||||
m_wglDeleteDCNV = (PFNWGLDELETEDCNVPROC)wglGetProcAddress("wglDeleteDCNV");
|
||||
|
||||
if(fn_wglEnumGpusNV && fn_wglCreateAffinityDCNV && m_wglDeleteDCNV)
|
||||
{
|
||||
const uint32_t MAX_GPU = 4;
|
||||
HGPUNV hGPU[MAX_GPU];
|
||||
_GPU_DEVICE devices[MAX_GPU];
|
||||
HGPUNV GpuMask[2] = {0};
|
||||
uint32_t gpuIndex = 0;
|
||||
// Get a list of the first MAX_GPU GPUs in the system
|
||||
while((gpuIndex < MAX_GPU) && fn_wglEnumGpusNV(gpuIndex, &hGPU[gpuIndex]))
|
||||
{
|
||||
fn_wglEnumGpuDevicesNV(hGPU[gpuIndex], 0, &devices[gpuIndex]);
|
||||
gpuIndex++;
|
||||
}
|
||||
|
||||
GpuMask[0] = hGPU[settings.device];
|
||||
|
||||
// delete old
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(m_hRC);
|
||||
|
||||
m_hDCaffinity = fn_wglCreateAffinityDCNV(GpuMask);
|
||||
hdcContext = m_hDCaffinity;
|
||||
|
||||
PixelFormat = ChoosePixelFormat(m_hDCaffinity, &pfd);
|
||||
SetPixelFormat(m_hDCaffinity, PixelFormat, &pfd);
|
||||
m_hRC = wglCreateContext(m_hDCaffinity);
|
||||
|
||||
wglMakeCurrent(m_hDC, m_hRC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PFNWGLCREATECONTEXTATTRIBSARBPROC fn_wglCreateContextAttribsARB =
|
||||
(PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
|
||||
if(fn_wglCreateContextAttribsARB)
|
||||
{
|
||||
HGLRC hRC = NULL;
|
||||
std::vector<int> attribList;
|
||||
#define ADDATTRIB(a, b) \
|
||||
{ \
|
||||
attribList.push_back(a); \
|
||||
attribList.push_back(b); \
|
||||
}
|
||||
int maj = settings.major;
|
||||
int min = settings.minor;
|
||||
ADDATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, maj)
|
||||
ADDATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, min)
|
||||
if(settings.core)
|
||||
ADDATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB)
|
||||
else
|
||||
ADDATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
|
||||
int ctxtflags = 0;
|
||||
if(settings.debug)
|
||||
ctxtflags |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||
if(settings.robust)
|
||||
ctxtflags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
||||
if(settings.forward) // use it if you want errors when compat options still used
|
||||
ctxtflags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
||||
ADDATTRIB(WGL_CONTEXT_FLAGS_ARB, ctxtflags);
|
||||
ADDATTRIB(0, 0)
|
||||
int* p = &(attribList[0]);
|
||||
if(!(hRC = fn_wglCreateContextAttribsARB(hdcContext, 0, p)))
|
||||
{
|
||||
GLint MajorVersionContext = 0;
|
||||
GLint MinorVersionContext = 0;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &MajorVersionContext);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &MinorVersionContext);
|
||||
if((MajorVersionContext * 100 + MinorVersionContext * 10) < (maj * 100 + min * 10))
|
||||
{
|
||||
LOGE("OpenGL version %d.%d not available. Only %d.%d found\n", maj, min, MajorVersionContext, MinorVersionContext);
|
||||
}
|
||||
LOGE("wglCreateContextAttribsARB() failed for OpenGL context.\n");
|
||||
return false;
|
||||
}
|
||||
if(!wglMakeCurrent(m_hDC, hRC))
|
||||
{
|
||||
LOGE("wglMakeCurrent() failed for OpenGL context.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
wglDeleteContext(m_hRC);
|
||||
m_hRC = hRC;
|
||||
#ifndef NDEBUG
|
||||
|
||||
PFNGLDEBUGMESSAGECALLBACKARBPROC fn_glDebugMessageCallbackARB =
|
||||
(PFNGLDEBUGMESSAGECALLBACKARBPROC)wglGetProcAddress("glDebugMessageCallbackARB");
|
||||
PFNGLDEBUGMESSAGECONTROLARBPROC fn_glDebugMessageControlARB =
|
||||
(PFNGLDEBUGMESSAGECONTROLARBPROC)wglGetProcAddress("glDebugMessageControlARB");
|
||||
|
||||
if(fn_glDebugMessageCallbackARB)
|
||||
{
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
||||
fn_glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
|
||||
fn_glDebugMessageCallbackARB(myOpenGLCallback, ctxwindow);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
m_wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
|
||||
m_wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
|
||||
|
||||
if(!s_module)
|
||||
{
|
||||
s_module = LoadLibraryA("opengl32.dll");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void deinit()
|
||||
{
|
||||
wglDeleteContext(m_hRC);
|
||||
if(m_hDCaffinity)
|
||||
{
|
||||
m_wglDeleteDCNV(m_hDCaffinity);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void ContextWindow::makeContextCurrent()
|
||||
{
|
||||
wglMakeCurrent(m_internal->m_hDC, m_internal->m_hRC);
|
||||
}
|
||||
|
||||
void ContextWindow::makeContextNonCurrent()
|
||||
{
|
||||
wglMakeCurrent(0, 0);
|
||||
}
|
||||
|
||||
|
||||
int ContextWindow::extensionSupported(const char* name)
|
||||
{
|
||||
// we are not using the glew query, as glew will only report
|
||||
// those extension it knows about, not what the actual driver may support
|
||||
|
||||
int i;
|
||||
GLint count;
|
||||
|
||||
// Check if extension is in the modern OpenGL extensions string list
|
||||
// This should be safe to use since GL 3.0 is around for a long time :)
|
||||
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &count);
|
||||
|
||||
for(i = 0; i < count; i++)
|
||||
{
|
||||
const char* en = (const char*)glGetStringi(GL_EXTENSIONS, i);
|
||||
if(!en)
|
||||
{
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if(strcmp(en, name) == 0)
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Check platform specifc gets
|
||||
const char* exts = NULL;
|
||||
|
||||
if(m_internal->m_wglGetExtensionsStringARB)
|
||||
{
|
||||
exts = m_internal->m_wglGetExtensionsStringARB(m_internal->m_hDC);
|
||||
}
|
||||
if(!exts)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return stringInExtensionString(name, exts);
|
||||
}
|
||||
|
||||
|
||||
void* ContextWindow::sysGetProcAddress(const char* name)
|
||||
{
|
||||
void* p = (void*)wglGetProcAddress(name);
|
||||
if(p == 0 || (p == (void*)0x1) || (p == (void*)0x2) || (p == (void*)0x3) || (p == (void*)-1))
|
||||
{
|
||||
p = (void*)GetProcAddress(s_module, name);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void ContextWindow::swapInterval(int i)
|
||||
{
|
||||
m_internal->m_wglSwapIntervalEXT(i);
|
||||
}
|
||||
|
||||
void ContextWindow::swapBuffers()
|
||||
{
|
||||
SwapBuffers(m_internal->m_hDC);
|
||||
}
|
||||
#else
|
||||
|
||||
struct ContextWindowInternalGL
|
||||
{
|
||||
GLFWwindow* m_glfwwindow = nullptr;
|
||||
|
||||
bool init(const ContextWindowCreateInfo& settings, GLFWwindow* sourcewindow, ContextWindow* ctxwindow)
|
||||
{
|
||||
m_glfwwindow = sourcewindow;
|
||||
glfwMakeContextCurrent(m_glfwwindow);
|
||||
|
||||
#ifndef NDEBUG
|
||||
PFNGLDEBUGMESSAGECALLBACKARBPROC fn_glDebugMessageCallbackARB =
|
||||
(PFNGLDEBUGMESSAGECALLBACKARBPROC)glfwGetProcAddress("glDebugMessageCallbackARB");
|
||||
PFNGLDEBUGMESSAGECONTROLARBPROC fn_glDebugMessageControlARB =
|
||||
(PFNGLDEBUGMESSAGECONTROLARBPROC)glfwGetProcAddress("glDebugMessageControlARB");
|
||||
|
||||
if(fn_glDebugMessageCallbackARB)
|
||||
{
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
||||
fn_glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
|
||||
fn_glDebugMessageCallbackARB(myOpenGLCallback, ctxwindow);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void deinit() {}
|
||||
};
|
||||
|
||||
void ContextWindow::makeContextCurrent()
|
||||
{
|
||||
glfwMakeContextCurrent(m_internal->m_glfwwindow);
|
||||
}
|
||||
|
||||
void ContextWindow::makeContextNonCurrent()
|
||||
{
|
||||
glfwMakeContextCurrent(NULL);
|
||||
}
|
||||
|
||||
|
||||
int ContextWindow::extensionSupported(const char* name)
|
||||
{
|
||||
// we are not using the glew query, as glew will only report
|
||||
// those extension it knows about, not what the actual driver may support
|
||||
|
||||
int i;
|
||||
GLint count;
|
||||
|
||||
// Check if extension is in the modern OpenGL extensions string list
|
||||
// This should be safe to use since GL 3.0 is around for a long time :)
|
||||
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &count);
|
||||
|
||||
for(i = 0; i < count; i++)
|
||||
{
|
||||
const char* en = (const char*)glGetStringi(GL_EXTENSIONS, i);
|
||||
if(!en)
|
||||
{
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if(strcmp(en, name) == 0)
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
// Check platform specifc gets
|
||||
const char* exts = glXQueryExtensionsString(glfwGetX11Display(), 0);
|
||||
|
||||
if(!exts)
|
||||
{
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
return stringInExtensionString(name, exts);
|
||||
}
|
||||
|
||||
void* ContextWindow::sysGetProcAddress(const char* name)
|
||||
{
|
||||
void* p = (void*)glfwGetProcAddress(name);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void ContextWindow::swapInterval(int i)
|
||||
{
|
||||
glfwSwapInterval(i);
|
||||
}
|
||||
|
||||
void ContextWindow::swapBuffers()
|
||||
{
|
||||
glfwSwapBuffers(m_internal->m_glfwwindow);
|
||||
}
|
||||
|
||||
#endif
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ContextWindow::ContextWindow()
|
||||
{
|
||||
if(m_internal)
|
||||
{
|
||||
delete m_internal;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool ContextWindow::init(const ContextWindowCreateInfo* cflags, GLFWwindow* sourcewindow, const char* dbgTitle)
|
||||
{
|
||||
if(!m_internal)
|
||||
{
|
||||
m_internal = new ContextWindowInternalGL;
|
||||
}
|
||||
|
||||
ContextWindowCreateInfo settings;
|
||||
if(cflags)
|
||||
{
|
||||
settings = *cflags;
|
||||
}
|
||||
|
||||
m_debugFilter = GL_DEBUG_SEVERITY_HIGH_ARB;
|
||||
m_debugTitle = dbgTitle;
|
||||
|
||||
if(m_internal->init(settings, sourcewindow, this))
|
||||
{
|
||||
load_GL(ContextWindow::sysGetProcAddress);
|
||||
|
||||
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
||||
|
||||
GLint major = 0;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||
GLint minor = 0;
|
||||
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
||||
|
||||
if(major < settings.major || (major == settings.major && minor < settings.minor))
|
||||
{
|
||||
LOGE(" OpenGL context version too low: required %d.%d, found %d.%d\n", settings.major, settings.minor, major, minor);
|
||||
return false;
|
||||
}
|
||||
|
||||
int version = major * 10 + minor;
|
||||
int success = 1;
|
||||
|
||||
#define HAS_VERSION(MA, MI) \
|
||||
if(version >= (MA * 10 + MI)) \
|
||||
success = success && has_GL_VERSION_##MA##_##MI;
|
||||
HAS_VERSION(1, 1);
|
||||
HAS_VERSION(1, 2);
|
||||
HAS_VERSION(1, 3);
|
||||
HAS_VERSION(1, 4);
|
||||
HAS_VERSION(1, 5);
|
||||
HAS_VERSION(2, 0);
|
||||
HAS_VERSION(2, 1);
|
||||
HAS_VERSION(3, 0);
|
||||
HAS_VERSION(3, 1);
|
||||
HAS_VERSION(3, 2);
|
||||
HAS_VERSION(3, 3);
|
||||
HAS_VERSION(4, 0);
|
||||
HAS_VERSION(4, 1);
|
||||
HAS_VERSION(4, 2);
|
||||
HAS_VERSION(4, 3);
|
||||
HAS_VERSION(4, 4);
|
||||
HAS_VERSION(4, 5);
|
||||
HAS_VERSION(4, 6);
|
||||
#undef HAS_VERSION
|
||||
|
||||
if(!success)
|
||||
{
|
||||
LOGE(" OpenGL context version incomplete symbols\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_deviceName = std::string(renderer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void* ContextWindow::getProcAddress(const char* name)
|
||||
{
|
||||
return sysGetProcAddress(name);
|
||||
}
|
||||
|
||||
void ContextWindow::screenshot(const char* filename, int x, int y, int width, int height, unsigned char* data)
|
||||
{
|
||||
glFinish();
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
if(filename)
|
||||
{
|
||||
saveBMP(filename, width, height, data);
|
||||
}
|
||||
}
|
||||
|
||||
void ContextWindow::deinit()
|
||||
{
|
||||
makeContextNonCurrent();
|
||||
m_internal->deinit();
|
||||
}
|
||||
} // namespace nvgl
|
||||
120
raytracer/nvpro_core/nvgl/contextwindow_gl.hpp
Normal file
120
raytracer/nvpro_core/nvgl/contextwindow_gl.hpp
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) 2013-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) 2013-2021 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
//--------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace nvgl {
|
||||
|
||||
/** @DOC_START
|
||||
# struct nvgl::ContextWindowCreateInfo
|
||||
|
||||
Set up the context properties for a OpenGL ContextWindow.
|
||||
e.g. version, core/compatibiltiy etc.
|
||||
@DOC_END */
|
||||
|
||||
struct ContextWindowCreateInfo
|
||||
{
|
||||
int major;
|
||||
int minor;
|
||||
int device;
|
||||
|
||||
int MSAA;
|
||||
int depth;
|
||||
int stencil;
|
||||
bool debug;
|
||||
bool robust;
|
||||
bool core;
|
||||
bool forward;
|
||||
bool stereo;
|
||||
class ContextWindow* share;
|
||||
|
||||
ContextWindowCreateInfo(int _major = 4,
|
||||
int _minor = 3,
|
||||
bool _core = false,
|
||||
int _MSAA = 0,
|
||||
int _depth = 24,
|
||||
int _stencil = 8,
|
||||
bool _debug = false,
|
||||
bool _robust = false,
|
||||
bool _forward = false,
|
||||
bool _stereo = false,
|
||||
class ContextWindow* _share = 0)
|
||||
{
|
||||
major = _major;
|
||||
minor = _minor;
|
||||
MSAA = _MSAA;
|
||||
depth = _depth;
|
||||
stencil = _stencil;
|
||||
core = _core;
|
||||
debug = _debug;
|
||||
robust = _robust;
|
||||
forward = _forward;
|
||||
stereo = _stereo;
|
||||
share = _share;
|
||||
device = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/** @DOC_START
|
||||
# class nvgl::ContextWindow
|
||||
|
||||
nvgl::ContextWindow sets up an OpenGL context from a provided `GLFWwindow`.
|
||||
Makes use of `glDebugMessageCallback` to hook up an error callback
|
||||
and loads all extensions provided by `extensions_gl.hpp`
|
||||
@DOC_END */
|
||||
|
||||
class ContextWindow
|
||||
{
|
||||
public:
|
||||
struct ContextWindowInternalGL* m_internal = nullptr;
|
||||
|
||||
uint32_t m_debugFilter = 0;
|
||||
std::string m_debugTitle;
|
||||
std::string m_deviceName;
|
||||
|
||||
ContextWindow(ContextWindow const&) = delete;
|
||||
ContextWindow& operator=(ContextWindow const&) = delete;
|
||||
|
||||
ContextWindow();
|
||||
|
||||
bool init(const ContextWindowCreateInfo* cflags, GLFWwindow* window, const char* dbgTitle = "test");
|
||||
void deinit();
|
||||
|
||||
void swapInterval(int i);
|
||||
void swapBuffers();
|
||||
|
||||
int extensionSupported(const char* name);
|
||||
void* getProcAddress(const char* name);
|
||||
|
||||
void makeContextCurrent();
|
||||
void makeContextNonCurrent();
|
||||
|
||||
void screenshot(const char* filename, int x, int y, int width, int height, unsigned char* data);
|
||||
|
||||
// TODO: check if this is really necessary : local method getProcAddressGL could be enough
|
||||
static void* sysGetProcAddress(const char* name);
|
||||
};
|
||||
|
||||
} // namespace nvgl
|
||||
399
raytracer/nvpro_core/nvgl/error_gl.cpp
Normal file
399
raytracer/nvpro_core/nvgl/error_gl.cpp
Normal file
|
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
||||
#include "error_gl.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace nvgl {
|
||||
|
||||
bool checkNamedFramebuffer(GLuint fbo)
|
||||
{
|
||||
GLenum status = glCheckNamedFramebufferStatus(fbo, GL_FRAMEBUFFER);
|
||||
switch(status)
|
||||
{
|
||||
case GL_FRAMEBUFFER_UNDEFINED:
|
||||
LOGE("OpenGL Error(%s)\n", "GL_FRAMEBUFFER_UNDEFINED");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
||||
LOGE("OpenGL Error(%s)\n", "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
|
||||
LOGE("OpenGL Error(%s)\n", "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
|
||||
LOGE("OpenGL Error(%s)\n", "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
|
||||
LOGE("OpenGL Error(%s)\n", "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED:
|
||||
LOGE("OpenGL Error(%s)\n", "GL_FRAMEBUFFER_UNSUPPORTED");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
|
||||
LOGE("OpenGL Error(%s)\n", "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
|
||||
LOGE("OpenGL Error(%s)\n", "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS");
|
||||
break;
|
||||
}
|
||||
|
||||
return status != GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
|
||||
bool checkGLVersion(GLint MajorVersionRequire, GLint MinorVersionRequire)
|
||||
{
|
||||
GLint MajorVersionContext = 0;
|
||||
GLint MinorVersionContext = 0;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &MajorVersionContext);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &MinorVersionContext);
|
||||
return (MajorVersionContext * 100 + MinorVersionContext * 10) >= (MajorVersionRequire * 100 + MinorVersionRequire * 10);
|
||||
}
|
||||
|
||||
bool checkExtension(char const* String)
|
||||
{
|
||||
GLint ExtensionCount = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &ExtensionCount);
|
||||
for(GLint i = 0; i < ExtensionCount; ++i)
|
||||
if(std::string((char const*)glGetStringi(GL_EXTENSIONS, i)) == std::string(String))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool checkError(const char* Title)
|
||||
{
|
||||
int Error;
|
||||
if((Error = glGetError()) != GL_NO_ERROR)
|
||||
{
|
||||
std::string ErrorString;
|
||||
switch(Error)
|
||||
{
|
||||
case GL_INVALID_ENUM:
|
||||
ErrorString = "GL_INVALID_ENUM";
|
||||
break;
|
||||
case GL_INVALID_VALUE:
|
||||
ErrorString = "GL_INVALID_VALUE";
|
||||
break;
|
||||
case GL_INVALID_OPERATION:
|
||||
ErrorString = "GL_INVALID_OPERATION";
|
||||
break;
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
ErrorString = "GL_INVALID_FRAMEBUFFER_OPERATION";
|
||||
break;
|
||||
case GL_OUT_OF_MEMORY:
|
||||
ErrorString = "GL_OUT_OF_MEMORY";
|
||||
break;
|
||||
default:
|
||||
ErrorString = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
LOGE("OpenGL Error(%s): %s\n", ErrorString.c_str(), Title);
|
||||
}
|
||||
return Error == GL_NO_ERROR;
|
||||
}
|
||||
|
||||
bool checkBindings(int bindingBits, const char* marker, int num)
|
||||
{
|
||||
bool bound = false;
|
||||
GLint obj = 0;
|
||||
|
||||
#define GLERRCHECKBOUND(name, obj) \
|
||||
glGetIntegerv(name, (obj)); \
|
||||
if(*(obj)) \
|
||||
{ \
|
||||
bound = true; \
|
||||
LOGW("OpenGL bound: %s\n", #name); \
|
||||
}
|
||||
|
||||
#define GLERRCHECKBOUNDFN(fn, what, obj) \
|
||||
fn; \
|
||||
if(*(obj)) \
|
||||
{ \
|
||||
bound = true; \
|
||||
LOGW("OpenGL bound: %s\n", what); \
|
||||
}
|
||||
|
||||
#define GLERRCHECKBOUNDUNIT(i, name, obj) \
|
||||
glGetIntegerv(name, (obj)); \
|
||||
if(*(obj)) \
|
||||
{ \
|
||||
bound = true; \
|
||||
LOGW("OpenGL bound: %s %d\n", #name, i); \
|
||||
}
|
||||
|
||||
#define GLERRCHECKBOUNDINDEXED(name, i, obj) \
|
||||
glGetIntegeri_v(name, i, (obj)); \
|
||||
if(*(obj)) \
|
||||
{ \
|
||||
bound = true; \
|
||||
LOGW("OpenGL bound: %s %d\n", #name, i); \
|
||||
}
|
||||
|
||||
if(bindingBits & CHECKBINDING_VAO_BIT)
|
||||
{
|
||||
GLERRCHECKBOUND(GL_VERTEX_ARRAY_BINDING, &obj);
|
||||
}
|
||||
if(bindingBits & CHECKBINDING_FBO_BIT)
|
||||
{
|
||||
GLERRCHECKBOUND(GL_DRAW_FRAMEBUFFER_BINDING, &obj);
|
||||
GLERRCHECKBOUND(GL_READ_FRAMEBUFFER_BINDING, &obj);
|
||||
}
|
||||
if(bindingBits & CHECKBINDING_PROGRAM_BIT)
|
||||
{
|
||||
GLERRCHECKBOUND(GL_CURRENT_PROGRAM, &obj);
|
||||
GLERRCHECKBOUND(GL_PROGRAM_PIPELINE_BINDING, &obj);
|
||||
}
|
||||
if(bindingBits & CHECKBINDING_IMAGES_BIT)
|
||||
{
|
||||
GLint units;
|
||||
glGetIntegerv(GL_MAX_IMAGE_UNITS, &units);
|
||||
for(int i = 0; i < units; i++)
|
||||
{
|
||||
GLERRCHECKBOUNDINDEXED(GL_IMAGE_BINDING_NAME, i, &obj);
|
||||
}
|
||||
}
|
||||
if(bindingBits & CHECKBINDING_BUFFERS_BIT)
|
||||
{
|
||||
GLERRCHECKBOUND(GL_ARRAY_BUFFER_BINDING, &obj);
|
||||
GLERRCHECKBOUND(GL_ELEMENT_ARRAY_BUFFER_BINDING, &obj);
|
||||
GLERRCHECKBOUND(GL_PIXEL_PACK_BUFFER_BINDING, &obj);
|
||||
GLERRCHECKBOUND(GL_PIXEL_UNPACK_BUFFER_BINDING, &obj);
|
||||
GLERRCHECKBOUND(GL_UNIFORM_BUFFER_BINDING, &obj);
|
||||
GLERRCHECKBOUND(GL_TRANSFORM_FEEDBACK_BINDING, &obj);
|
||||
GLERRCHECKBOUND(GL_SHADER_STORAGE_BUFFER_BINDING, &obj);
|
||||
GLERRCHECKBOUND(GL_ATOMIC_COUNTER_BUFFER_BINDING, &obj);
|
||||
GLERRCHECKBOUND(GL_TEXTURE_BUFFER_BINDING, &obj);
|
||||
GLERRCHECKBOUND(GL_COPY_READ_BUFFER_BINDING, &obj);
|
||||
GLERRCHECKBOUND(GL_COPY_WRITE_BUFFER_BINDING, &obj);
|
||||
|
||||
GLint units;
|
||||
glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &units);
|
||||
for(int i = 0; i < units; i++)
|
||||
{
|
||||
GLERRCHECKBOUNDINDEXED(GL_VERTEX_BINDING_BUFFER, i, &obj);
|
||||
}
|
||||
|
||||
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &units);
|
||||
for(int i = 0; i < units; i++)
|
||||
{
|
||||
GLERRCHECKBOUNDINDEXED(GL_UNIFORM_BUFFER_BINDING, i, &obj);
|
||||
}
|
||||
|
||||
glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &units);
|
||||
for(int i = 0; i < units; i++)
|
||||
{
|
||||
GLERRCHECKBOUNDINDEXED(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, i, &obj);
|
||||
}
|
||||
|
||||
glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &units);
|
||||
for(int i = 0; i < units; i++)
|
||||
{
|
||||
GLERRCHECKBOUNDINDEXED(GL_SHADER_STORAGE_BUFFER_BINDING, i, &obj);
|
||||
}
|
||||
|
||||
glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &units);
|
||||
for(int i = 0; i < units; i++)
|
||||
{
|
||||
GLERRCHECKBOUNDINDEXED(GL_ATOMIC_COUNTER_BUFFER_BINDING, i, &obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(bindingBits & (CHECKBINDING_TEXTURES_BIT | CHECKBINDING_SAMPLERS_BIT))
|
||||
{
|
||||
GLint currentUnit;
|
||||
GLint units;
|
||||
|
||||
glGetIntegerv(GL_ACTIVE_TEXTURE, ¤tUnit);
|
||||
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units);
|
||||
|
||||
for(int i = 0; i < units; i++)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
if(bindingBits & CHECKBINDING_TEXTURES_BIT)
|
||||
{
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_1D, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_2D, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_3D, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_1D_ARRAY, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_2D_ARRAY, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_CUBE_MAP, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_CUBE_MAP_ARRAY, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_2D_MULTISAMPLE, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_CUBE_MAP, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_CUBE_MAP_ARRAY, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_BUFFER, &obj);
|
||||
GLERRCHECKBOUNDUNIT(i, GL_TEXTURE_BINDING_RECTANGLE, &obj);
|
||||
}
|
||||
if(bindingBits & CHECKBINDING_SAMPLERS_BIT)
|
||||
{
|
||||
GLERRCHECKBOUND(GL_SAMPLER_BINDING, &obj);
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(currentUnit);
|
||||
}
|
||||
|
||||
if(bindingBits & CHECKBINDING_XFB_BIT)
|
||||
{
|
||||
GLERRCHECKBOUND(GL_TRANSFORM_FEEDBACK_BINDING, &obj);
|
||||
}
|
||||
|
||||
if(bindingBits & CHECKBINDING_VATTRIBS_BIT)
|
||||
{
|
||||
GLint units;
|
||||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &units);
|
||||
GLint enabled;
|
||||
for(int i = 0; i < units; i++)
|
||||
{
|
||||
glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
|
||||
if(enabled)
|
||||
{
|
||||
bound = true;
|
||||
LOGW("OpenGL enabled: vertex %d\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bound)
|
||||
{
|
||||
if(marker)
|
||||
{
|
||||
LOGW("%s %d\n\n", marker, num);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGW("\n");
|
||||
}
|
||||
}
|
||||
#undef GLERRCHECKBOUNDUNIT
|
||||
#undef GLERRCHECKBOUND
|
||||
#undef GLERRCHECKBOUNDINDEXED
|
||||
#undef GLERRCHECKBOUNDFN
|
||||
|
||||
return !bound;
|
||||
}
|
||||
|
||||
bool checkTextureTarget(GLuint texture, GLenum target)
|
||||
{
|
||||
GLenum param;
|
||||
glGetTextureParameterIiv(texture, GL_TEXTURE_TARGET, (GLint*)¶m);
|
||||
return param == target;
|
||||
}
|
||||
|
||||
bool checkTextureTarget(GLuint texture, GLenum target, const char* name, const char* marker, int num)
|
||||
{
|
||||
if(!checkTextureTarget(texture, target))
|
||||
{
|
||||
if(marker)
|
||||
{
|
||||
LOGW("OpenGL unexpected texture target (%s)\n - %s %d\n", name, marker, num);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGW("OpenGL unexpected texture target (%s)\n", name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CheckBufferResidency::addAddress(uint64_t address, uint64_t size)
|
||||
{
|
||||
Entry entry;
|
||||
entry.address = address;
|
||||
entry.size = size;
|
||||
|
||||
m_entries.push_back(entry);
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void CheckBufferResidency::removeAddress(uint64_t address)
|
||||
{
|
||||
size_t idx = find(address);
|
||||
|
||||
m_entries[idx] = m_entries[m_entries.size() - 1];
|
||||
m_entries.pop_back();
|
||||
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
bool CheckBufferResidency::checkAddress(uint64_t address)
|
||||
{
|
||||
size_t idx = find(address);
|
||||
|
||||
return (idx != ~0);
|
||||
}
|
||||
|
||||
size_t CheckBufferResidency::find(uint64_t address)
|
||||
{
|
||||
if(m_entries.empty())
|
||||
return ~0;
|
||||
|
||||
if(m_dirty)
|
||||
{
|
||||
sort();
|
||||
}
|
||||
|
||||
size_t count = m_entries.size();
|
||||
size_t begin = 0;
|
||||
|
||||
while(count > 0)
|
||||
{
|
||||
size_t idx = begin;
|
||||
size_t step = count / 2;
|
||||
idx += step;
|
||||
|
||||
if(m_entries[idx].address < address)
|
||||
{
|
||||
begin = idx + 1;
|
||||
count -= step + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = step;
|
||||
}
|
||||
}
|
||||
|
||||
if(begin == m_entries.size() || m_entries[begin].address != address)
|
||||
{
|
||||
begin = std::max(begin - 1, size_t(0));
|
||||
}
|
||||
|
||||
if(m_entries[begin].address <= address && address < m_entries[begin].address + m_entries[begin].size)
|
||||
{
|
||||
return begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ~0;
|
||||
}
|
||||
}
|
||||
|
||||
void CheckBufferResidency::sort()
|
||||
{
|
||||
std::sort(m_entries.begin(), m_entries.end(), Entry_compare);
|
||||
m_dirty = false;
|
||||
}
|
||||
} // namespace nvgl
|
||||
136
raytracer/nvpro_core/nvgl/error_gl.hpp
Normal file
136
raytracer/nvpro_core/nvgl/error_gl.hpp
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* 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 NVGL_ERROR_INCLUDED
|
||||
#define NVGL_ERROR_INCLUDED
|
||||
|
||||
#include <include_gl.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <nvh/nvprint.hpp>
|
||||
|
||||
/** @DOC_START
|
||||
# functions in nvgl
|
||||
|
||||
Several utility functions that aid debugging. Check if all bindings
|
||||
are cleared, framebuffer complete etc.
|
||||
@DOC_END */
|
||||
|
||||
namespace nvgl {
|
||||
// tests if version is available
|
||||
bool checkGLVersion(GLint MajorVersionRequire, GLint MinorVersionRequire);
|
||||
|
||||
// tests if extension string is available
|
||||
bool checkExtension(char const* String);
|
||||
|
||||
// tests against any gl error
|
||||
bool checkError(const char* Title);
|
||||
|
||||
// tests for framebuffer incompleteness, also prints errors
|
||||
bool checkNamedFramebuffer(GLuint fbo);
|
||||
|
||||
enum CheckBindingBits
|
||||
{
|
||||
CHECKBINDING_VAO_BIT = 1 << 0,
|
||||
CHECKBINDING_FBO_BIT = 1 << 1,
|
||||
CHECKBINDING_PROGRAM_BIT = 1 << 2,
|
||||
CHECKBINDING_TEXTURES_BIT = 1 << 3,
|
||||
CHECKBINDING_SAMPLERS_BIT = 1 << 4,
|
||||
CHECKBINDING_BUFFERS_BIT = 1 << 5,
|
||||
CHECKBINDING_IMAGES_BIT = 1 << 6,
|
||||
CHECKBINDING_XFB_BIT = 1 << 7,
|
||||
CHECKBINDING_VATTRIBS_BIT = 1 << 8,
|
||||
CHECKBINDING_ALL_BITS = ~0,
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define DBG_CHECKBINDINGS(bindingBits) nvgl::checkBindings(bindingBits, __FILE__, __LINE__);
|
||||
#else
|
||||
#define DBG_CHECKBINDINGS(bindingBits)
|
||||
#endif
|
||||
|
||||
// tests if the bindings specified by the bits are set to 0
|
||||
bool checkBindings(int bindingBits, const char* marker = NULL, int num = 0);
|
||||
|
||||
// tests if the texture has the expected target
|
||||
bool checkTextureTarget(GLuint texture, GLenum target);
|
||||
bool checkTextureTarget(GLuint texture, GLenum target, const char* name, const char* marker = NULL, int num = 0);
|
||||
|
||||
|
||||
/** @DOC_START
|
||||
# template class nvgl::CheckBufferContent
|
||||
Utility wrapper to downlad buffer data into a temp vector for debugging
|
||||
@DOC_END */
|
||||
template <class T>
|
||||
class CheckBufferContent
|
||||
{
|
||||
public:
|
||||
std::vector<T> content;
|
||||
|
||||
CheckBufferContent(GLuint buffer, size_t offset, size_t size)
|
||||
{
|
||||
size_t elements = size / sizeof(T);
|
||||
content.resize(elements);
|
||||
glGetNamedBufferSubData(buffer, offset, elements * sizeof(T), content.data());
|
||||
elements = elements;
|
||||
}
|
||||
};
|
||||
|
||||
/** @DOC_START
|
||||
# class nvgl::CheckBufferResidency
|
||||
nvgl::CheckBufferResidency utility class to test if a certain gpu address is coming from
|
||||
a resident buffer. Register the address of buffers in advance.
|
||||
@DOC_END */
|
||||
class CheckBufferResidency
|
||||
{
|
||||
public:
|
||||
void addAddress(uint64_t address, uint64_t size);
|
||||
void removeAddress(uint64_t address);
|
||||
bool checkAddress(uint64_t address);
|
||||
size_t getEntryNum() const { return m_entries.size(); }
|
||||
|
||||
private:
|
||||
struct Entry
|
||||
{
|
||||
uint64_t address = 0;
|
||||
uint64_t size = 0;
|
||||
|
||||
Entry() {}
|
||||
Entry(uint64_t address, uint64_t size = 0)
|
||||
: address(address)
|
||||
, size(size)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
size_t find(uint64_t address);
|
||||
|
||||
static bool Entry_compare(const Entry& a, const Entry& b) { return a.address < b.address; }
|
||||
|
||||
void sort();
|
||||
|
||||
bool m_dirty;
|
||||
std::vector<Entry> m_entries;
|
||||
};
|
||||
} // namespace nvgl
|
||||
|
||||
|
||||
#endif //NV_ERROR_INCLUDED
|
||||
2
raytracer/nvpro_core/nvgl/extensions_gl.bat
Normal file
2
raytracer/nvpro_core/nvgl/extensions_gl.bat
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
..\..\nvpro_internal\luajit\win_x64\luajit.exe extensions_gl.lua
|
||||
pause
|
||||
7946
raytracer/nvpro_core/nvgl/extensions_gl.cpp
Normal file
7946
raytracer/nvpro_core/nvgl/extensions_gl.cpp
Normal file
File diff suppressed because it is too large
Load diff
312
raytracer/nvpro_core/nvgl/extensions_gl.hpp
Normal file
312
raytracer/nvpro_core/nvgl/extensions_gl.hpp
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
/* auto generated by extensions_gl.lua */
|
||||
/*
|
||||
* Copyright (c) 2018-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) 2018-2021 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** @DOC_START
|
||||
# function load_GL
|
||||
> An OpenGL Extension loader
|
||||
|
||||
Provides a subset of OpenGL Extensions generated by `extensions_gl.lua`.
|
||||
The framework uses a sanitized OpenGL header that is mostly core functionality.
|
||||
`GL/glsubset.h` is generated using a enablelist by the lua script
|
||||
from `GL/glcustom.h` (which is mostly based on `glcorearb.h` with some
|
||||
additional extensions and features)
|
||||
@DOC_END */
|
||||
|
||||
#pragma once
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/glsubset.h>
|
||||
|
||||
typedef void* (* nvGLLoaderGetProcFN)(const char* name);
|
||||
|
||||
/* structs */
|
||||
/* GL_NV_command_list */
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
} TerminateSequenceCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
} NOPCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint count;
|
||||
GLuint firstIndex;
|
||||
GLuint baseVertex;
|
||||
} DrawElementsCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint count;
|
||||
GLuint first;
|
||||
} DrawArraysCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLenum mode;
|
||||
GLuint count;
|
||||
GLuint instanceCount;
|
||||
GLuint firstIndex;
|
||||
GLuint baseVertex;
|
||||
GLuint baseInstance;
|
||||
} DrawElementsInstancedCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLenum mode;
|
||||
GLuint count;
|
||||
GLuint instanceCount;
|
||||
GLuint first;
|
||||
GLuint baseInstance;
|
||||
} DrawArraysInstancedCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint addressLo;
|
||||
GLuint addressHi;
|
||||
GLuint typeSizeInByte;
|
||||
} ElementAddressCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint index;
|
||||
GLuint addressLo;
|
||||
GLuint addressHi;
|
||||
} AttributeAddressCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLushort index;
|
||||
GLushort stage;
|
||||
GLuint addressLo;
|
||||
GLuint addressHi;
|
||||
} UniformAddressCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
float alpha;
|
||||
} BlendColorCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint frontStencilRef;
|
||||
GLuint backStencilRef;
|
||||
} StencilRefCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
float lineWidth;
|
||||
} LineWidthCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
float scale;
|
||||
float bias;
|
||||
} PolygonOffsetCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
float alphaRef;
|
||||
} AlphaRefCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint x;
|
||||
GLuint y;
|
||||
GLuint width;
|
||||
GLuint height;
|
||||
} ViewportCommandNV; /* only ViewportIndex 0 */
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint x;
|
||||
GLuint y;
|
||||
GLuint width;
|
||||
GLuint height;
|
||||
} ScissorCommandNV; /* only ViewportIndex 0 */
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint frontFace; /* 0 for CW, 1 for CCW */
|
||||
} FrontFaceCommandNV;
|
||||
|
||||
|
||||
/* loader */
|
||||
|
||||
void load_GL(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
|
||||
/* availables */
|
||||
extern int has_GL_VERSION_1_1;
|
||||
extern int has_GL_VERSION_1_2;
|
||||
extern int has_GL_VERSION_1_3;
|
||||
extern int has_GL_VERSION_1_4;
|
||||
extern int has_GL_VERSION_1_5;
|
||||
extern int has_GL_VERSION_2_0;
|
||||
extern int has_GL_VERSION_2_1;
|
||||
extern int has_GL_VERSION_3_0;
|
||||
extern int has_GL_VERSION_3_1;
|
||||
extern int has_GL_VERSION_3_2;
|
||||
extern int has_GL_VERSION_3_3;
|
||||
extern int has_GL_VERSION_4_0;
|
||||
extern int has_GL_VERSION_4_1;
|
||||
extern int has_GL_VERSION_4_2;
|
||||
extern int has_GL_VERSION_4_3;
|
||||
extern int has_GL_VERSION_4_4;
|
||||
extern int has_GL_VERSION_4_5;
|
||||
extern int has_GL_VERSION_4_6;
|
||||
extern int has_GL_ARB_bindless_texture;
|
||||
extern int has_GL_ARB_cl_event;
|
||||
extern int has_GL_ARB_debug_output;
|
||||
extern int has_GL_ARB_indirect_parameters;
|
||||
extern int has_GL_ARB_shading_language_include;
|
||||
extern int has_GL_ARB_texture_filter_minmax;
|
||||
extern int has_GL_ARB_texture_float;
|
||||
extern int has_GL_EXT_memory_object;
|
||||
extern int has_GL_EXT_memory_object_fd;
|
||||
extern int has_GL_EXT_memory_object_win32;
|
||||
extern int has_GL_EXT_semaphore;
|
||||
extern int has_GL_EXT_semaphore_fd;
|
||||
extern int has_GL_EXT_semaphore_win32;
|
||||
extern int has_GL_EXT_texture_compression_latc;
|
||||
extern int has_GL_EXT_texture_compression_s3tc;
|
||||
extern int has_GL_NV_bindless_texture;
|
||||
extern int has_GL_NV_blend_equation_advanced;
|
||||
extern int has_GL_NV_clip_space_w_scaling;
|
||||
extern int has_GL_NV_command_list;
|
||||
extern int has_GL_NV_compute_shader_derivatives;
|
||||
extern int has_GL_NV_conservative_raster;
|
||||
extern int has_GL_NV_conservative_raster_dilate;
|
||||
extern int has_GL_NV_conservative_raster_pre_snap;
|
||||
extern int has_GL_NV_conservative_raster_pre_snap_triangles;
|
||||
extern int has_GL_NV_conservative_raster_underestimation;
|
||||
extern int has_GL_NV_draw_vulkan_image;
|
||||
extern int has_GL_NV_draw_texture;
|
||||
extern int has_GL_NV_fill_rectangle;
|
||||
extern int has_GL_NV_fragment_coverage_to_color;
|
||||
extern int has_GL_NV_fragment_shader_barycentric;
|
||||
extern int has_GL_NV_fragment_shader_interlock;
|
||||
extern int has_GL_NV_framebuffer_mixed_samples;
|
||||
extern int has_GL_NV_gpu_multicast;
|
||||
extern int has_GL_NV_gpu_shader5;
|
||||
extern int has_GL_NV_internalformat_sample_query;
|
||||
extern int has_GL_NV_memory_attachment;
|
||||
extern int has_GL_NV_mesh_shader;
|
||||
extern int has_GL_NV_path_rendering;
|
||||
extern int has_GL_NV_representative_fragment_test;
|
||||
extern int has_GL_NV_sample_locations;
|
||||
extern int has_GL_NV_sample_mask_override_coverage;
|
||||
extern int has_GL_NV_scissor_exclusive;
|
||||
extern int has_GL_NV_shader_atomic_int64;
|
||||
extern int has_GL_NV_shader_buffer_load;
|
||||
extern int has_GL_NV_shader_buffer_store;
|
||||
extern int has_GL_NV_shader_texture_footprint;
|
||||
extern int has_GL_NV_shader_thread_group;
|
||||
extern int has_GL_NV_shader_thread_shuffle;
|
||||
extern int has_GL_NV_shading_rate_image;
|
||||
extern int has_GL_NV_stereo_view_rendering;
|
||||
extern int has_GL_NV_texture_multisample;
|
||||
extern int has_GL_NV_uniform_buffer_unified_memory;
|
||||
extern int has_GL_NV_vertex_buffer_unified_memory;
|
||||
extern int has_GL_NV_viewport_swizzle;
|
||||
extern int has_GL_NVX_gpu_memory_info;
|
||||
extern int has_GL_NV_query_resource;
|
||||
extern int has_GL_NV_query_resource_tag;
|
||||
|
||||
/* loaders */
|
||||
int load_GL_VERSION_1_1(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_1_2(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_1_3(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_1_4(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_1_5(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_2_0(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_2_1(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_3_0(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_3_1(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_3_2(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_3_3(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_4_0(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_4_1(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_4_2(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_4_3(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_4_4(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_4_5(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_VERSION_4_6(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_ARB_bindless_texture(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_ARB_cl_event(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_ARB_debug_output(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_ARB_indirect_parameters(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_ARB_shading_language_include(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_ARB_texture_filter_minmax(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_ARB_texture_float(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_EXT_memory_object(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_EXT_memory_object_fd(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_EXT_memory_object_win32(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_EXT_semaphore(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_EXT_semaphore_fd(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_EXT_semaphore_win32(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_EXT_texture_compression_latc(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_EXT_texture_compression_s3tc(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_bindless_texture(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_blend_equation_advanced(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_clip_space_w_scaling(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_command_list(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_compute_shader_derivatives(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_conservative_raster(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_conservative_raster_dilate(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_conservative_raster_pre_snap(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_conservative_raster_pre_snap_triangles(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_conservative_raster_underestimation(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_draw_vulkan_image(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_draw_texture(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_fill_rectangle(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_fragment_coverage_to_color(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_fragment_shader_barycentric(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_fragment_shader_interlock(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_framebuffer_mixed_samples(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_gpu_multicast(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_gpu_shader5(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_internalformat_sample_query(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_memory_attachment(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_mesh_shader(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_path_rendering(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_representative_fragment_test(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_sample_locations(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_sample_mask_override_coverage(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_scissor_exclusive(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_shader_atomic_int64(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_shader_buffer_load(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_shader_buffer_store(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_shader_texture_footprint(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_shader_thread_group(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_shader_thread_shuffle(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_shading_rate_image(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_stereo_view_rendering(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_texture_multisample(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_uniform_buffer_unified_memory(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_vertex_buffer_unified_memory(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_viewport_swizzle(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NVX_gpu_memory_info(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_query_resource(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
int load_GL_NV_query_resource_tag(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
|
||||
525
raytracer/nvpro_core/nvgl/extensions_gl.lua
Normal file
525
raytracer/nvpro_core/nvgl/extensions_gl.lua
Normal file
|
|
@ -0,0 +1,525 @@
|
|||
--[[
|
||||
/*
|
||||
* Copyright (c) 2018-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) 2018-2021 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
HOW TO USE
|
||||
|
||||
* look if extension exists in ../GL/glcustom.h
|
||||
if not, then merge it from official https://www.khronos.org/registry/OpenGL/api/GL/glext.h
|
||||
|
||||
* check out:
|
||||
extensions_gl.lua
|
||||
extensions_gl.hpp
|
||||
extensions_gl.cpp
|
||||
../GL/glsubset.h
|
||||
|
||||
* edit the "subsetExtensions" string below, to add the extensions you need
|
||||
|
||||
* run this file with a lua interpreter
|
||||
|
||||
e.g get https://github.com/rjpcomputing/luaforwindows/blob/master/files/lua5.1.dll
|
||||
and https://github.com/rjpcomputing/luaforwindows/blob/master/files/lua5.1.exe
|
||||
|
||||
then run "lua.exe extensions_gl.lua" in this directory
|
||||
|
||||
* if the extension is still missing, then merge the extension from official glext.h into ../GL/glcustom.h
|
||||
and rerun the script
|
||||
|
||||
]]
|
||||
|
||||
local subsetExtensions =
|
||||
[[
|
||||
GL_ARB_debug_output
|
||||
GL_ARB_shading_language_include
|
||||
GL_ARB_indirect_parameters
|
||||
GL_ARB_bindless_texture
|
||||
GL_ARB_texture_filter_minmax
|
||||
GL_ARB_texture_float
|
||||
GL_ARB_cl_event
|
||||
WGL_ARB_pixel_format
|
||||
GL_NV_bindless_texture
|
||||
GL_NV_blend_equation_advanced
|
||||
GL_NV_clip_space_w_scaling
|
||||
GL_NV_command_list
|
||||
GL_NV_compute_shader_derivatives
|
||||
GL_NV_conservative_raster
|
||||
GL_NV_conservative_raster_dilate
|
||||
GL_NV_conservative_raster_pre_snap
|
||||
GL_NV_conservative_raster_pre_snap_triangles
|
||||
GL_NV_conservative_raster_underestimation
|
||||
GL_NV_draw_texture
|
||||
GL_NV_draw_vulkan_image
|
||||
GL_NV_fill_rectangle
|
||||
GL_NV_fragment_coverage_to_color
|
||||
GL_NV_fragment_shader_barycentric
|
||||
GL_NV_fragment_shader_interlock
|
||||
GL_NV_framebuffer_mixed_samples
|
||||
GL_NV_gpu_multicast
|
||||
GL_NV_gpu_shader5
|
||||
GL_NV_internalformat_sample_query
|
||||
GL_NV_memory_attachment
|
||||
GL_NV_mesh_shader
|
||||
GL_NV_path_rendering
|
||||
GL_NV_representative_fragment_test
|
||||
GL_NV_sample_locations
|
||||
GL_NV_sample_mask_override_coverage
|
||||
GL_NV_scissor_exclusive
|
||||
GL_NV_shader_atomic_int64
|
||||
GL_NV_shader_buffer_load
|
||||
GL_NV_shader_buffer_store
|
||||
GL_NV_shader_texture_footprint
|
||||
GL_NV_shader_thread_group
|
||||
GL_NV_shader_thread_shuffle
|
||||
GL_NV_shading_rate_image
|
||||
GL_NV_stereo_view_rendering
|
||||
GL_NV_texture_multisample
|
||||
GL_NV_uniform_buffer_unified_memory
|
||||
GL_NV_vertex_buffer_unified_memory
|
||||
GL_NV_viewport_swizzle
|
||||
GL_NVX_gpu_memory_info
|
||||
GL_EXT_texture_compression_latc
|
||||
GL_EXT_texture_compression_s3tc
|
||||
GL_EXT_memory_object
|
||||
GL_EXT_semaphore
|
||||
GL_EXT_semaphore_win32
|
||||
GL_EXT_semaphore_fd
|
||||
GL_EXT_memory_object_fd
|
||||
GL_EXT_memory_object_win32
|
||||
GL_NV_query_resource
|
||||
GL_NV_query_resource_tag
|
||||
]]
|
||||
|
||||
local function generate(outfilename, header, enablelist)
|
||||
|
||||
local function subsetheader(filename, outfilename, enablelist, prefix)
|
||||
local f = io.open(filename,"r")
|
||||
local str = f:read("*a")
|
||||
f:close()
|
||||
|
||||
str = str:gsub("__gl_glcustom_h_", "__gl_glsubset_h_")
|
||||
|
||||
if (enablelist) then
|
||||
local search = ("#ifndef $_[%w_]+\n#define $_[%w_]+ 1\n.-#endif /%* $_[%w_]+ %*/\n\n"):gsub("%$",prefix)
|
||||
local num
|
||||
str,num = str:gsub(search,
|
||||
function(cap)
|
||||
local feature = cap:match("#ifndef ("..prefix.."_[%w_]+)")
|
||||
|
||||
local is_version = feature:match(prefix.."_VERSION")
|
||||
if (is_version or not enablelist or enablelist[feature]) then
|
||||
return cap
|
||||
else
|
||||
return ""
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if (outfilename) then
|
||||
print(outfilename)
|
||||
|
||||
local f = io.open(outfilename,"w")
|
||||
assert(f,"could not open"..outfilename.." for writing (check out?)")
|
||||
f:write(str)
|
||||
f:close()
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
local function extractFeatureDefs(str, enablelist, prefix, api, apientry)
|
||||
local features = {}
|
||||
local disables = {}
|
||||
for feature,defstr in str:gmatch(("#ifndef ($_[%w_]+)\n#define $_[%w_]+ 1\n(.-)#endif /%* $_"):gsub("%$", prefix)) do
|
||||
local is_version = feature:match(prefix.."_VERSION")
|
||||
if (is_version or not enablelist or enablelist[feature]) then
|
||||
|
||||
local defs = ""
|
||||
for def in defstr:gmatch(("#ifdef $_$EXT_PROTOTYPES(.-)#endif\n"):gsub("%$", prefix)) do
|
||||
def = def:gsub(api, ""):gsub(apientry, "")
|
||||
defs = defs..def
|
||||
end
|
||||
|
||||
table.insert(features, {feature=feature, defs=defs})
|
||||
elseif (not is_version) then
|
||||
table.insert(disables, feature)
|
||||
end
|
||||
end
|
||||
|
||||
return features, disables
|
||||
end
|
||||
|
||||
local function toTab(str)
|
||||
local tab = {}
|
||||
for name in str:gmatch("[%w_]+") do
|
||||
tab[name] = true
|
||||
end
|
||||
return tab
|
||||
end
|
||||
|
||||
local enablelist = enablelist and toTab(enablelist)
|
||||
|
||||
local parsed = subsetheader("../GL/glcustom.h", "../GL/glsubset.h", enablelist, "GL")
|
||||
|
||||
local gl_features, gl_disables = extractFeatureDefs(parsed, enablelist, "GL", "GLAPI ", "APIENTRY ")
|
||||
|
||||
local availables_header = ""
|
||||
local availables_source = ""
|
||||
|
||||
local loaders_header = ""
|
||||
local loaders_source = ""
|
||||
local loaders_all = ""
|
||||
|
||||
local function process(f, prefix, api, apientry)
|
||||
|
||||
local major,minor = f.feature:match(prefix.."_VERSION_(%d)_(%d)")
|
||||
major,minor = tonumber(major), tonumber(minor)
|
||||
|
||||
availables_header = availables_header.."extern int has_"..f.feature..";\n"
|
||||
availables_source = availables_source.."int has_"..f.feature.." = 0;\n"
|
||||
|
||||
loaders_header = loaders_header.."int load_"..f.feature.."(nvGLLoaderGetProcFN fnGetProcAddress);\n"
|
||||
|
||||
local defs = "\n"..f.defs:gsub("%s*%*%s*","* ")
|
||||
|
||||
local func = ""
|
||||
local initfunc = ""
|
||||
local success = ""
|
||||
local variable = ""
|
||||
|
||||
for const,ret,name,arg in defs:gmatch("\n([%w_]-%s*)([%w_%*]+)%s+([%w_]+)%s*(%b());") do
|
||||
|
||||
local prot = "PFN"..string.upper(name).."PROC"
|
||||
local mangled = "pfn_"..name
|
||||
|
||||
local exec = ret ~= "void" and "return " or ""
|
||||
const = const == "\n" and "" or const
|
||||
|
||||
exec = exec..mangled.."("
|
||||
if (arg ~= "(void)") then
|
||||
for a in arg:sub(2,-2):gmatch("([^,%%]+),?") do
|
||||
local am = a:gsub("%b[]",""):match("([%w_]+)$")
|
||||
assert(am,a)
|
||||
exec = exec..am..","
|
||||
end
|
||||
exec = exec:sub(1,-2)..");"
|
||||
else
|
||||
exec = exec..");"
|
||||
end
|
||||
|
||||
variable = variable.."static "..prot.." "..mangled.." = 0;\n"
|
||||
|
||||
func = func..api..const..ret.." "..apientry..name..arg.."\n{\n"
|
||||
func = func.." assert("..mangled..");\n"
|
||||
func = func.." "..exec.."\n"
|
||||
func = func.."}\n"
|
||||
|
||||
initfunc = initfunc.." "..mangled..' = ('..prot..')fnGetProcAddress("'..name..'");\n'
|
||||
success = success.." success = success && ("..mangled..' != 0);\n'
|
||||
end
|
||||
|
||||
local test
|
||||
if (major and minor) then
|
||||
test = "has_version("..major..","..minor..")"
|
||||
else
|
||||
test = 'has_extension("'..f.feature..'")'
|
||||
end
|
||||
|
||||
-- already defined in win32 opengl32.dll
|
||||
local skip_functions = (prefix == "GL" and major == 1 and minor < 2) or
|
||||
(prefix == "WGL" and major == 1 and minor == 0)
|
||||
|
||||
loaders_source = loaders_source.."/* /////////////////////////////////// */\n"
|
||||
loaders_source = loaders_source.."/* "..f.feature.." */\n\n"
|
||||
loaders_source = loaders_source..variable.."\n"
|
||||
--loaders_source = loaders_source..(skip_functions and "#ifndef WIN32\n" or "")
|
||||
loaders_source = loaders_source..func.."\n"
|
||||
--loaders_source = loaders_source..(skip_functions and "#endif\n" or "")
|
||||
loaders_source = loaders_source.."int load_"..f.feature.."(nvGLLoaderGetProcFN fnGetProcAddress)\n{\n"
|
||||
loaders_source = loaders_source..initfunc
|
||||
loaders_source = loaders_source.." int success = "..test..";\n"
|
||||
loaders_source = loaders_source..success
|
||||
loaders_source = loaders_source.." return success;\n}\n\n"
|
||||
|
||||
print("output written", f.feature)
|
||||
|
||||
loaders_all = loaders_all.." has_"..f.feature.." = load_"..f.feature.."(fnGetProcAddress);\n"
|
||||
end
|
||||
|
||||
for i,f in ipairs(gl_features) do
|
||||
process(f, "GL", "GLAPI ", "APIENTRY ")
|
||||
end
|
||||
|
||||
local disables = ""
|
||||
|
||||
for i,f in ipairs(gl_disables) do
|
||||
disables = disables.."#define "..f.." 0\n"
|
||||
end
|
||||
|
||||
local fheader = io.open(outfilename..".hpp", "w")
|
||||
local fsource = io.open(outfilename..".cpp", "w")
|
||||
assert(fheader, "could not open "..outfilename..".hpp for writing (check out?)")
|
||||
assert(fsource, "could not open "..outfilename..".cpp for writing (check out?)")
|
||||
|
||||
local structs = ""
|
||||
|
||||
if (enablelist and enablelist.GL_NV_command_list) then
|
||||
structs = structs..[[
|
||||
/* GL_NV_command_list */
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
} TerminateSequenceCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
} NOPCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint count;
|
||||
GLuint firstIndex;
|
||||
GLuint baseVertex;
|
||||
} DrawElementsCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint count;
|
||||
GLuint first;
|
||||
} DrawArraysCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLenum mode;
|
||||
GLuint count;
|
||||
GLuint instanceCount;
|
||||
GLuint firstIndex;
|
||||
GLuint baseVertex;
|
||||
GLuint baseInstance;
|
||||
} DrawElementsInstancedCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLenum mode;
|
||||
GLuint count;
|
||||
GLuint instanceCount;
|
||||
GLuint first;
|
||||
GLuint baseInstance;
|
||||
} DrawArraysInstancedCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint addressLo;
|
||||
GLuint addressHi;
|
||||
GLuint typeSizeInByte;
|
||||
} ElementAddressCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint index;
|
||||
GLuint addressLo;
|
||||
GLuint addressHi;
|
||||
} AttributeAddressCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLushort index;
|
||||
GLushort stage;
|
||||
GLuint addressLo;
|
||||
GLuint addressHi;
|
||||
} UniformAddressCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
float alpha;
|
||||
} BlendColorCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint frontStencilRef;
|
||||
GLuint backStencilRef;
|
||||
} StencilRefCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
float lineWidth;
|
||||
} LineWidthCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
float scale;
|
||||
float bias;
|
||||
} PolygonOffsetCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
float alphaRef;
|
||||
} AlphaRefCommandNV;
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint x;
|
||||
GLuint y;
|
||||
GLuint width;
|
||||
GLuint height;
|
||||
} ViewportCommandNV; /* only ViewportIndex 0 */
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint x;
|
||||
GLuint y;
|
||||
GLuint width;
|
||||
GLuint height;
|
||||
} ScissorCommandNV; /* only ViewportIndex 0 */
|
||||
|
||||
typedef struct {
|
||||
GLuint header;
|
||||
GLuint frontFace; /* 0 for CW, 1 for CCW */
|
||||
} FrontFaceCommandNV;
|
||||
|
||||
]]
|
||||
end
|
||||
|
||||
fheader:write(header..[[
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018-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) 2018-2021 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** @DOC_START
|
||||
# OpenGL Extension loader
|
||||
|
||||
Provides a subset of OpenGL Extensions generated by `extensions_gl.lua`.
|
||||
The framework uses a sanitized OpenGL header that is mostly core functionality.
|
||||
`GL/glsubset.h` is generated using a enablelist by the lua script
|
||||
from `GL/glcustom.h` (which is mostly based on `glcorearb.h` with some
|
||||
additional extensions and features)
|
||||
@DOC_END */
|
||||
|
||||
#pragma once
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/glsubset.h>
|
||||
|
||||
typedef void* (* nvGLLoaderGetProcFN)(const char* name);
|
||||
|
||||
/* structs */
|
||||
]]..structs..[[
|
||||
|
||||
/* loader */
|
||||
|
||||
void load_GL(nvGLLoaderGetProcFN fnGetProcAddress);
|
||||
|
||||
/* availables */
|
||||
]]..availables_header..[[
|
||||
|
||||
/* loaders */
|
||||
]]..loaders_header..[[
|
||||
|
||||
]])
|
||||
|
||||
fsource:write(header..[[
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018-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) 2018-2021 NVIDIA CORPORATION
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstring>
|
||||
#include "]]..outfilename..[[.hpp"
|
||||
|
||||
/* availables */
|
||||
]]..availables_source..[[
|
||||
|
||||
/* tests */
|
||||
static int has_extension(const char* name)
|
||||
{
|
||||
GLint numExtensions = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
|
||||
for (int i = 0; i < numExtensions; i++) {
|
||||
const char* ext = (const char*)glGetStringi(GL_EXTENSIONS, i);
|
||||
if (strcmp(name, ext) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
static int has_version(int major, int minor)
|
||||
{
|
||||
GLint ctx_major;
|
||||
GLint ctx_minor;
|
||||
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &ctx_major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &ctx_minor);
|
||||
|
||||
return (ctx_major >= major && (ctx_major > major || ctx_minor >= minor));
|
||||
}
|
||||
|
||||
/* loaders */
|
||||
|
||||
void load_GL(nvGLLoaderGetProcFN fnGetProcAddress)
|
||||
{
|
||||
]]..loaders_all..[[
|
||||
}
|
||||
|
||||
/* loaders */
|
||||
]]..loaders_source..[[
|
||||
|
||||
]])
|
||||
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
generate("extensions_gl",
|
||||
"/* auto generated by extensions_gl.lua */",
|
||||
subsetExtensions)
|
||||
end
|
||||
101
raytracer/nvpro_core/nvgl/glsltypes_gl.hpp
Normal file
101
raytracer/nvpro_core/nvgl/glsltypes_gl.hpp
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/// @DOC_SKIP (keyword to exclude this file from automatic README.md generation)
|
||||
|
||||
#ifndef NV_GLSLTYPES_INCLUDED
|
||||
#define NV_GLSLTYPES_INCLUDED
|
||||
|
||||
/** @DOC_START
|
||||
# type definitions for nvgl and nvmath
|
||||
Sets up vector, matrix etc. types available in GLSL
|
||||
@DOC_END */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace nvgl
|
||||
{
|
||||
typedef uint64_t sampler1D;
|
||||
typedef uint64_t sampler2D;
|
||||
typedef uint64_t sampler2DMS;
|
||||
typedef uint64_t sampler3D;
|
||||
typedef uint64_t samplerBuffer;
|
||||
typedef uint64_t samplerCube;
|
||||
typedef uint64_t sampler1DArray;
|
||||
typedef uint64_t sampler2DArray;
|
||||
typedef uint64_t sampler2DMSArray;
|
||||
typedef uint64_t samplerCubeArray;
|
||||
|
||||
typedef uint64_t usampler1D;
|
||||
typedef uint64_t usampler2D;
|
||||
typedef uint64_t usampler2DMS;
|
||||
typedef uint64_t usampler3D;
|
||||
typedef uint64_t usamplerBuffer;
|
||||
typedef uint64_t usamplerCube;
|
||||
typedef uint64_t usampler1DArray;
|
||||
typedef uint64_t usampler2DArray;
|
||||
typedef uint64_t usampler2DMSArray;
|
||||
typedef uint64_t usamplerCubeArray;
|
||||
|
||||
typedef uint64_t isampler1D;
|
||||
typedef uint64_t isampler2D;
|
||||
typedef uint64_t isampler2DMS;
|
||||
typedef uint64_t isampler3D;
|
||||
typedef uint64_t isamplerBuffer;
|
||||
typedef uint64_t isamplerCube;
|
||||
typedef uint64_t isampler1DArray;
|
||||
typedef uint64_t isampler2DArray;
|
||||
typedef uint64_t isampler2DMSArray;
|
||||
typedef uint64_t isamplerCubeArray;
|
||||
|
||||
typedef uint64_t image1D;
|
||||
typedef uint64_t image2D;
|
||||
typedef uint64_t image2DMS;
|
||||
typedef uint64_t image3D;
|
||||
typedef uint64_t imageBuffer;
|
||||
typedef uint64_t imageCube;
|
||||
typedef uint64_t image1DArray;
|
||||
typedef uint64_t image2DArray;
|
||||
typedef uint64_t image2DMSArray;
|
||||
typedef uint64_t imageCubeArray;
|
||||
|
||||
typedef uint64_t uimage1D;
|
||||
typedef uint64_t uimage2D;
|
||||
typedef uint64_t uimage2DMS;
|
||||
typedef uint64_t uimage3D;
|
||||
typedef uint64_t uimageBuffer;
|
||||
typedef uint64_t uimageCube;
|
||||
typedef uint64_t uimage1DArray;
|
||||
typedef uint64_t uimage2DArray;
|
||||
typedef uint64_t uimage2DMSArray;
|
||||
typedef uint64_t uimageCubeArray;
|
||||
|
||||
typedef uint64_t iimage1D;
|
||||
typedef uint64_t iimage2D;
|
||||
typedef uint64_t iimage2DMS;
|
||||
typedef uint64_t iimage3D;
|
||||
typedef uint64_t iimageBuffer;
|
||||
typedef uint64_t iimageCube;
|
||||
typedef uint64_t iimage1DArray;
|
||||
typedef uint64_t iimage2DArray;
|
||||
typedef uint64_t iimage2DMSArray;
|
||||
typedef uint64_t iimageCubeArray;
|
||||
}
|
||||
|
||||
#endif
|
||||
109
raytracer/nvpro_core/nvgl/profiler_gl.cpp
Normal file
109
raytracer/nvpro_core/nvgl/profiler_gl.cpp
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
||||
#include "profiler_gl.hpp"
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace nvgl {
|
||||
|
||||
void ProfilerGL::resizeQueries()
|
||||
{
|
||||
uint32_t timers = getRequiredTimers();
|
||||
uint32_t old = (uint32_t)m_queries.size();
|
||||
|
||||
if(old == timers)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_queries.resize(timers, 0);
|
||||
uint32_t add = timers - old;
|
||||
glGenQueries(add, &m_queries[old]);
|
||||
}
|
||||
|
||||
void ProfilerGL::init()
|
||||
{
|
||||
resizeQueries();
|
||||
}
|
||||
|
||||
void ProfilerGL::deinit()
|
||||
{
|
||||
if(m_queries.empty())
|
||||
return;
|
||||
|
||||
glDeleteQueries((GLuint)m_queries.size(), m_queries.data());
|
||||
m_queries.clear();
|
||||
}
|
||||
|
||||
|
||||
nvh::Profiler::SectionID ProfilerGL::beginSection(const char* name, bool singleShot)
|
||||
{
|
||||
nvh::Profiler::gpuTimeProvider_fn fnProvider = [&](SectionID i, uint32_t queryFrame, double& gpuTime) {
|
||||
uint32_t idxBegin = getTimerIdx(i, queryFrame, true);
|
||||
uint32_t idxEnd = getTimerIdx(i, queryFrame, false);
|
||||
|
||||
GLint available = 0;
|
||||
glGetQueryObjectiv(m_queries[idxEnd], GL_QUERY_RESULT_AVAILABLE, &available);
|
||||
|
||||
if(available)
|
||||
{
|
||||
GLuint64 beginTime;
|
||||
GLuint64 endTime;
|
||||
glGetQueryObjectui64v(m_queries[idxBegin], GL_QUERY_RESULT, &beginTime);
|
||||
glGetQueryObjectui64v(m_queries[idxEnd], GL_QUERY_RESULT, &endTime);
|
||||
|
||||
gpuTime = double(endTime - beginTime) / double(1000);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
SectionID slot = Profiler::beginSection(name, "GL ", fnProvider, singleShot);
|
||||
|
||||
if(m_queries.size() != getRequiredTimers())
|
||||
{
|
||||
resizeQueries();
|
||||
}
|
||||
|
||||
glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, name);
|
||||
|
||||
uint32_t idx = getTimerIdx(slot, getSubFrame(slot), true);
|
||||
glQueryCounter(m_queries[idx], GL_TIMESTAMP);
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
void ProfilerGL::endSection(SectionID slot)
|
||||
{
|
||||
uint32_t idx = getTimerIdx(slot, getSubFrame(slot), false);
|
||||
glQueryCounter(m_queries[idx], GL_TIMESTAMP);
|
||||
glPopDebugGroup();
|
||||
Profiler::endSection(slot);
|
||||
}
|
||||
|
||||
|
||||
} // namespace nvgl
|
||||
86
raytracer/nvpro_core/nvgl/profiler_gl.hpp
Normal file
86
raytracer/nvpro_core/nvgl/profiler_gl.hpp
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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_PROFILERGL_INCLUDED
|
||||
#define NV_PROFILERGL_INCLUDED
|
||||
|
||||
#include "../nvh/profiler.hpp"
|
||||
#include "extensions_gl.hpp"
|
||||
|
||||
namespace nvgl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/** @DOC_START
|
||||
# class nvgl::ProfilerGL
|
||||
|
||||
nvgl::ProfilerGL extends Profiler and uses `glQueryCounter(... GL_TIMESTAMP)`
|
||||
to compute the GPU time of a section.
|
||||
`glPushDebugGroup` and `glPopDebugGroup` are used within each timed
|
||||
section, so that the section names can show up in NSightGraphics,
|
||||
renderdoc or comparable tools.
|
||||
|
||||
@DOC_END */
|
||||
|
||||
class ProfilerGL : public nvh::Profiler
|
||||
{
|
||||
public:
|
||||
// utility class to call begin/end within local scope
|
||||
class Section
|
||||
{
|
||||
public:
|
||||
Section(ProfilerGL& profiler, const char* name, bool singleShot = false)
|
||||
: m_profiler(profiler)
|
||||
{
|
||||
m_id = profiler.beginSection(name, singleShot);
|
||||
}
|
||||
~Section() { m_profiler.endSection(m_id); }
|
||||
|
||||
private:
|
||||
SectionID m_id;
|
||||
ProfilerGL& m_profiler;
|
||||
};
|
||||
|
||||
// recurring, must be within beginFrame/endFrame
|
||||
Section timeRecurring(const char* name) { return Section(*this, name, false); }
|
||||
|
||||
// singleShot, results are available after FRAME_DELAY many endFrame
|
||||
Section timeSingle(const char* name) { return Section(*this, name, true); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ProfilerGL(nvh::Profiler* masterProfiler = nullptr)
|
||||
: Profiler(masterProfiler)
|
||||
{
|
||||
}
|
||||
|
||||
void init();
|
||||
void deinit();
|
||||
|
||||
SectionID beginSection(const char* name, bool singleShot = false);
|
||||
void endSection(SectionID slot);
|
||||
|
||||
private:
|
||||
void resizeQueries();
|
||||
|
||||
std::vector<GLuint> m_queries;
|
||||
};
|
||||
} // namespace nvgl
|
||||
|
||||
#endif
|
||||
463
raytracer/nvpro_core/nvgl/programmanager_gl.cpp
Normal file
463
raytracer/nvpro_core/nvgl/programmanager_gl.cpp
Normal file
|
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
||||
#include "programmanager_gl.hpp"
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <nvh/fileoperations.hpp>
|
||||
#include <nvh/nvprint.hpp>
|
||||
|
||||
namespace nvgl {
|
||||
|
||||
static bool checkProgram(GLuint program)
|
||||
{
|
||||
if(!program)
|
||||
return false;
|
||||
|
||||
GLint result = GL_FALSE;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &result);
|
||||
|
||||
int infoLogLength;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||
if(infoLogLength > 1
|
||||
#ifdef NDEBUG
|
||||
&& result == GL_FALSE
|
||||
#endif
|
||||
)
|
||||
{
|
||||
std::vector<char> buffer(infoLogLength);
|
||||
glGetProgramInfoLog(program, infoLogLength, NULL, &buffer[0]);
|
||||
LOGW("%s\n", &buffer[0]);
|
||||
}
|
||||
|
||||
return result == GL_TRUE;
|
||||
}
|
||||
|
||||
static bool checkShader(GLuint shader, std::string const& filename)
|
||||
{
|
||||
if(!shader)
|
||||
return false;
|
||||
|
||||
GLint result = GL_FALSE;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
|
||||
|
||||
LOGI("%s ...\n", filename.c_str());
|
||||
int infoLogLength;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
|
||||
if(infoLogLength > 1
|
||||
#ifdef NDEBUG
|
||||
&& result == GL_FALSE
|
||||
#endif
|
||||
)
|
||||
{
|
||||
std::vector<char> buffer(infoLogLength);
|
||||
glGetShaderInfoLog(shader, infoLogLength, NULL, &buffer[0]);
|
||||
LOGW("%s\n", &buffer[0]);
|
||||
}
|
||||
|
||||
return result == GL_TRUE;
|
||||
}
|
||||
|
||||
bool ProgramManager::setupProgram(Program& prog)
|
||||
{
|
||||
prog.program = 0;
|
||||
|
||||
if(prog.definitions.empty())
|
||||
return false;
|
||||
|
||||
m_supportsExtendedInclude = has_GL_ARB_shading_language_include != 0;
|
||||
|
||||
std::string combinedPrepend = m_prepend;
|
||||
std::string combinedFilenames;
|
||||
for(size_t i = 0; i < prog.definitions.size(); i++)
|
||||
{
|
||||
combinedPrepend += prog.definitions[i].prepend;
|
||||
combinedFilenames += prog.definitions[i].filename;
|
||||
}
|
||||
|
||||
bool allFound = true;
|
||||
for(size_t i = 0; i < prog.definitions.size(); i++)
|
||||
{
|
||||
Definition& definition = prog.definitions[i];
|
||||
if(definition.filetype == FILETYPE_DEFAULT)
|
||||
{
|
||||
definition.filetype = m_filetype;
|
||||
}
|
||||
|
||||
if(m_rawOnly)
|
||||
{
|
||||
definition.content = getContent(definition.filename, definition.filenameFound);
|
||||
}
|
||||
else
|
||||
{
|
||||
char const* strDefine = "";
|
||||
|
||||
switch(definition.type)
|
||||
{
|
||||
case GL_VERTEX_SHADER:
|
||||
strDefine = "#define _VERTEX_SHADER_ 1\n";
|
||||
break;
|
||||
case GL_FRAGMENT_SHADER:
|
||||
strDefine = "#define _FRAGMENT_SHADER_ 1\n";
|
||||
break;
|
||||
case GL_COMPUTE_SHADER:
|
||||
strDefine = "#define _COMPUTE_SHADER_ 1\n";
|
||||
break;
|
||||
case GL_GEOMETRY_SHADER:
|
||||
strDefine = "#define _GEOMETRY_SHADER_ 1\n";
|
||||
break;
|
||||
case GL_TESS_CONTROL_SHADER:
|
||||
strDefine = "#define _TESS_CONTROL_SHADER_ 1\n";
|
||||
break;
|
||||
case GL_TESS_EVALUATION_SHADER:
|
||||
strDefine = "#define _TESS_EVALUATION_SHADER_ 1\n";
|
||||
break;
|
||||
#if GL_NV_mesh_shader
|
||||
case GL_MESH_SHADER_NV:
|
||||
strDefine = "#define _MESH_SHADER_ 1\n";
|
||||
break;
|
||||
case GL_TASK_SHADER_NV:
|
||||
strDefine = "#define _TASK_SHADER_ 1\n";
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
definition.content = manualInclude(definition.filename, definition.filenameFound,
|
||||
m_prepend + definition.prepend + std::string(strDefine), false);
|
||||
}
|
||||
allFound = allFound && !definition.content.empty();
|
||||
}
|
||||
|
||||
if(m_preprocessOnly)
|
||||
{
|
||||
prog.program = PREPROCESS_ONLY_PROGRAM;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
prog.program = glCreateProgram();
|
||||
if(!m_useCacheFile.empty() && has_GL_VERSION_4_1)
|
||||
{
|
||||
glProgramParameteri(prog.program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
bool loadedCache = false;
|
||||
if(!m_useCacheFile.empty() && (!allFound || m_preferCache) && has_GL_VERSION_4_1)
|
||||
{
|
||||
// try cache
|
||||
loadedCache = loadBinary(prog.program, combinedPrepend, combinedFilenames);
|
||||
}
|
||||
if(!loadedCache)
|
||||
{
|
||||
for(size_t i = 0; i < prog.definitions.size(); i++)
|
||||
{
|
||||
Definition& definition = prog.definitions[i];
|
||||
GLuint shader = 0;
|
||||
if(!definition.content.empty())
|
||||
{
|
||||
char const* sourcePointer = definition.content.c_str();
|
||||
shader = glCreateShader(definition.type);
|
||||
glShaderSource(shader, 1, &sourcePointer, NULL);
|
||||
glCompileShader(shader);
|
||||
}
|
||||
if(!shader || !checkShader(shader, definition.filename))
|
||||
{
|
||||
glDeleteShader(shader);
|
||||
glDeleteProgram(prog.program);
|
||||
prog.program = 0;
|
||||
return false;
|
||||
}
|
||||
glAttachShader(prog.program, shader);
|
||||
glDeleteShader(shader);
|
||||
}
|
||||
glLinkProgram(prog.program);
|
||||
}
|
||||
|
||||
if(checkProgram(prog.program))
|
||||
{
|
||||
if(!m_useCacheFile.empty() && !loadedCache && has_GL_VERSION_4_1)
|
||||
{
|
||||
saveBinary(prog.program, combinedPrepend, combinedFilenames);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
glDeleteProgram(prog.program);
|
||||
prog.program = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
ProgramID ProgramManager::createProgram(const Definition& def0,
|
||||
const Definition& def1 /*= ShaderDefinition()*/,
|
||||
const Definition& def2 /*= ShaderDefinition()*/,
|
||||
const Definition& def3 /*= ShaderDefinition()*/,
|
||||
const Definition& def4 /*= ShaderDefinition()*/)
|
||||
{
|
||||
std::vector<ProgramManager::Definition> defs;
|
||||
defs.push_back(def0);
|
||||
if(def1.type)
|
||||
defs.push_back(def1);
|
||||
if(def2.type)
|
||||
defs.push_back(def2);
|
||||
if(def3.type)
|
||||
defs.push_back(def3);
|
||||
if(def4.type)
|
||||
defs.push_back(def4);
|
||||
|
||||
return createProgram(defs);
|
||||
}
|
||||
|
||||
ProgramID ProgramManager::createProgram(const std::vector<ProgramManager::Definition>& definitions)
|
||||
{
|
||||
Program prog;
|
||||
prog.definitions = definitions;
|
||||
|
||||
setupProgram(prog);
|
||||
|
||||
for(size_t i = 0; i < m_programs.size(); i++)
|
||||
{
|
||||
if(m_programs[i].definitions.empty())
|
||||
{
|
||||
m_programs[i] = prog;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
m_programs.push_back(prog);
|
||||
return m_programs.size() - 1;
|
||||
}
|
||||
|
||||
bool ProgramManager::areProgramsValid()
|
||||
{
|
||||
bool valid = true;
|
||||
for(size_t i = 0; i < m_programs.size(); i++)
|
||||
{
|
||||
valid = valid && isValid((ProgramID)i);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
void ProgramManager::deletePrograms()
|
||||
{
|
||||
for(size_t i = 0; i < m_programs.size(); i++)
|
||||
{
|
||||
if(m_programs[i].program && m_programs[i].program != PREPROCESS_ONLY_PROGRAM)
|
||||
{
|
||||
glDeleteProgram(m_programs[i].program);
|
||||
}
|
||||
m_programs[i].program = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ProgramManager::reloadProgram(ProgramID i)
|
||||
{
|
||||
if(!isValid(i))
|
||||
return;
|
||||
|
||||
bool old = m_preprocessOnly;
|
||||
|
||||
if(m_programs[i].program && m_programs[i].program != PREPROCESS_ONLY_PROGRAM)
|
||||
{
|
||||
glDeleteProgram(m_programs[i].program);
|
||||
}
|
||||
|
||||
m_preprocessOnly = m_programs[i].program == PREPROCESS_ONLY_PROGRAM;
|
||||
m_programs[i].program = 0;
|
||||
if(!m_programs[i].definitions.empty())
|
||||
{
|
||||
setupProgram(m_programs[i]);
|
||||
}
|
||||
m_preprocessOnly = old;
|
||||
}
|
||||
|
||||
void ProgramManager::reloadPrograms()
|
||||
{
|
||||
LOGI("Reloading programs...\n");
|
||||
|
||||
for(size_t i = 0; i < m_programs.size(); i++)
|
||||
{
|
||||
reloadProgram((ProgramID)i);
|
||||
}
|
||||
|
||||
LOGI("done\n");
|
||||
}
|
||||
|
||||
bool ProgramManager::isValid(ProgramID idx) const
|
||||
{
|
||||
return idx.isValid() && (m_programs[idx].definitions.empty() || m_programs[idx].program != 0);
|
||||
}
|
||||
|
||||
unsigned int ProgramManager::get(ProgramID idx) const
|
||||
{
|
||||
assert(m_programs[idx].program != PREPROCESS_ONLY_PROGRAM);
|
||||
return m_programs[idx].program;
|
||||
}
|
||||
|
||||
void ProgramManager::destroyProgram(ProgramID idx)
|
||||
{
|
||||
if(m_programs[idx].program && m_programs[idx].program != PREPROCESS_ONLY_PROGRAM)
|
||||
{
|
||||
glDeleteProgram(m_programs[idx].program);
|
||||
}
|
||||
m_programs[idx].program = 0;
|
||||
m_programs[idx].definitions.clear();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MurmurHash2A, by Austin Appleby
|
||||
|
||||
// This is a variant of MurmurHash2 modified to use the Merkle-Damgard
|
||||
// construction. Bulk speed should be identical to Murmur2, small-key speed
|
||||
// will be 10%-20% slower due to the added overhead at the end of the hash.
|
||||
|
||||
// This variant fixes a minor issue where null keys were more likely to
|
||||
// collide with each other than expected, and also makes the algorithm
|
||||
// more amenable to incremental implementations. All other caveats from
|
||||
// MurmurHash2 still apply.
|
||||
|
||||
#define mmix(h, k) \
|
||||
{ \
|
||||
k *= m; \
|
||||
k ^= k >> r; \
|
||||
k *= m; \
|
||||
h *= m; \
|
||||
h ^= k; \
|
||||
}
|
||||
|
||||
static unsigned int strMurmurHash2A(const void* key, size_t len, unsigned int seed)
|
||||
{
|
||||
const unsigned int m = 0x5bd1e995;
|
||||
const int r = 24;
|
||||
unsigned int l = (unsigned int)len;
|
||||
|
||||
const unsigned char* data = (const unsigned char*)key;
|
||||
|
||||
unsigned int h = seed;
|
||||
unsigned int t = 0;
|
||||
|
||||
while(len >= 4)
|
||||
{
|
||||
unsigned int k = *(unsigned int*)data;
|
||||
|
||||
mmix(h, k);
|
||||
|
||||
data += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
|
||||
switch(len)
|
||||
{
|
||||
case 3:
|
||||
t ^= data[2] << 16;
|
||||
case 2:
|
||||
t ^= data[1] << 8;
|
||||
case 1:
|
||||
t ^= data[0];
|
||||
};
|
||||
|
||||
mmix(h, t);
|
||||
mmix(h, l);
|
||||
|
||||
h ^= h >> 13;
|
||||
h *= m;
|
||||
h ^= h >> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
#undef mmix
|
||||
|
||||
|
||||
static size_t strHexFromByte(char* buffer, size_t bufferlen, const void* data, size_t len)
|
||||
{
|
||||
const char tostr[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
const unsigned char* d = (const unsigned char*)data;
|
||||
char* out = buffer;
|
||||
size_t i = 0;
|
||||
for(; i < len && (i * 2) + 1 < bufferlen; i++, d++, out += 2)
|
||||
{
|
||||
unsigned int val = *d;
|
||||
unsigned int hi = val / 16;
|
||||
unsigned int lo = val % 16;
|
||||
out[0] = tostr[hi];
|
||||
out[1] = tostr[lo];
|
||||
}
|
||||
|
||||
return i * 2;
|
||||
}
|
||||
|
||||
std::string ProgramManager::binaryName(const std::string& combinedPrepend, const std::string& combinedFilenames)
|
||||
{
|
||||
unsigned int hashCombine = combinedPrepend.empty() ? 0 : strMurmurHash2A(&combinedPrepend[0], combinedPrepend.size(), 127);
|
||||
unsigned int hashFilenames = strMurmurHash2A(&combinedFilenames[0], combinedFilenames.size(), 129);
|
||||
|
||||
std::string hexCombine;
|
||||
std::string hexFilenames;
|
||||
hexCombine.resize(8);
|
||||
hexFilenames.resize(8);
|
||||
strHexFromByte(&hexCombine[0], 8, &hashCombine, 4);
|
||||
strHexFromByte(&hexFilenames[0], 8, &hashFilenames, 4);
|
||||
|
||||
return m_useCacheFile + "_" + hexCombine + "_" + hexFilenames + ".glp";
|
||||
}
|
||||
|
||||
bool ProgramManager::loadBinary(GLuint program, const std::string& combinedPrepend, const std::string& combinedFilenames)
|
||||
{
|
||||
std::string filename = binaryName(combinedPrepend, combinedFilenames);
|
||||
std::string filenameFound;
|
||||
std::string binraw = nvh::loadFile(filename, true, m_directories, filenameFound);
|
||||
if(!binraw.empty())
|
||||
{
|
||||
const char* bindata = &binraw[0];
|
||||
glProgramBinary(program, *(GLenum*)bindata, bindata + 4, GLsizei(binraw.size() - 4));
|
||||
return checkProgram(program);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ProgramManager::saveBinary(GLuint program, const std::string& combinedPrepend, const std::string& combinedFilenames)
|
||||
{
|
||||
std::string filename = binaryName(combinedPrepend, combinedFilenames);
|
||||
|
||||
GLint datasize;
|
||||
GLint datasize2;
|
||||
glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &datasize);
|
||||
|
||||
std::string binraw;
|
||||
binraw.resize(datasize + 4ULL);
|
||||
char* bindata = &binraw[0];
|
||||
glGetProgramBinary(program, datasize, &datasize2, (GLenum*)bindata, bindata + 4);
|
||||
|
||||
std::ofstream binfile;
|
||||
binfile.open(filename.c_str(), std::ios::binary | std::ios::out);
|
||||
if(binfile.is_open())
|
||||
{
|
||||
binfile.write(bindata, datasize + 4ULL);
|
||||
}
|
||||
}
|
||||
} // namespace nvgl
|
||||
162
raytracer/nvpro_core/nvgl/programmanager_gl.hpp
Normal file
162
raytracer/nvpro_core/nvgl/programmanager_gl.hpp
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue