diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt index 5fcd8d963e4..01545bcaeb5 100644 --- a/intern/opensubdiv/CMakeLists.txt +++ b/intern/opensubdiv/CMakeLists.txt @@ -4,6 +4,7 @@ set(INC . + ../../source/blender/gpu/intern ) set(INC_SYS @@ -56,8 +57,10 @@ if(WITH_OPENSUBDIV) internal/evaluator/evaluator_cache_impl.h internal/evaluator/evaluator_capi.cc internal/evaluator/evaluator_impl.cc - internal/evaluator/gl_compute_evaluator.cc - internal/evaluator/gl_compute_evaluator.h + internal/evaluator/gpu_compute_evaluator.cc + internal/evaluator/gpu_compute_evaluator.h + internal/evaluator/gpu_patch_table.cc + internal/evaluator/gpu_patch_table.hh internal/evaluator/patch_map.cc internal/evaluator/patch_map.h @@ -87,10 +90,35 @@ if(WITH_OPENSUBDIV) add_definitions(-D_USE_MATH_DEFINES) endif() - data_to_c_simple( - internal/evaluator/shaders/glsl_compute_kernel.glsl - SRC + set(GLSL_SRC + internal/evaluator/shaders/osd_kernel_comp.glsl ) + + set(GLSL_C) + foreach(GLSL_FILE ${GLSL_SRC}) + glsl_to_c(${GLSL_FILE} GLSL_C) + endforeach() + + blender_add_lib(bf_osd_shaders "${GLSL_C}" "" "" "") + + list(APPEND LIB + bf_osd_shaders + ) + + set(GLSL_SOURCE_CONTENT "") + foreach(GLSL_FILE ${GLSL_SRC}) + get_filename_component(GLSL_FILE_NAME ${GLSL_FILE} NAME) + string(REPLACE "." "_" GLSL_FILE_NAME_UNDERSCORES ${GLSL_FILE_NAME}) + string(APPEND GLSL_SOURCE_CONTENT "SHADER_SOURCE\(datatoc_${GLSL_FILE_NAME_UNDERSCORES}, \"${GLSL_FILE_NAME}\", \"${GLSL_FILE}\"\)\n") + endforeach() + + set(glsl_source_list_file "${CMAKE_CURRENT_BINARY_DIR}/glsl_osd_source_list.h") + file(GENERATE OUTPUT ${glsl_source_list_file} CONTENT "${GLSL_SOURCE_CONTENT}") + list(APPEND SRC ${glsl_source_list_file}) + list(APPEND INC ${CMAKE_CURRENT_BINARY_DIR}) + + target_include_directories(bf_osd_shaders PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) + else() list(APPEND SRC stub/opensubdiv_stub.cc diff --git a/intern/opensubdiv/internal/evaluator/eval_output.cc b/intern/opensubdiv/internal/evaluator/eval_output.cc index 86ea03e67fa..f9af9a7d56e 100644 --- a/intern/opensubdiv/internal/evaluator/eval_output.cc +++ b/intern/opensubdiv/internal/evaluator/eval_output.cc @@ -12,7 +12,7 @@ bool is_adaptive(const CpuPatchTable *patch_table) return patch_table->GetPatchArrayBuffer()[0].GetDescriptor().IsAdaptive(); } -bool is_adaptive(const GLPatchTable *patch_table) +bool is_adaptive(const GPUPatchTable *patch_table) { return patch_table->GetPatchArrays()[0].GetDescriptor().IsAdaptive(); } diff --git a/intern/opensubdiv/internal/evaluator/eval_output.h b/intern/opensubdiv/internal/evaluator/eval_output.h index 864f525b881..78c7e5603e0 100644 --- a/intern/opensubdiv/internal/evaluator/eval_output.h +++ b/intern/opensubdiv/internal/evaluator/eval_output.h @@ -8,18 +8,18 @@ #define OPENSUBDIV_EVAL_OUTPUT_H_ #include -#include #include #include #include "opensubdiv_evaluator.hh" #include "opensubdiv_evaluator_capi.hh" +#include "gpu_patch_table.hh" + using OpenSubdiv::Far::PatchTable; using OpenSubdiv::Far::StencilTable; using OpenSubdiv::Osd::BufferDescriptor; using OpenSubdiv::Osd::CpuPatchTable; -using OpenSubdiv::Osd::GLPatchTable; using OpenSubdiv::Osd::PatchCoord; namespace blender::opensubdiv { @@ -76,37 +76,54 @@ class EvalOutputAPI::EvalOutput { // data structure. They need to be overridden in the specific instances of the EvalOutput derived // classes if needed, while the interfaces above are overridden through VolatileEvalOutput. - virtual void fillPatchArraysBuffer(blender::gpu::VertBuf * /*patch_arrays_buffer*/) {} - - virtual void wrapPatchIndexBuffer(blender::gpu::VertBuf * /*patch_index_buffer*/) {} - - virtual void wrapPatchParamBuffer(blender::gpu::VertBuf * /*patch_param_buffer*/) {} - - virtual void wrapSrcBuffer(blender::gpu::VertBuf * /*src_buffer*/) {} - - virtual void wrapSrcVertexDataBuffer(blender::gpu::VertBuf * /*src_buffer*/) {} - - virtual void fillFVarPatchArraysBuffer(const int /*face_varying_channel*/, - blender::gpu::VertBuf * /*patch_arrays_buffer*/) + virtual GPUStorageBuf *create_patch_arrays_buf() { + return nullptr; } - virtual void wrapFVarPatchIndexBuffer(const int /*face_varying_channel*/, - blender::gpu::VertBuf * /*patch_index_buffer*/) + virtual GPUStorageBuf *get_patch_index_buf() { + return nullptr; } - virtual void wrapFVarPatchParamBuffer(const int /*face_varying_channel*/, - blender::gpu::VertBuf * /*patch_param_buffer*/) + virtual GPUStorageBuf *get_patch_param_buf() { + return nullptr; } - virtual void wrapFVarSrcBuffer(const int /*face_varying_channel*/, - blender::gpu::VertBuf * /*src_buffer*/) + virtual gpu::VertBuf *get_source_buf() { + return nullptr; } - virtual int getFVarSrcBufferOffset(const int face_varying_channel) const = 0; + virtual gpu::VertBuf *get_source_data_buf() + { + return nullptr; + } + + virtual GPUStorageBuf *create_face_varying_patch_array_buf(const int /*face_varying_channel*/) + { + return nullptr; + } + + virtual GPUStorageBuf *get_face_varying_patch_index_buf(const int /*face_varying_channel*/) + { + return nullptr; + } + + virtual GPUStorageBuf *get_face_varying_patch_param_buf(const int /*face_varying_channel*/) + { + return nullptr; + } + virtual gpu::VertBuf *get_face_varying_source_buf(const int /*face_varying_channel*/) + { + return nullptr; + } + + virtual int get_face_varying_source_offset(const int /*face_varying_channel*/) const + { + return 0; + } virtual bool hasVertexData() const { @@ -125,9 +142,9 @@ template class RawDataWrapperBuffer { return data_; } - int BindVBO() + gpu::VertBuf *get_vertex_buffer() { - return 0; + return nullptr; } // TODO(sergey): Support UpdateData(). @@ -163,7 +180,7 @@ class ConstPatchCoordWrapperBuffer : public RawDataWrapperVertexBuffer( + EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( evaluator_cache_, src_face_varying_desc_, dst_face_varying_desc, device_context_); // in and out points to same buffer so output is put directly after coarse vertices, needed in // adaptive mode @@ -231,7 +248,7 @@ class FaceVaryingVolatileEval { RawDataWrapperBuffer face_varying_data(face_varying); BufferDescriptor face_varying_desc(0, 2, 2); ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords); - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( + EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( evaluator_cache_, src_face_varying_desc_, face_varying_desc, device_context_); BufferDescriptor src_desc = get_src_varying_desc(); @@ -253,7 +270,7 @@ class FaceVaryingVolatileEval { return src_face_varying_data_; } - int getFVarSrcBufferOffset() const + int get_face_varying_source_offset() const { BufferDescriptor src_desc = get_src_varying_desc(); return src_desc.offset; @@ -439,7 +456,7 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput { // Evaluate vertex positions. BufferDescriptor dst_desc = src_desc_; dst_desc.offset += num_coarse_vertices_ * src_desc_.stride; - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( + EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( evaluator_cache_, src_desc_, dst_desc, device_context_); EVALUATOR::EvalStencils(src_data_, src_desc_, @@ -453,7 +470,7 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput { if (src_vertex_data_) { BufferDescriptor dst_vertex_data_desc = src_vertex_data_desc_; dst_vertex_data_desc.offset += num_coarse_vertices_ * src_vertex_data_desc_.stride; - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( + EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( evaluator_cache_, src_vertex_data_desc_, dst_vertex_data_desc, device_context_); EVALUATOR::EvalStencils(src_vertex_data_, src_vertex_data_desc_, @@ -493,7 +510,7 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput { // TODO(sergey): Support interleaved vertex-varying data. BufferDescriptor P_desc(0, 3, 3); ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords); - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( + EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( evaluator_cache_, src_desc_, P_desc, device_context_); EVALUATOR::EvalPatches(src_data_, src_desc_, @@ -521,7 +538,7 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput { BufferDescriptor P_desc(0, 3, 3); BufferDescriptor dpDu_desc(0, 3, 3), pPdv_desc(0, 3, 3); ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords); - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( + EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( evaluator_cache_, src_desc_, P_desc, dpDu_desc, pPdv_desc, device_context_); EVALUATOR::EvalPatches(src_data_, src_desc_, @@ -546,7 +563,7 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput { RawDataWrapperBuffer varying_data(varying); BufferDescriptor varying_desc(3, 3, 6); ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords); - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( + EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( evaluator_cache_, src_varying_desc_, varying_desc, device_context_); EVALUATOR::EvalPatchesVarying(src_varying_data_, src_varying_desc_, @@ -567,7 +584,7 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput { RawDataWrapperBuffer vertex_data(data); BufferDescriptor vertex_desc(0, src_vertex_data_desc_.length, src_vertex_data_desc_.length); ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords); - const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( + EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator( evaluator_cache_, src_vertex_data_desc_, vertex_desc, device_context_); EVALUATOR::EvalPatches(src_vertex_data_, src_vertex_data_desc_, @@ -611,9 +628,9 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput { return face_varying_evaluators_[face_varying_channel]->getSrcBuffer(); } - int getFVarSrcBufferOffset(const int face_varying_channel) const override + int get_face_varying_source_offset(const int face_varying_channel) const override { - return face_varying_evaluators_[face_varying_channel]->getFVarSrcBufferOffset(); + return face_varying_evaluators_[face_varying_channel]->get_face_varying_source_offset(); } PATCH_TABLE *getFVarPatchTable(const int face_varying_channel) const diff --git a/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc b/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc index 64da58e4ca6..56910b349c5 100644 --- a/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc +++ b/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc @@ -8,19 +8,22 @@ #include "opensubdiv_evaluator.hh" +#include "gpu_patch_table.hh" + using OpenSubdiv::Osd::PatchArray; using OpenSubdiv::Osd::PatchArrayVector; namespace blender::opensubdiv { -static void buildPatchArraysBufferFromVector(const PatchArrayVector &patch_arrays, - blender::gpu::VertBuf *patch_arrays_buffer) +static GPUStorageBuf *create_patch_array_buffer(const PatchArrayVector &patch_arrays) { const size_t patch_array_size = sizeof(PatchArray); const size_t patch_array_byte_site = patch_array_size * patch_arrays.size(); - GPU_vertbuf_data_alloc(*patch_arrays_buffer, patch_arrays.size()); - GPU_vertbuf_use(patch_arrays_buffer); - GPU_vertbuf_update_sub(patch_arrays_buffer, 0, patch_array_byte_site, patch_arrays.data()); + const size_t patch_array_alloc_size = (patch_array_byte_site + 15) & ~0b1111; + // TODO: potential read out of bounds. + GPUStorageBuf *storage_buf = GPU_storagebuf_create_ex( + patch_array_alloc_size, patch_arrays.data(), GPU_USAGE_STATIC, "osd_patch_array"); + return storage_buf; } GpuEvalOutput::GpuEvalOutput(const StencilTable *vertex_stencils, @@ -29,78 +32,29 @@ GpuEvalOutput::GpuEvalOutput(const StencilTable *vertex_stencils, const int face_varying_width, const PatchTable *patch_table, VolatileEvalOutput::EvaluatorCache *evaluator_cache) - : VolatileEvalOutput(vertex_stencils, - varying_stencils, - all_face_varying_stencils, - face_varying_width, - patch_table, - evaluator_cache) + : VolatileEvalOutput(vertex_stencils, + varying_stencils, + all_face_varying_stencils, + face_varying_width, + patch_table, + evaluator_cache) { } -void GpuEvalOutput::fillPatchArraysBuffer(blender::gpu::VertBuf *patch_arrays_buffer) +GPUStorageBuf *GpuEvalOutput::create_patch_arrays_buf() { - GLPatchTable *patch_table = getPatchTable(); - buildPatchArraysBufferFromVector(patch_table->GetPatchArrays(), patch_arrays_buffer); + GPUPatchTable *patch_table = getPatchTable(); + return create_patch_array_buffer(patch_table->GetPatchArrays()); } -void GpuEvalOutput::wrapPatchIndexBuffer(blender::gpu::VertBuf *patch_index_buffer) +GPUStorageBuf *GpuEvalOutput::create_face_varying_patch_array_buf(const int face_varying_channel) { - GLPatchTable *patch_table = getPatchTable(); - GPU_vertbuf_wrap_handle(patch_index_buffer, patch_table->GetPatchIndexBuffer()); -} - -void GpuEvalOutput::wrapPatchParamBuffer(blender::gpu::VertBuf *patch_param_buffer) -{ - GLPatchTable *patch_table = getPatchTable(); - GPU_vertbuf_wrap_handle(patch_param_buffer, patch_table->GetPatchParamBuffer()); -} - -void GpuEvalOutput::wrapSrcBuffer(blender::gpu::VertBuf *src_buffer) -{ - GLVertexBuffer *vertex_buffer = getSrcBuffer(); - GPU_vertbuf_wrap_handle(src_buffer, vertex_buffer->BindVBO()); -} - -void GpuEvalOutput::wrapSrcVertexDataBuffer(blender::gpu::VertBuf *src_buffer) -{ - GLVertexBuffer *vertex_buffer = getSrcVertexDataBuffer(); - GPU_vertbuf_wrap_handle(src_buffer, vertex_buffer->BindVBO()); -} - -void GpuEvalOutput::fillFVarPatchArraysBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_arrays_buffer) -{ - GLPatchTable *patch_table = getFVarPatchTable(face_varying_channel); - buildPatchArraysBufferFromVector(patch_table->GetFVarPatchArrays(face_varying_channel), - patch_arrays_buffer); -} - -void GpuEvalOutput::wrapFVarPatchIndexBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_index_buffer) -{ - GLPatchTable *patch_table = getFVarPatchTable(face_varying_channel); - GPU_vertbuf_wrap_handle(patch_index_buffer, - patch_table->GetFVarPatchIndexBuffer(face_varying_channel)); -} - -void GpuEvalOutput::wrapFVarPatchParamBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_param_buffer) -{ - GLPatchTable *patch_table = getFVarPatchTable(face_varying_channel); - GPU_vertbuf_wrap_handle(patch_param_buffer, - patch_table->GetFVarPatchParamBuffer(face_varying_channel)); -} - -void GpuEvalOutput::wrapFVarSrcBuffer(const int face_varying_channel, - blender::gpu::VertBuf *src_buffer) -{ - GLVertexBuffer *vertex_buffer = getFVarSrcBuffer(face_varying_channel); - GPU_vertbuf_wrap_handle(src_buffer, vertex_buffer->BindVBO()); + GPUPatchTable *patch_table = getFVarPatchTable(face_varying_channel); + return create_patch_array_buffer(patch_table->GetFVarPatchArrays(face_varying_channel)); } } // namespace blender::opensubdiv diff --git a/intern/opensubdiv/internal/evaluator/eval_output_gpu.h b/intern/opensubdiv/internal/evaluator/eval_output_gpu.h index f52454ddc07..7b54c4d6307 100644 --- a/intern/opensubdiv/internal/evaluator/eval_output_gpu.h +++ b/intern/opensubdiv/internal/evaluator/eval_output_gpu.h @@ -8,20 +8,21 @@ #define OPENSUBDIV_EVAL_OUTPUT_GPU_H_ #include "internal/evaluator/eval_output.h" -#include "internal/evaluator/gl_compute_evaluator.h" +#include "internal/evaluator/gpu_compute_evaluator.h" +#include "internal/evaluator/gpu_patch_table.hh" #include #include -using OpenSubdiv::Osd::GLVertexBuffer; +#include "gpu_vertex_buffer_wrapper.hh" namespace blender::opensubdiv { -class GpuEvalOutput : public VolatileEvalOutput { +class GpuEvalOutput : public VolatileEvalOutput { public: GpuEvalOutput(const StencilTable *vertex_stencils, const StencilTable *varying_stencils, @@ -30,27 +31,47 @@ class GpuEvalOutput : public VolatileEvalOutputGetPatchIndexBuffer(); + } - void wrapPatchParamBuffer(blender::gpu::VertBuf *patch_param_buffer) override; + GPUStorageBuf *get_patch_param_buf() override + { + return getPatchTable()->GetPatchParamBuffer(); + } - void wrapSrcBuffer(blender::gpu::VertBuf *src_buffer) override; + gpu::VertBuf *get_source_buf() override + { + return getSrcBuffer()->get_vertex_buffer(); + } - void wrapSrcVertexDataBuffer(blender::gpu::VertBuf *src_buffer) override; + gpu::VertBuf *get_source_data_buf() override + { + return getSrcVertexDataBuffer()->get_vertex_buffer(); + } - void fillFVarPatchArraysBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_arrays_buffer) override; + GPUStorageBuf *create_face_varying_patch_array_buf(const int face_varying_channel) override; - void wrapFVarPatchIndexBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_index_buffer) override; + GPUStorageBuf *get_face_varying_patch_index_buf(const int face_varying_channel) override + { + GPUPatchTable *patch_table = getFVarPatchTable(face_varying_channel); + return patch_table->GetFVarPatchIndexBuffer(face_varying_channel); + } - void wrapFVarPatchParamBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_param_buffer) override; + GPUStorageBuf *get_face_varying_patch_param_buf(const int face_varying_channel) override + { + GPUPatchTable *patch_table = getFVarPatchTable(face_varying_channel); + return patch_table->GetFVarPatchParamBuffer(face_varying_channel); + } - void wrapFVarSrcBuffer(const int face_varying_channel, - blender::gpu::VertBuf *src_buffer) override; + gpu::VertBuf *get_face_varying_source_buf(const int face_varying_channel) override + { + GPUVertexBuffer *vertex_buffer = getFVarSrcBuffer(face_varying_channel); + return vertex_buffer->get_vertex_buffer(); + } }; } // namespace blender::opensubdiv diff --git a/intern/opensubdiv/internal/evaluator/evaluator_impl.cc b/intern/opensubdiv/internal/evaluator/evaluator_impl.cc index 1f4bec6d015..30709bfdb41 100644 --- a/intern/opensubdiv/internal/evaluator/evaluator_impl.cc +++ b/intern/opensubdiv/internal/evaluator/evaluator_impl.cc @@ -352,58 +352,54 @@ void EvalOutputAPI::getPatchMap(blender::gpu::VertBuf *patch_map_handles, memcpy(buffer_nodes.data(), quadtree.data(), sizeof(PatchMap::QuadNode) * quadtree.size()); } -void EvalOutputAPI::fillPatchArraysBuffer(blender::gpu::VertBuf *patch_arrays_buffer) +GPUStorageBuf *EvalOutputAPI::create_patch_arrays_buf() { - implementation_->fillPatchArraysBuffer(patch_arrays_buffer); + return implementation_->create_patch_arrays_buf(); } -void EvalOutputAPI::wrapPatchIndexBuffer(blender::gpu::VertBuf *patch_index_buffer) +GPUStorageBuf *EvalOutputAPI::get_patch_index_buf() { - implementation_->wrapPatchIndexBuffer(patch_index_buffer); + return implementation_->get_patch_index_buf(); } -void EvalOutputAPI::wrapPatchParamBuffer(blender::gpu::VertBuf *patch_param_buffer) +GPUStorageBuf *EvalOutputAPI::get_patch_param_buf() { - implementation_->wrapPatchParamBuffer(patch_param_buffer); + return implementation_->get_patch_param_buf(); } -void EvalOutputAPI::wrapSrcBuffer(blender::gpu::VertBuf *src_buffer) +gpu::VertBuf *EvalOutputAPI::get_source_buf() { - implementation_->wrapSrcBuffer(src_buffer); + return implementation_->get_source_buf(); } -void EvalOutputAPI::wrapSrcVertexDataBuffer(blender::gpu::VertBuf *src_buffer) +gpu::VertBuf *EvalOutputAPI::get_source_data_buf() { - implementation_->wrapSrcVertexDataBuffer(src_buffer); + return implementation_->get_source_data_buf(); } -void EvalOutputAPI::fillFVarPatchArraysBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_arrays_buffer) +GPUStorageBuf *EvalOutputAPI::create_face_varying_patch_array_buf(const int face_varying_channel) { - implementation_->fillFVarPatchArraysBuffer(face_varying_channel, patch_arrays_buffer); + return implementation_->create_face_varying_patch_array_buf(face_varying_channel); } -void EvalOutputAPI::wrapFVarPatchIndexBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_index_buffer) +GPUStorageBuf *EvalOutputAPI::get_face_varying_patch_index_buf(const int face_varying_channel) { - implementation_->wrapFVarPatchIndexBuffer(face_varying_channel, patch_index_buffer); + return implementation_->get_face_varying_patch_index_buf(face_varying_channel); } -void EvalOutputAPI::wrapFVarPatchParamBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_param_buffer) +GPUStorageBuf *EvalOutputAPI::get_face_varying_patch_param_buf(const int face_varying_channel) { - implementation_->wrapFVarPatchParamBuffer(face_varying_channel, patch_param_buffer); + return implementation_->get_face_varying_patch_param_buf(face_varying_channel); } -void EvalOutputAPI::wrapFVarSrcBuffer(const int face_varying_channel, - blender::gpu::VertBuf *src_buffer) +gpu::VertBuf *EvalOutputAPI::get_face_varying_source_buf(const int face_varying_channel) { - implementation_->wrapFVarSrcBuffer(face_varying_channel, src_buffer); + return implementation_->get_face_varying_source_buf(face_varying_channel); } -int EvalOutputAPI::getFVarSrcBufferOffset(const int face_varying_channel) const +int EvalOutputAPI::get_face_varying_source_offset(const int face_varying_channel) const { - return implementation_->getFVarSrcBufferOffset(face_varying_channel); + return implementation_->get_face_varying_source_offset(face_varying_channel); } bool EvalOutputAPI::hasVertexData() const diff --git a/intern/opensubdiv/internal/evaluator/gl_compute_evaluator.cc b/intern/opensubdiv/internal/evaluator/gl_compute_evaluator.cc deleted file mode 100644 index 1344d219eae..00000000000 --- a/intern/opensubdiv/internal/evaluator/gl_compute_evaluator.cc +++ /dev/null @@ -1,659 +0,0 @@ -/* SPDX-FileCopyrightText: 2015 Pixar - * - * SPDX-License-Identifier: Apache-2.0 */ - -#include - -/* There are few aspects here: - * - macOS is strict about including both gl.h and gl3.h - * - libepoxy only pretends to be a replacement for gl.h - * - OpenSubdiv internally uses `OpenGL/gl3.h` on macOS - * - * In order to silence the warning pretend that gl3 has been included, fully relying on symbols - * from the epoxy. - * - * This works differently from how OpenSubdiv internally will use `OpenGL/gl3.h` without epoxy. - * Sounds fragile, but so far things seems to work. */ -#if defined(__APPLE__) -# define __gl3_h_ -#endif - -#include "gl_compute_evaluator.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -using OpenSubdiv::Far::LimitStencilTable; -using OpenSubdiv::Far::StencilTable; -using OpenSubdiv::Osd::BufferDescriptor; -using OpenSubdiv::Osd::PatchArray; -using OpenSubdiv::Osd::PatchArrayVector; - -extern "C" char datatoc_glsl_compute_kernel_glsl[]; - -namespace blender::opensubdiv { - -template GLuint createSSBO(std::vector const &src) -{ - if (src.empty()) { - return 0; - } - - GLuint devicePtr = 0; - -#if defined(GL_ARB_direct_state_access) - if (epoxy_has_gl_extension("GL_ARB_direct_state_access")) { - glCreateBuffers(1, &devicePtr); - glNamedBufferData(devicePtr, src.size() * sizeof(T), &src.at(0), GL_STATIC_DRAW); - } - else -#endif - { - GLint prev = 0; - glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &prev); - glGenBuffers(1, &devicePtr); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, devicePtr); - glBufferData(GL_SHADER_STORAGE_BUFFER, src.size() * sizeof(T), &src.at(0), GL_STATIC_DRAW); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, prev); - } - - return devicePtr; -} - -GLStencilTableSSBO::GLStencilTableSSBO(StencilTable const *stencilTable) -{ - _numStencils = stencilTable->GetNumStencils(); - if (_numStencils > 0) { - _sizes = createSSBO(stencilTable->GetSizes()); - _offsets = createSSBO(stencilTable->GetOffsets()); - _indices = createSSBO(stencilTable->GetControlIndices()); - _weights = createSSBO(stencilTable->GetWeights()); - _duWeights = _dvWeights = 0; - _duuWeights = _duvWeights = _dvvWeights = 0; - } - else { - _sizes = _offsets = _indices = _weights = 0; - _duWeights = _dvWeights = 0; - _duuWeights = _duvWeights = _dvvWeights = 0; - } -} - -GLStencilTableSSBO::GLStencilTableSSBO(LimitStencilTable const *limitStencilTable) -{ - _numStencils = limitStencilTable->GetNumStencils(); - if (_numStencils > 0) { - _sizes = createSSBO(limitStencilTable->GetSizes()); - _offsets = createSSBO(limitStencilTable->GetOffsets()); - _indices = createSSBO(limitStencilTable->GetControlIndices()); - _weights = createSSBO(limitStencilTable->GetWeights()); - _duWeights = createSSBO(limitStencilTable->GetDuWeights()); - _dvWeights = createSSBO(limitStencilTable->GetDvWeights()); - _duuWeights = createSSBO(limitStencilTable->GetDuuWeights()); - _duvWeights = createSSBO(limitStencilTable->GetDuvWeights()); - _dvvWeights = createSSBO(limitStencilTable->GetDvvWeights()); - } - else { - _sizes = _offsets = _indices = _weights = 0; - _duWeights = _dvWeights = 0; - _duuWeights = _duvWeights = _dvvWeights = 0; - } -} - -GLStencilTableSSBO::~GLStencilTableSSBO() -{ - if (_sizes) { - glDeleteBuffers(1, &_sizes); - } - if (_offsets) { - glDeleteBuffers(1, &_offsets); - } - if (_indices) { - glDeleteBuffers(1, &_indices); - } - if (_weights) { - glDeleteBuffers(1, &_weights); - } - if (_duWeights) { - glDeleteBuffers(1, &_duWeights); - } - if (_dvWeights) { - glDeleteBuffers(1, &_dvWeights); - } - if (_duuWeights) { - glDeleteBuffers(1, &_duuWeights); - } - if (_duvWeights) { - glDeleteBuffers(1, &_duvWeights); - } - if (_dvvWeights) { - glDeleteBuffers(1, &_dvvWeights); - } -} - -// --------------------------------------------------------------------------- - -GLComputeEvaluator::GLComputeEvaluator() : _workGroupSize(64), _patchArraysSSBO(0) -{ - memset((void *)&_stencilKernel, 0, sizeof(_stencilKernel)); - memset((void *)&_patchKernel, 0, sizeof(_patchKernel)); -} - -GLComputeEvaluator::~GLComputeEvaluator() -{ - if (_patchArraysSSBO) { - glDeleteBuffers(1, &_patchArraysSSBO); - } -} - -static GLuint compileKernel(BufferDescriptor const &srcDesc, - BufferDescriptor const &dstDesc, - BufferDescriptor const &duDesc, - BufferDescriptor const &dvDesc, - BufferDescriptor const &duuDesc, - BufferDescriptor const &duvDesc, - BufferDescriptor const &dvvDesc, - const char *kernelDefine, - int workGroupSize) -{ - GLuint program = glCreateProgram(); - - GLuint shader = glCreateShader(GL_COMPUTE_SHADER); - - std::string patchBasisShaderSource = - OpenSubdiv::Osd::GLSLPatchShaderSource::GetPatchBasisShaderSource(); - const char *patchBasisShaderSourceDefine = "#define OSD_PATCH_BASIS_GLSL\n"; - - std::ostringstream defines; - defines << "#define LENGTH " << srcDesc.length << "\n" - << "#define SRC_STRIDE " << srcDesc.stride << "\n" - << "#define DST_STRIDE " << dstDesc.stride << "\n" - << "#define WORK_GROUP_SIZE " << workGroupSize << "\n" - << kernelDefine << "\n" - << patchBasisShaderSourceDefine << "\n"; - - bool deriv1 = (duDesc.length > 0 || dvDesc.length > 0); - bool deriv2 = (duuDesc.length > 0 || duvDesc.length > 0 || dvvDesc.length > 0); - if (deriv1) { - defines << "#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"; - } - if (deriv2) { - defines << "#define OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES\n"; - } - - std::string defineStr = defines.str(); - - const char *shaderSources[4] = {"#version 430\n", nullptr, nullptr, nullptr}; - - shaderSources[1] = defineStr.c_str(); - shaderSources[2] = patchBasisShaderSource.c_str(); - shaderSources[3] = datatoc_glsl_compute_kernel_glsl; - glShaderSource(shader, 4, shaderSources, nullptr); - glCompileShader(shader); - glAttachShader(program, shader); - - GLint linked = 0; - glLinkProgram(program); - glGetProgramiv(program, GL_LINK_STATUS, &linked); - - if (linked == GL_FALSE) { - char buffer[1024]; - glGetShaderInfoLog(shader, 1024, nullptr, buffer); - OpenSubdiv::Far::Error(OpenSubdiv::Far::FAR_RUNTIME_ERROR, buffer); - - glGetProgramInfoLog(program, 1024, nullptr, buffer); - OpenSubdiv::Far::Error(OpenSubdiv::Far::FAR_RUNTIME_ERROR, buffer); - - glDeleteProgram(program); - return 0; - } - - glDeleteShader(shader); - - return program; -} - -bool GLComputeEvaluator::Compile(BufferDescriptor const &srcDesc, - BufferDescriptor const &dstDesc, - BufferDescriptor const &duDesc, - BufferDescriptor const &dvDesc, - BufferDescriptor const &duuDesc, - BufferDescriptor const &duvDesc, - BufferDescriptor const &dvvDesc) -{ - - // create a stencil kernel - if (!_stencilKernel.Compile( - srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, _workGroupSize)) - { - return false; - } - - // create a patch kernel - if (!_patchKernel.Compile( - srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, _workGroupSize)) - { - return false; - } - - // create a patch arrays buffer - if (!_patchArraysSSBO) { - glGenBuffers(1, &_patchArraysSSBO); - } - - return true; -} - -/* static */ -void GLComputeEvaluator::Synchronize(void * /*kernel*/) -{ - // XXX: this is currently just for the performance measuring purpose. - // need to be reimplemented by fence and sync. - glFinish(); -} - -int GLComputeEvaluator::GetDispatchSize(int count) const -{ - return (count + _workGroupSize - 1) / _workGroupSize; -} - -void GLComputeEvaluator::DispatchCompute(int totalDispatchSize) const -{ - int maxWorkGroupCount[2] = {0, 0}; - - glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &maxWorkGroupCount[0]); - glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &maxWorkGroupCount[1]); - - const GLuint maxResX = static_cast(maxWorkGroupCount[0]); - - const int dispatchSize = GetDispatchSize(totalDispatchSize); - GLuint dispatchRX = static_cast(dispatchSize); - GLuint dispatchRY = 1u; - if (dispatchRX > maxResX) { - /* Since there are some limitations with regards to the maximum work group size (could be as - * low as 64k elements per call), we split the number elements into a "2d" number, with the - * final index being computed as `res_x + res_y * max_work_group_size`. Even with a maximum - * work group size of 64k, that still leaves us with roughly `64k * 64k = 4` billion elements - * total, which should be enough. If not, we could also use the 3rd dimension. */ - /* TODO(fclem): We could dispatch fewer groups if we compute the prime factorization and - * get the smallest rect fitting the requirements. */ - dispatchRX = dispatchRY = std::ceil(std::sqrt(dispatchSize)); - /* Avoid a completely empty dispatch line caused by rounding. */ - if ((dispatchRX * (dispatchRY - 1)) >= dispatchSize) { - dispatchRY -= 1; - } - } - - /* X and Y dimensions may have different limits so the above computation may not be right, but - * even with the standard 64k minimum on all dimensions we still have a lot of room. Therefore, - * we presume it all fits. */ - assert(dispatchRY < static_cast(maxWorkGroupCount[1])); - - glDispatchCompute(dispatchRX, dispatchRY, 1); -} - -bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer, - BufferDescriptor const &srcDesc, - GLuint dstBuffer, - BufferDescriptor const &dstDesc, - GLuint duBuffer, - BufferDescriptor const &duDesc, - GLuint dvBuffer, - BufferDescriptor const &dvDesc, - GLuint sizesBuffer, - GLuint offsetsBuffer, - GLuint indicesBuffer, - GLuint weightsBuffer, - GLuint duWeightsBuffer, - GLuint dvWeightsBuffer, - int start, - int end) const -{ - - return EvalStencils(srcBuffer, - srcDesc, - dstBuffer, - dstDesc, - duBuffer, - duDesc, - dvBuffer, - dvDesc, - 0, - BufferDescriptor(), - 0, - BufferDescriptor(), - 0, - BufferDescriptor(), - sizesBuffer, - offsetsBuffer, - indicesBuffer, - weightsBuffer, - duWeightsBuffer, - dvWeightsBuffer, - 0, - 0, - 0, - start, - end); -} - -bool GLComputeEvaluator::EvalStencils(GLuint srcBuffer, - BufferDescriptor const &srcDesc, - GLuint dstBuffer, - BufferDescriptor const &dstDesc, - GLuint duBuffer, - BufferDescriptor const &duDesc, - GLuint dvBuffer, - BufferDescriptor const &dvDesc, - GLuint duuBuffer, - BufferDescriptor const &duuDesc, - GLuint duvBuffer, - BufferDescriptor const &duvDesc, - GLuint dvvBuffer, - BufferDescriptor const &dvvDesc, - GLuint sizesBuffer, - GLuint offsetsBuffer, - GLuint indicesBuffer, - GLuint weightsBuffer, - GLuint duWeightsBuffer, - GLuint dvWeightsBuffer, - GLuint duuWeightsBuffer, - GLuint duvWeightsBuffer, - GLuint dvvWeightsBuffer, - int start, - int end) const -{ - - if (!_stencilKernel.program) { - return false; - } - int count = end - start; - if (count <= 0) { - return true; - } - - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, duuBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, duvBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, dvvBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, sizesBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, offsetsBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, indicesBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, weightsBuffer); - if (duWeightsBuffer) { - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, duWeightsBuffer); - } - if (dvWeightsBuffer) { - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 9, dvWeightsBuffer); - } - if (duuWeightsBuffer) { - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 13, duuWeightsBuffer); - } - if (duvWeightsBuffer) { - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 14, duvWeightsBuffer); - } - if (dvvWeightsBuffer) { - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 15, dvvWeightsBuffer); - } - - GLint activeProgram; - glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram); - glUseProgram(_stencilKernel.program); - - glUniform1i(_stencilKernel.uniformStart, start); - glUniform1i(_stencilKernel.uniformEnd, end); - glUniform1i(_stencilKernel.uniformSrcOffset, srcDesc.offset); - glUniform1i(_stencilKernel.uniformDstOffset, dstDesc.offset); - if (_stencilKernel.uniformDuDesc > 0) { - glUniform3i(_stencilKernel.uniformDuDesc, duDesc.offset, duDesc.length, duDesc.stride); - } - if (_stencilKernel.uniformDvDesc > 0) { - glUniform3i(_stencilKernel.uniformDvDesc, dvDesc.offset, dvDesc.length, dvDesc.stride); - } - if (_stencilKernel.uniformDuuDesc > 0) { - glUniform3i(_stencilKernel.uniformDuuDesc, duuDesc.offset, duuDesc.length, duuDesc.stride); - } - if (_stencilKernel.uniformDuvDesc > 0) { - glUniform3i(_stencilKernel.uniformDuvDesc, duvDesc.offset, duvDesc.length, duvDesc.stride); - } - if (_stencilKernel.uniformDvvDesc > 0) { - glUniform3i(_stencilKernel.uniformDvvDesc, dvvDesc.offset, dvvDesc.length, dvvDesc.stride); - } - - DispatchCompute(count); - - glUseProgram(activeProgram); - - glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); - for (int i = 0; i < 16; ++i) { - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0); - } - - return true; -} - -bool GLComputeEvaluator::EvalPatches(GLuint srcBuffer, - BufferDescriptor const &srcDesc, - GLuint dstBuffer, - BufferDescriptor const &dstDesc, - GLuint duBuffer, - BufferDescriptor const &duDesc, - GLuint dvBuffer, - BufferDescriptor const &dvDesc, - int numPatchCoords, - GLuint patchCoordsBuffer, - const PatchArrayVector &patchArrays, - GLuint patchIndexBuffer, - GLuint patchParamsBuffer) const -{ - - return EvalPatches(srcBuffer, - srcDesc, - dstBuffer, - dstDesc, - duBuffer, - duDesc, - dvBuffer, - dvDesc, - 0, - BufferDescriptor(), - 0, - BufferDescriptor(), - 0, - BufferDescriptor(), - numPatchCoords, - patchCoordsBuffer, - patchArrays, - patchIndexBuffer, - patchParamsBuffer); -} - -bool GLComputeEvaluator::EvalPatches(GLuint srcBuffer, - BufferDescriptor const &srcDesc, - GLuint dstBuffer, - BufferDescriptor const &dstDesc, - GLuint duBuffer, - BufferDescriptor const &duDesc, - GLuint dvBuffer, - BufferDescriptor const &dvDesc, - GLuint duuBuffer, - BufferDescriptor const &duuDesc, - GLuint duvBuffer, - BufferDescriptor const &duvDesc, - GLuint dvvBuffer, - BufferDescriptor const &dvvDesc, - int numPatchCoords, - GLuint patchCoordsBuffer, - const PatchArrayVector &patchArrays, - GLuint patchIndexBuffer, - GLuint patchParamsBuffer) const -{ - - if (!_patchKernel.program) { - return false; - } - - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, duBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, dvBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, duuBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, duvBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, dvvBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, patchCoordsBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, patchIndexBuffer); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 7, patchParamsBuffer); - - GLint activeProgram; - glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram); - glUseProgram(_patchKernel.program); - - glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset); - glUniform1i(_patchKernel.uniformDstOffset, dstDesc.offset); - - int patchArraySize = sizeof(PatchArray); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, _patchArraysSSBO); - glBufferData( - GL_SHADER_STORAGE_BUFFER, patchArrays.size() * patchArraySize, nullptr, GL_STATIC_DRAW); - for (int i = 0; i < (int)patchArrays.size(); ++i) { - glBufferSubData( - GL_SHADER_STORAGE_BUFFER, i * patchArraySize, sizeof(PatchArray), &patchArrays[i]); - } - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, _patchArraysSSBO); - - if (_patchKernel.uniformDuDesc > 0) { - glUniform3i(_patchKernel.uniformDuDesc, duDesc.offset, duDesc.length, duDesc.stride); - } - if (_patchKernel.uniformDvDesc > 0) { - glUniform3i(_patchKernel.uniformDvDesc, dvDesc.offset, dvDesc.length, dvDesc.stride); - } - if (_patchKernel.uniformDuuDesc > 0) { - glUniform3i(_patchKernel.uniformDuuDesc, duuDesc.offset, duuDesc.length, duuDesc.stride); - } - if (_patchKernel.uniformDuvDesc > 0) { - glUniform3i(_patchKernel.uniformDuvDesc, duvDesc.offset, duvDesc.length, duvDesc.stride); - } - if (_patchKernel.uniformDvvDesc > 0) { - glUniform3i(_patchKernel.uniformDvvDesc, dvvDesc.offset, dvvDesc.length, dvvDesc.stride); - } - - DispatchCompute(numPatchCoords); - - glUseProgram(activeProgram); - - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, 0); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, 0); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, 0); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, 0); - - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, 0); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, 0); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 12, 0); - - return true; -} -// --------------------------------------------------------------------------- - -GLComputeEvaluator::_StencilKernel::_StencilKernel() : program(0) {} -GLComputeEvaluator::_StencilKernel::~_StencilKernel() -{ - if (program) { - glDeleteProgram(program); - } -} - -bool GLComputeEvaluator::_StencilKernel::Compile(BufferDescriptor const &srcDesc, - BufferDescriptor const &dstDesc, - BufferDescriptor const &duDesc, - BufferDescriptor const &dvDesc, - BufferDescriptor const &duuDesc, - BufferDescriptor const &duvDesc, - BufferDescriptor const &dvvDesc, - int workGroupSize) -{ - // create stencil kernel - if (program) { - glDeleteProgram(program); - } - - const char *kernelDefine = "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS\n"; - - program = compileKernel( - srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize); - if (program == 0) { - return false; - } - - // cache uniform locations (TODO: use uniform block) - uniformStart = glGetUniformLocation(program, "batchStart"); - uniformEnd = glGetUniformLocation(program, "batchEnd"); - uniformSrcOffset = glGetUniformLocation(program, "srcOffset"); - uniformDstOffset = glGetUniformLocation(program, "dstOffset"); - uniformDuDesc = glGetUniformLocation(program, "duDesc"); - uniformDvDesc = glGetUniformLocation(program, "dvDesc"); - uniformDuuDesc = glGetUniformLocation(program, "duuDesc"); - uniformDuvDesc = glGetUniformLocation(program, "duvDesc"); - uniformDvvDesc = glGetUniformLocation(program, "dvvDesc"); - - return true; -} - -// --------------------------------------------------------------------------- - -GLComputeEvaluator::_PatchKernel::_PatchKernel() : program(0) {} -GLComputeEvaluator::_PatchKernel::~_PatchKernel() -{ - if (program) { - glDeleteProgram(program); - } -} - -bool GLComputeEvaluator::_PatchKernel::Compile(BufferDescriptor const &srcDesc, - BufferDescriptor const &dstDesc, - BufferDescriptor const &duDesc, - BufferDescriptor const &dvDesc, - BufferDescriptor const &duuDesc, - BufferDescriptor const &duvDesc, - BufferDescriptor const &dvvDesc, - int workGroupSize) -{ - // create stencil kernel - if (program) { - glDeleteProgram(program); - } - - const char *kernelDefine = "#define OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES\n"; - - program = compileKernel( - srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, kernelDefine, workGroupSize); - if (program == 0) { - return false; - } - - // cache uniform locations - uniformSrcOffset = glGetUniformLocation(program, "srcOffset"); - uniformDstOffset = glGetUniformLocation(program, "dstOffset"); - uniformPatchArray = glGetUniformLocation(program, "patchArray"); - uniformDuDesc = glGetUniformLocation(program, "duDesc"); - uniformDvDesc = glGetUniformLocation(program, "dvDesc"); - uniformDuuDesc = glGetUniformLocation(program, "duuDesc"); - uniformDuvDesc = glGetUniformLocation(program, "duvDesc"); - uniformDvvDesc = glGetUniformLocation(program, "dvvDesc"); - - return true; -} - -} // namespace blender::opensubdiv diff --git a/intern/opensubdiv/internal/evaluator/gpu_compute_evaluator.cc b/intern/opensubdiv/internal/evaluator/gpu_compute_evaluator.cc new file mode 100644 index 00000000000..f41d18a5b3e --- /dev/null +++ b/intern/opensubdiv/internal/evaluator/gpu_compute_evaluator.cc @@ -0,0 +1,662 @@ +/* SPDX-FileCopyrightText: 2025 Blender Foundation + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include + +#include "gpu_compute_evaluator.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "GPU_capabilities.hh" +#include "GPU_compute.hh" +#include "GPU_context.hh" +#include "GPU_debug.hh" +#include "GPU_state.hh" +#include "GPU_vertex_buffer.hh" +#include "gpu_shader_create_info.hh" + +using OpenSubdiv::Far::LimitStencilTable; +using OpenSubdiv::Far::StencilTable; +using OpenSubdiv::Osd::BufferDescriptor; +using OpenSubdiv::Osd::PatchArray; +using OpenSubdiv::Osd::PatchArrayVector; + +#define SHADER_SRC_VERTEX_BUFFER_BUF_SLOT 0 +#define SHADER_DST_VERTEX_BUFFER_BUF_SLOT 1 +#define SHADER_DU_BUFFER_BUF_SLOT 2 +#define SHADER_DV_BUFFER_BUF_SLOT 3 +#define SHADER_SIZES_BUF_SLOT 4 +#define SHADER_OFFSETS_BUF_SLOT 5 +#define SHADER_INDICES_BUF_SLOT 6 +#define SHADER_WEIGHTS_BUF_SLOT 7 +#define SHADER_DU_WEIGHTS_BUF_SLOT 8 +#define SHADER_DV_WEIGHTS_BUF_SLOT 9 +#define SHADER_DUU_BUFFER_BUF_SLOT 10 +#define SHADER_DUV_BUFFER_BUF_SLOT 11 +#define SHADER_DVV_BUFFER_BUF_SLOT 12 +#define SHADER_DUU_WEIGHTS_BUF_SLOT 13 +#define SHADER_DUV_WEIGHTS_BUF_SLOT 14 +#define SHADER_DVV_WEIGHTS_BUF_SLOT 15 + +#define SHADER_PATCH_ARRAY_BUFFER_BUF_SLOT 4 +#define SHADER_PATCH_COORDS_BUF_SLOT 5 +#define SHADER_PATCH_INDEX_BUFFER_BUF_SLOT 6 +#define SHADER_PATCH_PARAM_BUFFER_BUF_SLOT 7 + +namespace blender::opensubdiv { + +template GPUStorageBuf *create_buffer(std::vector const &src, const char *name) +{ + if (src.empty()) { + return nullptr; + } + + // TODO: this can lead to an out of bound read. `GPU_storagebuf_update` should have a number of + // bytes. + size_t buffer_size = src.size() * sizeof(T); + size_t buffer_alloc_size = (buffer_size + 15) & ~0b1111; + + GPUStorageBuf *storage_buffer = GPU_storagebuf_create_ex( + buffer_alloc_size, &src.at(0), GPU_USAGE_STATIC, name); + return storage_buffer; +} + +GPUStencilTableSSBO::GPUStencilTableSSBO(StencilTable const *stencilTable) +{ + _numStencils = stencilTable->GetNumStencils(); + if (_numStencils > 0) { + sizes_buf = create_buffer(stencilTable->GetSizes(), "osd_sized"); + offsets_buf = create_buffer(stencilTable->GetOffsets(), "osd_offsets"); + indices_buf = create_buffer(stencilTable->GetControlIndices(), "osd_control_indices"); + weights_buf = create_buffer(stencilTable->GetWeights(), "osd_weights"); + } +} + +GPUStencilTableSSBO::GPUStencilTableSSBO(LimitStencilTable const *limitStencilTable) +{ + _numStencils = limitStencilTable->GetNumStencils(); + if (_numStencils > 0) { + sizes_buf = create_buffer(limitStencilTable->GetSizes(), "osd_sized"); + offsets_buf = create_buffer(limitStencilTable->GetOffsets(), "osd_offsets"); + indices_buf = create_buffer(limitStencilTable->GetControlIndices(), "osd_control_indices"); + weights_buf = create_buffer(limitStencilTable->GetWeights(), "osd_weights"); + du_weights_buf = create_buffer(limitStencilTable->GetDuWeights(), "osd_du_weights"); + dv_weights_buf = create_buffer(limitStencilTable->GetDvWeights(), "osd_dv_weights"); + duu_weights_buf = create_buffer(limitStencilTable->GetDuuWeights(), "osd_duu_weights"); + duv_weights_buf = create_buffer(limitStencilTable->GetDuvWeights(), "osd_duv_weights"); + dvv_weights_buf = create_buffer(limitStencilTable->GetDvvWeights(), "osd_dvv_weights"); + } +} + +static void storage_buffer_free(GPUStorageBuf **buffer) +{ + if (*buffer) { + GPU_storagebuf_free(*buffer); + *buffer = nullptr; + } +} + +GPUStencilTableSSBO::~GPUStencilTableSSBO() +{ + storage_buffer_free(&sizes_buf); + storage_buffer_free(&offsets_buf); + storage_buffer_free(&indices_buf); + storage_buffer_free(&weights_buf); + storage_buffer_free(&du_weights_buf); + storage_buffer_free(&dv_weights_buf); + storage_buffer_free(&duu_weights_buf); + storage_buffer_free(&duv_weights_buf); + storage_buffer_free(&dvv_weights_buf); +} + +// --------------------------------------------------------------------------- + +GPUComputeEvaluator::GPUComputeEvaluator() : _workGroupSize(64), _patchArraysSSBO(nullptr) +{ + memset((void *)&_stencilKernel, 0, sizeof(_stencilKernel)); + memset((void *)&_patchKernel, 0, sizeof(_patchKernel)); +} + +GPUComputeEvaluator::~GPUComputeEvaluator() +{ + if (_patchArraysSSBO) { + GPU_storagebuf_free(_patchArraysSSBO); + _patchArraysSSBO = nullptr; + } +} + +static GPUShader *compileKernel(BufferDescriptor const &srcDesc, + BufferDescriptor const &dstDesc, + BufferDescriptor const &duDesc, + BufferDescriptor const &dvDesc, + BufferDescriptor const &duuDesc, + BufferDescriptor const &duvDesc, + BufferDescriptor const &dvvDesc, + bool use_eval_stencil_kernel, + int workGroupSize) +{ + using namespace blender::gpu::shader; + ShaderCreateInfo info("opensubdiv_compute_eval"); + info.local_group_size(workGroupSize, 1, 1); + if (GPU_backend_get_type() == GPU_BACKEND_METAL) { + info.define("OSD_PATCH_BASIS_METAL"); + } + else { + info.define("OSD_PATCH_BASIS_GLSL"); + } + if (use_eval_stencil_kernel) { + info.define("OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS"); + } + else { + info.define("OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES"); + } + + // TODO: use specialization constants for src_stride, dst_stride. Not sure we can use + // work group size as that requires extensions. This allows us to compile less shaders and + // improve overall performance. Adding length as specialization constant will not work as it is + // used to define an array length. This is not supported by Metal. + std::string length = std::to_string(srcDesc.length); + std::string src_stride = std::to_string(srcDesc.stride); + std::string dst_stride = std::to_string(dstDesc.stride); + std::string work_group_size = std::to_string(workGroupSize); + info.define("LENGTH", length); + info.define("SRC_STRIDE", src_stride); + info.define("DST_STRIDE", dst_stride); + info.define("WORK_GROUP_SIZE", work_group_size); + info.typedef_source("osd_patch_basis.glsl"); + info.storage_buf( + SHADER_SRC_VERTEX_BUFFER_BUF_SLOT, Qualifier::READ, "float", "srcVertexBuffer[]"); + info.storage_buf( + SHADER_DST_VERTEX_BUFFER_BUF_SLOT, Qualifier::WRITE, "float", "dstVertexBuffer[]"); + info.push_constant(Type::INT, "srcOffset"); + info.push_constant(Type::INT, "dstOffset"); + + bool deriv1 = (duDesc.length > 0 || dvDesc.length > 0); + bool deriv2 = (duuDesc.length > 0 || duvDesc.length > 0 || dvvDesc.length > 0); + if (deriv1) { + info.define("OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES"); + info.storage_buf(SHADER_DU_BUFFER_BUF_SLOT, Qualifier::READ_WRITE, "float", "duBuffer[]"); + info.storage_buf(SHADER_DV_BUFFER_BUF_SLOT, Qualifier::READ_WRITE, "float", "dvBuffer[]"); + info.push_constant(Type::IVEC3, "duDesc"); + info.push_constant(Type::IVEC3, "dvDesc"); + } + if (deriv2) { + info.define("OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES"); + info.storage_buf(SHADER_DUU_BUFFER_BUF_SLOT, Qualifier::READ_WRITE, "float", "duuBuffer[]"); + info.storage_buf(SHADER_DUV_BUFFER_BUF_SLOT, Qualifier::READ_WRITE, "float", "duvBuffer[]"); + info.storage_buf(SHADER_DVV_BUFFER_BUF_SLOT, Qualifier::READ_WRITE, "float", "dvvBuffer[]"); + info.push_constant(Type::IVEC3, "duuDesc"); + info.push_constant(Type::IVEC3, "duvDesc"); + info.push_constant(Type::IVEC3, "dvvDesc"); + } + + if (use_eval_stencil_kernel) { + info.storage_buf(SHADER_SIZES_BUF_SLOT, Qualifier::READ, "int", "sizes_buf[]"); + info.storage_buf(SHADER_OFFSETS_BUF_SLOT, Qualifier::READ, "int", "offsets_buf[]"); + info.storage_buf(SHADER_INDICES_BUF_SLOT, Qualifier::READ, "int", "indices_buf[]"); + info.storage_buf(SHADER_WEIGHTS_BUF_SLOT, Qualifier::READ, "float", "weights_buf[]"); + if (deriv1) { + info.storage_buf( + SHADER_DU_WEIGHTS_BUF_SLOT, Qualifier::READ_WRITE, "float", "du_weights_buf[]"); + info.storage_buf( + SHADER_DV_WEIGHTS_BUF_SLOT, Qualifier::READ_WRITE, "float", "dv_weights_buf[]"); + } + if (deriv2) { + info.storage_buf( + SHADER_DUU_WEIGHTS_BUF_SLOT, Qualifier::READ_WRITE, "float", "duu_weights_buf[]"); + info.storage_buf( + SHADER_DUV_WEIGHTS_BUF_SLOT, Qualifier::READ_WRITE, "float", "duv_weights_buf[]"); + info.storage_buf( + SHADER_DVV_WEIGHTS_BUF_SLOT, Qualifier::READ_WRITE, "float", "dvv_weights_buf[]"); + } + info.push_constant(Type::INT, "batchStart"); + info.push_constant(Type::INT, "batchEnd"); + } + else { + info.storage_buf(SHADER_PATCH_ARRAY_BUFFER_BUF_SLOT, + Qualifier::READ, + "OsdPatchArray", + "patchArrayBuffer[]"); + info.storage_buf( + SHADER_PATCH_COORDS_BUF_SLOT, Qualifier::READ, "OsdPatchCoord", "patchCoords[]"); + info.storage_buf( + SHADER_PATCH_INDEX_BUFFER_BUF_SLOT, Qualifier::READ, "int", "patchIndexBuffer[]"); + info.storage_buf(SHADER_PATCH_PARAM_BUFFER_BUF_SLOT, + Qualifier::READ, + "OsdPatchParam", + "patchParamBuffer[]"); + } + info.compute_source("osd_kernel_comp.glsl"); + GPUShader *shader = GPU_shader_create_from_info( + reinterpret_cast(&info)); + return shader; +} + +bool GPUComputeEvaluator::Compile(BufferDescriptor const &srcDesc, + BufferDescriptor const &dstDesc, + BufferDescriptor const &duDesc, + BufferDescriptor const &dvDesc, + BufferDescriptor const &duuDesc, + BufferDescriptor const &duvDesc, + BufferDescriptor const &dvvDesc) +{ + + if (!_stencilKernel.Compile( + srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, _workGroupSize)) + { + return false; + } + + if (!_patchKernel.Compile( + srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, _workGroupSize)) + { + return false; + } + + return true; +} + +/* static */ +void GPUComputeEvaluator::Synchronize(void * /*kernel*/) +{ + // XXX: this is currently just for the performance measuring purpose. + // need to be reimplemented by fence and sync. + GPU_finish(); +} + +int GPUComputeEvaluator::GetDispatchSize(int count) const +{ + return (count + _workGroupSize - 1) / _workGroupSize; +} + +void GPUComputeEvaluator::DispatchCompute(GPUShader *shader, int totalDispatchSize) const +{ + const int dispatchSize = GetDispatchSize(totalDispatchSize); + int dispatchRX = dispatchSize; + int dispatchRY = 1u; + if (dispatchRX > GPU_max_work_group_count(0)) { + /* Since there are some limitations with regards to the maximum work group size (could be as + * low as 64k elements per call), we split the number elements into a "2d" number, with the + * final index being computed as `res_x + res_y * max_work_group_size`. Even with a maximum + * work group size of 64k, that still leaves us with roughly `64k * 64k = 4` billion elements + * total, which should be enough. If not, we could also use the 3rd dimension. */ + /* TODO(fclem): We could dispatch fewer groups if we compute the prime factorization and + * get the smallest rect fitting the requirements. */ + dispatchRX = dispatchRY = std::ceil(std::sqrt(dispatchSize)); + /* Avoid a completely empty dispatch line caused by rounding. */ + if ((dispatchRX * (dispatchRY - 1)) >= dispatchSize) { + dispatchRY -= 1; + } + } + + /* X and Y dimensions may have different limits so the above computation may not be right, but + * even with the standard 64k minimum on all dimensions we still have a lot of room. Therefore, + * we presume it all fits. */ + assert(dispatchRY < GPU_max_work_group_count(1)); + GPU_compute_dispatch(shader, dispatchRX, dispatchRY, 1); + + /* Next usage of the src/dst buffers will always be a shader storage. Vertices/normals/attributes + * are copied over to the final buffers using compute shaders. */ + GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE); +} + +bool GPUComputeEvaluator::EvalStencils(gpu::VertBuf *srcBuffer, + BufferDescriptor const &srcDesc, + gpu::VertBuf *dstBuffer, + BufferDescriptor const &dstDesc, + gpu::VertBuf *duBuffer, + BufferDescriptor const &duDesc, + gpu::VertBuf *dvBuffer, + BufferDescriptor const &dvDesc, + GPUStorageBuf *sizesBuffer, + GPUStorageBuf *offsetsBuffer, + GPUStorageBuf *indicesBuffer, + GPUStorageBuf *weightsBuffer, + GPUStorageBuf *duWeightsBuffer, + GPUStorageBuf *dvWeightsBuffer, + int start, + int end) const +{ + + return EvalStencils(srcBuffer, + srcDesc, + dstBuffer, + dstDesc, + duBuffer, + duDesc, + dvBuffer, + dvDesc, + nullptr, + BufferDescriptor(), + nullptr, + BufferDescriptor(), + nullptr, + BufferDescriptor(), + sizesBuffer, + offsetsBuffer, + indicesBuffer, + weightsBuffer, + duWeightsBuffer, + dvWeightsBuffer, + nullptr, + nullptr, + nullptr, + start, + end); +} + +bool GPUComputeEvaluator::EvalStencils(gpu::VertBuf *srcBuffer, + BufferDescriptor const &srcDesc, + gpu::VertBuf *dstBuffer, + BufferDescriptor const &dstDesc, + gpu::VertBuf *duBuffer, + BufferDescriptor const &duDesc, + gpu::VertBuf *dvBuffer, + BufferDescriptor const &dvDesc, + gpu::VertBuf *duuBuffer, + BufferDescriptor const &duuDesc, + gpu::VertBuf *duvBuffer, + BufferDescriptor const &duvDesc, + gpu::VertBuf *dvvBuffer, + BufferDescriptor const &dvvDesc, + GPUStorageBuf *sizesBuffer, + GPUStorageBuf *offsetsBuffer, + GPUStorageBuf *indicesBuffer, + GPUStorageBuf *weightsBuffer, + GPUStorageBuf *duWeightsBuffer, + GPUStorageBuf *dvWeightsBuffer, + GPUStorageBuf *duuWeightsBuffer, + GPUStorageBuf *duvWeightsBuffer, + GPUStorageBuf *dvvWeightsBuffer, + int start, + int end) const +{ + + if (_stencilKernel.shader == nullptr) { + return false; + } + int count = end - start; + if (count <= 0) { + return true; + } + + GPU_shader_bind(_stencilKernel.shader); + GPU_vertbuf_bind_as_ssbo(srcBuffer, SHADER_SRC_VERTEX_BUFFER_BUF_SLOT); + GPU_vertbuf_bind_as_ssbo(dstBuffer, SHADER_DST_VERTEX_BUFFER_BUF_SLOT); + if (duBuffer) { + GPU_vertbuf_bind_as_ssbo(duBuffer, SHADER_DU_BUFFER_BUF_SLOT); + } + if (dvBuffer) { + GPU_vertbuf_bind_as_ssbo(dvBuffer, SHADER_DV_BUFFER_BUF_SLOT); + } + if (duuBuffer) { + GPU_vertbuf_bind_as_ssbo(duuBuffer, SHADER_DUU_BUFFER_BUF_SLOT); + } + if (duvBuffer) { + GPU_vertbuf_bind_as_ssbo(duvBuffer, SHADER_DUV_BUFFER_BUF_SLOT); + } + if (dvvBuffer) { + GPU_vertbuf_bind_as_ssbo(dvvBuffer, SHADER_DVV_BUFFER_BUF_SLOT); + } + GPU_storagebuf_bind(sizesBuffer, SHADER_SIZES_BUF_SLOT); + GPU_storagebuf_bind(offsetsBuffer, SHADER_OFFSETS_BUF_SLOT); + GPU_storagebuf_bind(indicesBuffer, SHADER_INDICES_BUF_SLOT); + GPU_storagebuf_bind(weightsBuffer, SHADER_WEIGHTS_BUF_SLOT); + if (duWeightsBuffer) { + GPU_storagebuf_bind(duWeightsBuffer, SHADER_DU_WEIGHTS_BUF_SLOT); + } + if (dvWeightsBuffer) { + GPU_storagebuf_bind(dvWeightsBuffer, SHADER_DV_WEIGHTS_BUF_SLOT); + } + if (duuWeightsBuffer) { + GPU_storagebuf_bind(duuWeightsBuffer, SHADER_DUU_WEIGHTS_BUF_SLOT); + } + if (duvWeightsBuffer) { + GPU_storagebuf_bind(duvWeightsBuffer, SHADER_DUV_WEIGHTS_BUF_SLOT); + } + if (dvvWeightsBuffer) { + GPU_storagebuf_bind(dvvWeightsBuffer, SHADER_DVV_WEIGHTS_BUF_SLOT); + } + + GPU_shader_uniform_int_ex(_stencilKernel.shader, _stencilKernel.uniformStart, 1, 1, &start); + GPU_shader_uniform_int_ex(_stencilKernel.shader, _stencilKernel.uniformEnd, 1, 1, &end); + GPU_shader_uniform_int_ex( + _stencilKernel.shader, _stencilKernel.uniformSrcOffset, 1, 1, &srcDesc.offset); + GPU_shader_uniform_int_ex( + _stencilKernel.shader, _stencilKernel.uniformDstOffset, 1, 1, &dstDesc.offset); + +// TODO init to -1 and check >= 0 to align with GPU module. Currently we assume that the uniform +// location is not zero as there are other uniforms defined as well. +#define BIND_BUF_DESC(uniform, desc) \ + if (_stencilKernel.uniform > 0) { \ + int value[] = {desc.offset, desc.length, desc.stride}; \ + GPU_shader_uniform_int_ex(_stencilKernel.shader, _stencilKernel.uniform, 3, 1, value); \ + } + BIND_BUF_DESC(uniformDuDesc, duDesc) + BIND_BUF_DESC(uniformDvDesc, dvDesc) + BIND_BUF_DESC(uniformDuuDesc, duuDesc) + BIND_BUF_DESC(uniformDuvDesc, duvDesc) + BIND_BUF_DESC(uniformDvvDesc, dvvDesc) +#undef BIND_BUF_DESC + DispatchCompute(_stencilKernel.shader, count); + // GPU_storagebuf_unbind_all(); + GPU_shader_unbind(); + + return true; +} + +bool GPUComputeEvaluator::EvalPatches(gpu::VertBuf *srcBuffer, + BufferDescriptor const &srcDesc, + gpu::VertBuf *dstBuffer, + BufferDescriptor const &dstDesc, + gpu::VertBuf *duBuffer, + BufferDescriptor const &duDesc, + gpu::VertBuf *dvBuffer, + BufferDescriptor const &dvDesc, + int numPatchCoords, + gpu::VertBuf *patchCoordsBuffer, + const PatchArrayVector &patchArrays, + GPUStorageBuf *patchIndexBuffer, + GPUStorageBuf *patchParamsBuffer) +{ + + return EvalPatches(srcBuffer, + srcDesc, + dstBuffer, + dstDesc, + duBuffer, + duDesc, + dvBuffer, + dvDesc, + nullptr, + BufferDescriptor(), + nullptr, + BufferDescriptor(), + nullptr, + BufferDescriptor(), + numPatchCoords, + patchCoordsBuffer, + patchArrays, + patchIndexBuffer, + patchParamsBuffer); +} + +bool GPUComputeEvaluator::EvalPatches(gpu::VertBuf *srcBuffer, + BufferDescriptor const &srcDesc, + gpu::VertBuf *dstBuffer, + BufferDescriptor const &dstDesc, + gpu::VertBuf *duBuffer, + BufferDescriptor const &duDesc, + gpu::VertBuf *dvBuffer, + BufferDescriptor const &dvDesc, + gpu::VertBuf *duuBuffer, + BufferDescriptor const &duuDesc, + gpu::VertBuf *duvBuffer, + BufferDescriptor const &duvDesc, + gpu::VertBuf *dvvBuffer, + BufferDescriptor const &dvvDesc, + int numPatchCoords, + gpu::VertBuf *patchCoordsBuffer, + const PatchArrayVector &patchArrays, + GPUStorageBuf *patchIndexBuffer, + GPUStorageBuf *patchParamsBuffer) +{ + + if (_patchKernel.shader == nullptr) { + return false; + } + + GPU_shader_bind(_patchKernel.shader); + GPU_vertbuf_bind_as_ssbo(srcBuffer, SHADER_SRC_VERTEX_BUFFER_BUF_SLOT); + GPU_vertbuf_bind_as_ssbo(dstBuffer, SHADER_DST_VERTEX_BUFFER_BUF_SLOT); + if (duBuffer) { + GPU_vertbuf_bind_as_ssbo(duBuffer, SHADER_DU_BUFFER_BUF_SLOT); + } + if (dvBuffer) { + GPU_vertbuf_bind_as_ssbo(dvBuffer, SHADER_DV_BUFFER_BUF_SLOT); + } + if (duuBuffer) { + GPU_vertbuf_bind_as_ssbo(duuBuffer, SHADER_DUU_BUFFER_BUF_SLOT); + } + if (duvBuffer) { + GPU_vertbuf_bind_as_ssbo(duvBuffer, SHADER_DUV_BUFFER_BUF_SLOT); + } + if (dvvBuffer) { + GPU_vertbuf_bind_as_ssbo(dvvBuffer, SHADER_DVV_BUFFER_BUF_SLOT); + } + GPU_vertbuf_bind_as_ssbo(patchCoordsBuffer, SHADER_PATCH_COORDS_BUF_SLOT); + GPU_storagebuf_bind(patchIndexBuffer, SHADER_PATCH_INDEX_BUFFER_BUF_SLOT); + GPU_storagebuf_bind(patchParamsBuffer, SHADER_PATCH_PARAM_BUFFER_BUF_SLOT); + int patchArraySize = sizeof(PatchArray); + if (_patchArraysSSBO) { + GPU_storagebuf_free(_patchArraysSSBO); + _patchArraysSSBO = nullptr; + } + _patchArraysSSBO = GPU_storagebuf_create_ex(patchArrays.size() * patchArraySize, + static_cast(&patchArrays[0]), + GPU_USAGE_STATIC, + "osd_patch_array"); + GPU_storagebuf_bind(_patchArraysSSBO, SHADER_PATCH_ARRAY_BUFFER_BUF_SLOT); + + GPU_shader_uniform_int_ex( + _patchKernel.shader, _patchKernel.uniformSrcOffset, 1, 1, &srcDesc.offset); + GPU_shader_uniform_int_ex( + _patchKernel.shader, _patchKernel.uniformDstOffset, 1, 1, &dstDesc.offset); + +// TODO init to -1 and check >= 0 to align with GPU module. +#define BIND_BUF_DESC(uniform, desc) \ + if (_stencilKernel.uniform > 0) { \ + int value[] = {desc.offset, desc.length, desc.stride}; \ + GPU_shader_uniform_int_ex(_patchKernel.shader, _patchKernel.uniform, 3, 1, value); \ + } + BIND_BUF_DESC(uniformDuDesc, duDesc) + BIND_BUF_DESC(uniformDvDesc, dvDesc) + BIND_BUF_DESC(uniformDuuDesc, duuDesc) + BIND_BUF_DESC(uniformDuvDesc, duvDesc) + BIND_BUF_DESC(uniformDvvDesc, dvvDesc) +#undef BIND_BUF_DESC + + DispatchCompute(_patchKernel.shader, numPatchCoords); + GPU_shader_unbind(); + + return true; +} +// --------------------------------------------------------------------------- + +GPUComputeEvaluator::_StencilKernel::_StencilKernel() {} +GPUComputeEvaluator::_StencilKernel::~_StencilKernel() +{ + if (shader) { + GPU_shader_free(shader); + shader = nullptr; + } +} + +bool GPUComputeEvaluator::_StencilKernel::Compile(BufferDescriptor const &srcDesc, + BufferDescriptor const &dstDesc, + BufferDescriptor const &duDesc, + BufferDescriptor const &dvDesc, + BufferDescriptor const &duuDesc, + BufferDescriptor const &duvDesc, + BufferDescriptor const &dvvDesc, + int workGroupSize) +{ + if (shader) { + GPU_shader_free(shader); + shader = nullptr; + } + + shader = compileKernel( + srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, true, workGroupSize); + if (shader == nullptr) { + return false; + } + + // cache uniform locations (TODO: use uniform block) + uniformStart = GPU_shader_get_uniform(shader, "batchStart"); + uniformEnd = GPU_shader_get_uniform(shader, "batchEnd"); + uniformSrcOffset = GPU_shader_get_uniform(shader, "srcOffset"); + uniformDstOffset = GPU_shader_get_uniform(shader, "dstOffset"); + uniformDuDesc = GPU_shader_get_uniform(shader, "duDesc"); + uniformDvDesc = GPU_shader_get_uniform(shader, "dvDesc"); + uniformDuuDesc = GPU_shader_get_uniform(shader, "duuDesc"); + uniformDuvDesc = GPU_shader_get_uniform(shader, "duvDesc"); + uniformDvvDesc = GPU_shader_get_uniform(shader, "dvvDesc"); + + return true; +} + +// --------------------------------------------------------------------------- + +GPUComputeEvaluator::_PatchKernel::_PatchKernel() {} +GPUComputeEvaluator::_PatchKernel::~_PatchKernel() +{ + if (shader) { + GPU_shader_free(shader); + shader = nullptr; + } +} + +bool GPUComputeEvaluator::_PatchKernel::Compile(BufferDescriptor const &srcDesc, + BufferDescriptor const &dstDesc, + BufferDescriptor const &duDesc, + BufferDescriptor const &dvDesc, + BufferDescriptor const &duuDesc, + BufferDescriptor const &duvDesc, + BufferDescriptor const &dvvDesc, + int workGroupSize) +{ + if (shader) { + GPU_shader_free(shader); + shader = nullptr; + } + + shader = compileKernel( + srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc, false, workGroupSize); + if (shader == nullptr) { + return false; + } + + // cache uniform locations + uniformSrcOffset = GPU_shader_get_uniform(shader, "srcOffset"); + uniformDstOffset = GPU_shader_get_uniform(shader, "dstOffset"); + uniformDuDesc = GPU_shader_get_uniform(shader, "duDesc"); + uniformDvDesc = GPU_shader_get_uniform(shader, "dvDesc"); + uniformDuuDesc = GPU_shader_get_uniform(shader, "duuDesc"); + uniformDuvDesc = GPU_shader_get_uniform(shader, "duvDesc"); + uniformDvvDesc = GPU_shader_get_uniform(shader, "dvvDesc"); + + return true; +} + +} // namespace blender::opensubdiv diff --git a/intern/opensubdiv/internal/evaluator/gl_compute_evaluator.h b/intern/opensubdiv/internal/evaluator/gpu_compute_evaluator.h similarity index 82% rename from intern/opensubdiv/internal/evaluator/gl_compute_evaluator.h rename to intern/opensubdiv/internal/evaluator/gpu_compute_evaluator.h index 40d6c73abf8..b814fa24dde 100644 --- a/intern/opensubdiv/internal/evaluator/gl_compute_evaluator.h +++ b/intern/opensubdiv/internal/evaluator/gpu_compute_evaluator.h @@ -2,14 +2,15 @@ * * SPDX-License-Identifier: Apache-2.0 */ -#ifndef OPENSUBDIV_GL_COMPUTE_EVALUATOR_H_ -#define OPENSUBDIV_GL_COMPUTE_EVALUATOR_H_ +#ifndef OPENSUBDIV_GPU_COMPUTE_EVALUATOR_H_ +#define OPENSUBDIV_GPU_COMPUTE_EVALUATOR_H_ #include -#include #include #include +#include "GPU_storage_buffer.hh" + namespace OpenSubdiv::OPENSUBDIV_VERSION::Far { class LimitStencilTable; class StencilTable; @@ -24,61 +25,61 @@ namespace blender::opensubdiv { /// /// GLSLComputeKernel consumes this table to apply stencils /// -class GLStencilTableSSBO { +class GPUStencilTableSSBO { public: - static GLStencilTableSSBO *Create(OpenSubdiv::Far::StencilTable const *stencilTable, - void *deviceContext = nullptr) + static GPUStencilTableSSBO *Create(OpenSubdiv::Far::StencilTable const *stencilTable, + void *deviceContext = nullptr) { (void)deviceContext; // unused - return new GLStencilTableSSBO(stencilTable); + return new GPUStencilTableSSBO(stencilTable); } - static GLStencilTableSSBO *Create(OpenSubdiv::Far::LimitStencilTable const *limitStencilTable, - void *deviceContext = nullptr) + static GPUStencilTableSSBO *Create(OpenSubdiv::Far::LimitStencilTable const *limitStencilTable, + void *deviceContext = nullptr) { (void)deviceContext; // unused - return new GLStencilTableSSBO(limitStencilTable); + return new GPUStencilTableSSBO(limitStencilTable); } - explicit GLStencilTableSSBO(OpenSubdiv::Far::StencilTable const *stencilTable); - explicit GLStencilTableSSBO(OpenSubdiv::Far::LimitStencilTable const *limitStencilTable); - ~GLStencilTableSSBO(); + explicit GPUStencilTableSSBO(OpenSubdiv::Far::StencilTable const *stencilTable); + explicit GPUStencilTableSSBO(OpenSubdiv::Far::LimitStencilTable const *limitStencilTable); + ~GPUStencilTableSSBO(); // interfaces needed for GLSLComputeKernel - GLuint GetSizesBuffer() const + GPUStorageBuf *GetSizesBuffer() const { - return _sizes; + return sizes_buf; } - GLuint GetOffsetsBuffer() const + GPUStorageBuf *GetOffsetsBuffer() const { - return _offsets; + return offsets_buf; } - GLuint GetIndicesBuffer() const + GPUStorageBuf *GetIndicesBuffer() const { - return _indices; + return indices_buf; } - GLuint GetWeightsBuffer() const + GPUStorageBuf *GetWeightsBuffer() const { - return _weights; + return weights_buf; } - GLuint GetDuWeightsBuffer() const + GPUStorageBuf *GetDuWeightsBuffer() const { - return _duWeights; + return du_weights_buf; } - GLuint GetDvWeightsBuffer() const + GPUStorageBuf *GetDvWeightsBuffer() const { - return _dvWeights; + return dv_weights_buf; } - GLuint GetDuuWeightsBuffer() const + GPUStorageBuf *GetDuuWeightsBuffer() const { - return _duuWeights; + return duu_weights_buf; } - GLuint GetDuvWeightsBuffer() const + GPUStorageBuf *GetDuvWeightsBuffer() const { - return _duvWeights; + return duv_weights_buf; } - GLuint GetDvvWeightsBuffer() const + GPUStorageBuf *GetDvvWeightsBuffer() const { - return _dvvWeights; + return dvv_weights_buf; } int GetNumStencils() const { @@ -86,28 +87,28 @@ class GLStencilTableSSBO { } private: - GLuint _sizes; - GLuint _offsets; - GLuint _indices; - GLuint _weights; - GLuint _duWeights; - GLuint _dvWeights; - GLuint _duuWeights; - GLuint _duvWeights; - GLuint _dvvWeights; + GPUStorageBuf *sizes_buf = nullptr; + GPUStorageBuf *offsets_buf = nullptr; + GPUStorageBuf *indices_buf = nullptr; + GPUStorageBuf *weights_buf = nullptr; + GPUStorageBuf *du_weights_buf = nullptr; + GPUStorageBuf *dv_weights_buf = nullptr; + GPUStorageBuf *duu_weights_buf = nullptr; + GPUStorageBuf *duv_weights_buf = nullptr; + GPUStorageBuf *dvv_weights_buf = nullptr; int _numStencils; }; // --------------------------------------------------------------------------- -class GLComputeEvaluator { +class GPUComputeEvaluator { public: using Instantiatable = bool; - static GLComputeEvaluator *Create(OpenSubdiv::Osd::BufferDescriptor const &srcDesc, - OpenSubdiv::Osd::BufferDescriptor const &dstDesc, - OpenSubdiv::Osd::BufferDescriptor const &duDesc, - OpenSubdiv::Osd::BufferDescriptor const &dvDesc, - void *deviceContext = nullptr) + static GPUComputeEvaluator *Create(OpenSubdiv::Osd::BufferDescriptor const &srcDesc, + OpenSubdiv::Osd::BufferDescriptor const &dstDesc, + OpenSubdiv::Osd::BufferDescriptor const &duDesc, + OpenSubdiv::Osd::BufferDescriptor const &dvDesc, + void *deviceContext = nullptr) { return Create(srcDesc, dstDesc, @@ -119,17 +120,17 @@ class GLComputeEvaluator { deviceContext); } - static GLComputeEvaluator *Create(OpenSubdiv::Osd::BufferDescriptor const &srcDesc, - OpenSubdiv::Osd::BufferDescriptor const &dstDesc, - OpenSubdiv::Osd::BufferDescriptor const &duDesc, - OpenSubdiv::Osd::BufferDescriptor const &dvDesc, - OpenSubdiv::Osd::BufferDescriptor const &duuDesc, - OpenSubdiv::Osd::BufferDescriptor const &duvDesc, - OpenSubdiv::Osd::BufferDescriptor const &dvvDesc, - void *deviceContext = nullptr) + static GPUComputeEvaluator *Create(OpenSubdiv::Osd::BufferDescriptor const &srcDesc, + OpenSubdiv::Osd::BufferDescriptor const &dstDesc, + OpenSubdiv::Osd::BufferDescriptor const &duDesc, + OpenSubdiv::Osd::BufferDescriptor const &dvDesc, + OpenSubdiv::Osd::BufferDescriptor const &duuDesc, + OpenSubdiv::Osd::BufferDescriptor const &duvDesc, + OpenSubdiv::Osd::BufferDescriptor const &dvvDesc, + void *deviceContext = nullptr) { (void)deviceContext; // not used - GLComputeEvaluator *instance = new GLComputeEvaluator(); + GPUComputeEvaluator *instance = new GPUComputeEvaluator(); if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc, duuDesc, duvDesc, dvvDesc)) { return instance; } @@ -138,10 +139,10 @@ class GLComputeEvaluator { } /// Constructor. - GLComputeEvaluator(); + GPUComputeEvaluator(); /// Destructor. note that the GL context must be made current. - ~GLComputeEvaluator(); + ~GPUComputeEvaluator(); /// ---------------------------------------------------------------------- /// @@ -154,13 +155,13 @@ class GLComputeEvaluator { /// transparently from OsdMesh template interface. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer @@ -182,7 +183,7 @@ class GLComputeEvaluator { DST_BUFFER *dstBuffer, OpenSubdiv::Osd::BufferDescriptor const &dstDesc, STENCIL_TABLE const *stencilTable, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { @@ -209,25 +210,25 @@ class GLComputeEvaluator { /// transparently from OsdMesh template interface. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the dstBuffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer @@ -253,7 +254,7 @@ class GLComputeEvaluator { DST_BUFFER *dvBuffer, OpenSubdiv::Osd::BufferDescriptor const &dvDesc, STENCIL_TABLE const *stencilTable, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { @@ -293,43 +294,43 @@ class GLComputeEvaluator { /// transparently from OsdMesh template interface. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the dstBuffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer /// /// @param duuBuffer Output buffer 2nd derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duuDesc vertex buffer descriptor for the duuBuffer /// /// @param duvBuffer Output buffer 2nd derivative wrt u and v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duvDesc vertex buffer descriptor for the duvBuffer /// /// @param dvvBuffer Output buffer 2nd derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvvDesc vertex buffer descriptor for the dvvBuffer @@ -361,7 +362,7 @@ class GLComputeEvaluator { DST_BUFFER *dvvBuffer, OpenSubdiv::Osd::BufferDescriptor const &dvvDesc, STENCIL_TABLE const *stencilTable, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { @@ -411,13 +412,13 @@ class GLComputeEvaluator { /// \brief Generic stencil function. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer @@ -432,13 +433,13 @@ class GLComputeEvaluator { OpenSubdiv::Osd::BufferDescriptor const &dstDesc, STENCIL_TABLE const *stencilTable) const { - return EvalStencils(srcBuffer->BindVBO(), + return EvalStencils(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, - 0, + nullptr, OpenSubdiv::Osd::BufferDescriptor(), - 0, + nullptr, OpenSubdiv::Osd::BufferDescriptor(), stencilTable->GetSizesBuffer(), stencilTable->GetOffsetsBuffer(), @@ -453,25 +454,25 @@ class GLComputeEvaluator { /// \brief Generic stencil function. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the dstBuffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer @@ -490,13 +491,13 @@ class GLComputeEvaluator { OpenSubdiv::Osd::BufferDescriptor const &dvDesc, STENCIL_TABLE const *stencilTable) const { - return EvalStencils(srcBuffer->BindVBO(), + return EvalStencils(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, - duBuffer->BindVBO(), + duBuffer->get_vertex_buffer(), duDesc, - dvBuffer->BindVBO(), + dvBuffer->get_vertex_buffer(), dvDesc, stencilTable->GetSizesBuffer(), stencilTable->GetOffsetsBuffer(), @@ -511,43 +512,43 @@ class GLComputeEvaluator { /// \brief Generic stencil function. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the dstBuffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer /// /// @param duuBuffer Output buffer 2nd derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duuDesc vertex buffer descriptor for the duuBuffer /// /// @param duvBuffer Output buffer 2nd derivative wrt u and v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duvDesc vertex buffer descriptor for the duvBuffer /// /// @param dvvBuffer Output buffer 2nd derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvvDesc vertex buffer descriptor for the dvvBuffer @@ -572,19 +573,19 @@ class GLComputeEvaluator { OpenSubdiv::Osd::BufferDescriptor const &dvvDesc, STENCIL_TABLE const *stencilTable) const { - return EvalStencils(srcBuffer->BindVBO(), + return EvalStencils(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, - duBuffer->BindVBO(), + duBuffer->get_vertex_buffer(), duDesc, - dvBuffer->BindVBO(), + dvBuffer->get_vertex_buffer(), dvDesc, - duuBuffer->BindVBO(), + duuBuffer->get_vertex_buffer(), duuDesc, - duvBuffer->BindVBO(), + duvBuffer->get_vertex_buffer(), duvDesc, - dvvBuffer->BindVBO(), + dvvBuffer->get_vertex_buffer(), dvvDesc, stencilTable->GetSizesBuffer(), stencilTable->GetOffsetsBuffer(), @@ -634,20 +635,20 @@ class GLComputeEvaluator { /// /// @param end end index of stencil table /// - bool EvalStencils(GLuint srcBuffer, + bool EvalStencils(gpu::VertBuf *srcBuffer, OpenSubdiv::Osd::BufferDescriptor const &srcDesc, - GLuint dstBuffer, + gpu::VertBuf *dstBuffer, OpenSubdiv::Osd::BufferDescriptor const &dstDesc, - GLuint duBuffer, + gpu::VertBuf *duBuffer, OpenSubdiv::Osd::BufferDescriptor const &duDesc, - GLuint dvBuffer, + gpu::VertBuf *dvBuffer, OpenSubdiv::Osd::BufferDescriptor const &dvDesc, - GLuint sizesBuffer, - GLuint offsetsBuffer, - GLuint indicesBuffer, - GLuint weightsBuffer, - GLuint duWeightsBuffer, - GLuint dvWeightsBuffer, + GPUStorageBuf *sizesBuffer, + GPUStorageBuf *offsetsBuffer, + GPUStorageBuf *indicesBuffer, + GPUStorageBuf *weightsBuffer, + GPUStorageBuf *duWeightsBuffer, + GPUStorageBuf *dvWeightsBuffer, int start, int end) const; @@ -704,29 +705,29 @@ class GLComputeEvaluator { /// /// @param end end index of stencil table /// - bool EvalStencils(GLuint srcBuffer, + bool EvalStencils(gpu::VertBuf *srcBuffer, OpenSubdiv::Osd::BufferDescriptor const &srcDesc, - GLuint dstBuffer, + gpu::VertBuf *dstBuffer, OpenSubdiv::Osd::BufferDescriptor const &dstDesc, - GLuint duBuffer, + gpu::VertBuf *duBuffer, OpenSubdiv::Osd::BufferDescriptor const &duDesc, - GLuint dvBuffer, + gpu::VertBuf *dvBuffer, OpenSubdiv::Osd::BufferDescriptor const &dvDesc, - GLuint duuBuffer, + gpu::VertBuf *duuBuffer, OpenSubdiv::Osd::BufferDescriptor const &duuDesc, - GLuint duvBuffer, + gpu::VertBuf *duvBuffer, OpenSubdiv::Osd::BufferDescriptor const &duvDesc, - GLuint dvvBuffer, + gpu::VertBuf *dvvBuffer, OpenSubdiv::Osd::BufferDescriptor const &dvvDesc, - GLuint sizesBuffer, - GLuint offsetsBuffer, - GLuint indicesBuffer, - GLuint weightsBuffer, - GLuint duWeightsBuffer, - GLuint dvWeightsBuffer, - GLuint duuWeightsBuffer, - GLuint duvWeightsBuffer, - GLuint dvvWeightsBuffer, + GPUStorageBuf *sizesBuffer, + GPUStorageBuf *offsetsBuffer, + GPUStorageBuf *indicesBuffer, + GPUStorageBuf *weightsBuffer, + GPUStorageBuf *duWeightsBuffer, + GPUStorageBuf *dvWeightsBuffer, + GPUStorageBuf *duuWeightsBuffer, + GPUStorageBuf *duvWeightsBuffer, + GPUStorageBuf *dvvWeightsBuffer, int start, int end) const; @@ -741,13 +742,13 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer @@ -779,7 +780,7 @@ class GLComputeEvaluator { int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { @@ -807,25 +808,25 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer @@ -861,7 +862,7 @@ class GLComputeEvaluator { int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { if (instance) { @@ -904,43 +905,43 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer /// /// @param duuBuffer Output buffer 2nd derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duuDesc vertex buffer descriptor for the duuBuffer /// /// @param duvBuffer Output buffer 2nd derivative wrt u and v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duvDesc vertex buffer descriptor for the duvBuffer /// /// @param dvvBuffer Output buffer 2nd derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvvDesc vertex buffer descriptor for the dvvBuffer @@ -982,7 +983,7 @@ class GLComputeEvaluator { int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { if (instance) { @@ -1037,13 +1038,13 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer @@ -1066,19 +1067,19 @@ class GLComputeEvaluator { OpenSubdiv::Osd::BufferDescriptor const &dstDesc, int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, - PATCH_TABLE *patchTable) const + PATCH_TABLE *patchTable) { - return EvalPatches(srcBuffer->BindVBO(), + return EvalPatches(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, - 0, + nullptr, OpenSubdiv::Osd::BufferDescriptor(), - 0, + nullptr, OpenSubdiv::Osd::BufferDescriptor(), numPatchCoords, - patchCoords->BindVBO(), + patchCoords->get_vertex_buffer(), patchTable->GetPatchArrays(), patchTable->GetPatchIndexBuffer(), patchTable->GetPatchParamBuffer()); @@ -1089,25 +1090,25 @@ class GLComputeEvaluator { /// called in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer @@ -1132,19 +1133,19 @@ class GLComputeEvaluator { OpenSubdiv::Osd::BufferDescriptor const &dvDesc, int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, - PATCH_TABLE *patchTable) const + PATCH_TABLE *patchTable) { - return EvalPatches(srcBuffer->BindVBO(), + return EvalPatches(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, - duBuffer->BindVBO(), + duBuffer->get_vertex_buffer(), duDesc, - dvBuffer->BindVBO(), + dvBuffer->get_vertex_buffer(), dvDesc, numPatchCoords, - patchCoords->BindVBO(), + patchCoords->get_vertex_buffer(), patchTable->GetPatchArrays(), patchTable->GetPatchIndexBuffer(), patchTable->GetPatchParamBuffer()); @@ -1155,43 +1156,43 @@ class GLComputeEvaluator { /// called in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer /// /// @param duuBuffer Output buffer 2nd derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duuDesc vertex buffer descriptor for the duuBuffer /// /// @param duvBuffer Output buffer 2nd derivative wrt u and v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duvDesc vertex buffer descriptor for the duvBuffer /// /// @param dvvBuffer Output buffer 2nd derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvvDesc vertex buffer descriptor for the dvvBuffer @@ -1222,76 +1223,76 @@ class GLComputeEvaluator { OpenSubdiv::Osd::BufferDescriptor const &dvvDesc, int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, - PATCH_TABLE *patchTable) const + PATCH_TABLE *patchTable) { - return EvalPatches(srcBuffer->BindVBO(), + return EvalPatches(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, - duBuffer->BindVBO(), + duBuffer->get_vertex_buffer(), duDesc, - dvBuffer->BindVBO(), + dvBuffer->get_vertex_buffer(), dvDesc, - duuBuffer->BindVBO(), + duuBuffer->get_vertex_buffer(), duuDesc, - duvBuffer->BindVBO(), + duvBuffer->get_vertex_buffer(), duvDesc, - dvvBuffer->BindVBO(), + dvvBuffer->get_vertex_buffer(), dvvDesc, numPatchCoords, - patchCoords->BindVBO(), + patchCoords->get_vertex_buffer(), patchTable->GetPatchArrays(), patchTable->GetPatchIndexBuffer(), patchTable->GetPatchParamBuffer()); } - bool EvalPatches(GLuint srcBuffer, + bool EvalPatches(gpu::VertBuf *srcBuffer, OpenSubdiv::Osd::BufferDescriptor const &srcDesc, - GLuint dstBuffer, + gpu::VertBuf *dstBuffer, OpenSubdiv::Osd::BufferDescriptor const &dstDesc, - GLuint duBuffer, + gpu::VertBuf *duBuffer, OpenSubdiv::Osd::BufferDescriptor const &duDesc, - GLuint dvBuffer, + gpu::VertBuf *dvBuffer, OpenSubdiv::Osd::BufferDescriptor const &dvDesc, int numPatchCoords, - GLuint patchCoordsBuffer, + gpu::VertBuf *patchCoordsBuffer, const OpenSubdiv::Osd::PatchArrayVector &patchArrays, - GLuint patchIndexBuffer, - GLuint patchParamsBuffer) const; + GPUStorageBuf *patchIndexBuffer, + GPUStorageBuf *patchParamsBuffer); - bool EvalPatches(GLuint srcBuffer, + bool EvalPatches(gpu::VertBuf *srcBuffer, OpenSubdiv::Osd::BufferDescriptor const &srcDesc, - GLuint dstBuffer, + gpu::VertBuf *dstBuffer, OpenSubdiv::Osd::BufferDescriptor const &dstDesc, - GLuint duBuffer, + gpu::VertBuf *duBuffer, OpenSubdiv::Osd::BufferDescriptor const &duDesc, - GLuint dvBuffer, + gpu::VertBuf *dvBuffer, OpenSubdiv::Osd::BufferDescriptor const &dvDesc, - GLuint duuBuffer, + gpu::VertBuf *duuBuffer, OpenSubdiv::Osd::BufferDescriptor const &duuDesc, - GLuint duvBuffer, + gpu::VertBuf *duvBuffer, OpenSubdiv::Osd::BufferDescriptor const &duvDesc, - GLuint dvvBuffer, + gpu::VertBuf *dvvBuffer, OpenSubdiv::Osd::BufferDescriptor const &dvvDesc, int numPatchCoords, - GLuint patchCoordsBuffer, + gpu::VertBuf *patchCoordsBuffer, const OpenSubdiv::Osd::PatchArrayVector &patchArrays, - GLuint patchIndexBuffer, - GLuint patchParamsBuffer) const; + GPUStorageBuf *patchIndexBuffer, + GPUStorageBuf *patchParamsBuffer); /// \brief Generic limit eval function. This function has a same /// signature as other device kernels have so that it can be called /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer @@ -1323,7 +1324,7 @@ class GLComputeEvaluator { int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { if (instance) { @@ -1351,13 +1352,13 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer @@ -1380,19 +1381,19 @@ class GLComputeEvaluator { OpenSubdiv::Osd::BufferDescriptor const &dstDesc, int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, - PATCH_TABLE *patchTable) const + PATCH_TABLE *patchTable) { - return EvalPatches(srcBuffer->BindVBO(), + return EvalPatches(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, - 0, + nullptr, OpenSubdiv::Osd::BufferDescriptor(), - 0, + nullptr, OpenSubdiv::Osd::BufferDescriptor(), numPatchCoords, - patchCoords->BindVBO(), + patchCoords->get_vertex_buffer(), patchTable->GetVaryingPatchArrays(), patchTable->GetVaryingPatchIndexBuffer(), patchTable->GetPatchParamBuffer()); @@ -1403,25 +1404,25 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer @@ -1457,7 +1458,7 @@ class GLComputeEvaluator { int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { if (instance) { @@ -1500,25 +1501,25 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer @@ -1545,19 +1546,19 @@ class GLComputeEvaluator { OpenSubdiv::Osd::BufferDescriptor const &dvDesc, int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, - PATCH_TABLE *patchTable) const + PATCH_TABLE *patchTable) { - return EvalPatches(srcBuffer->BindVBO(), + return EvalPatches(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, - duBuffer->BindVBO(), + duBuffer->get_vertex_buffer(), duDesc, - dvBuffer->BindVBO(), + dvBuffer->get_vertex_buffer(), dvDesc, numPatchCoords, - patchCoords->BindVBO(), + patchCoords->get_vertex_buffer(), patchTable->GetVaryingPatchArrays(), patchTable->GetVaryingPatchIndexBuffer(), patchTable->GetPatchParamBuffer()); @@ -1568,43 +1569,43 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer /// /// @param duuBuffer Output buffer 2nd derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duuDesc vertex buffer descriptor for the duuBuffer /// /// @param duvBuffer Output buffer 2nd derivative wrt u and v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duvDesc vertex buffer descriptor for the duvBuffer /// /// @param dvvBuffer Output buffer 2nd derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvvDesc vertex buffer descriptor for the dvvBuffer @@ -1646,7 +1647,7 @@ class GLComputeEvaluator { int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { if (instance) { @@ -1701,43 +1702,43 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer /// /// @param duuBuffer Output buffer 2nd derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duuDesc vertex buffer descriptor for the duuBuffer /// /// @param duvBuffer Output buffer 2nd derivative wrt u and v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duvDesc vertex buffer descriptor for the duvBuffer /// /// @param dvvBuffer Output buffer 2nd derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvvDesc vertex buffer descriptor for the dvvBuffer @@ -1770,25 +1771,25 @@ class GLComputeEvaluator { OpenSubdiv::Osd::BufferDescriptor const &dvvDesc, int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, - PATCH_TABLE *patchTable) const + PATCH_TABLE *patchTable) { - return EvalPatches(srcBuffer->BindVBO(), + return EvalPatches(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, - duBuffer->BindVBO(), + duBuffer->get_vertex_buffer(), duDesc, - dvBuffer->BindVBO(), + dvBuffer->get_vertex_buffer(), dvDesc, - duuBuffer->BindVBO(), + duuBuffer->get_vertex_buffer(), duuDesc, - duvBuffer->BindVBO(), + duvBuffer->get_vertex_buffer(), duvDesc, - dvvBuffer->BindVBO(), + dvvBuffer->get_vertex_buffer(), dvvDesc, numPatchCoords, - patchCoords->BindVBO(), + patchCoords->get_vertex_buffer(), patchTable->GetVaryingPatchArrays(), patchTable->GetVaryingPatchIndexBuffer(), patchTable->GetPatchParamBuffer()); @@ -1799,13 +1800,13 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer @@ -1840,7 +1841,7 @@ class GLComputeEvaluator { PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, int fvarChannel, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { if (instance) { @@ -1880,13 +1881,13 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer @@ -1912,19 +1913,19 @@ class GLComputeEvaluator { int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, - int fvarChannel = 0) const + int fvarChannel = 0) { - return EvalPatches(srcBuffer->BindVBO(), + return EvalPatches(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, 0, OpenSubdiv::Osd::BufferDescriptor(), 0, OpenSubdiv::Osd::BufferDescriptor(), numPatchCoords, - patchCoords->BindVBO(), + patchCoords->get_vertex_buffer(), patchTable->GetFVarPatchArrays(fvarChannel), patchTable->GetFVarPatchIndexBuffer(fvarChannel), patchTable->GetFVarPatchParamBuffer(fvarChannel)); @@ -1935,25 +1936,25 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer @@ -1992,7 +1993,7 @@ class GLComputeEvaluator { PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, int fvarChannel, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { if (instance) { @@ -2037,25 +2038,25 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer @@ -2085,19 +2086,19 @@ class GLComputeEvaluator { int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, - int fvarChannel = 0) const + int fvarChannel = 0) { - return EvalPatches(srcBuffer->BindVBO(), + return EvalPatches(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, - duBuffer->BindVBO(), + duBuffer->get_vertex_buffer(), duDesc, - dvBuffer->BindVBO(), + dvBuffer->get_vertex_buffer(), dvDesc, numPatchCoords, - patchCoords->BindVBO(), + patchCoords->get_vertex_buffer(), patchTable->GetFVarPatchArrays(fvarChannel), patchTable->GetFVarPatchIndexBuffer(fvarChannel), patchTable->GetFVarPatchParamBuffer(fvarChannel)); @@ -2108,43 +2109,43 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer /// /// @param duuBuffer Output buffer 2nd derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duuDesc vertex buffer descriptor for the duuBuffer /// /// @param duvBuffer Output buffer 2nd derivative wrt u and v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duvDesc vertex buffer descriptor for the duvBuffer /// /// @param dvvBuffer Output buffer 2nd derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvvDesc vertex buffer descriptor for the dvvBuffer @@ -2189,7 +2190,7 @@ class GLComputeEvaluator { PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, int fvarChannel, - GLComputeEvaluator const *instance, + GPUComputeEvaluator *instance, void *deviceContext = nullptr) { if (instance) { @@ -2246,43 +2247,43 @@ class GLComputeEvaluator { /// in the same way. /// /// @param srcBuffer Input primvar buffer. - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of source data /// /// @param srcDesc vertex buffer descriptor for the input buffer /// /// @param dstBuffer Output primvar buffer - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dstDesc vertex buffer descriptor for the output buffer /// /// @param duBuffer Output buffer derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duDesc vertex buffer descriptor for the duBuffer /// /// @param dvBuffer Output buffer derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvDesc vertex buffer descriptor for the dvBuffer /// /// @param duuBuffer Output buffer 2nd derivative wrt u - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duuDesc vertex buffer descriptor for the duuBuffer /// /// @param duvBuffer Output buffer 2nd derivative wrt u and v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param duvDesc vertex buffer descriptor for the duvBuffer /// /// @param dvvBuffer Output buffer 2nd derivative wrt v - /// must have BindVBO() method returning a GL + /// Must have `get_vertex_buffer()` returning a `gpu::VertBuf` /// buffer object of destination data /// /// @param dvvDesc vertex buffer descriptor for the dvvBuffer @@ -2318,25 +2319,25 @@ class GLComputeEvaluator { int numPatchCoords, PATCHCOORD_BUFFER *patchCoords, PATCH_TABLE *patchTable, - int fvarChannel = 0) const + int fvarChannel = 0) { - return EvalPatches(srcBuffer->BindVBO(), + return EvalPatches(srcBuffer->get_vertex_buffer(), srcDesc, - dstBuffer->BindVBO(), + dstBuffer->get_vertex_buffer(), dstDesc, - duBuffer->BindVBO(), + duBuffer->get_vertex_buffer(), duDesc, - dvBuffer->BindVBO(), + dvBuffer->get_vertex_buffer(), dvDesc, - duuBuffer->BindVBO(), + duuBuffer->get_vertex_buffer(), duuDesc, - duvBuffer->BindVBO(), + duvBuffer->get_vertex_buffer(), duvDesc, - dvvBuffer->BindVBO(), + dvvBuffer->get_vertex_buffer(), dvvDesc, numPatchCoords, - patchCoords->BindVBO(), + patchCoords->get_vertex_buffer(), patchTable->GetFVarPatchArrays(fvarChannel), patchTable->GetFVarPatchIndexBuffer(fvarChannel), patchTable->GetFVarPatchParamBuffer(fvarChannel)); @@ -2374,16 +2375,16 @@ class GLComputeEvaluator { OpenSubdiv::Osd::BufferDescriptor const &duvDesc, OpenSubdiv::Osd::BufferDescriptor const &dvvDesc, int workGroupSize); - GLuint program; - GLuint uniformStart; - GLuint uniformEnd; - GLuint uniformSrcOffset; - GLuint uniformDstOffset; - GLuint uniformDuDesc; - GLuint uniformDvDesc; - GLuint uniformDuuDesc; - GLuint uniformDuvDesc; - GLuint uniformDvvDesc; + GPUShader *shader = nullptr; + int uniformStart = 0; + int uniformEnd = 0; + int uniformSrcOffset = 0; + int uniformDstOffset = 0; + int uniformDuDesc = 0; + int uniformDvDesc = 0; + int uniformDuuDesc = 0; + int uniformDuvDesc = 0; + int uniformDvvDesc = 0; } _stencilKernel; struct _PatchKernel { @@ -2397,25 +2398,24 @@ class GLComputeEvaluator { OpenSubdiv::Osd::BufferDescriptor const &duvDesc, OpenSubdiv::Osd::BufferDescriptor const &dvvDesc, int workGroupSize); - GLuint program; - GLuint uniformSrcOffset; - GLuint uniformDstOffset; - GLuint uniformPatchArray; - GLuint uniformDuDesc; - GLuint uniformDvDesc; - GLuint uniformDuuDesc; - GLuint uniformDuvDesc; - GLuint uniformDvvDesc; + GPUShader *shader = nullptr; + int uniformSrcOffset = 0; + int uniformDstOffset = 0; + int uniformDuDesc = 0; + int uniformDvDesc = 0; + int uniformDuuDesc = 0; + int uniformDuvDesc = 0; + int uniformDvvDesc = 0; } _patchKernel; int _workGroupSize; - GLuint _patchArraysSSBO; + GPUStorageBuf *_patchArraysSSBO = nullptr; int GetDispatchSize(int count) const; - void DispatchCompute(int totalDispatchSize) const; + void DispatchCompute(GPUShader *shader, int totalDispatchSize) const; }; } // namespace blender::opensubdiv -#endif // OPENSUBDIV_GL_COMPUTE_EVALUATOR_H_ +#endif // OPENSUBDIV_GPU_COMPUTE_EVALUATOR_H_ diff --git a/intern/opensubdiv/internal/evaluator/gpu_patch_table.cc b/intern/opensubdiv/internal/evaluator/gpu_patch_table.cc new file mode 100644 index 00000000000..849e327bab2 --- /dev/null +++ b/intern/opensubdiv/internal/evaluator/gpu_patch_table.cc @@ -0,0 +1,130 @@ +/* SPDX-FileCopyrightText: 2025 Blender Foundation + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "gpu_patch_table.hh" + +#include "opensubdiv/far/patchTable.h" +#include "opensubdiv/osd/cpuPatchTable.h" + +using namespace OpenSubdiv::Osd; + +namespace blender::opensubdiv { + +GPUPatchTable *GPUPatchTable::Create(PatchTable const *far_patch_table, void * /*deviceContext*/) +{ + GPUPatchTable *instance = new GPUPatchTable(); + if (instance->allocate(far_patch_table)) + return instance; + delete instance; + return nullptr; +} + +static void discard_buffer(GPUStorageBuf **buffer) +{ + if (*buffer != nullptr) { + GPU_storagebuf_free(*buffer); + *buffer = nullptr; + } +} + +static void discard_list(std::vector &buffers) +{ + while (!buffers.empty()) { + GPUStorageBuf *buffer = buffers.back(); + buffers.pop_back(); + GPU_storagebuf_free(buffer); + } +} + +GPUPatchTable::~GPUPatchTable() +{ + discard_buffer(&_patchIndexBuffer); + discard_buffer(&_patchParamBuffer); + discard_buffer(&_varyingIndexBuffer); + discard_list(_fvarIndexBuffers); + discard_list(_fvarParamBuffers); +} + +/** + * Storage buffers sizes needs to be divisable by 16 (float4). + */ +static size_t storage_buffer_size(size_t size) +{ + return (size + 15) & (~0b1111); +} + +/** + * Function to create a storage buffer and upload it with data. + * + * - Ensures that allocated size is aligned to 16 byte + * - WARNING: Can read from not allocated data after `data`. + */ +// TODO: this means that if buffer size is adjusted we need to copy into a temp buffer otherwise we +// could read out of bounds. The performance impact of this is measurable so I would suggest to +// support GPU_storagebuf_update() with a max len to update. +static GPUStorageBuf *storage_buffer_create(size_t size, const void *data, const char *name) +{ + size_t storage_size = storage_buffer_size(size); + return GPU_storagebuf_create_ex(storage_size, data, GPU_USAGE_STATIC, name); +} + +bool GPUPatchTable::allocate(PatchTable const *far_patch_table) +{ + CpuPatchTable patch_table(far_patch_table); + + /* Patch array */ + size_t num_patch_arrays = patch_table.GetNumPatchArrays(); + _patchArrays.assign(patch_table.GetPatchArrayBuffer(), + patch_table.GetPatchArrayBuffer() + num_patch_arrays); + + /* Patch index buffer */ + const size_t index_size = patch_table.GetPatchIndexSize(); + _patchIndexBuffer = storage_buffer_create( + index_size * sizeof(int32_t), + static_cast(patch_table.GetPatchIndexBuffer()), + "osd_patch_index"); + + /* Patch param buffer */ + const size_t patch_param_size = patch_table.GetPatchParamSize(); + _patchParamBuffer = storage_buffer_create( + patch_param_size * sizeof(PatchParam), patch_table.GetPatchParamBuffer(), "osd_patch_param"); + + /* Varying patch array */ + _varyingPatchArrays.assign(patch_table.GetVaryingPatchArrayBuffer(), + patch_table.GetVaryingPatchArrayBuffer() + num_patch_arrays); + + /* Varying index buffer */ + _varyingIndexBuffer = storage_buffer_create(patch_table.GetVaryingPatchIndexSize() * + sizeof(uint32_t), + patch_table.GetVaryingPatchIndexBuffer(), + "osd_varying_index"); + + /* Face varying */ + const int num_face_varying_channels = patch_table.GetNumFVarChannels(); + _fvarPatchArrays.resize(num_face_varying_channels); + _fvarIndexBuffers.resize(num_face_varying_channels); + _fvarParamBuffers.resize(num_face_varying_channels); + for (int index = 0; index < num_face_varying_channels; index++) { + /* Face varying patch arrays */ + _fvarPatchArrays[index].assign(patch_table.GetFVarPatchArrayBuffer(), + patch_table.GetFVarPatchArrayBuffer() + num_patch_arrays); + + /* Face varying patch index buffer */ + _fvarIndexBuffers[index] = storage_buffer_create(patch_table.GetFVarPatchIndexSize(index) * + sizeof(int32_t), + patch_table.GetFVarPatchIndexBuffer(index), + "osd_face_varying_index"); + + /* Face varying patch param buffer */ + _fvarParamBuffers[index] = storage_buffer_create(patch_table.GetFVarPatchParamSize(index) * + sizeof(PatchParam), + patch_table.GetFVarPatchParamBuffer(index), + "osd_face_varying_params"); + } + + return true; +} + +} // namespace blender::opensubdiv diff --git a/intern/opensubdiv/internal/evaluator/gpu_patch_table.hh b/intern/opensubdiv/internal/evaluator/gpu_patch_table.hh new file mode 100644 index 00000000000..536fd8dd2e2 --- /dev/null +++ b/intern/opensubdiv/internal/evaluator/gpu_patch_table.hh @@ -0,0 +1,96 @@ +#pragma once + +#include "GPU_storage_buffer.hh" + +#include + +#include +#include + +using OpenSubdiv::Far::PatchTable; +using OpenSubdiv::Osd::NonCopyable; +using OpenSubdiv::Osd::PatchArrayVector; + +namespace blender::opensubdiv { + +// TODO: use Blenlib NonCopyable. +class GPUPatchTable : private NonCopyable { + public: + ~GPUPatchTable(); + + static GPUPatchTable *Create(PatchTable const *farPatchTable, void *deviceContext = NULL); + + /// Returns the patch arrays for vertex index buffer data + PatchArrayVector const &GetPatchArrays() const + { + return _patchArrays; + } + + /// Returns the GL index buffer containing the patch control vertices + GPUStorageBuf *GetPatchIndexBuffer() const + { + return _patchIndexBuffer; + } + + /// Returns the GL index buffer containing the patch parameter + GPUStorageBuf *GetPatchParamBuffer() const + { + return _patchParamBuffer; + } + + /// Returns the patch arrays for varying index buffer data + PatchArrayVector const &GetVaryingPatchArrays() const + { + return _varyingPatchArrays; + } + + /// Returns the GL index buffer containing the varying control vertices + GPUStorageBuf *GetVaryingPatchIndexBuffer() const + { + return _varyingIndexBuffer; + } + + /// Returns the number of face-varying channel buffers + int GetNumFVarChannels() const + { + return (int)_fvarPatchArrays.size(); + } + + /// Returns the patch arrays for face-varying index buffer data + PatchArrayVector const &GetFVarPatchArrays(int fvarChannel = 0) const + { + return _fvarPatchArrays[fvarChannel]; + } + + /// Returns the GL index buffer containing face-varying control vertices + GPUStorageBuf *GetFVarPatchIndexBuffer(int fvarChannel = 0) const + { + return _fvarIndexBuffers[fvarChannel]; + } + + /// Returns the GL index buffer containing face-varying patch params + GPUStorageBuf *GetFVarPatchParamBuffer(int fvarChannel = 0) const + { + return _fvarParamBuffers[fvarChannel]; + } + + protected: + GPUPatchTable() {} + + // allocate buffers from patchTable + bool allocate(PatchTable const *farPatchTable); + + PatchArrayVector _patchArrays; + + GPUStorageBuf *_patchIndexBuffer = nullptr; + GPUStorageBuf *_patchParamBuffer = nullptr; + + PatchArrayVector _varyingPatchArrays; + GPUStorageBuf *_varyingIndexBuffer = nullptr; + + std::vector _fvarPatchArrays; + std::vector _fvarIndexBuffers; + std::vector _fvarParamBuffers; +}; + +} // namespace blender::opensubdiv diff --git a/intern/opensubdiv/internal/evaluator/gpu_vertex_buffer_wrapper.hh b/intern/opensubdiv/internal/evaluator/gpu_vertex_buffer_wrapper.hh new file mode 100644 index 00000000000..07e75e56d46 --- /dev/null +++ b/intern/opensubdiv/internal/evaluator/gpu_vertex_buffer_wrapper.hh @@ -0,0 +1,102 @@ +/* SPDX-FileCopyrightText: 2025 Blender Foundation + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "GPU_context.hh" +#include "GPU_vertex_buffer.hh" + +namespace blender::opensubdiv { + +/** + * GLVertexBuffer compatible API wrapped around a blender::gpu::VertBuf + * + * The blender::gpu::VertBuf is owned by the wrapper. + * Vertex buffer is used as its API is able to wrap around SSBOs as well. + */ +class GPUVertexBuffer { + gpu::VertBuf &gpu_vertex_buffer_; + + /** Number of float elements/components does a single vertex have. */ + int element_count_; + + /** Should we upload data directly to the GPU, or should we use a staging buffer. */ + bool use_update_sub_; + + public: + GPUVertexBuffer(gpu::VertBuf &gpu_vertex_buffer, int element_count, bool use_update_sub) + : gpu_vertex_buffer_(gpu_vertex_buffer), + element_count_(element_count), + use_update_sub_(use_update_sub) + { + } + + /** + * Create a new gpu::VertBuf wrapped in a GPUVertexBuffer. + * + * @param element_count: Number of elements per vertex + * @param vertex_len: Number of vertices + * @param device_context: Unused. + */ + + static GPUVertexBuffer *Create(int element_count, int vertex_len, void *device_context = nullptr) + { + (void)device_context; + GPUVertFormat format; + GPU_vertformat_clear(&format); + GPU_vertformat_attr_add(&format, "elements", GPU_COMP_F32, element_count, GPU_FETCH_FLOAT); + const bool use_update_sub = GPU_backend_get_type() != GPU_BACKEND_VULKAN; + gpu::VertBuf *vertex_buffer = nullptr; + if (use_update_sub) { + vertex_buffer = GPU_vertbuf_calloc(); + GPU_vertbuf_init_build_on_device(*vertex_buffer, format, vertex_len); + } + else { + vertex_buffer = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DYNAMIC); + GPU_vertbuf_data_alloc(*vertex_buffer, vertex_len); + } + return new GPUVertexBuffer(*vertex_buffer, element_count, use_update_sub); + } + + /// Destructor. + ~GPUVertexBuffer() + { + GPU_vertbuf_discard(&gpu_vertex_buffer_); + } + + /// This method is meant to be used in client code in order to provide coarse + /// vertices data to Osd. + void UpdateData(const float *src, + int start_vertex, + int num_vertices, + void *device_context = NULL) + { + (void)device_context; + if (use_update_sub_) { + GPU_vertbuf_use(&gpu_vertex_buffer_); + size_t offset = start_vertex * element_count_ * sizeof(float); + size_t data_len = num_vertices * element_count_ * sizeof(float); + GPU_vertbuf_update_sub(&gpu_vertex_buffer_, offset, data_len, src); + } + else { + MutableSpan buffer_nodes = gpu_vertex_buffer_.data(); + buffer_nodes = buffer_nodes.drop_front(start_vertex * element_count_); + memcpy(buffer_nodes.data(), src, sizeof(float) * element_count_ * num_vertices); + GPU_vertbuf_tag_dirty(&gpu_vertex_buffer_); + } + } + + /// Returns how many vertices allocated in this vertex buffer. + int GetNumVertices() const + { + return GPU_vertbuf_get_vertex_len(&gpu_vertex_buffer_); + } + + gpu::VertBuf *get_vertex_buffer() + { + return &gpu_vertex_buffer_; + } +}; + +} // namespace blender::opensubdiv diff --git a/intern/opensubdiv/internal/evaluator/shaders/glsl_compute_kernel.glsl b/intern/opensubdiv/internal/evaluator/shaders/osd_kernel_comp.glsl similarity index 71% rename from intern/opensubdiv/internal/evaluator/shaders/glsl_compute_kernel.glsl rename to intern/opensubdiv/internal/evaluator/shaders/osd_kernel_comp.glsl index 952c65bc919..7726ebd593b 100644 --- a/intern/opensubdiv/internal/evaluator/shaders/glsl_compute_kernel.glsl +++ b/intern/opensubdiv/internal/evaluator/shaders/osd_kernel_comp.glsl @@ -24,133 +24,15 @@ //------------------------------------------------------------------------------ -layout(local_size_x = WORK_GROUP_SIZE, local_size_y = 1, local_size_z = 1) in; -layout(std430) buffer; - -// source and destination buffers - -uniform int srcOffset = 0; -uniform int dstOffset = 0; -layout(binding = 0) buffer src_buffer -{ - float srcVertexBuffer[]; -}; -layout(binding = 1) buffer dst_buffer -{ - float dstVertexBuffer[]; -}; - -// derivative buffers (if needed) - -#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES) -uniform ivec3 duDesc; -uniform ivec3 dvDesc; -layout(binding = 2) buffer du_buffer -{ - float duBuffer[]; -}; -layout(binding = 3) buffer dv_buffer -{ - float dvBuffer[]; -}; -#endif - -#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES) -uniform ivec3 duuDesc; -uniform ivec3 duvDesc; -uniform ivec3 dvvDesc; -layout(binding = 10) buffer duu_buffer -{ - float duuBuffer[]; -}; -layout(binding = 11) buffer duv_buffer -{ - float duvBuffer[]; -}; -layout(binding = 12) buffer dvv_buffer -{ - float dvvBuffer[]; -}; -#endif - -// stencil buffers - #if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS) - -uniform int batchStart = 0; -uniform int batchEnd = 0; -layout(binding = 4) buffer stencilSizes -{ - int _sizes[]; -}; -layout(binding = 5) buffer stencilOffsets -{ - int _offsets[]; -}; -layout(binding = 6) buffer stencilIndices -{ - int _indices[]; -}; -layout(binding = 7) buffer stencilWeights -{ - float _weights[]; -}; - -# if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES) -layout(binding = 8) buffer stencilDuWeights -{ - float _duWeights[]; -}; -layout(binding = 9) buffer stencilDvWeights -{ - float _dvWeights[]; -}; -# endif - -# if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES) -layout(binding = 13) buffer stencilDuuWeights -{ - float _duuWeights[]; -}; -layout(binding = 14) buffer stencilDuvWeights -{ - float _duvWeights[]; -}; -layout(binding = 15) buffer stencilDvvWeights -{ - float _dvvWeights[]; -}; -# endif - uint getGlobalInvocationIndex() { uint invocations_per_row = gl_WorkGroupSize.x * gl_NumWorkGroups.x; return gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * invocations_per_row; } - #endif -// patch buffers - #if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES) - -layout(binding = 4) buffer patchArray_buffer -{ - OsdPatchArray patchArrayBuffer[]; -}; -layout(binding = 5) buffer patchCoord_buffer -{ - OsdPatchCoord patchCoords[]; -}; -layout(binding = 6) buffer patchIndex_buffer -{ - int patchIndexBuffer[]; -}; -layout(binding = 7) buffer patchParam_buffer -{ - OsdPatchParam patchParamBuffer[]; -}; - OsdPatchCoord GetPatchCoord(int coordIndex) { return patchCoords[coordIndex]; @@ -165,7 +47,6 @@ OsdPatchParam GetPatchParam(int patchIndex) { return patchParamBuffer[patchIndex]; } - #endif //------------------------------------------------------------------------------ @@ -264,11 +145,11 @@ void main() Vertex dst; clear(dst); - int offset = _offsets[current], size = _sizes[current]; + int offset = offsets_buf[current], size = sizes_buf[current]; for (int stencil = 0; stencil < size; ++stencil) { int vindex = offset + stencil; - addWithWeight(dst, readVertex(_indices[vindex]), _weights[vindex]); + addWithWeight(dst, readVertex(indices_buf[vindex]), weights_buf[vindex]); } writeVertex(current, dst); @@ -279,9 +160,9 @@ void main() clear(dv); for (int i = 0; i < size; ++i) { // expects the compiler optimizes readVertex out here. - Vertex src = readVertex(_indices[offset + i]); - addWithWeight(du, src, _duWeights[offset + i]); - addWithWeight(dv, src, _dvWeights[offset + i]); + Vertex src = readVertex(indices_buf[offset + i]); + addWithWeight(du, src, du_weights_buf[offset + i]); + addWithWeight(dv, src, dv_weights_buf[offset + i]); } if (duDesc.y > 0) { // length @@ -298,10 +179,10 @@ void main() clear(dvv); for (int i = 0; i < size; ++i) { // expects the compiler optimizes readVertex out here. - Vertex src = readVertex(_indices[offset + i]); - addWithWeight(duu, src, _duuWeights[offset + i]); - addWithWeight(duv, src, _duvWeights[offset + i]); - addWithWeight(dvv, src, _dvvWeights[offset + i]); + Vertex src = readVertex(indices_buf[offset + i]); + addWithWeight(duu, src, duu_weights_buf[offset + i]); + addWithWeight(duv, src, duv_weights_buf[offset + i]); + addWithWeight(dvv, src, dvv_weights_buf[offset + i]); } if (duuDesc.y > 0) { // length diff --git a/intern/opensubdiv/opensubdiv_evaluator.hh b/intern/opensubdiv/opensubdiv_evaluator.hh index 0386a320ba1..6067acbe65d 100644 --- a/intern/opensubdiv/opensubdiv_evaluator.hh +++ b/intern/opensubdiv/opensubdiv_evaluator.hh @@ -16,6 +16,8 @@ #include "opensubdiv_capi_type.hh" +#include "GPU_storage_buffer.hh" + struct OpenSubdiv_EvaluatorCache; struct OpenSubdiv_EvaluatorSettings; struct OpenSubdiv_PatchCoord; @@ -137,39 +139,36 @@ class EvalOutputAPI { int *patches_are_triangular); // Copy the patch arrays buffer used by OpenSubDiv for the source data to the given buffer. - void fillPatchArraysBuffer(blender::gpu::VertBuf *patch_arrays_buffer); + GPUStorageBuf *create_patch_arrays_buf(); // Wrap the patch index buffer used by OpenSubDiv for the source data with the given buffer. - void wrapPatchIndexBuffer(blender::gpu::VertBuf *patch_index_buffer); + GPUStorageBuf *get_patch_index_buf(); // Wrap the patch param buffer used by OpenSubDiv for the source data with the given buffer. - void wrapPatchParamBuffer(blender::gpu::VertBuf *patch_param_buffer); + GPUStorageBuf *get_patch_param_buf(); // Wrap the buffer used by OpenSubDiv for the source data with the given buffer. - void wrapSrcBuffer(blender::gpu::VertBuf *src_buffer); + gpu::VertBuf *get_source_buf(); // Wrap the buffer used by OpenSubDiv for the extra source data with the given buffer. - void wrapSrcVertexDataBuffer(blender::gpu::VertBuf *src_buffer); + gpu::VertBuf *get_source_data_buf(); // Copy the patch arrays buffer used by OpenSubDiv for the face varying channel with the given // buffer. - void fillFVarPatchArraysBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_arrays_buffer); + GPUStorageBuf *create_face_varying_patch_array_buf(const int face_varying_channel); // Wrap the patch index buffer used by OpenSubDiv for the face varying channel with the given // buffer. - void wrapFVarPatchIndexBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_index_buffer); + GPUStorageBuf *get_face_varying_patch_index_buf(const int face_varying_channel); // Wrap the patch param buffer used by OpenSubDiv for the face varying channel with the given // buffer. - void wrapFVarPatchParamBuffer(const int face_varying_channel, - blender::gpu::VertBuf *patch_param_buffer); + GPUStorageBuf *get_face_varying_patch_param_buf(const int face_varying_channel); // Wrap thebuffer used by OpenSubDiv for the face varying channel with the given buffer. - void wrapFVarSrcBuffer(const int face_varying_channel, blender::gpu::VertBuf *src_buffer); + gpu::VertBuf *get_face_varying_source_buf(const int face_varying_channel); /** Get the source buffer offset for the given channel. */ - int getFVarSrcBufferOffset(const int face_varying_channel) const; + int get_face_varying_source_offset(const int face_varying_channel) const; // Return true if source vertex data has been set. bool hasVertexData() const; diff --git a/intern/opensubdiv/opensubdiv_evaluator_capi.hh b/intern/opensubdiv/opensubdiv_evaluator_capi.hh index 474b0831c94..955d2a90c07 100644 --- a/intern/opensubdiv/opensubdiv_evaluator_capi.hh +++ b/intern/opensubdiv/opensubdiv_evaluator_capi.hh @@ -8,8 +8,6 @@ #include "opensubdiv_capi_type.hh" -#include "GPU_vertex_buffer.hh" - struct OpenSubdiv_EvaluatorCacheImpl; struct OpenSubdiv_PatchCoord; namespace blender::opensubdiv { diff --git a/source/blender/blenkernel/intern/subdiv_modifier.cc b/source/blender/blenkernel/intern/subdiv_modifier.cc index c74a6996af6..b4fbd0a994c 100644 --- a/source/blender/blenkernel/intern/subdiv_modifier.cc +++ b/source/blender/blenkernel/intern/subdiv_modifier.cc @@ -101,14 +101,13 @@ bool BKE_subsurf_modifier_has_split_normals(const SubsurfModifierData *smd, cons static bool is_subdivision_evaluation_possible_on_gpu() { - /* Only OpenGL is supported for OpenSubdiv evaluation for now. */ if (GPU_backend_get_type() != GPU_BACKEND_OPENGL) { return false; } /* Now that we know it is OpenGL, check for Qualcomm GPUs, * which GPU subdiv is broken on some of (#124515) */ - if (GPU_type_matches(GPU_DEVICE_QUALCOMM, GPU_OS_WIN, GPU_DRIVER_ANY)) { + if (GPU_type_matches_ex(GPU_DEVICE_QUALCOMM, GPU_OS_WIN, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { return false; } diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index f3b9cae12a0..7ae464dc7a1 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -58,33 +58,6 @@ namespace blender::draw { * \{ */ #ifdef WITH_OPENSUBDIV - -static const GPUVertFormat &get_uvs_format() -{ - static const GPUVertFormat format = [&]() { - GPUVertFormat format{}; - GPU_vertformat_attr_add(&format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - return format; - }(); - return format; -} - -/* Vertex format for `OpenSubdiv::Osd::PatchArray`. */ -static const GPUVertFormat &get_patch_array_format() -{ - static const GPUVertFormat format = [&]() { - GPUVertFormat format{}; - GPU_vertformat_attr_add(&format, "regDesc", GPU_COMP_I32, 1, GPU_FETCH_INT); - GPU_vertformat_attr_add(&format, "desc", GPU_COMP_I32, 1, GPU_FETCH_INT); - GPU_vertformat_attr_add(&format, "numPatches", GPU_COMP_I32, 1, GPU_FETCH_INT); - GPU_vertformat_attr_add(&format, "indexBase", GPU_COMP_I32, 1, GPU_FETCH_INT); - GPU_vertformat_attr_add(&format, "stride", GPU_COMP_I32, 1, GPU_FETCH_INT); - GPU_vertformat_attr_add(&format, "primitiveIdBase", GPU_COMP_I32, 1, GPU_FETCH_INT); - return format; - }(); - return format; -} - /* Vertex format used for the `PatchTable::PatchHandle`. */ static const GPUVertFormat &get_patch_handle_format() { @@ -109,42 +82,6 @@ static const GPUVertFormat &get_quadtree_format() return format; } -/* Vertex format for `OpenSubdiv::Osd::PatchParam`, not really used, it is only for making sure - * that the #gpu::VertBuf used to wrap the OpenSubdiv patch param buffer is valid. */ -static const GPUVertFormat &get_patch_param_format() -{ - static const GPUVertFormat format = [&]() { - GPUVertFormat format{}; - GPU_vertformat_attr_add(&format, "data", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - return format; - }(); - return format; -} - -/* Vertex format for the patches' vertices index buffer. */ -static const GPUVertFormat &get_patch_index_format() -{ - static const GPUVertFormat format = [&]() { - GPUVertFormat format{}; - GPU_vertformat_attr_add(&format, "data", GPU_COMP_I32, 1, GPU_FETCH_INT); - return format; - }(); - return format; -} - -/* Vertex format for the OpenSubdiv vertex buffer. */ -static const GPUVertFormat &get_subdiv_vertex_format() -{ - static const GPUVertFormat format = [&]() { - GPUVertFormat format{}; - /* We use 4 components for the vectors to account for padding in the compute shaders, where - * vec3 is promoted to vec4. */ - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - return format; - }(); - return format; -} - struct CompressedPatchCoord { int ptex_face_index; /* UV coordinate encoded as u << 16 | v, where u and v are quantized on 16-bits. */ @@ -1054,28 +991,15 @@ void draw_subdiv_extract_pos_nor(const DRWSubdivCache &cache, bke::subdiv::Subdiv *subdiv = cache.subdiv; OpenSubdiv_Evaluator *evaluator = subdiv->evaluator; - gpu::VertBuf *src_buffer = GPU_vertbuf_create_with_format_ex(get_subdiv_vertex_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->wrapSrcBuffer(src_buffer); - + gpu::VertBuf *src_buffer = evaluator->eval_output->get_source_buf(); gpu::VertBuf *src_extra_buffer = nullptr; if (orco) { - src_extra_buffer = GPU_vertbuf_create_with_format_ex(get_subdiv_vertex_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->wrapSrcVertexDataBuffer(src_extra_buffer); + src_extra_buffer = evaluator->eval_output->get_source_data_buf(); } - gpu::VertBuf *patch_arrays_buffer = GPU_vertbuf_create_with_format_ex(get_patch_array_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->fillPatchArraysBuffer(patch_arrays_buffer); - - gpu::VertBuf *patch_index_buffer = GPU_vertbuf_create_with_format_ex(get_patch_index_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->wrapPatchIndexBuffer(patch_index_buffer); - - gpu::VertBuf *patch_param_buffer = GPU_vertbuf_create_with_format_ex(get_patch_param_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->wrapPatchParamBuffer(patch_param_buffer); + GPUStorageBuf *patch_arrays_buffer = evaluator->eval_output->create_patch_arrays_buf(); + GPUStorageBuf *patch_index_buffer = evaluator->eval_output->get_patch_index_buf(); + GPUStorageBuf *patch_param_buffer = evaluator->eval_output->get_patch_param_buf(); GPUShader *shader = DRW_shader_subdiv_get(orco ? SubdivShaderType::PATCH_EVALUATION_ORCO : SubdivShaderType::PATCH_EVALUATION); @@ -1089,9 +1013,9 @@ void draw_subdiv_extract_pos_nor(const DRWSubdivCache &cache, GPU_vertbuf_bind_as_ssbo(cache.patch_coords, PATCH_EVALUATION_PATCH_COORDS_BUF_SLOT); GPU_vertbuf_bind_as_ssbo(cache.verts_orig_index, PATCH_EVALUATION_INPUT_VERTEX_ORIG_INDEX_BUF_SLOT); - GPU_vertbuf_bind_as_ssbo(patch_arrays_buffer, PATCH_EVALUATION_PATCH_ARRAY_BUFFER_BUF_SLOT); - GPU_vertbuf_bind_as_ssbo(patch_index_buffer, PATCH_EVALUATION_PATCH_INDEX_BUFFER_BUF_SLOT); - GPU_vertbuf_bind_as_ssbo(patch_param_buffer, PATCH_EVALUATION_PATCH_PARAM_BUFFER_BUF_SLOT); + GPU_storagebuf_bind(patch_arrays_buffer, PATCH_EVALUATION_PATCH_ARRAY_BUFFER_BUF_SLOT); + GPU_storagebuf_bind(patch_index_buffer, PATCH_EVALUATION_PATCH_INDEX_BUFFER_BUF_SLOT); + GPU_storagebuf_bind(patch_param_buffer, PATCH_EVALUATION_PATCH_PARAM_BUFFER_BUF_SLOT); if (flags_buffer) { GPU_vertbuf_bind_as_ssbo(flags_buffer, PATCH_EVALUATION_FLAGS_BUFFER_BUF_SLOT); } @@ -1112,11 +1036,7 @@ void draw_subdiv_extract_pos_nor(const DRWSubdivCache &cache, /* Cleanup. */ GPU_shader_unbind(); - GPU_vertbuf_discard(patch_index_buffer); - GPU_vertbuf_discard(patch_param_buffer); - GPU_vertbuf_discard(patch_arrays_buffer); - GPU_vertbuf_discard(src_buffer); - GPU_VERTBUF_DISCARD_SAFE(src_extra_buffer); + GPU_storagebuf_free(patch_arrays_buffer); #else UNUSED_VARS(cache, flags_buffer, pos_nor, orco); #endif @@ -1136,22 +1056,17 @@ void draw_subdiv_extract_uvs(const DRWSubdivCache &cache, bke::subdiv::Subdiv *subdiv = cache.subdiv; OpenSubdiv_Evaluator *evaluator = subdiv->evaluator; - gpu::VertBuf *src_buffer = GPU_vertbuf_create_with_format_ex(get_uvs_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->wrapFVarSrcBuffer(face_varying_channel, src_buffer); - int src_buffer_offset = evaluator->eval_output->getFVarSrcBufferOffset(face_varying_channel); + gpu::VertBuf *src_buffer = evaluator->eval_output->get_face_varying_source_buf( + face_varying_channel); + int src_buffer_offset = evaluator->eval_output->get_face_varying_source_offset( + face_varying_channel); - gpu::VertBuf *patch_arrays_buffer = GPU_vertbuf_create_with_format_ex(get_patch_array_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->fillFVarPatchArraysBuffer(face_varying_channel, patch_arrays_buffer); - - gpu::VertBuf *patch_index_buffer = GPU_vertbuf_create_with_format_ex(get_patch_index_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->wrapFVarPatchIndexBuffer(face_varying_channel, patch_index_buffer); - - gpu::VertBuf *patch_param_buffer = GPU_vertbuf_create_with_format_ex(get_patch_param_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->wrapFVarPatchParamBuffer(face_varying_channel, patch_param_buffer); + GPUStorageBuf *patch_arrays_buffer = evaluator->eval_output->create_face_varying_patch_array_buf( + face_varying_channel); + GPUStorageBuf *patch_index_buffer = evaluator->eval_output->get_face_varying_patch_index_buf( + face_varying_channel); + GPUStorageBuf *patch_param_buffer = evaluator->eval_output->get_face_varying_patch_param_buf( + face_varying_channel); GPUShader *shader = DRW_shader_subdiv_get(SubdivShaderType::PATCH_EVALUATION_FVAR); GPU_shader_bind(shader); @@ -1164,9 +1079,9 @@ void draw_subdiv_extract_uvs(const DRWSubdivCache &cache, GPU_vertbuf_bind_as_ssbo(cache.corner_patch_coords, PATCH_EVALUATION_PATCH_COORDS_BUF_SLOT); GPU_vertbuf_bind_as_ssbo(cache.verts_orig_index, PATCH_EVALUATION_INPUT_VERTEX_ORIG_INDEX_BUF_SLOT); - GPU_vertbuf_bind_as_ssbo(patch_arrays_buffer, PATCH_EVALUATION_PATCH_ARRAY_BUFFER_BUF_SLOT); - GPU_vertbuf_bind_as_ssbo(patch_index_buffer, PATCH_EVALUATION_PATCH_INDEX_BUFFER_BUF_SLOT); - GPU_vertbuf_bind_as_ssbo(patch_param_buffer, PATCH_EVALUATION_PATCH_PARAM_BUFFER_BUF_SLOT); + GPU_storagebuf_bind(patch_arrays_buffer, PATCH_EVALUATION_PATCH_ARRAY_BUFFER_BUF_SLOT); + GPU_storagebuf_bind(patch_index_buffer, PATCH_EVALUATION_PATCH_INDEX_BUFFER_BUF_SLOT); + GPU_storagebuf_bind(patch_param_buffer, PATCH_EVALUATION_PATCH_PARAM_BUFFER_BUF_SLOT); GPU_vertbuf_bind_as_ssbo(uvs, PATCH_EVALUATION_OUTPUT_FVAR_BUF_SLOT); /* The buffer offset has the stride baked in (which is 2 as we have UVs) so remove the stride by @@ -1182,10 +1097,7 @@ void draw_subdiv_extract_uvs(const DRWSubdivCache &cache, /* Cleanup. */ GPU_shader_unbind(); - GPU_vertbuf_discard(patch_index_buffer); - GPU_vertbuf_discard(patch_param_buffer); - GPU_vertbuf_discard(patch_arrays_buffer); - GPU_vertbuf_discard(src_buffer); + GPU_storagebuf_free(patch_arrays_buffer); #else UNUSED_VARS(cache, uvs, face_varying_channel, dst_offset); #endif @@ -1375,21 +1287,10 @@ void draw_subdiv_build_fdots_buffers(const DRWSubdivCache &cache, bke::subdiv::Subdiv *subdiv = cache.subdiv; OpenSubdiv_Evaluator *evaluator = subdiv->evaluator; - gpu::VertBuf *src_buffer = GPU_vertbuf_create_with_format_ex(get_subdiv_vertex_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->wrapSrcBuffer(src_buffer); - - gpu::VertBuf *patch_arrays_buffer = GPU_vertbuf_create_with_format_ex(get_patch_array_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->fillPatchArraysBuffer(patch_arrays_buffer); - - gpu::VertBuf *patch_index_buffer = GPU_vertbuf_create_with_format_ex(get_patch_index_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->wrapPatchIndexBuffer(patch_index_buffer); - - gpu::VertBuf *patch_param_buffer = GPU_vertbuf_create_with_format_ex(get_patch_param_format(), - GPU_USAGE_DEVICE_ONLY); - evaluator->eval_output->wrapPatchParamBuffer(patch_param_buffer); + gpu::VertBuf *src_buffer = evaluator->eval_output->get_source_buf(); + GPUStorageBuf *patch_arrays_buffer = evaluator->eval_output->create_patch_arrays_buf(); + GPUStorageBuf *patch_index_buffer = evaluator->eval_output->get_patch_index_buf(); + GPUStorageBuf *patch_param_buffer = evaluator->eval_output->get_patch_param_buf(); GPUShader *shader = DRW_shader_subdiv_get( fdots_nor ? SubdivShaderType::PATCH_EVALUATION_FACE_DOTS_WITH_NORMALS : @@ -1404,9 +1305,9 @@ void draw_subdiv_build_fdots_buffers(const DRWSubdivCache &cache, GPU_vertbuf_bind_as_ssbo(cache.fdots_patch_coords, PATCH_EVALUATION_PATCH_COORDS_BUF_SLOT); GPU_vertbuf_bind_as_ssbo(cache.verts_orig_index, PATCH_EVALUATION_INPUT_VERTEX_ORIG_INDEX_BUF_SLOT); - GPU_vertbuf_bind_as_ssbo(patch_arrays_buffer, PATCH_EVALUATION_PATCH_ARRAY_BUFFER_BUF_SLOT); - GPU_vertbuf_bind_as_ssbo(patch_index_buffer, PATCH_EVALUATION_PATCH_INDEX_BUFFER_BUF_SLOT); - GPU_vertbuf_bind_as_ssbo(patch_param_buffer, PATCH_EVALUATION_PATCH_PARAM_BUFFER_BUF_SLOT); + GPU_storagebuf_bind(patch_arrays_buffer, PATCH_EVALUATION_PATCH_ARRAY_BUFFER_BUF_SLOT); + GPU_storagebuf_bind(patch_index_buffer, PATCH_EVALUATION_PATCH_INDEX_BUFFER_BUF_SLOT); + GPU_storagebuf_bind(patch_param_buffer, PATCH_EVALUATION_PATCH_PARAM_BUFFER_BUF_SLOT); GPU_vertbuf_bind_as_ssbo(fdots_pos, PATCH_EVALUATION_OUTPUT_FDOTS_VERTEX_BUFFER_BUF_SLOT); /* F-dots normals may not be requested, still reserve the binding point. */ if (fdots_nor) { @@ -1425,10 +1326,7 @@ void draw_subdiv_build_fdots_buffers(const DRWSubdivCache &cache, /* Cleanup. */ GPU_shader_unbind(); - GPU_vertbuf_discard(patch_index_buffer); - GPU_vertbuf_discard(patch_param_buffer); - GPU_vertbuf_discard(patch_arrays_buffer); - GPU_vertbuf_discard(src_buffer); + GPU_storagebuf_free(patch_arrays_buffer); #else UNUSED_VARS(cache, fdots_pos, fdots_nor, fdots_indices); #endif diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index d399f6a681f..4ab1481f198 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -770,6 +770,10 @@ if(WITH_OPENCOLORIO) target_link_libraries(bf_gpu PUBLIC bf_ocio_shaders) endif() +if(WITH_OPENSUBDIV) + target_link_libraries(bf_gpu PUBLIC bf_osd_shaders) +endif() + if(WITH_RENDERDOC) target_link_libraries(bf_gpu PUBLIC bf_intern_renderdoc_dynload) endif() diff --git a/source/blender/gpu/intern/gpu_shader_dependency.cc b/source/blender/gpu/intern/gpu_shader_dependency.cc index 644b2c80d4c..96fd209fc02 100644 --- a/source/blender/gpu/intern/gpu_shader_dependency.cc +++ b/source/blender/gpu/intern/gpu_shader_dependency.cc @@ -38,6 +38,9 @@ extern "C" { #ifdef WITH_OCIO # include "glsl_ocio_source_list.h" #endif +#ifdef WITH_OPENSUBDIV +# include "glsl_osd_source_list.h" +#endif #undef SHADER_SOURCE } @@ -450,6 +453,9 @@ void gpu_shader_dependency_init() #ifdef WITH_OCIO # include "glsl_ocio_source_list.h" #endif +#ifdef WITH_OPENSUBDIV +# include "glsl_osd_source_list.h" +#endif #undef SHADER_SOURCE #ifdef WITH_OPENSUBDIV const blender::StringRefNull patch_basis_source = openSubdiv_getGLSLPatchBasisSource();