From 9f6a4ee946e00ea3733e1f576d65433566cc89f7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Nov 2025 03:15:35 +0000 Subject: [PATCH 1/4] Initial plan From b31a48a8f8735738a2e541a4ff77fafa6e62914e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Nov 2025 03:23:04 +0000 Subject: [PATCH 2/4] Implement WebGL2 transformFeedbackVaryings API - Add TRANSFORM_FEEDBACK_VARYINGS command buffer request type - Implement TransformFeedbackVaryingsCommandBufferRequest structure - Add transformFeedbackVaryings method to WebGL2Context class - Update JavaScript binding to properly parse arguments and call native method - All C++ code formatted with clang-format Co-authored-by: EndlessJour9527 <155411404+EndlessJour9527@users.noreply.github.com> --- src/client/graphics/webgl_context.cpp | 15 +++++ src/client/graphics/webgl_context.hpp | 1 + .../script_bindings/webgl/active_info.cpp | 2 +- .../script_bindings/webgl/active_info.hpp | 2 +- .../script_bindings/webgl/framebuffer.cpp | 2 +- .../script_bindings/webgl/framebuffer.hpp | 2 +- src/client/script_bindings/webgl/object.cpp | 2 +- src/client/script_bindings/webgl/object.hpp | 2 +- src/client/script_bindings/webgl/program.cpp | 2 +- src/client/script_bindings/webgl/program.hpp | 2 +- .../script_bindings/webgl/renderbuffer.cpp | 2 +- .../script_bindings/webgl/renderbuffer.hpp | 2 +- src/client/script_bindings/webgl/texture.cpp | 2 +- src/client/script_bindings/webgl/texture.hpp | 2 +- .../webgl/uniform_location.cpp | 2 +- .../webgl/uniform_location.hpp | 2 +- .../script_bindings/webgl/vertex_array.cpp | 2 +- .../script_bindings/webgl/vertex_array.hpp | 2 +- .../webgl/webgl2_rendering_context.cpp | 60 ++++++++++++++++- .../command_buffers/details/program.hpp | 65 +++++++++++++++++++ src/common/command_buffers/macros.hpp | 1 + 21 files changed, 156 insertions(+), 18 deletions(-) diff --git a/src/client/graphics/webgl_context.cpp b/src/client/graphics/webgl_context.cpp index 9e60d485b..6c2ab9635 100644 --- a/src/client/graphics/webgl_context.cpp +++ b/src/client/graphics/webgl_context.cpp @@ -2188,6 +2188,21 @@ namespace endor sendCommandBufferRequest(req); } + void WebGL2Context::transformFeedbackVaryings(shared_ptr program, + const vector &varyings, + uint32_t bufferMode) + { + if (program == nullptr || !program->isValid()) + { + return; + } + + auto commandBuffer = commandbuffers::TransformFeedbackVaryingsCommandBufferRequest(program->id, + varyings, + bufferMode); + sendCommandBufferRequest(commandBuffer); + } + void WebGL2Context::uniformBlockBinding(shared_ptr program, int uniformBlockIndex, uint32_t uniformBlockBinding) diff --git a/src/client/graphics/webgl_context.hpp b/src/client/graphics/webgl_context.hpp index 32567de43..3ce0ff68e 100644 --- a/src/client/graphics/webgl_context.hpp +++ b/src/client/graphics/webgl_context.hpp @@ -973,6 +973,7 @@ namespace endor WebGLPixelType type, unsigned char *pixels); + void transformFeedbackVaryings(std::shared_ptr program, const std::vector &varyings, uint32_t bufferMode); void uniformBlockBinding(std::shared_ptr program, int uniformBlockIndex, uint32_t uniformBlockBinding); void uniformMatrix3x2fv(WebGLUniformLocation location, bool transpose, std::vector values); void uniformMatrix4x2fv(WebGLUniformLocation location, bool transpose, std::vector values); diff --git a/src/client/script_bindings/webgl/active_info.cpp b/src/client/script_bindings/webgl/active_info.cpp index c0f9d3e81..803ffe763 100644 --- a/src/client/script_bindings/webgl/active_info.cpp +++ b/src/client/script_bindings/webgl/active_info.cpp @@ -60,5 +60,5 @@ namespace endor } } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor diff --git a/src/client/script_bindings/webgl/active_info.hpp b/src/client/script_bindings/webgl/active_info.hpp index b125c893c..c2d6c9080 100644 --- a/src/client/script_bindings/webgl/active_info.hpp +++ b/src/client/script_bindings/webgl/active_info.hpp @@ -38,5 +38,5 @@ namespace endor }; } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor \ No newline at end of file diff --git a/src/client/script_bindings/webgl/framebuffer.cpp b/src/client/script_bindings/webgl/framebuffer.cpp index dbe790869..d38e0687c 100644 --- a/src/client/script_bindings/webgl/framebuffer.cpp +++ b/src/client/script_bindings/webgl/framebuffer.cpp @@ -31,5 +31,5 @@ namespace endor { } } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor \ No newline at end of file diff --git a/src/client/script_bindings/webgl/framebuffer.hpp b/src/client/script_bindings/webgl/framebuffer.hpp index c54189e65..fd3ab4ec2 100644 --- a/src/client/script_bindings/webgl/framebuffer.hpp +++ b/src/client/script_bindings/webgl/framebuffer.hpp @@ -37,5 +37,5 @@ namespace endor }; } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor diff --git a/src/client/script_bindings/webgl/object.cpp b/src/client/script_bindings/webgl/object.cpp index b03f846b5..78779213d 100644 --- a/src/client/script_bindings/webgl/object.cpp +++ b/src/client/script_bindings/webgl/object.cpp @@ -28,5 +28,5 @@ namespace endor // WebGLObject is a base class, typically not instantiated directly } } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor diff --git a/src/client/script_bindings/webgl/object.hpp b/src/client/script_bindings/webgl/object.hpp index cd48b93ae..f69bb78c8 100644 --- a/src/client/script_bindings/webgl/object.hpp +++ b/src/client/script_bindings/webgl/object.hpp @@ -45,5 +45,5 @@ namespace endor }; } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor \ No newline at end of file diff --git a/src/client/script_bindings/webgl/program.cpp b/src/client/script_bindings/webgl/program.cpp index e4a68a6f8..8c21d7e26 100644 --- a/src/client/script_bindings/webgl/program.cpp +++ b/src/client/script_bindings/webgl/program.cpp @@ -20,5 +20,5 @@ namespace endor } } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor \ No newline at end of file diff --git a/src/client/script_bindings/webgl/program.hpp b/src/client/script_bindings/webgl/program.hpp index ede29c134..0971e7271 100644 --- a/src/client/script_bindings/webgl/program.hpp +++ b/src/client/script_bindings/webgl/program.hpp @@ -32,5 +32,5 @@ namespace endor WebGLProgram(v8::Isolate *isolate, const v8::FunctionCallbackInfo &args); }; } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor diff --git a/src/client/script_bindings/webgl/renderbuffer.cpp b/src/client/script_bindings/webgl/renderbuffer.cpp index 7f512b63d..d858602e8 100644 --- a/src/client/script_bindings/webgl/renderbuffer.cpp +++ b/src/client/script_bindings/webgl/renderbuffer.cpp @@ -19,5 +19,5 @@ namespace endor // WebGLRenderbuffer objects are created by WebGL context, not by user code } } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor diff --git a/src/client/script_bindings/webgl/renderbuffer.hpp b/src/client/script_bindings/webgl/renderbuffer.hpp index a9651c800..581ff1b2e 100644 --- a/src/client/script_bindings/webgl/renderbuffer.hpp +++ b/src/client/script_bindings/webgl/renderbuffer.hpp @@ -33,5 +33,5 @@ namespace endor }; } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor \ No newline at end of file diff --git a/src/client/script_bindings/webgl/texture.cpp b/src/client/script_bindings/webgl/texture.cpp index 3b51f5dfa..3d034839c 100644 --- a/src/client/script_bindings/webgl/texture.cpp +++ b/src/client/script_bindings/webgl/texture.cpp @@ -27,5 +27,5 @@ namespace endor { } } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor diff --git a/src/client/script_bindings/webgl/texture.hpp b/src/client/script_bindings/webgl/texture.hpp index b40acad08..9272d305c 100644 --- a/src/client/script_bindings/webgl/texture.hpp +++ b/src/client/script_bindings/webgl/texture.hpp @@ -45,5 +45,5 @@ namespace endor }; } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor \ No newline at end of file diff --git a/src/client/script_bindings/webgl/uniform_location.cpp b/src/client/script_bindings/webgl/uniform_location.cpp index 597a73e97..ce71bd5d6 100644 --- a/src/client/script_bindings/webgl/uniform_location.cpp +++ b/src/client/script_bindings/webgl/uniform_location.cpp @@ -47,5 +47,5 @@ namespace endor } } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor diff --git a/src/client/script_bindings/webgl/uniform_location.hpp b/src/client/script_bindings/webgl/uniform_location.hpp index a5e7de1f2..a1f98b66d 100644 --- a/src/client/script_bindings/webgl/uniform_location.hpp +++ b/src/client/script_bindings/webgl/uniform_location.hpp @@ -44,5 +44,5 @@ namespace endor }; } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor \ No newline at end of file diff --git a/src/client/script_bindings/webgl/vertex_array.cpp b/src/client/script_bindings/webgl/vertex_array.cpp index 3e6ed5f0a..48e8e644b 100644 --- a/src/client/script_bindings/webgl/vertex_array.cpp +++ b/src/client/script_bindings/webgl/vertex_array.cpp @@ -20,5 +20,5 @@ namespace endor { } } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor diff --git a/src/client/script_bindings/webgl/vertex_array.hpp b/src/client/script_bindings/webgl/vertex_array.hpp index 7ba162aa3..a4a03cc1d 100644 --- a/src/client/script_bindings/webgl/vertex_array.hpp +++ b/src/client/script_bindings/webgl/vertex_array.hpp @@ -33,5 +33,5 @@ namespace endor }; } // namespace webgl - } // namespace script_bindings + } // namespace script_bindings } // namespace endor \ No newline at end of file diff --git a/src/client/script_bindings/webgl/webgl2_rendering_context.cpp b/src/client/script_bindings/webgl/webgl2_rendering_context.cpp index 8bace804f..055317f1f 100644 --- a/src/client/script_bindings/webgl/webgl2_rendering_context.cpp +++ b/src/client/script_bindings/webgl/webgl2_rendering_context.cpp @@ -993,9 +993,65 @@ namespace endor { Isolate *isolate = args.GetIsolate(); HandleScope scope(isolate); + Local context = isolate->GetCurrentContext(); - isolate->ThrowException(Exception::Error( - MakeMethodError(isolate, "transformFeedbackVaryings", "Not implemented"))); + if (args.Length() < 3) + { + isolate->ThrowException(Exception::TypeError( + MakeMethodArgCountError(isolate, "transformFeedbackVaryings", 3, args.Length()))); + return; + } + if (!WebGLProgram::IsInstanceOf(isolate, args[0])) + { + isolate->ThrowException(Exception::TypeError( + MakeMethodArgTypeError(isolate, "transformFeedbackVaryings", 0, "WebGLProgram", args[0]))); + return; + } + if (!args[1]->IsArray()) + { + isolate->ThrowException(Exception::TypeError( + MakeMethodArgTypeError(isolate, "transformFeedbackVaryings", 1, "Array", args[1]))); + return; + } + if (!args[2]->IsNumber()) + { + isolate->ThrowException(Exception::TypeError( + MakeMethodArgTypeError(isolate, "transformFeedbackVaryings", 2, "number", args[2]))); + return; + } + + auto programObj = args[0].As(); + auto program = WebGLProgram::Unwrap(isolate, programObj); + if (program == nullptr || !program->hasData()) + { + isolate->ThrowException(Exception::TypeError( + MakeMethodError(isolate, "transformFeedbackVaryings", "Invalid WebGLProgram"))); + return; + } + + // Extract varyings array + vector varyings; + Local varyingsArray = args[1].As(); + uint32_t length = varyingsArray->Length(); + varyings.reserve(length); + + for (uint32_t i = 0; i < length; ++i) + { + Local item = varyingsArray->Get(context, i).ToLocalChecked(); + if (!item->IsString()) + { + isolate->ThrowException(Exception::TypeError( + MakeMethodError(isolate, "transformFeedbackVaryings", "All varyings must be strings"))); + return; + } + String::Utf8Value utf8Value(isolate, item); + varyings.push_back(string(*utf8Value)); + } + + uint32_t bufferMode = args[2]->Uint32Value(context).ToChecked(); + + handle()->transformFeedbackVaryings(program->handle(), varyings, bufferMode); + args.GetReturnValue().SetUndefined(); } void WebGL2RenderingContext::GetTransformFeedbackVarying(const FunctionCallbackInfo &args) diff --git a/src/common/command_buffers/details/program.hpp b/src/common/command_buffers/details/program.hpp index 57dac3e2b..a1dbfc756 100644 --- a/src/common/command_buffers/details/program.hpp +++ b/src/common/command_buffers/details/program.hpp @@ -494,4 +494,69 @@ namespace commandbuffers public: std::string infoLog; }; + + class TransformFeedbackVaryingsCommandBufferRequest final + : public TrCommandBufferSimpleRequest + { + public: + TransformFeedbackVaryingsCommandBufferRequest() = delete; + TransformFeedbackVaryingsCommandBufferRequest(uint32_t program, const std::vector &varyings, uint32_t bufferMode) + : TrCommandBufferSimpleRequest() + , program(program) + , varyings(varyings) + , bufferMode(bufferMode) + { + } + TransformFeedbackVaryingsCommandBufferRequest(const TransformFeedbackVaryingsCommandBufferRequest &that, bool clone = false) + : TrCommandBufferSimpleRequest(that, clone) + , program(that.program) + , varyings(that.varyings) + , bufferMode(that.bufferMode) + { + } + + std::string toString(const char *line_prefix) const override + { + std::stringstream ss; + ss << TrCommandBufferSimpleRequest::toString(line_prefix) << "(" << program << ", ["; + for (size_t i = 0; i < varyings.size(); i++) + { + if (i > 0) + ss << ", "; + ss << varyings[i]; + } + ss << "], " << bufferMode << ")"; + return ss.str(); + } + + TrCommandBufferMessage *serialize() override + { + auto message = new TrCommandBufferMessage(type, size, this); + // Serialize the varyings array + for (const auto &varying : varyings) + { + message->addStringSegment(varying); + } + return message; + } + + void deserialize(TrCommandBufferMessage &message) override + { + varyings.clear(); + for (size_t i = 0; i < message.getSegmentCount(); i++) + { + auto segment = message.getSegment(i); + if (segment != nullptr) + { + varyings.push_back(segment->toString()); + } + } + } + + public: + uint32_t program; + std::vector varyings; + uint32_t bufferMode; + }; } diff --git a/src/common/command_buffers/macros.hpp b/src/common/command_buffers/macros.hpp index 00c9ad7d6..b44575857 100644 --- a/src/common/command_buffers/macros.hpp +++ b/src/common/command_buffers/macros.hpp @@ -75,6 +75,7 @@ XX(VERTEX_ATTRIB_I4IV, VertexAttribI4ivCommandBufferRequest, "GL::VertexAttribI4iv") \ XX(VERTEX_ATTRIB_I4UIV, VertexAttribI4uivCommandBufferRequest, "GL::VertexAttribI4uiv") \ XX(UNIFORM_BLOCK_BINDING, UniformBlockBindingCommandBufferRequest, "GL::UniformBlockBinding") \ + XX(TRANSFORM_FEEDBACK_VARYINGS, TransformFeedbackVaryingsCommandBufferRequest, "GL::TransformFeedbackVaryings") \ XX(UNIFORM1F, Uniform1fCommandBufferRequest, "GL::Uniform1f") \ XX(UNIFORM1FV, Uniform1fvCommandBufferRequest, "GL::Uniform1fv") \ XX(UNIFORM1I, Uniform1iCommandBufferRequest, "GL::Uniform1i") \ From 7e6e29d186788e2a57ad20dc1761ff9e52f96c01 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Nov 2025 03:25:37 +0000 Subject: [PATCH 3/4] Add renderer-side OpenGL handler for transformFeedbackVaryings - Implement OnTransformFeedbackVaryings handler in render_api_opengles.cpp - Convert C++ string vector to C-style char* array for glTransformFeedbackVaryings - Register handler with command buffer dispatcher - Full end-to-end implementation from JavaScript to OpenGL now complete Co-authored-by: EndlessJour9527 <155411404+EndlessJour9527@users.noreply.github.com> --- src/renderer/render_api_opengles.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/renderer/render_api_opengles.cpp b/src/renderer/render_api_opengles.cpp index 37683c8ef..1f31b9337 100644 --- a/src/renderer/render_api_opengles.cpp +++ b/src/renderer/render_api_opengles.cpp @@ -1717,6 +1717,26 @@ class RHI_OpenGL : public TrRenderHardwareInterface if (TR_UNLIKELY(CheckError(req, reqContentRenderer) != GL_NO_ERROR || options.printsCall)) PrintDebugInfo(req, nullptr, nullptr, options); } + TR_OPENGL_FUNC void OnTransformFeedbackVaryings(TransformFeedbackVaryingsCommandBufferRequest *req, + renderer::TrContentRenderer *reqContentRenderer, + ApiCallOptions &options) + { + auto &glObjectManager = reqContentRenderer->getContextGL()->ObjectManagerRef(); + auto program = glObjectManager.FindProgram(req->program); + + // Convert vector of strings to array of C strings for OpenGL API + std::vector varyings; + varyings.reserve(req->varyings.size()); + for (const auto &varying : req->varyings) + { + varyings.push_back(varying.c_str()); + } + + glTransformFeedbackVaryings(program, static_cast(varyings.size()), varyings.data(), req->bufferMode); + + if (TR_UNLIKELY(CheckError(req, reqContentRenderer) != GL_NO_ERROR || options.printsCall)) + PrintDebugInfo(req, nullptr, nullptr, options); + } TR_OPENGL_FUNC void OnUniform1f(Uniform1fCommandBufferRequest *req, renderer::TrContentRenderer *reqContentRenderer, ApiCallOptions &options) @@ -2937,6 +2957,7 @@ bool RHI_OpenGL::ExecuteCommandBuffer(vector Date: Thu, 20 Nov 2025 10:56:49 +0800 Subject: [PATCH 4/4] fix --- src/common/command_buffers/details/program.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/command_buffers/details/program.hpp b/src/common/command_buffers/details/program.hpp index a1dbfc756..24381d480 100644 --- a/src/common/command_buffers/details/program.hpp +++ b/src/common/command_buffers/details/program.hpp @@ -536,7 +536,7 @@ namespace commandbuffers // Serialize the varyings array for (const auto &varying : varyings) { - message->addStringSegment(varying); + message->addStringSegment(const_cast(varying)); } return message; }