SubDiv: Migrate GPU subdivision to use GPU module
Blender already had its own copy of OpenSubDiv containing some local fixes and code-style. This code still used gl-calls. This PR updates the calls to use GPU module. This allows us to use OpenSubDiv to be usable on other backends as well. This PR was tested on OpenGL, Vulkan and Metal. Metal can be enabled, but Vulkan requires some API changes to work with loose geometry.  # Considerations **ShaderCreateInfo** intern/opensubdiv now requires access to GPU module. This to create buffers in the correct context and trigger correct dispatches. ShaderCreateInfo is used to construct the shader for cross compilation to Metal/Vulkan. However opensubdiv shader caching structures are still used. **Vertex buffers vs storage buffers** Implementation tries to keep as close to the original OSD implementation. If they used storage buffers for data, we will use GPUStorageBuf. If it uses vertex buffers, we will use gpu::VertBuf. **Evaluator const** The evaluator cannot be const anymore as the GPU module API only allows updating SSBOs when constructing. API could be improved to support updating SSBOs. Current implementation has a change to use reads out of bounds when constructing SSBOs. An API change is in the planning to remove this issue. This will be fixed in an upcoming PR. We wanted to land this PR as the visibility of the issue is not common and multiple other changes rely on this PR to land. Pull Request: https://projects.blender.org/blender/blender/pulls/135296
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -8,18 +8,18 @@
|
||||
#define OPENSUBDIV_EVAL_OUTPUT_H_
|
||||
|
||||
#include <opensubdiv/osd/cpuPatchTable.h>
|
||||
#include <opensubdiv/osd/glPatchTable.h>
|
||||
#include <opensubdiv/osd/mesh.h>
|
||||
#include <opensubdiv/osd/types.h>
|
||||
|
||||
#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<typename T> 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<const Pat
|
||||
// Discriminators used in FaceVaryingVolatileEval in order to detect whether we are using adaptive
|
||||
// patches as the CPU and OpenGL PatchTable have different APIs.
|
||||
bool is_adaptive(const CpuPatchTable *patch_table);
|
||||
bool is_adaptive(const GLPatchTable *patch_table);
|
||||
bool is_adaptive(const GPUPatchTable *patch_table);
|
||||
|
||||
template<typename EVAL_VERTEX_BUFFER,
|
||||
typename STENCIL_TABLE,
|
||||
@@ -212,7 +229,7 @@ class FaceVaryingVolatileEval {
|
||||
BufferDescriptor dst_face_varying_desc = src_face_varying_desc_;
|
||||
dst_face_varying_desc.offset += num_coarse_face_varying_vertices_ *
|
||||
src_face_varying_desc_.stride;
|
||||
const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
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<float> 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>(
|
||||
EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
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>(
|
||||
EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
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>(
|
||||
EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
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>(
|
||||
EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
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>(
|
||||
EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
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<float> 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>(
|
||||
EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
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<float> 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>(
|
||||
EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
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
|
||||
|
||||
@@ -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<GLVertexBuffer,
|
||||
GLVertexBuffer,
|
||||
GLStencilTableSSBO,
|
||||
GLPatchTable,
|
||||
GLComputeEvaluator>(vertex_stencils,
|
||||
varying_stencils,
|
||||
all_face_varying_stencils,
|
||||
face_varying_width,
|
||||
patch_table,
|
||||
evaluator_cache)
|
||||
: VolatileEvalOutput<GPUVertexBuffer,
|
||||
GPUVertexBuffer,
|
||||
GPUStencilTableSSBO,
|
||||
GPUPatchTable,
|
||||
GPUComputeEvaluator>(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
|
||||
|
||||
@@ -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 <opensubdiv/osd/glPatchTable.h>
|
||||
#include <opensubdiv/osd/glVertexBuffer.h>
|
||||
|
||||
using OpenSubdiv::Osd::GLVertexBuffer;
|
||||
#include "gpu_vertex_buffer_wrapper.hh"
|
||||
|
||||
namespace blender::opensubdiv {
|
||||
|
||||
class GpuEvalOutput : public VolatileEvalOutput<GLVertexBuffer,
|
||||
GLVertexBuffer,
|
||||
GLStencilTableSSBO,
|
||||
GLPatchTable,
|
||||
GLComputeEvaluator> {
|
||||
class GpuEvalOutput : public VolatileEvalOutput<GPUVertexBuffer,
|
||||
GPUVertexBuffer,
|
||||
GPUStencilTableSSBO,
|
||||
GPUPatchTable,
|
||||
GPUComputeEvaluator> {
|
||||
public:
|
||||
GpuEvalOutput(const StencilTable *vertex_stencils,
|
||||
const StencilTable *varying_stencils,
|
||||
@@ -30,27 +31,47 @@ class GpuEvalOutput : public VolatileEvalOutput<GLVertexBuffer,
|
||||
const PatchTable *patch_table,
|
||||
EvaluatorCache *evaluator_cache = nullptr);
|
||||
|
||||
void fillPatchArraysBuffer(blender::gpu::VertBuf *patch_arrays_buffer) override;
|
||||
GPUStorageBuf *create_patch_arrays_buf() override;
|
||||
|
||||
void wrapPatchIndexBuffer(blender::gpu::VertBuf *patch_index_buffer) override;
|
||||
GPUStorageBuf *get_patch_index_buf() override
|
||||
{
|
||||
return getPatchTable()->GetPatchIndexBuffer();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,659 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2015 Pixar
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
/* 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 <opensubdiv/far/error.h>
|
||||
#include <opensubdiv/far/patchDescriptor.h>
|
||||
#include <opensubdiv/far/stencilTable.h>
|
||||
#include <opensubdiv/osd/glslPatchShaderSource.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
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<class T> GLuint createSSBO(std::vector<T> 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<GLuint>(maxWorkGroupCount[0]);
|
||||
|
||||
const int dispatchSize = GetDispatchSize(totalDispatchSize);
|
||||
GLuint dispatchRX = static_cast<GLuint>(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<GLuint>(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
|
||||
662
intern/opensubdiv/internal/evaluator/gpu_compute_evaluator.cc
Normal file
662
intern/opensubdiv/internal/evaluator/gpu_compute_evaluator.cc
Normal file
@@ -0,0 +1,662 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
#include "gpu_compute_evaluator.h"
|
||||
|
||||
#include <opensubdiv/far/error.h>
|
||||
#include <opensubdiv/far/patchDescriptor.h>
|
||||
#include <opensubdiv/far/stencilTable.h>
|
||||
#include <opensubdiv/osd/glslPatchShaderSource.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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<class T> GPUStorageBuf *create_buffer(std::vector<T> 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<const GPUShaderCreateInfo *>(&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<const void *>(&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
|
||||
@@ -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 <opensubdiv/osd/bufferDescriptor.h>
|
||||
#include <opensubdiv/osd/opengl.h>
|
||||
#include <opensubdiv/osd/types.h>
|
||||
#include <opensubdiv/version.h>
|
||||
|
||||
#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_
|
||||
130
intern/opensubdiv/internal/evaluator/gpu_patch_table.cc
Normal file
130
intern/opensubdiv/internal/evaluator/gpu_patch_table.cc
Normal file
@@ -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<GPUStorageBuf *> &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<const void *>(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
|
||||
96
intern/opensubdiv/internal/evaluator/gpu_patch_table.hh
Normal file
96
intern/opensubdiv/internal/evaluator/gpu_patch_table.hh
Normal file
@@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include "GPU_storage_buffer.hh"
|
||||
|
||||
#include <opensubdiv/version.h>
|
||||
|
||||
#include <opensubdiv/osd/nonCopyable.h>
|
||||
#include <opensubdiv/osd/types.h>
|
||||
|
||||
using OpenSubdiv::Far::PatchTable;
|
||||
using OpenSubdiv::Osd::NonCopyable;
|
||||
using OpenSubdiv::Osd::PatchArrayVector;
|
||||
|
||||
namespace blender::opensubdiv {
|
||||
|
||||
// TODO: use Blenlib NonCopyable.
|
||||
class GPUPatchTable : private NonCopyable<GPUPatchTable> {
|
||||
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<PatchArrayVector> _fvarPatchArrays;
|
||||
std::vector<GPUStorageBuf *> _fvarIndexBuffers;
|
||||
std::vector<GPUStorageBuf *> _fvarParamBuffers;
|
||||
};
|
||||
|
||||
} // namespace blender::opensubdiv
|
||||
@@ -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<float> buffer_nodes = gpu_vertex_buffer_.data<float>();
|
||||
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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
#include "opensubdiv_capi_type.hh"
|
||||
|
||||
#include "GPU_vertex_buffer.hh"
|
||||
|
||||
struct OpenSubdiv_EvaluatorCacheImpl;
|
||||
struct OpenSubdiv_PatchCoord;
|
||||
namespace blender::opensubdiv {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user