[Bf-blender-cvs] [fdda05bf15c] temp-gpu-push-constants: [WIP] GPU: Push Constants.
Jeroen Bakker
noreply at git.blender.org
Wed Jun 30 17:11:36 CEST 2021
Commit: fdda05bf15c12f07ec1b6d813e4e12a0f7a89255
Author: Jeroen Bakker
Date: Wed Jun 30 17:10:47 2021 +0200
Branches: temp-gpu-push-constants
https://developer.blender.org/rBfdda05bf15c12f07ec1b6d813e4e12a0f7a89255
[WIP] GPU: Push Constants.
See T89553 for more details.
===================================================================
M source/blender/gpu/CMakeLists.txt
M source/blender/gpu/opengl/gl_shader.cc
M source/blender/gpu/opengl/gl_shader.hh
A source/blender/gpu/opengl/gl_shader_converter.cc
A source/blender/gpu/opengl/gl_shader_converter.hh
A source/blender/gpu/tests/gpu_shader_push_constants_test.cc
===================================================================
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index abb7330d292..ba3a23f2641 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -104,6 +104,7 @@ set(SRC
opengl/gl_query.cc
opengl/gl_shader.cc
opengl/gl_shader_log.cc
+ opengl/gl_shader_converter.cc
opengl/gl_shader_interface.cc
opengl/gl_state.cc
opengl/gl_texture.cc
@@ -399,6 +400,7 @@ if(WITH_GTESTS)
tests/gpu_index_buffer_test.cc
tests/gpu_shader_builtin_test.cc
+ tests/gpu_shader_push_constants_test.cc
tests/gpu_shader_test.cc
tests/gpu_testing.hh
diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc
index 66a1bd5ceb7..78544035416 100644
--- a/source/blender/gpu/opengl/gl_shader.cc
+++ b/source/blender/gpu/opengl/gl_shader.cc
@@ -148,6 +148,11 @@ GLuint GLShader::create_shader_stage(GLenum gl_stage, MutableSpan<const char *>
/* Patch the shader code using the first source slot. */
sources[0] = glsl_patch_get(gl_stage);
+ converter_.patch(sources);
+ if (converter_.has_error()) {
+ compilation_failed_ = true;
+ return 0;
+ }
glShaderSource(shader, sources.size(), sources.data(), nullptr);
glCompileShader(shader);
@@ -228,6 +233,10 @@ bool GLShader::finalize()
interface = new GLShaderInterface(shader_program_);
+ /* Only patched sources are only freed when shader compilation and linking succeeds for
+ * debugging. */
+ converter_.free();
+
return true;
}
diff --git a/source/blender/gpu/opengl/gl_shader.hh b/source/blender/gpu/opengl/gl_shader.hh
index 770bc29747e..76919b6b803 100644
--- a/source/blender/gpu/opengl/gl_shader.hh
+++ b/source/blender/gpu/opengl/gl_shader.hh
@@ -29,6 +29,8 @@
#include "gpu_shader_private.hh"
+#include "gl_shader_converter.hh"
+
namespace blender {
namespace gpu {
@@ -48,6 +50,7 @@ class GLShader : public Shader {
bool compilation_failed_ = false;
eGPUShaderTFBType transform_feedback_type_ = GPU_SHADER_TFB_NONE;
+ GLShaderConverter converter_;
public:
GLShader(const char *name);
diff --git a/source/blender/gpu/opengl/gl_shader_converter.cc b/source/blender/gpu/opengl/gl_shader_converter.cc
new file mode 100644
index 00000000000..c2f06b74e31
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_shader_converter.cc
@@ -0,0 +1,110 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Parse/convert GLSL source from Vulkan GLSL to OpenGL GLSL.
+ */
+
+#include "gl_shader_converter.hh"
+
+namespace blender::gpu {
+
+void GLShaderConverter::patch(MutableSpan<const char *> sources)
+{
+ for (int i = 0; i < sources.size(); i++) {
+ std::string patched_source = patch(sources[i]);
+ patched_sources_.append(patched_source);
+ sources[i] = patched_sources_.last().c_str();
+ }
+}
+
+bool GLShaderConverter::has_error() const
+{
+ return status != GLShaderConverterState::Ok;
+}
+
+void GLShaderConverter::free()
+{
+ patched_sources_.clear();
+}
+
+std::string GLShaderConverter::patch(StringRef src)
+{
+ std::string result = patch_push_constants(src);
+ return result;
+}
+
+StringRef GLShaderConverter::skip_whitespace(StringRef ref)
+{
+ static constexpr StringRef WHITESPACES = " \t\n\v\f\r";
+
+ size_t skip = ref.find_first_not_of(WHITESPACES);
+ if (skip == blender::StringRef::not_found) {
+ return ref;
+ }
+ return ref.drop_prefix(skip);
+}
+
+StringRef GLShaderConverter::extract_name(StringRef src)
+{
+ static constexpr StringRef VALID_CHARS =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01232456789_";
+ StringRef result = src;
+
+ size_t skip = result.find_first_not_of(VALID_CHARS);
+ BLI_assert(skip != StringRef::not_found);
+ return result.substr(0, skip);
+}
+
+std::string GLShaderConverter::patch_push_constants(StringRef src)
+{
+ static constexpr StringRef LAYOUT_PUSH_CONSTANTS = "layout(push_constant)";
+ static constexpr StringRef LAYOUT_STD140 = "layout(std140)";
+
+ size_t pos = src.find(LAYOUT_PUSH_CONSTANTS);
+ if (pos == StringRef::not_found) {
+ return src;
+ }
+ std::stringstream result;
+ result << src.substr(0, pos);
+ result << LAYOUT_STD140;
+ result << src.substr(pos + LAYOUT_PUSH_CONSTANTS.size());
+
+ StringRef name = src.substr(pos + LAYOUT_PUSH_CONSTANTS.size());
+ name = skip_whitespace(name);
+ name = name.drop_known_prefix("uniform");
+ name = skip_whitespace(name);
+ name = extract_name(name);
+
+ if (push_constants.name.empty()) {
+ push_constants.name = name;
+ }
+ else {
+ /* Push constant name must be the same across all stages. */
+ if (push_constants.name != name) {
+ status = GLShaderConverterState::NOT_MATCHING_PUSH_CONSTANT_NAME;
+ }
+ }
+
+ return patch_push_constants(result.str());
+}
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/opengl/gl_shader_converter.hh b/source/blender/gpu/opengl/gl_shader_converter.hh
new file mode 100644
index 00000000000..0ba58cccf4c
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_shader_converter.hh
@@ -0,0 +1,61 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "BLI_string_ref.hh"
+#include "BLI_vector.hh"
+
+namespace blender::gpu {
+
+enum class GLShaderConverterState {
+ Ok,
+ NOT_MATCHING_PUSH_CONSTANT_NAME,
+};
+class GLShaderConverter {
+ public:
+ struct {
+ std::string name;
+ } push_constants;
+ GLShaderConverterState status = GLShaderConverterState::Ok;
+
+ private:
+ Vector<std::string> patched_sources_;
+
+ public:
+ void patch(MutableSpan<const char *> sources);
+ bool has_error() const;
+ void free();
+
+ private:
+ std::string patch(StringRef src);
+ bool is_valid_name_char(const char c) const;
+ StringRef skip_whitespace(StringRef src);
+
+ StringRef extract_name(StringRef src);
+ std::string patch_push_constants(StringRef src);
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("GLShaderConverter");
+};
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/tests/gpu_shader_push_constants_test.cc b/source/blender/gpu/tests/gpu_shader_push_constants_test.cc
new file mode 100644
index 00000000000..dca6810068b
--- /dev/null
+++ b/source/blender/gpu/tests/gpu_shader_push_constants_test.cc
@@ -0,0 +1,227 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+#include "GPU_shader.h"
+
+#include "gpu_testing.hh"
+
+namespace blender::gpu::tests {
+
+static void test_gpu_shader_push_constants()
+{
+ const char *vert_glsl = R"(
+
+uniform mat4 ModelViewProjectionMatrix;
+in vec3 pos;
+
+void main() {
+ vec4 pos_4d = vec4(pos, 1.0);
+ gl_Position = ModelViewProjectionMatrix * pos_4d;
+}
+
+)";
+
+ const char *frag_glsl = R"(
+
+layout(push_constant) uniform PushConstants {
+ vec4 color;
+};
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = color;
+}
+
+)";
+
+ GPUShader *shader = GPU_shader_create(
+ vert_glsl, frag_glsl, nullptr, nullptr, nullptr, "test_gpu_shader_push_constants");
+ EXPECT_NE(shader, nullptr);
+
+ GPU_shader_free(shader);
+}
+GPU_TEST(gpu_shader_push_constants)
+
+static void test_gpu_shader_push_constants_2_definitions()
+{
+ const char *vert_glsl = R"(
+
+uniform mat4 ModelViewProjectionMatrix;
+in vec3 pos;
+
+void main() {
+ vec4 pos_4d = vec4(pos, 1.0);
+ gl_Position = ModelViewProjectionMatrix * pos_4d;
+}
+
+)";
+
+ const char *frag_glsl = R"(
+
+#ifdef NEW
+layout(push_constant) uniform PushConstants {
+ vec4 color;
+};
+#else
+layout(push_constant) uniform PushConstants {
+ vec4 color;
+};
+#endif
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = color;
+}
+
+)";
+
+ GPUShader *shader = GPU_shader_create(
+ vert_glsl, frag_glsl, nullptr, nullptr, nullptr, "gpu_shader_push_constants_2_definitions");
+ EXPECT_NE(shader, nullptr);
+
+ GPU_shader_free(shader);
+}
+GPU_TEST(gpu_shader_push_constants_2_definitions)
+
+static void test_gpu_shader_push_constants_2_stages()
+{
+ const char *vert_glsl = R"(
+
+uniform mat4 ModelViewProjectionMatrix;
+in vec3 pos;
+
+layout(push_constant) uniform PushConstants {
+ vec4 color;
+};
+
+void main() {
+ vec4 pos_4d = vec4(pos, 1.0);
+ gl_Position = ModelViewProjectionMatrix * pos_4d;
+}
+
+)";
+
+ const char *frag_glsl = R"(
+
+layout(push_constant) uniform PushConstants {
+ vec4 color;
+};
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = color;
+}
+
+)";
+
+ GPUShader *shader = GPU_shader_create(
+ vert_glsl, frag_glsl, nullptr, nullptr, nullptr, "test_gpu_shader_push_constants_2_stages");
+ EXPECT_NE(shader, nullptr);
+
+ GPU_shader_free(shader);
+}
+GPU_TEST(gpu_shader_push_constant
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list