From f598bc25873b346014438a3e7856b078bf6ccd7b Mon Sep 17 00:00:00 2001 From: clach Date: Fri, 22 Nov 2024 13:44:28 -0800 Subject: [PATCH] [hgiInterop] Portion of Autodesk PR #3391. Relevant PR description: Autodesk: Enable experimental Vulkan testing on macOS - Add OpenGL 3.1/GLSL 1.4 support to HgiInterop and use a VertexArray, as required by Apple OpenGL. See #3391 (Internal change: 2349264) --- pxr/imaging/hgiInterop/opengl.cpp | 12 ++-- pxr/imaging/hgiInterop/vulkan.cpp | 112 +++++++++++++++++++++++++++--- pxr/imaging/hgiInterop/vulkan.h | 1 + 3 files changed, 108 insertions(+), 17 deletions(-) diff --git a/pxr/imaging/hgiInterop/opengl.cpp b/pxr/imaging/hgiInterop/opengl.cpp index 98b29972f7..36bc59bdf2 100644 --- a/pxr/imaging/hgiInterop/opengl.cpp +++ b/pxr/imaging/hgiInterop/opengl.cpp @@ -14,7 +14,7 @@ PXR_NAMESPACE_OPEN_SCOPE -static const char* _vertexFullscreen = +static const char* _vertexFullscreen120 = "#version 120\n" "attribute vec4 position;\n" "attribute vec2 uvIn;\n" @@ -25,7 +25,7 @@ static const char* _vertexFullscreen = " uv = uvIn;\n" "}\n"; -static const char* _fragmentNoDepthFullscreen = +static const char* _fragmentNoDepthFullscreen120 = "#version 120\n" "varying vec2 uv;\n" "uniform sampler2D colorIn;\n" @@ -34,7 +34,7 @@ static const char* _fragmentNoDepthFullscreen = " gl_FragColor = texture2D(colorIn, uv);\n" "}\n"; -static const char* _fragmentDepthFullscreen = +static const char* _fragmentDepthFullscreen120 = "#version 120\n" "varying vec2 uv;\n" "uniform sampler2D colorIn;\n" @@ -95,9 +95,9 @@ HgiInteropOpenGL::HgiInteropOpenGL() , _prgDepth(0) , _vertexBuffer(0) { - _vs = _CompileShader(_vertexFullscreen, GL_VERTEX_SHADER); - _fsNoDepth = _CompileShader(_fragmentNoDepthFullscreen, GL_FRAGMENT_SHADER); - _fsDepth = _CompileShader(_fragmentDepthFullscreen, GL_FRAGMENT_SHADER); + _vs = _CompileShader(_vertexFullscreen120, GL_VERTEX_SHADER); + _fsNoDepth = _CompileShader(_fragmentNoDepthFullscreen120, GL_FRAGMENT_SHADER); + _fsDepth = _CompileShader(_fragmentDepthFullscreen120, GL_FRAGMENT_SHADER); _prgNoDepth = _LinkProgram(_vs, _fsNoDepth); _prgDepth = _LinkProgram(_vs, _fsDepth); _vertexBuffer = _CreateVertexBuffer(); diff --git a/pxr/imaging/hgiInterop/vulkan.cpp b/pxr/imaging/hgiInterop/vulkan.cpp index c615dacfab..1c3d9a92e4 100644 --- a/pxr/imaging/hgiInterop/vulkan.cpp +++ b/pxr/imaging/hgiInterop/vulkan.cpp @@ -14,7 +14,7 @@ PXR_NAMESPACE_OPEN_SCOPE -static const char* _vertexFullscreen = +static const char* _vertexFullscreen120 = "#version 120\n" "attribute vec4 position;\n" "attribute vec2 uvIn;\n" @@ -25,7 +25,18 @@ static const char* _vertexFullscreen = " uv = uvIn;\n" "}\n"; -static const char* _fragmentNoDepthFullscreen = +static const char* _vertexFullscreen140 = + "#version 140\n" + "in vec4 position;\n" + "in vec2 uvIn;\n" + "out vec2 uv;\n" + "void main(void)\n" + "{\n" + " gl_Position = position;\n" + " uv = uvIn;\n" + "}\n"; + +static const char* _fragmentNoDepthFullscreen120 = "#version 120\n" "varying vec2 uv;\n" "uniform sampler2D colorIn;\n" @@ -34,7 +45,17 @@ static const char* _fragmentNoDepthFullscreen = " gl_FragColor = texture2D(colorIn, uv);\n" "}\n"; -static const char* _fragmentDepthFullscreen = +static const char* _fragmentNoDepthFullscreen140 = + "#version 140\n" + "in vec2 uv;\n" + "out vec4 colorOut;\n" + "uniform sampler2D colorIn;\n" + "void main(void)\n" + "{\n" + " colorOut = texture(colorIn, uv);\n" + "}\n"; + +static const char* _fragmentDepthFullscreen120 = "#version 120\n" "varying vec2 uv;\n" "uniform sampler2D colorIn;\n" @@ -46,6 +67,30 @@ static const char* _fragmentDepthFullscreen = " gl_FragDepth = depth;\n" "}\n"; +static const char* _fragmentDepthFullscreen140 = + "#version 140\n" + "in vec2 uv;\n" + "out vec4 colorOut;\n" + "uniform sampler2D colorIn;\n" + "uniform sampler2D depthIn;\n" + "void main(void)\n" + "{\n" + " colorOut = texture(colorIn, uv);\n" + " gl_FragDepth = texture(depthIn, uv).r;\n" + "}\n"; + + +static void +_ProcessShaderCompilationErrors(uint32_t shaderId) +{ + int logSize = 0; + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logSize); + std::string errors; + errors.resize(logSize + 1); + glGetShaderInfoLog(shaderId, logSize, nullptr, errors.data()); + TF_VERIFY(false, "Failed to compile shader: %s", errors.c_str()); +} + static uint32_t _CompileShader(const char* src, GLenum stage) { @@ -54,7 +99,10 @@ _CompileShader(const char* src, GLenum stage) glCompileShader(shaderId); GLint status; glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status); - TF_VERIFY(status == GL_TRUE); + if (status != GL_TRUE) { + _ProcessShaderCompilationErrors(shaderId); + } + return shaderId; } @@ -87,6 +135,14 @@ _CreateVertexBuffer() return vertexBuffer; } +static uint32_t +_CreateVertexArray() +{ + uint32_t vertexArray = 0; + glGenVertexArrays(1, &vertexArray); + return vertexArray; +} + static void _ConvertVulkanTextureToOpenGL( HgiVulkan* hgiVulkan, @@ -155,17 +211,32 @@ HgiInteropVulkan::HgiInteropVulkan(Hgi* hgiVulkan) , _prgNoDepth(0) , _prgDepth(0) , _vertexBuffer(0) + , _vertexArray(0) , _glColorTex(0) , _glDepthTex(0) { GarchGLApiLoad(); - _vs = _CompileShader(_vertexFullscreen, GL_VERTEX_SHADER); - _fsNoDepth = _CompileShader(_fragmentNoDepthFullscreen, GL_FRAGMENT_SHADER); - _fsDepth = _CompileShader(_fragmentDepthFullscreen, GL_FRAGMENT_SHADER); + _vs = _CompileShader( + GARCH_GL_VERSION_3_1 ? _vertexFullscreen140 : + _vertexFullscreen120, + GL_VERTEX_SHADER); + _fsNoDepth = _CompileShader( + GARCH_GL_VERSION_3_1 ? _fragmentNoDepthFullscreen140 : + _fragmentNoDepthFullscreen120, + GL_FRAGMENT_SHADER); + _fsDepth = _CompileShader( + GARCH_GL_VERSION_3_1 ? _fragmentDepthFullscreen140 : + _fragmentDepthFullscreen120, + GL_FRAGMENT_SHADER); _prgNoDepth = _LinkProgram(_vs, _fsNoDepth); _prgDepth = _LinkProgram(_vs, _fsDepth); _vertexBuffer = _CreateVertexBuffer(); - TF_VERIFY(glGetError() == GL_NO_ERROR); + if (GARCH_GL_VERSION_3_0) { + _vertexArray = _CreateVertexArray(); + } + + const GLenum error = glGetError(); + TF_VERIFY(error == GL_NO_ERROR, "OpenGL error: 0x%04x", error); } HgiInteropVulkan::~HgiInteropVulkan() @@ -176,13 +247,18 @@ HgiInteropVulkan::~HgiInteropVulkan() glDeleteProgram(_prgNoDepth); glDeleteProgram(_prgDepth); glDeleteBuffers(1, &_vertexBuffer); + if (_vertexArray) { + glDeleteVertexArrays(1, &_vertexArray); + } if (_glColorTex) { glDeleteTextures(1, &_glColorTex); } if (_glDepthTex) { glDeleteTextures(1, &_glDepthTex); } - TF_VERIFY(glGetError() == GL_NO_ERROR); + + const GLenum error = glGetError(); + TF_VERIFY(error == GL_NO_ERROR, "OpenGL error: 0x%04x", error); } void @@ -198,7 +274,10 @@ HgiInteropVulkan::CompositeToInterop( } // Verify there were no gl errors coming in. - TF_VERIFY(glGetError() == GL_NO_ERROR); + { + const GLenum error = glGetError(); + TF_VERIFY(error == GL_NO_ERROR, "OpenGL error: 0x%04x", error); + } GLint restoreDrawFramebuffer = 0; bool doRestoreDrawFramebuffer = false; @@ -260,6 +339,10 @@ HgiInteropVulkan::CompositeToInterop( GLint restoreArrayBuffer = 0; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &restoreArrayBuffer); + if (_vertexArray) { + glBindVertexArray(_vertexArray); + } + // Vertex attributes const GLint locPosition = glGetAttribLocation(prg, "position"); glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); @@ -325,6 +408,10 @@ HgiInteropVulkan::CompositeToInterop( // Restore state and verify gl errors glDisableVertexAttribArray(locPosition); glDisableVertexAttribArray(locUv); + if (_vertexArray) { + glBindVertexArray(0); + } + glBindBuffer(GL_ARRAY_BUFFER, restoreArrayBuffer); if (!blendEnabled) { @@ -367,7 +454,10 @@ HgiInteropVulkan::CompositeToInterop( restoreDrawFramebuffer); } - TF_VERIFY(glGetError() == GL_NO_ERROR); + { + const GLenum error = glGetError(); + TF_VERIFY(error == GL_NO_ERROR, "OpenGL error: 0x%04x", error); + } } PXR_NAMESPACE_CLOSE_SCOPE diff --git a/pxr/imaging/hgiInterop/vulkan.h b/pxr/imaging/hgiInterop/vulkan.h index b418f7e6ec..f792b6d440 100644 --- a/pxr/imaging/hgiInterop/vulkan.h +++ b/pxr/imaging/hgiInterop/vulkan.h @@ -50,6 +50,7 @@ class HgiInteropVulkan final uint32_t _prgNoDepth; uint32_t _prgDepth; uint32_t _vertexBuffer; + uint32_t _vertexArray; // XXX We tmp copy Vulkan's GPU texture to CPU and then to GL texture // Once we share GPU memory between Vulkan and GL we can remove this.