/* SPDX-FileCopyrightText: 2025 Blender Foundation * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "gpu_patch_table.hh" #include "opensubdiv/far/patchTable.h" #include "opensubdiv/osd/cpuPatchTable.h" using namespace OpenSubdiv::Osd; namespace blender::opensubdiv { GPUPatchTable *GPUPatchTable::Create(PatchTable const *far_patch_table, void * /*deviceContext*/) { GPUPatchTable *instance = new GPUPatchTable(); if (instance->allocate(far_patch_table)) return instance; delete instance; return nullptr; } static void discard_buffer(GPUStorageBuf **buffer) { if (*buffer != nullptr) { GPU_storagebuf_free(*buffer); *buffer = nullptr; } } static void discard_list(std::vector &buffers) { while (!buffers.empty()) { GPUStorageBuf *buffer = buffers.back(); buffers.pop_back(); GPU_storagebuf_free(buffer); } } GPUPatchTable::~GPUPatchTable() { discard_buffer(&_patchIndexBuffer); discard_buffer(&_patchParamBuffer); discard_buffer(&_varyingIndexBuffer); discard_list(_fvarIndexBuffers); discard_list(_fvarParamBuffers); } 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 = GPU_storagebuf_create_ex( index_size * sizeof(int32_t), static_cast(patch_table.GetPatchIndexBuffer()), GPU_USAGE_STATIC, "osd_patch_index"); /* Patch param buffer */ const size_t patch_param_size = patch_table.GetPatchParamSize(); _patchParamBuffer = GPU_storagebuf_create_ex(patch_param_size * sizeof(PatchParam), patch_table.GetPatchParamBuffer(), GPU_USAGE_STATIC, "osd_patch_param"); /* Varying patch array */ _varyingPatchArrays.assign(patch_table.GetVaryingPatchArrayBuffer(), patch_table.GetVaryingPatchArrayBuffer() + num_patch_arrays); /* Varying index buffer */ _varyingIndexBuffer = GPU_storagebuf_create_ex(patch_table.GetVaryingPatchIndexSize() * sizeof(uint32_t), patch_table.GetVaryingPatchIndexBuffer(), GPU_USAGE_STATIC, "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] = GPU_storagebuf_create_ex(patch_table.GetFVarPatchIndexSize(index) * sizeof(int32_t), patch_table.GetFVarPatchIndexBuffer(index), GPU_USAGE_STATIC, "osd_face_varying_index"); /* Face varying patch param buffer */ _fvarParamBuffers[index] = GPU_storagebuf_create_ex(patch_table.GetFVarPatchParamSize(index) * sizeof(PatchParam), patch_table.GetFVarPatchParamBuffer(index), GPU_USAGE_STATIC, "osd_face_varying_params"); } return true; } } // namespace blender::opensubdiv