Add Chromium-only Blender WebEngine parity work
This commit is contained in:
28
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/Android.mk
vendored
Normal file
28
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/Android.mk
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# Copyright 2013 Pixar
|
||||
#
|
||||
# Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
# https://opensubdiv.org/license.
|
||||
#
|
||||
|
||||
# This file is used by the Android NDK to allow OpenSubdiv libraries
|
||||
# to be imported by client modules.
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE = OpenSubdivOsdCPU
|
||||
LOCAL_SRC_FILES = libs/armeabi-v7a/libosdCPU.so
|
||||
LOCAL_EXPORT_C_INCLUDES = $(LOCAL_PATH)/include
|
||||
|
||||
include $(PREBUILT_SHARED_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE = OpenSubdivOsdGPU
|
||||
LOCAL_SRC_FILES = libs/armeabi-v7a/libosdGPU.so
|
||||
LOCAL_EXPORT_C_INCLUDES = $(LOCAL_PATH)/include
|
||||
|
||||
include $(PREBUILT_SHARED_LIBRARY)
|
||||
|
||||
442
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/CMakeLists.txt
vendored
Normal file
442
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,442 @@
|
||||
#
|
||||
# Copyright 2013 Pixar
|
||||
#
|
||||
# Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
# https://opensubdiv.org/license.
|
||||
#
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# source & headers
|
||||
set(CPU_SOURCE_FILES
|
||||
cpuEvaluator.cpp
|
||||
cpuKernel.cpp
|
||||
cpuPatchTable.cpp
|
||||
cpuVertexBuffer.cpp
|
||||
)
|
||||
|
||||
set(GPU_SOURCE_FILES )
|
||||
|
||||
set(INC_FILES )
|
||||
|
||||
set(PRIVATE_HEADER_FILES
|
||||
cpuKernel.h
|
||||
)
|
||||
|
||||
set(PUBLIC_HEADER_FILES
|
||||
bufferDescriptor.h
|
||||
cpuEvaluator.h
|
||||
cpuPatchTable.h
|
||||
cpuVertexBuffer.h
|
||||
mesh.h
|
||||
nonCopyable.h
|
||||
opengl.h
|
||||
types.h
|
||||
)
|
||||
|
||||
set(DOXY_HEADER_FILES ${PUBLIC_HEADER_FILES})
|
||||
|
||||
# These are public but excluded from doxygen
|
||||
list(APPEND PUBLIC_HEADER_FILES
|
||||
patchBasisTypes.h
|
||||
patchBasis.h
|
||||
)
|
||||
|
||||
list(APPEND KERNEL_FILES
|
||||
patchBasisTypes.h
|
||||
patchBasis.h
|
||||
)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# GLSL patch shader source
|
||||
if( OSD_PATCH_SHADER_SOURCE_GLSL OR
|
||||
(NOT NO_OPENGL AND (OPENGL_FOUND OR OPENGLES_FOUND)) )
|
||||
list(APPEND PUBLIC_HEADER_FILES
|
||||
glslPatchShaderSource.h
|
||||
)
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
glslPatchShaderSource.cpp
|
||||
)
|
||||
list(APPEND KERNEL_FILES
|
||||
glslPatchCommon.glsl
|
||||
glslPatchCommonTess.glsl
|
||||
glslPatchBoxSplineTriangle.glsl
|
||||
glslPatchBSpline.glsl
|
||||
glslPatchGregory.glsl
|
||||
glslPatchGregoryBasis.glsl
|
||||
glslPatchGregoryTriangle.glsl
|
||||
glslPatchLegacy.glsl
|
||||
)
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# HLSL patch shader source
|
||||
if( OSD_PATCH_SHADER_SOURCE_HLSL OR DXSDK_FOUND )
|
||||
list(APPEND PUBLIC_HEADER_FILES
|
||||
hlslPatchShaderSource.h
|
||||
)
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
hlslPatchShaderSource.cpp
|
||||
)
|
||||
list(APPEND KERNEL_FILES
|
||||
hlslPatchCommon.hlsl
|
||||
hlslPatchCommonTess.hlsl
|
||||
hlslPatchBoxSplineTriangle.hlsl
|
||||
hlslPatchBSpline.hlsl
|
||||
hlslPatchGregory.hlsl
|
||||
hlslPatchGregoryBasis.hlsl
|
||||
hlslPatchGregoryTriangle.hlsl
|
||||
hlslPatchLegacy.hlsl
|
||||
)
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# MSL patch shader source
|
||||
if( OSD_PATCH_SHADER_SOURCE_MSL OR METAL_FOUND )
|
||||
list(APPEND PUBLIC_HEADER_FILES
|
||||
mtlPatchShaderSource.h
|
||||
)
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
mtlPatchShaderSource.mm
|
||||
)
|
||||
list(APPEND KERNEL_FILES
|
||||
mtlPatchCommon.metal
|
||||
mtlPatchCommonTess.metal
|
||||
mtlPatchBoxSplineTriangle.metal
|
||||
mtlPatchBSpline.metal
|
||||
mtlPatchGregory.metal
|
||||
mtlPatchGregoryBasis.metal
|
||||
mtlPatchGregoryTriangle.metal
|
||||
mtlPatchLegacy.metal
|
||||
)
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
set(OPENMP_PUBLIC_HEADERS
|
||||
ompEvaluator.h
|
||||
ompKernel.h
|
||||
)
|
||||
|
||||
if(OPENMP_FOUND )
|
||||
list(APPEND CPU_SOURCE_FILES
|
||||
ompEvaluator.cpp
|
||||
ompKernel.cpp
|
||||
)
|
||||
|
||||
list(APPEND PUBLIC_HEADER_FILES ${OPENMP_PUBLIC_HEADERS})
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
list(APPEND PLATFORM_CPU_LIBRARIES gomp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND DOXY_HEADER_FILES ${OPENMP_PUBLIC_HEADERS})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
set(TBB_PUBLIC_HEADERS
|
||||
tbbEvaluator.h
|
||||
tbbKernel.h
|
||||
)
|
||||
|
||||
if( TBB_FOUND )
|
||||
list(APPEND CPU_SOURCE_FILES
|
||||
tbbEvaluator.cpp
|
||||
tbbKernel.cpp
|
||||
)
|
||||
|
||||
list(APPEND PUBLIC_HEADER_FILES ${TBB_PUBLIC_HEADERS})
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
list(APPEND PLATFORM_CPU_LIBRARIES gomp)
|
||||
endif()
|
||||
|
||||
list(APPEND PLATFORM_CPU_LIBRARIES
|
||||
TBB::tbb
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND DOXY_HEADER_FILES ${TBB_PUBLIC_HEADERS})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# GL code & dependencies
|
||||
set(GL_PUBLIC_HEADERS
|
||||
cpuGLVertexBuffer.h
|
||||
glLegacyGregoryPatchTable.h
|
||||
glPatchTable.h
|
||||
glVertexBuffer.h
|
||||
glMesh.h
|
||||
)
|
||||
|
||||
if( (NOT NO_OPENGL) AND (OPENGL_FOUND OR OPENGLES_FOUND) )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
cpuGLVertexBuffer.cpp
|
||||
glLegacyGregoryPatchTable.cpp
|
||||
glPatchTable.cpp
|
||||
glVertexBuffer.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES ${GL_PUBLIC_HEADERS})
|
||||
endif()
|
||||
|
||||
list(APPEND DOXY_HEADER_FILES ${GL_PUBLIC_HEADERS})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# OpenGL 4.2 dependencies
|
||||
# note : (GLSL transform feedback kernels require GL 4.2)
|
||||
set(GL_4_2_PUBLIC_HEADERS
|
||||
glXFBEvaluator.h
|
||||
)
|
||||
|
||||
if( OPENGL_4_2_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
glXFBEvaluator.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES ${GL_4_2_PUBLIC_HEADERS})
|
||||
list(APPEND KERNEL_FILES
|
||||
glslXFBKernel.glsl
|
||||
)
|
||||
list(APPEND PLATFORM_GPU_LIBRARIES
|
||||
${OPENGL_LOADER_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND DOXY_HEADER_FILES ${GL_4_2_PUBLIC_HEADERS})
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# OpenGL 4.3 dependencies
|
||||
# note : (GLSL compute shader kernels require GL 4.3)
|
||||
set(GL_4_3_PUBLIC_HEADERS
|
||||
glComputeEvaluator.h
|
||||
)
|
||||
|
||||
if( OPENGL_4_3_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
glComputeEvaluator.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES ${GL_4_3_PUBLIC_HEADERS})
|
||||
list(APPEND KERNEL_FILES
|
||||
glslComputeKernel.glsl
|
||||
)
|
||||
list(APPEND PLATFORM_GPU_LIBRARIES
|
||||
${OPENGL_LOADER_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND DOXY_HEADER_FILES ${GL_4_3_PUBLIC_HEADERS})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# DX11 code & dependencies
|
||||
set(DXSDK_PUBLIC_HEADERS
|
||||
cpuD3D11VertexBuffer.h
|
||||
d3d11ComputeEvaluator.h
|
||||
d3d11LegacyGregoryPatchTable.h
|
||||
d3d11PatchTable.h
|
||||
d3d11VertexBuffer.h
|
||||
d3d11Mesh.h
|
||||
)
|
||||
if( DXSDK_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
cpuD3D11VertexBuffer.cpp
|
||||
d3d11ComputeEvaluator.cpp
|
||||
d3d11LegacyGregoryPatchTable.cpp
|
||||
d3d11PatchTable.cpp
|
||||
d3d11VertexBuffer.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES ${DXSDK_PUBLIC_HEADERS})
|
||||
list(APPEND KERNEL_FILES
|
||||
hlslComputeKernel.hlsl
|
||||
)
|
||||
list(APPEND PLATFORM_GPU_LIBRARIES
|
||||
${DXSDK_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND DOXY_HEADER_FILES ${DXSDK_PUBLIC_HEADERS})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Metal code & dependencies
|
||||
set(METAL_PUBLIC_HEADERS
|
||||
mtlVertexBuffer.h
|
||||
mtlComputeEvaluator.h
|
||||
mtlLegacyGregoryPatchTable.h
|
||||
mtlPatchTable.h
|
||||
mtlMesh.h
|
||||
mtlCommon.h
|
||||
)
|
||||
|
||||
|
||||
if( METAL_FOUND )
|
||||
set(METAL_SOURCE_FILES
|
||||
mtlVertexBuffer.mm
|
||||
mtlComputeEvaluator.mm
|
||||
mtlLegacyGregoryPatchTable.mm
|
||||
mtlPatchTable.mm
|
||||
mtlVertexBuffer.mm
|
||||
)
|
||||
|
||||
set_source_files_properties(
|
||||
${METAL_SOURCE_FILES}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"-fobjc-arc")
|
||||
|
||||
list(APPEND GPU_SOURCE_FILES ${METAL_SOURCE_FILES})
|
||||
list(APPEND PUBLIC_HEADER_FILES ${METAL_PUBLIC_HEADERS})
|
||||
list(APPEND KERNEL_FILES
|
||||
mtlComputeKernel.metal
|
||||
)
|
||||
list(APPEND PLATFORM_GPU_LIBRARIES
|
||||
${METAL_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND DOXY_HEADER_FILES ${METAL_PUBLIC_HEADERS})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# OpenCL code & dependencies
|
||||
set(OPENCL_PUBLIC_HEADERS
|
||||
clEvaluator.h
|
||||
clPatchTable.h
|
||||
clVertexBuffer.h
|
||||
opencl.h
|
||||
)
|
||||
|
||||
if ( OPENCL_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
clEvaluator.cpp
|
||||
clPatchTable.cpp
|
||||
clVertexBuffer.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES ${OPENCL_PUBLIC_HEADERS})
|
||||
list(APPEND KERNEL_FILES
|
||||
clKernel.cl
|
||||
)
|
||||
list(APPEND PLATFORM_GPU_LIBRARIES
|
||||
${OPENCL_LIBRARIES}
|
||||
)
|
||||
include_directories( "${OPENCL_INCLUDE_DIRS}" )
|
||||
if ( OPENGL_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES clGLVertexBuffer.cpp)
|
||||
list(APPEND PUBLIC_HEADER_FILES clGLVertexBuffer.h)
|
||||
endif()
|
||||
|
||||
if ( OPENCL_D3D11_INTEROP_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
clD3D11VertexBuffer.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES
|
||||
clD3D11VertexBuffer.h
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND DOXY_HEADER_FILES ${OPENCL_PUBLIC_HEADERS})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# CUDA code & dependencies
|
||||
set(CUDA_PUBLIC_HEADERS
|
||||
cudaEvaluator.h
|
||||
cudaPatchTable.h
|
||||
cudaVertexBuffer.h
|
||||
)
|
||||
|
||||
if( CUDA_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
cudaEvaluator.cpp
|
||||
cudaPatchTable.cpp
|
||||
cudaVertexBuffer.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES ${CUDA_PUBLIC_HEADERS})
|
||||
list(APPEND CUDA_KERNEL_FILES
|
||||
osd/cudaKernel.cu
|
||||
)
|
||||
set (CUDA_KERNEL_FILES ${CUDA_KERNEL_FILES} PARENT_SCOPE)
|
||||
if ( OPENGL_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
cudaGLVertexBuffer.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES
|
||||
cudaGLVertexBuffer.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if( DXSDK_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
cudaD3D11VertexBuffer.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES
|
||||
cudaD3D11VertexBuffer.h
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND DOXY_HEADER_FILES ${CUDA_PUBLIC_HEADERS})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
osd_stringify("${KERNEL_FILES}" INC_FILES)
|
||||
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
source_group("Kernels" FILES ${KERNEL_FILES})
|
||||
|
||||
source_group("Inc" FILES ${INC_FILES})
|
||||
|
||||
# Compile objs first for both the CPU and GPU libs -----
|
||||
add_library(osd_cpu_obj
|
||||
OBJECT
|
||||
${CPU_SOURCE_FILES}
|
||||
${PRIVATE_HEADER_FILES}
|
||||
${PUBLIC_HEADER_FILES}
|
||||
)
|
||||
|
||||
set_target_properties(osd_cpu_obj
|
||||
PROPERTIES
|
||||
FOLDER "opensubdiv"
|
||||
)
|
||||
|
||||
target_link_libraries(osd_cpu_obj
|
||||
${PLATFORM_CPU_LIBRARIES}
|
||||
)
|
||||
|
||||
if( GPU_SOURCE_FILES )
|
||||
add_library(osd_gpu_obj
|
||||
OBJECT
|
||||
${GPU_SOURCE_FILES}
|
||||
${PRIVATE_HEADER_FILES}
|
||||
${PUBLIC_HEADER_FILES}
|
||||
${INC_FILES}
|
||||
)
|
||||
set_target_properties(osd_gpu_obj
|
||||
PROPERTIES
|
||||
FOLDER "opensubdiv"
|
||||
)
|
||||
endif()
|
||||
|
||||
osd_add_doxy_headers( "${DOXY_HEADER_FILES}" )
|
||||
|
||||
install(
|
||||
FILES
|
||||
${PUBLIC_HEADER_FILES}
|
||||
DESTINATION
|
||||
"${CMAKE_INCDIR_BASE}/osd"
|
||||
PERMISSIONS
|
||||
OWNER_READ
|
||||
GROUP_READ
|
||||
WORLD_READ )
|
||||
|
||||
if (ANDROID)
|
||||
install(
|
||||
FILES
|
||||
Android.mk
|
||||
DESTINATION
|
||||
"${LIBRARY_OUTPUT_PATH_ROOT}"
|
||||
PERMISSIONS
|
||||
OWNER_READ
|
||||
GROUP_READ
|
||||
WORLD_READ )
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
95
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/bufferDescriptor.h
vendored
Normal file
95
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/bufferDescriptor.h
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_BUFFER_DESCRIPTOR_H
|
||||
#define OPENSUBDIV3_OSD_BUFFER_DESCRIPTOR_H
|
||||
|
||||
#include "../version.h"
|
||||
#include <string.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief BufferDescriptor is a struct which describes buffer elements in
|
||||
/// interleaved data buffers. Almost all Osd Evaluator APIs take
|
||||
/// BufferDescriptors along with device-specific buffer objects.
|
||||
///
|
||||
/// The offset of BufferDescriptor can also be used to express a
|
||||
/// batching offset if the data buffer is combined across multiple
|
||||
/// objects together.
|
||||
///
|
||||
/// * Note that each element has the same data type (float)
|
||||
///
|
||||
|
||||
// example:
|
||||
// n
|
||||
// -----+----------------------------------------+-------------------------
|
||||
// | vertex 0 |
|
||||
// -----+----------------------------------------+-------------------------
|
||||
// | X Y Z R G B A Xu Yu Zu Xv Yv Zv |
|
||||
// -----+----------------------------------------+-------------------------
|
||||
// <------------- stride = 13 -------------->
|
||||
//
|
||||
// - XYZ (offset = n+0, length = 3, stride = 13)
|
||||
// - RGBA (offset = n+3, length = 4, stride = 13)
|
||||
// - uTangent (offset = n+7, length = 3, stride = 13)
|
||||
// - vTangent (offset = n+10, length = 3, stride = 13)
|
||||
//
|
||||
struct BufferDescriptor {
|
||||
|
||||
/// Default Constructor
|
||||
BufferDescriptor() : offset(0), length(0), stride(0) { }
|
||||
|
||||
/// Constructor
|
||||
BufferDescriptor(int o, int l, int s) : offset(o), length(l), stride(s) { }
|
||||
|
||||
/// Returns the relative offset within a stride
|
||||
int GetLocalOffset() const {
|
||||
return stride > 0 ? offset % stride : 0;
|
||||
}
|
||||
|
||||
/// True if the descriptor values are internally consistent
|
||||
bool IsValid() const {
|
||||
return ((length > 0) &&
|
||||
(length <= stride - GetLocalOffset()));
|
||||
}
|
||||
|
||||
/// Resets the descriptor to default
|
||||
void Reset() {
|
||||
offset = length = stride = 0;
|
||||
}
|
||||
|
||||
/// True if the descriptors are identical
|
||||
bool operator == (BufferDescriptor const &other) const {
|
||||
return (offset == other.offset &&
|
||||
length == other.length &&
|
||||
stride == other.stride);
|
||||
}
|
||||
|
||||
/// True if the descriptors are not identical
|
||||
bool operator != (BufferDescriptor const &other) const {
|
||||
return !(this->operator==(other));
|
||||
}
|
||||
|
||||
/// offset to desired element data
|
||||
int offset;
|
||||
/// number or length of the data
|
||||
int length;
|
||||
/// stride to the next element
|
||||
int stride;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_BUFFER_DESCRIPTOR_H
|
||||
216
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clD3D11VertexBuffer.cpp
vendored
Normal file
216
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clD3D11VertexBuffer.cpp
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/clD3D11VertexBuffer.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <D3D11.h>
|
||||
#if defined(OPENSUBDIV_HAS_CL_D3D11_H)
|
||||
#include <CL/cl_d3d11.h>
|
||||
#elif defined(OPENSUBDIV_HAS_CL_D3D11_EXT_H)
|
||||
#include <CL/cl_d3d11_ext.h>
|
||||
#else
|
||||
#error "d3d11.h or d3d11_ext.h must be found in cmake"
|
||||
#endif
|
||||
|
||||
#include "../far/error.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
#if defined(OPENSUBDIV_HAS_CL_D3D11_H)
|
||||
typedef clCreateFromD3D11BufferKHR_fn clCreateFromD3D11Buffer_fn;
|
||||
typedef clEnqueueAcquireD3D11ObjectsKHR_fn clEnqueueAcquireD3D11Objects_fn;
|
||||
typedef clEnqueueReleaseD3D11ObjectsKHR_fn clEnqueueReleaseD3D11Objects_fn;
|
||||
#else
|
||||
typedef clCreateFromD3D11BufferNV_fn clCreateFromD3D11Buffer_fn;
|
||||
typedef clEnqueueAcquireD3D11ObjectsNV_fn clEnqueueAcquireD3D11Objects_fn;
|
||||
typedef clEnqueueReleaseD3D11ObjectsNV_fn clEnqueueReleaseD3D11Objects_fn;
|
||||
#endif
|
||||
|
||||
static clCreateFromD3D11Buffer_fn clCreateFromD3D11Buffer = NULL;
|
||||
static clEnqueueAcquireD3D11Objects_fn clEnqueueAcquireD3D11Objects = NULL;
|
||||
static clEnqueueReleaseD3D11Objects_fn clEnqueueReleaseD3D11Objects = NULL;
|
||||
|
||||
// XXX: clGetExtensionFunctionAddress is marked as deprecated and
|
||||
// clGetExtensionFunctionAddressForPlatform should be used,
|
||||
// however it requires OpenCL 1.2.
|
||||
// until we bump the requirement to 1.2, mute the deprecated warning.
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
|
||||
static void resolveInteropFunctions() {
|
||||
|
||||
if (! clCreateFromD3D11Buffer) {
|
||||
clCreateFromD3D11Buffer =
|
||||
(clCreateFromD3D11Buffer_fn)
|
||||
clGetExtensionFunctionAddress("clCreateFromD3D11BufferKHR");
|
||||
}
|
||||
if (! clCreateFromD3D11Buffer) {
|
||||
clCreateFromD3D11Buffer =
|
||||
(clCreateFromD3D11Buffer_fn)
|
||||
clGetExtensionFunctionAddress("clCreateFromD3D11BufferNV");
|
||||
}
|
||||
|
||||
if (! clEnqueueAcquireD3D11Objects) {
|
||||
clEnqueueAcquireD3D11Objects = (clEnqueueAcquireD3D11Objects_fn)
|
||||
clGetExtensionFunctionAddress("clEnqueueAcquireD3D11ObjectsKHR");
|
||||
}
|
||||
if (! clEnqueueAcquireD3D11Objects) {
|
||||
clEnqueueAcquireD3D11Objects = (clEnqueueAcquireD3D11Objects_fn)
|
||||
clGetExtensionFunctionAddress("clEnqueueAcquireD3D11ObjectsNV");
|
||||
}
|
||||
|
||||
if (! clEnqueueReleaseD3D11Objects) {
|
||||
clEnqueueReleaseD3D11Objects = (clEnqueueReleaseD3D11Objects_fn)
|
||||
clGetExtensionFunctionAddress("clEnqueueReleaseD3D11ObjectsKHR");
|
||||
}
|
||||
if (! clEnqueueReleaseD3D11Objects) {
|
||||
clEnqueueReleaseD3D11Objects = (clEnqueueReleaseD3D11Objects_fn)
|
||||
clGetExtensionFunctionAddress("clEnqueueReleaseD3D11ObjectsNV");
|
||||
}
|
||||
}
|
||||
|
||||
CLD3D11VertexBuffer::CLD3D11VertexBuffer(int numElements, int numVertices)
|
||||
: _numElements(numElements), _numVertices(numVertices),
|
||||
_d3d11Buffer(NULL), _clMemory(NULL), _clQueue(NULL), _clMapped(false) {
|
||||
}
|
||||
|
||||
CLD3D11VertexBuffer::~CLD3D11VertexBuffer() {
|
||||
|
||||
unmap();
|
||||
clReleaseMemObject(_clMemory);
|
||||
_d3d11Buffer->Release();
|
||||
}
|
||||
|
||||
CLD3D11VertexBuffer *
|
||||
CLD3D11VertexBuffer::Create(int numElements, int numVertices,
|
||||
cl_context clContext,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
CLD3D11VertexBuffer *instance =
|
||||
new CLD3D11VertexBuffer(numElements, numVertices);
|
||||
|
||||
ID3D11Device *device;
|
||||
deviceContext->GetDevice(&device);
|
||||
|
||||
if (instance->allocate(clContext, device)) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
CLD3D11VertexBuffer::UpdateData(const float *src, int startVertex,
|
||||
int numVertices, cl_command_queue queue) {
|
||||
|
||||
size_t size = numVertices * _numElements * sizeof(float);
|
||||
size_t offset = startVertex * _numElements * sizeof(float);
|
||||
|
||||
map(queue);
|
||||
clEnqueueWriteBuffer(queue, _clMemory, true, offset, size, src, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
CLD3D11VertexBuffer::GetNumElements() const {
|
||||
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int
|
||||
CLD3D11VertexBuffer::GetNumVertices() const {
|
||||
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLD3D11VertexBuffer::BindCLBuffer(cl_command_queue queue) {
|
||||
|
||||
map(queue);
|
||||
return _clMemory;
|
||||
}
|
||||
|
||||
ID3D11Buffer *
|
||||
CLD3D11VertexBuffer::BindD3D11Buffer(ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
unmap();
|
||||
return _d3d11Buffer;
|
||||
}
|
||||
|
||||
bool
|
||||
CLD3D11VertexBuffer::allocate(cl_context clContext, ID3D11Device *device) {
|
||||
|
||||
D3D11_BUFFER_DESC hBufferDesc;
|
||||
hBufferDesc.ByteWidth = _numElements * _numVertices * sizeof(float);
|
||||
hBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
hBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_SHADER_RESOURCE;
|
||||
hBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
hBufferDesc.MiscFlags = 0;
|
||||
hBufferDesc.StructureByteStride = sizeof(float);
|
||||
|
||||
HRESULT hr;
|
||||
hr = device->CreateBuffer(&hBufferDesc, NULL, &_d3d11Buffer);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "Fail in CreateBuffer\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! clCreateFromD3D11Buffer) {
|
||||
resolveInteropFunctions();
|
||||
if (! clCreateFromD3D11Buffer) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// register d3d11buffer as cl memory
|
||||
cl_int err;
|
||||
|
||||
_clMemory = clCreateFromD3D11Buffer(clContext, CL_MEM_READ_WRITE, _d3d11Buffer, &err);
|
||||
|
||||
if (err != CL_SUCCESS) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CLD3D11VertexBuffer::map(cl_command_queue queue) {
|
||||
|
||||
if (_clMapped) return;
|
||||
_clQueue = queue;
|
||||
|
||||
if (! clEnqueueAcquireD3D11Objects) {
|
||||
resolveInteropFunctions();
|
||||
if (! clEnqueueAcquireD3D11Objects) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
clEnqueueAcquireD3D11Objects(queue, 1, &_clMemory, 0, 0, 0);
|
||||
_clMapped = true;
|
||||
}
|
||||
|
||||
void
|
||||
CLD3D11VertexBuffer::unmap() {
|
||||
|
||||
if (! _clMapped) return;
|
||||
if (! clEnqueueReleaseD3D11Objects) {
|
||||
resolveInteropFunctions();
|
||||
if (! clEnqueueReleaseD3D11Objects) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
clEnqueueReleaseD3D11Objects(_clQueue, 1, &_clMemory, 0, 0, 0);
|
||||
_clMapped = false;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
126
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clD3D11VertexBuffer.h
vendored
Normal file
126
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clD3D11VertexBuffer.h
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CL_D3D11_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_CL_D3D11_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../osd/opencl.h"
|
||||
|
||||
struct ID3D11VertexShader;
|
||||
struct ID3D11HullShader;
|
||||
struct ID3D11DomainShader;
|
||||
struct ID3D11GeometryShader;
|
||||
struct ID3D11PixelShader;
|
||||
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11ShaderResourceView;
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief Concrete vertex buffer class for OpenCL subdivision and DirectX
|
||||
/// drawing.
|
||||
///
|
||||
/// D3D11VertexBuffer implements CLVertexBufferInterface and
|
||||
/// D3D11VertexBufferInterface.
|
||||
///
|
||||
/// An instance of this buffer class can be passed to D3D11ComputeEvaluator.
|
||||
///
|
||||
class CLD3D11VertexBuffer {
|
||||
public:
|
||||
/// Creator. Returns NULL if error.
|
||||
static CLD3D11VertexBuffer * Create(int numElements, int numVertices,
|
||||
cl_context clContext,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// template version for custom context (OpenCL) used by OsdMesh
|
||||
template<typename DEVICE_CONTEXT>
|
||||
static CLD3D11VertexBuffer * Create(int numElements, int numVertices,
|
||||
DEVICE_CONTEXT context) {
|
||||
return Create(numElements, numVertices,
|
||||
context->GetContext(),
|
||||
context->GetDeviceContext());
|
||||
}
|
||||
|
||||
|
||||
/// Destructor.
|
||||
virtual ~CLD3D11VertexBuffer();
|
||||
|
||||
/// 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 startVertex, int numVertices,
|
||||
cl_command_queue clQueue);
|
||||
|
||||
/// template version for custom context (OpenCL) used by OsdMesh
|
||||
template<typename DEVICE_CONTEXT>
|
||||
void UpdateData(const float *src, int startVertex, int numVertices,
|
||||
DEVICE_CONTEXT context) {
|
||||
UpdateData(src, startVertex, numVertices, context->GetCommandQueue());
|
||||
}
|
||||
|
||||
/// Returns how many elements defined in this vertex buffer.
|
||||
int GetNumElements() const;
|
||||
|
||||
/// Returns how many vertices allocated in this vertex buffer.
|
||||
int GetNumVertices() const;
|
||||
|
||||
/// Returns the CL memory object.
|
||||
cl_mem BindCLBuffer(cl_command_queue queue);
|
||||
|
||||
/// Returns the D3D11 buffer object.
|
||||
ID3D11Buffer *BindD3D11Buffer(ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Returns the D3D11 buffer object (for Osd::Mesh interface)
|
||||
ID3D11Buffer *BindVBO(ID3D11DeviceContext *deviceContext) {
|
||||
return BindD3D11Buffer(deviceContext);
|
||||
}
|
||||
|
||||
/// template version for custom context (OpenCL) used by OsdMesh
|
||||
template<typename DEVICE_CONTEXT>
|
||||
ID3D11Buffer *BindVBO(DEVICE_CONTEXT context) {
|
||||
return BindD3D11Buffer(context->GetDeviceContext());
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
CLD3D11VertexBuffer(int numElements, int numVertices);
|
||||
|
||||
/// Allocates this buffer and registers as a cl resource.
|
||||
/// Returns true if success.
|
||||
bool allocate(cl_context clContext, ID3D11Device *device);
|
||||
|
||||
/// Acquire a resource from DirectX.
|
||||
void map(cl_command_queue queue);
|
||||
|
||||
/// Releases a resource to DirectX.
|
||||
void unmap();
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
ID3D11Buffer *_d3d11Buffer;
|
||||
cl_command_queue _clQueue;
|
||||
cl_mem _clMemory;
|
||||
|
||||
bool _clMapped;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CL_D3D11_VERTEX_BUFFER_H
|
||||
520
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clEvaluator.cpp
vendored
Normal file
520
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clEvaluator.cpp
vendored
Normal file
@@ -0,0 +1,520 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/clEvaluator.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
|
||||
#include "../osd/opencl.h"
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static const char *clSource =
|
||||
#include "clKernel.gen.h"
|
||||
;
|
||||
static const char *patchBasisTypesSource =
|
||||
#include "patchBasisTypes.gen.h"
|
||||
;
|
||||
static const char *patchBasisSource =
|
||||
#include "patchBasis.gen.h"
|
||||
;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
template <class T> cl_mem
|
||||
createCLBuffer(std::vector<T> const & src, cl_context clContext) {
|
||||
if (src.empty()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cl_int errNum = 0;
|
||||
cl_mem devicePtr = clCreateBuffer(clContext,
|
||||
CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,
|
||||
src.size()*sizeof(T),
|
||||
(void*)(&src.at(0)),
|
||||
&errNum);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clCreateBuffer: %d", errNum);
|
||||
}
|
||||
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CLStencilTable::CLStencilTable(Far::StencilTable const *stencilTable,
|
||||
cl_context clContext) {
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCLBuffer(stencilTable->GetSizes(), clContext);
|
||||
_offsets = createCLBuffer(stencilTable->GetOffsets(), clContext);
|
||||
_indices = createCLBuffer(stencilTable->GetControlIndices(),
|
||||
clContext);
|
||||
_weights = createCLBuffer(stencilTable->GetWeights(), clContext);
|
||||
_duWeights = _dvWeights = NULL;
|
||||
_duuWeights = _duvWeights = _dvvWeights = NULL;
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
_duWeights = _dvWeights = NULL;
|
||||
_duuWeights = _duvWeights = _dvvWeights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CLStencilTable::CLStencilTable(Far::LimitStencilTable const *limitStencilTable,
|
||||
cl_context clContext) {
|
||||
_numStencils = limitStencilTable->GetNumStencils();
|
||||
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCLBuffer(limitStencilTable->GetSizes(), clContext);
|
||||
_offsets = createCLBuffer(limitStencilTable->GetOffsets(), clContext);
|
||||
_indices = createCLBuffer(limitStencilTable->GetControlIndices(),
|
||||
clContext);
|
||||
_weights = createCLBuffer(limitStencilTable->GetWeights(), clContext);
|
||||
_duWeights = createCLBuffer(
|
||||
limitStencilTable->GetDuWeights(), clContext);
|
||||
_dvWeights = createCLBuffer(
|
||||
limitStencilTable->GetDvWeights(), clContext);
|
||||
_duuWeights = createCLBuffer(
|
||||
limitStencilTable->GetDuuWeights(), clContext);
|
||||
_duvWeights = createCLBuffer(
|
||||
limitStencilTable->GetDuvWeights(), clContext);
|
||||
_dvvWeights = createCLBuffer(
|
||||
limitStencilTable->GetDvvWeights(), clContext);
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
_duWeights = _dvWeights = NULL;
|
||||
_duuWeights = _duvWeights = _dvvWeights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CLStencilTable::~CLStencilTable() {
|
||||
if (_sizes) clReleaseMemObject(_sizes);
|
||||
if (_offsets) clReleaseMemObject(_offsets);
|
||||
if (_indices) clReleaseMemObject(_indices);
|
||||
if (_weights) clReleaseMemObject(_weights);
|
||||
if (_duWeights) clReleaseMemObject(_duWeights);
|
||||
if (_dvWeights) clReleaseMemObject(_dvWeights);
|
||||
if (_duuWeights) clReleaseMemObject(_duuWeights);
|
||||
if (_duvWeights) clReleaseMemObject(_duvWeights);
|
||||
if (_dvvWeights) clReleaseMemObject(_dvvWeights);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
CLEvaluator::CLEvaluator(cl_context context, cl_command_queue queue)
|
||||
: _clContext(context), _clCommandQueue(queue),
|
||||
_program(NULL), _stencilKernel(NULL), _stencilDerivKernel(NULL),
|
||||
_patchKernel(NULL) {
|
||||
}
|
||||
|
||||
CLEvaluator::~CLEvaluator() {
|
||||
if (_stencilKernel) clReleaseKernel(_stencilKernel);
|
||||
if (_stencilDerivKernel) clReleaseKernel(_stencilDerivKernel);
|
||||
if (_patchKernel) clReleaseKernel(_patchKernel);
|
||||
if (_program) clReleaseProgram(_program);
|
||||
}
|
||||
|
||||
bool
|
||||
CLEvaluator::Compile(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const & /*duDesc*/,
|
||||
BufferDescriptor const & /*dvDesc*/,
|
||||
BufferDescriptor const & /*duuDesc*/,
|
||||
BufferDescriptor const & /*duvDesc*/,
|
||||
BufferDescriptor const & /*dvvDesc*/) {
|
||||
if (srcDesc.length > dstDesc.length) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"srcDesc length must be less than or equal to "
|
||||
"dstDesc length.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
cl_int errNum;
|
||||
|
||||
std::ostringstream defines;
|
||||
defines << "#define LENGTH " << srcDesc.length << "\n"
|
||||
<< "#define SRC_STRIDE " << srcDesc.stride << "\n"
|
||||
<< "#define DST_STRIDE " << dstDesc.stride << "\n"
|
||||
<< "#define OSD_PATCH_BASIS_OPENCL\n";
|
||||
std::string defineStr = defines.str();
|
||||
|
||||
const char *sources[] = { defineStr.c_str(),
|
||||
patchBasisTypesSource,
|
||||
patchBasisSource,
|
||||
clSource };
|
||||
_program = clCreateProgramWithSource(_clContext, 4, sources, 0, &errNum);
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"clCreateProgramWithSource (%d)", errNum);
|
||||
}
|
||||
|
||||
errNum = clBuildProgram(_program, 0, NULL, NULL, NULL, NULL);
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clBuildProgram (%d) \n", errNum);
|
||||
|
||||
cl_int numDevices = 0;
|
||||
clGetContextInfo(
|
||||
_clContext, CL_CONTEXT_NUM_DEVICES,
|
||||
sizeof(cl_uint), &numDevices, NULL);
|
||||
|
||||
cl_device_id *devices = new cl_device_id[numDevices];
|
||||
clGetContextInfo(_clContext, CL_CONTEXT_DEVICES,
|
||||
sizeof(cl_device_id)*numDevices, devices, NULL);
|
||||
|
||||
for (int i = 0; i < numDevices; ++i) {
|
||||
char cBuildLog[10240];
|
||||
clGetProgramBuildInfo(
|
||||
_program, devices[i],
|
||||
CL_PROGRAM_BUILD_LOG, sizeof(cBuildLog), cBuildLog, NULL);
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, cBuildLog);
|
||||
}
|
||||
delete[] devices;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_stencilKernel = clCreateKernel(_program, "computeStencils", &errNum);
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "buildKernel (%d)\n", errNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
_stencilDerivKernel = clCreateKernel(_program,
|
||||
"computeStencilsDerivatives", &errNum);
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "buildKernel (%d)\n", errNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
_patchKernel = clCreateKernel(_program, "computePatches", &errNum);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "buildKernel (%d)\n", errNum);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CLEvaluator::EvalStencils(cl_mem src, BufferDescriptor const &srcDesc,
|
||||
cl_mem dst, BufferDescriptor const &dstDesc,
|
||||
cl_mem sizes,
|
||||
cl_mem offsets,
|
||||
cl_mem indices,
|
||||
cl_mem weights,
|
||||
int start, int end,
|
||||
unsigned int numStartEvents,
|
||||
const cl_event* startEvents,
|
||||
cl_event* endEvent) const {
|
||||
if (end <= start) return true;
|
||||
|
||||
size_t globalWorkSize = (size_t)(end - start);
|
||||
|
||||
clSetKernelArg(_stencilKernel, 0, sizeof(cl_mem), &src);
|
||||
clSetKernelArg(_stencilKernel, 1, sizeof(int), &srcDesc.offset);
|
||||
clSetKernelArg(_stencilKernel, 2, sizeof(cl_mem), &dst);
|
||||
clSetKernelArg(_stencilKernel, 3, sizeof(int), &dstDesc.offset);
|
||||
clSetKernelArg(_stencilKernel, 4, sizeof(cl_mem), &sizes);
|
||||
clSetKernelArg(_stencilKernel, 5, sizeof(cl_mem), &offsets);
|
||||
clSetKernelArg(_stencilKernel, 6, sizeof(cl_mem), &indices);
|
||||
clSetKernelArg(_stencilKernel, 7, sizeof(cl_mem), &weights);
|
||||
clSetKernelArg(_stencilKernel, 8, sizeof(int), &start);
|
||||
clSetKernelArg(_stencilKernel, 9, sizeof(int), &end);
|
||||
|
||||
cl_int errNum = clEnqueueNDRangeKernel(
|
||||
_clCommandQueue, _stencilKernel, 1, NULL,
|
||||
&globalWorkSize, NULL, numStartEvents, startEvents, endEvent);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"ApplyStencilKernel (%d) ", errNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (endEvent == NULL)
|
||||
{
|
||||
clFinish(_clCommandQueue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CLEvaluator::EvalStencils(cl_mem src, BufferDescriptor const &srcDesc,
|
||||
cl_mem dst, BufferDescriptor const &dstDesc,
|
||||
cl_mem du, BufferDescriptor const &duDesc,
|
||||
cl_mem dv, BufferDescriptor const &dvDesc,
|
||||
cl_mem sizes,
|
||||
cl_mem offsets,
|
||||
cl_mem indices,
|
||||
cl_mem weights,
|
||||
cl_mem duWeights,
|
||||
cl_mem dvWeights,
|
||||
int start, int end,
|
||||
unsigned int numStartEvents,
|
||||
const cl_event* startEvents,
|
||||
cl_event* endEvent) const {
|
||||
if (end <= start) return true;
|
||||
|
||||
size_t globalWorkSize = (size_t)(end - start);
|
||||
|
||||
BufferDescriptor empty;
|
||||
clSetKernelArg(_stencilDerivKernel, 0, sizeof(cl_mem), &src);
|
||||
clSetKernelArg(_stencilDerivKernel, 1, sizeof(int), &srcDesc.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 2, sizeof(cl_mem), &dst);
|
||||
clSetKernelArg(_stencilDerivKernel, 3, sizeof(int), &dstDesc.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 4, sizeof(cl_mem), &du);
|
||||
clSetKernelArg(_stencilDerivKernel, 5, sizeof(int), &duDesc.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 6, sizeof(int), &duDesc.stride);
|
||||
clSetKernelArg(_stencilDerivKernel, 7, sizeof(cl_mem), &dv);
|
||||
clSetKernelArg(_stencilDerivKernel, 8, sizeof(int), &dvDesc.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 9, sizeof(int), &dvDesc.stride);
|
||||
clSetKernelArg(_stencilDerivKernel, 10, sizeof(cl_mem), NULL);
|
||||
clSetKernelArg(_stencilDerivKernel, 11, sizeof(int), &empty.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 12, sizeof(int), &empty.stride);
|
||||
clSetKernelArg(_stencilDerivKernel, 13, sizeof(cl_mem), NULL);
|
||||
clSetKernelArg(_stencilDerivKernel, 14, sizeof(int), &empty.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 15, sizeof(int), &empty.stride);
|
||||
clSetKernelArg(_stencilDerivKernel, 16, sizeof(cl_mem), NULL);
|
||||
clSetKernelArg(_stencilDerivKernel, 17, sizeof(int), &empty.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 18, sizeof(int), &empty.stride);
|
||||
clSetKernelArg(_stencilDerivKernel, 19, sizeof(cl_mem), &sizes);
|
||||
clSetKernelArg(_stencilDerivKernel, 20, sizeof(cl_mem), &offsets);
|
||||
clSetKernelArg(_stencilDerivKernel, 21, sizeof(cl_mem), &indices);
|
||||
clSetKernelArg(_stencilDerivKernel, 22, sizeof(cl_mem), &weights);
|
||||
clSetKernelArg(_stencilDerivKernel, 23, sizeof(cl_mem), &duWeights);
|
||||
clSetKernelArg(_stencilDerivKernel, 24, sizeof(cl_mem), &dvWeights);
|
||||
clSetKernelArg(_stencilDerivKernel, 25, sizeof(cl_mem), NULL);
|
||||
clSetKernelArg(_stencilDerivKernel, 26, sizeof(cl_mem), NULL);
|
||||
clSetKernelArg(_stencilDerivKernel, 27, sizeof(cl_mem), NULL);
|
||||
clSetKernelArg(_stencilDerivKernel, 28, sizeof(int), &start);
|
||||
clSetKernelArg(_stencilDerivKernel, 29, sizeof(int), &end);
|
||||
|
||||
cl_int errNum = clEnqueueNDRangeKernel(
|
||||
_clCommandQueue, _stencilDerivKernel, 1, NULL,
|
||||
&globalWorkSize, NULL, numStartEvents, startEvents, endEvent);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"ApplyStencilKernel (%d) ", errNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (endEvent == NULL) {
|
||||
clFinish(_clCommandQueue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CLEvaluator::EvalStencils(cl_mem src, BufferDescriptor const &srcDesc,
|
||||
cl_mem dst, BufferDescriptor const &dstDesc,
|
||||
cl_mem du, BufferDescriptor const &duDesc,
|
||||
cl_mem dv, BufferDescriptor const &dvDesc,
|
||||
cl_mem duu, BufferDescriptor const &duuDesc,
|
||||
cl_mem duv, BufferDescriptor const &duvDesc,
|
||||
cl_mem dvv, BufferDescriptor const &dvvDesc,
|
||||
cl_mem sizes,
|
||||
cl_mem offsets,
|
||||
cl_mem indices,
|
||||
cl_mem weights,
|
||||
cl_mem duWeights,
|
||||
cl_mem dvWeights,
|
||||
cl_mem duuWeights,
|
||||
cl_mem duvWeights,
|
||||
cl_mem dvvWeights,
|
||||
int start, int end,
|
||||
unsigned int numStartEvents,
|
||||
const cl_event* startEvents,
|
||||
cl_event* endEvent) const {
|
||||
if (end <= start) return true;
|
||||
|
||||
size_t globalWorkSize = (size_t)(end - start);
|
||||
|
||||
clSetKernelArg(_stencilDerivKernel, 0, sizeof(cl_mem), &src);
|
||||
clSetKernelArg(_stencilDerivKernel, 1, sizeof(int), &srcDesc.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 2, sizeof(cl_mem), &dst);
|
||||
clSetKernelArg(_stencilDerivKernel, 3, sizeof(int), &dstDesc.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 4, sizeof(cl_mem), &du);
|
||||
clSetKernelArg(_stencilDerivKernel, 5, sizeof(int), &duDesc.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 6, sizeof(int), &duDesc.stride);
|
||||
clSetKernelArg(_stencilDerivKernel, 7, sizeof(cl_mem), &dv);
|
||||
clSetKernelArg(_stencilDerivKernel, 8, sizeof(int), &dvDesc.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 9, sizeof(int), &dvDesc.stride);
|
||||
clSetKernelArg(_stencilDerivKernel, 10, sizeof(cl_mem), &duu);
|
||||
clSetKernelArg(_stencilDerivKernel, 11, sizeof(int), &duuDesc.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 12, sizeof(int), &duuDesc.stride);
|
||||
clSetKernelArg(_stencilDerivKernel, 13, sizeof(cl_mem), &duv);
|
||||
clSetKernelArg(_stencilDerivKernel, 14, sizeof(int), &duvDesc.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 15, sizeof(int), &duvDesc.stride);
|
||||
clSetKernelArg(_stencilDerivKernel, 16, sizeof(cl_mem), &dvv);
|
||||
clSetKernelArg(_stencilDerivKernel, 17, sizeof(int), &dvvDesc.offset);
|
||||
clSetKernelArg(_stencilDerivKernel, 18, sizeof(int), &dvvDesc.stride);
|
||||
clSetKernelArg(_stencilDerivKernel, 19, sizeof(cl_mem), &sizes);
|
||||
clSetKernelArg(_stencilDerivKernel, 20, sizeof(cl_mem), &offsets);
|
||||
clSetKernelArg(_stencilDerivKernel, 21, sizeof(cl_mem), &indices);
|
||||
clSetKernelArg(_stencilDerivKernel, 22, sizeof(cl_mem), &weights);
|
||||
clSetKernelArg(_stencilDerivKernel, 23, sizeof(cl_mem), &duWeights);
|
||||
clSetKernelArg(_stencilDerivKernel, 24, sizeof(cl_mem), &dvWeights);
|
||||
clSetKernelArg(_stencilDerivKernel, 25, sizeof(cl_mem), &duuWeights);
|
||||
clSetKernelArg(_stencilDerivKernel, 26, sizeof(cl_mem), &duvWeights);
|
||||
clSetKernelArg(_stencilDerivKernel, 27, sizeof(cl_mem), &dvvWeights);
|
||||
clSetKernelArg(_stencilDerivKernel, 28, sizeof(int), &start);
|
||||
clSetKernelArg(_stencilDerivKernel, 29, sizeof(int), &end);
|
||||
|
||||
cl_int errNum = clEnqueueNDRangeKernel(
|
||||
_clCommandQueue, _stencilDerivKernel, 1, NULL,
|
||||
&globalWorkSize, NULL, numStartEvents, startEvents, endEvent);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"ApplyStencilKernel (%d) ", errNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (endEvent == NULL) {
|
||||
clFinish(_clCommandQueue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CLEvaluator::EvalPatches(cl_mem src, BufferDescriptor const &srcDesc,
|
||||
cl_mem dst, BufferDescriptor const &dstDesc,
|
||||
cl_mem du, BufferDescriptor const &duDesc,
|
||||
cl_mem dv, BufferDescriptor const &dvDesc,
|
||||
int numPatchCoords,
|
||||
cl_mem patchCoordsBuffer,
|
||||
cl_mem patchArrayBuffer,
|
||||
cl_mem patchIndexBuffer,
|
||||
cl_mem patchParamBuffer,
|
||||
unsigned int numStartEvents,
|
||||
const cl_event* startEvents,
|
||||
cl_event* endEvent) const {
|
||||
|
||||
size_t globalWorkSize = (size_t)(numPatchCoords);
|
||||
|
||||
BufferDescriptor empty;
|
||||
clSetKernelArg(_patchKernel, 0, sizeof(cl_mem), &src);
|
||||
clSetKernelArg(_patchKernel, 1, sizeof(int), &srcDesc.offset);
|
||||
clSetKernelArg(_patchKernel, 2, sizeof(cl_mem), &dst);
|
||||
clSetKernelArg(_patchKernel, 3, sizeof(int), &dstDesc.offset);
|
||||
clSetKernelArg(_patchKernel, 4, sizeof(cl_mem), &du);
|
||||
clSetKernelArg(_patchKernel, 5, sizeof(int), &duDesc.offset);
|
||||
clSetKernelArg(_patchKernel, 6, sizeof(int), &duDesc.stride);
|
||||
clSetKernelArg(_patchKernel, 7, sizeof(cl_mem), &dv);
|
||||
clSetKernelArg(_patchKernel, 8, sizeof(int), &dvDesc.offset);
|
||||
clSetKernelArg(_patchKernel, 9, sizeof(int), &dvDesc.stride);
|
||||
clSetKernelArg(_patchKernel, 10, sizeof(cl_mem), NULL);
|
||||
clSetKernelArg(_patchKernel, 11, sizeof(int), &empty.offset);
|
||||
clSetKernelArg(_patchKernel, 12, sizeof(int), &empty.stride);
|
||||
clSetKernelArg(_patchKernel, 13, sizeof(cl_mem), NULL);
|
||||
clSetKernelArg(_patchKernel, 14, sizeof(int), &empty.offset);
|
||||
clSetKernelArg(_patchKernel, 15, sizeof(int), &empty.stride);
|
||||
clSetKernelArg(_patchKernel, 16, sizeof(cl_mem), NULL);
|
||||
clSetKernelArg(_patchKernel, 17, sizeof(int), &empty.offset);
|
||||
clSetKernelArg(_patchKernel, 18, sizeof(int), &empty.stride);
|
||||
clSetKernelArg(_patchKernel, 19, sizeof(cl_mem), &patchCoordsBuffer);
|
||||
clSetKernelArg(_patchKernel, 20, sizeof(cl_mem), &patchArrayBuffer);
|
||||
clSetKernelArg(_patchKernel, 21, sizeof(cl_mem), &patchIndexBuffer);
|
||||
clSetKernelArg(_patchKernel, 22, sizeof(cl_mem), &patchParamBuffer);
|
||||
|
||||
cl_int errNum = clEnqueueNDRangeKernel(
|
||||
_clCommandQueue, _patchKernel, 1, NULL,
|
||||
&globalWorkSize, NULL, numStartEvents, startEvents, endEvent);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"ApplyPatchKernel (%d) ", errNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (endEvent == NULL) {
|
||||
clFinish(_clCommandQueue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CLEvaluator::EvalPatches(cl_mem src, BufferDescriptor const &srcDesc,
|
||||
cl_mem dst, BufferDescriptor const &dstDesc,
|
||||
cl_mem du, BufferDescriptor const &duDesc,
|
||||
cl_mem dv, BufferDescriptor const &dvDesc,
|
||||
cl_mem duu, BufferDescriptor const &duuDesc,
|
||||
cl_mem duv, BufferDescriptor const &duvDesc,
|
||||
cl_mem dvv, BufferDescriptor const &dvvDesc,
|
||||
int numPatchCoords,
|
||||
cl_mem patchCoordsBuffer,
|
||||
cl_mem patchArrayBuffer,
|
||||
cl_mem patchIndexBuffer,
|
||||
cl_mem patchParamBuffer,
|
||||
unsigned int numStartEvents,
|
||||
const cl_event* startEvents,
|
||||
cl_event* endEvent) const {
|
||||
|
||||
size_t globalWorkSize = (size_t)(numPatchCoords);
|
||||
|
||||
clSetKernelArg(_patchKernel, 0, sizeof(cl_mem), &src);
|
||||
clSetKernelArg(_patchKernel, 1, sizeof(int), &srcDesc.offset);
|
||||
clSetKernelArg(_patchKernel, 2, sizeof(cl_mem), &dst);
|
||||
clSetKernelArg(_patchKernel, 3, sizeof(int), &dstDesc.offset);
|
||||
clSetKernelArg(_patchKernel, 4, sizeof(cl_mem), &du);
|
||||
clSetKernelArg(_patchKernel, 5, sizeof(int), &duDesc.offset);
|
||||
clSetKernelArg(_patchKernel, 6, sizeof(int), &duDesc.stride);
|
||||
clSetKernelArg(_patchKernel, 7, sizeof(cl_mem), &dv);
|
||||
clSetKernelArg(_patchKernel, 8, sizeof(int), &dvDesc.offset);
|
||||
clSetKernelArg(_patchKernel, 9, sizeof(int), &dvDesc.stride);
|
||||
clSetKernelArg(_patchKernel, 10, sizeof(cl_mem), &duu);
|
||||
clSetKernelArg(_patchKernel, 11, sizeof(int), &duuDesc.offset);
|
||||
clSetKernelArg(_patchKernel, 12, sizeof(int), &duuDesc.stride);
|
||||
clSetKernelArg(_patchKernel, 13, sizeof(cl_mem), &duv);
|
||||
clSetKernelArg(_patchKernel, 14, sizeof(int), &duvDesc.offset);
|
||||
clSetKernelArg(_patchKernel, 15, sizeof(int), &duvDesc.stride);
|
||||
clSetKernelArg(_patchKernel, 16, sizeof(cl_mem), &dvv);
|
||||
clSetKernelArg(_patchKernel, 17, sizeof(int), &dvvDesc.offset);
|
||||
clSetKernelArg(_patchKernel, 18, sizeof(int), &dvvDesc.stride);
|
||||
clSetKernelArg(_patchKernel, 19, sizeof(cl_mem), &patchCoordsBuffer);
|
||||
clSetKernelArg(_patchKernel, 20, sizeof(cl_mem), &patchArrayBuffer);
|
||||
clSetKernelArg(_patchKernel, 21, sizeof(cl_mem), &patchIndexBuffer);
|
||||
clSetKernelArg(_patchKernel, 22, sizeof(cl_mem), &patchParamBuffer);
|
||||
|
||||
cl_int errNum = clEnqueueNDRangeKernel(
|
||||
_clCommandQueue, _patchKernel, 1, NULL,
|
||||
&globalWorkSize, NULL, numStartEvents, startEvents, endEvent);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"ApplyPatchKernel (%d) ", errNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (endEvent == NULL) {
|
||||
clFinish(_clCommandQueue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* static */
|
||||
void
|
||||
CLEvaluator::Synchronize(cl_command_queue clCommandQueue) {
|
||||
clFinish(clCommandQueue);
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
2619
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clEvaluator.h
vendored
Normal file
2619
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clEvaluator.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
135
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clGLVertexBuffer.cpp
vendored
Normal file
135
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clGLVertexBuffer.cpp
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "glLoader.h"
|
||||
|
||||
#include "../osd/clGLVertexBuffer.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CLGLVertexBuffer::CLGLVertexBuffer(int numElements,
|
||||
int numVertices,
|
||||
cl_context /* clContext */)
|
||||
: _numElements(numElements), _numVertices(numVertices),
|
||||
_vbo(0), _clQueue(0), _clMemory(0), _clMapped(false) {
|
||||
|
||||
// Initialize internal OpenGL loader library if necessary
|
||||
OpenSubdiv::internal::GLLoader::libraryInitializeGL();
|
||||
}
|
||||
|
||||
CLGLVertexBuffer::~CLGLVertexBuffer() {
|
||||
|
||||
unmap();
|
||||
clReleaseMemObject(_clMemory);
|
||||
glDeleteBuffers(1, &_vbo);
|
||||
}
|
||||
|
||||
CLGLVertexBuffer *
|
||||
CLGLVertexBuffer::Create(int numElements, int numVertices, cl_context clContext)
|
||||
{
|
||||
CLGLVertexBuffer *instance =
|
||||
new CLGLVertexBuffer(numElements, numVertices, clContext);
|
||||
if (instance->allocate(clContext)) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
CLGLVertexBuffer::UpdateData(const float *src, int startVertex, int numVertices,
|
||||
cl_command_queue queue) {
|
||||
|
||||
size_t size = numVertices * _numElements * sizeof(float);
|
||||
size_t offset = startVertex * _numElements * sizeof(float);
|
||||
|
||||
map(queue);
|
||||
clEnqueueWriteBuffer(queue, _clMemory, true, offset, size, src, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
CLGLVertexBuffer::GetNumElements() const {
|
||||
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int
|
||||
CLGLVertexBuffer::GetNumVertices() const {
|
||||
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLGLVertexBuffer::BindCLBuffer(cl_command_queue queue) {
|
||||
|
||||
map(queue);
|
||||
return _clMemory;
|
||||
}
|
||||
|
||||
CLGLVertexBuffer::ID
|
||||
CLGLVertexBuffer::BindVBO(void * /*deviceContext*/) {
|
||||
|
||||
unmap();
|
||||
return _vbo;
|
||||
}
|
||||
|
||||
bool
|
||||
CLGLVertexBuffer::allocate(cl_context clContext) {
|
||||
|
||||
assert(clContext);
|
||||
|
||||
// create GL buffer first
|
||||
int size = _numElements * _numVertices * sizeof(float);
|
||||
|
||||
#if defined(GL_ARB_direct_state_access)
|
||||
if (OSD_OPENGL_HAS(ARB_direct_state_access)) {
|
||||
glCreateBuffers(1, &_vbo);
|
||||
glNamedBufferData(_vbo, size, 0, GL_DYNAMIC_DRAW);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLint prev = 0;
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev);
|
||||
glGenBuffers(1, &_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, prev);
|
||||
}
|
||||
|
||||
// register vbo as cl memory
|
||||
cl_int err;
|
||||
_clMemory = clCreateFromGLBuffer(clContext,
|
||||
CL_MEM_READ_WRITE, _vbo, &err);
|
||||
|
||||
if (err != CL_SUCCESS) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CLGLVertexBuffer::map(cl_command_queue queue) {
|
||||
|
||||
if (_clMapped) return; // XXX: what if another queue is given?
|
||||
_clQueue = queue;
|
||||
clEnqueueAcquireGLObjects(queue, 1, &_clMemory, 0, 0, 0);
|
||||
_clMapped = true;
|
||||
}
|
||||
|
||||
void
|
||||
CLGLVertexBuffer::unmap() {
|
||||
|
||||
if (! _clMapped) return;
|
||||
clEnqueueReleaseGLObjects(_clQueue, 1, &_clMemory, 0, 0, 0);
|
||||
_clMapped = false;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
103
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clGLVertexBuffer.h
vendored
Normal file
103
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clGLVertexBuffer.h
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CL_GL_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_CL_GL_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/opencl.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief Concrete vertex buffer class for OpenCL subdivision and OpenGL drawing.
|
||||
///
|
||||
/// CLGLVertexBuffer implements CLVertexBufferInterface and
|
||||
/// GLVertexBufferInterface.
|
||||
///
|
||||
/// The buffer interop between OpenCL and GL is handled automatically when a
|
||||
/// client calls BindCLBuffer and BindVBO methods.
|
||||
///
|
||||
class CLGLVertexBuffer {
|
||||
public:
|
||||
using ID = unsigned int; // GLuint resource ID
|
||||
|
||||
/// Creator. Returns NULL if error.
|
||||
static CLGLVertexBuffer * Create(int numElements,
|
||||
int numVertices,
|
||||
cl_context clContext);
|
||||
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static CLGLVertexBuffer * Create(int numElements, int numVertices,
|
||||
DEVICE_CONTEXT context) {
|
||||
return Create(numElements, numVertices, context->GetContext());
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
~CLGLVertexBuffer();
|
||||
|
||||
/// 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 startVertex, int numVertices,
|
||||
cl_command_queue clQueue);
|
||||
|
||||
template<typename DEVICE_CONTEXT>
|
||||
void UpdateData(const float *src, int startVertex, int numVertices,
|
||||
DEVICE_CONTEXT context) {
|
||||
UpdateData(src, startVertex, numVertices, context->GetCommandQueue());
|
||||
}
|
||||
|
||||
/// Returns how many elements defined in this vertex buffer.
|
||||
int GetNumElements() const;
|
||||
|
||||
/// Returns how many vertices allocated in this vertex buffer.
|
||||
int GetNumVertices() const;
|
||||
|
||||
/// Returns the CL memory object. GL buffer will be mapped to CL memory
|
||||
/// space if necessary.
|
||||
cl_mem BindCLBuffer(cl_command_queue queue);
|
||||
|
||||
/// Returns the GL buffer object. If the buffer is mapped to CL memory
|
||||
/// space, it will be unmapped back to GL.
|
||||
ID BindVBO(void *deviceContext = NULL);
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
CLGLVertexBuffer(int numElements, int numVertices, cl_context clContext);
|
||||
|
||||
/// Allocates VBO for this buffer and register as a CL resource.
|
||||
/// Returns true if success.
|
||||
bool allocate(cl_context clContext);
|
||||
|
||||
/// Acquires a resource from GL.
|
||||
void map(cl_command_queue queue);
|
||||
|
||||
/// Releases a resource to GL.
|
||||
void unmap();
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
ID _vbo;
|
||||
cl_command_queue _clQueue;
|
||||
cl_mem _clMemory;
|
||||
|
||||
bool _clMapped;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CL_GL_VERTEX_BUFFER_H
|
||||
232
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clKernel.cl
vendored
Normal file
232
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clKernel.cl
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
struct Vertex {
|
||||
float v[LENGTH];
|
||||
};
|
||||
|
||||
static void clear(struct Vertex *vertex) {
|
||||
for (int i = 0; i < LENGTH; i++) {
|
||||
vertex->v[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
static void addWithWeight(struct Vertex *dst,
|
||||
__global float *srcOrigin,
|
||||
int index, float weight) {
|
||||
|
||||
__global float *src = srcOrigin + index * SRC_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dst->v[i] += src[i] * weight;
|
||||
}
|
||||
}
|
||||
|
||||
static void writeVertex(__global float *dstOrigin,
|
||||
int index,
|
||||
struct Vertex *src) {
|
||||
|
||||
__global float *dst = dstOrigin + index * DST_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dst[i] = src->v[i];
|
||||
}
|
||||
}
|
||||
static void writeVertexStride(__global float *dstOrigin,
|
||||
int index,
|
||||
struct Vertex *src,
|
||||
int stride) {
|
||||
|
||||
__global float *dst = dstOrigin + index * stride;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dst[i] = src->v[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__kernel void computeStencils(
|
||||
__global float * src, int srcOffset,
|
||||
__global float * dst, int dstOffset,
|
||||
__global int * sizes,
|
||||
__global int * offsets,
|
||||
__global int * indices,
|
||||
__global float * weights,
|
||||
int batchStart, int batchEnd) {
|
||||
|
||||
int current = get_global_id(0) + batchStart;
|
||||
|
||||
if (current>=batchEnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct Vertex v;
|
||||
clear(&v);
|
||||
|
||||
int size = sizes[current],
|
||||
offset = offsets[current];
|
||||
|
||||
src += srcOffset;
|
||||
dst += dstOffset;
|
||||
|
||||
for (int i=0; i<size; ++i) {
|
||||
addWithWeight(&v, src, indices[offset+i], weights[offset+i]);
|
||||
}
|
||||
|
||||
writeVertex(dst, current, &v);
|
||||
}
|
||||
|
||||
__kernel void computeStencilsDerivatives(
|
||||
__global float * src, int srcOffset,
|
||||
__global float * dst, int dstOffset,
|
||||
__global float * du, int duOffset, int duStride,
|
||||
__global float * dv, int dvOffset, int dvStride,
|
||||
__global float * duu, int duuOffset, int duuStride,
|
||||
__global float * duv, int duvOffset, int duvStride,
|
||||
__global float * dvv, int dvvOffset, int dvvStride,
|
||||
__global int * sizes,
|
||||
__global int * offsets,
|
||||
__global int * indices,
|
||||
__global float * weights,
|
||||
__global float * duWeights,
|
||||
__global float * dvWeights,
|
||||
__global float * duuWeights,
|
||||
__global float * duvWeights,
|
||||
__global float * dvvWeights,
|
||||
int batchStart, int batchEnd) {
|
||||
|
||||
int current = get_global_id(0) + batchStart;
|
||||
|
||||
if (current>=batchEnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct Vertex v, vdu, vdv, vduu, vduv, vdvv;
|
||||
clear(&v);
|
||||
clear(&vdu);
|
||||
clear(&vdv);
|
||||
clear(&vduu);
|
||||
clear(&vduv);
|
||||
clear(&vdvv);
|
||||
|
||||
int size = sizes[current],
|
||||
offset = offsets[current];
|
||||
|
||||
if (src) src += srcOffset;
|
||||
if (dst) dst += dstOffset;
|
||||
if (du) du += duOffset;
|
||||
if (dv) dv += dvOffset;
|
||||
if (duu) duu += duuOffset;
|
||||
if (duv) duv += duvOffset;
|
||||
if (dvv) dvv += dvvOffset;
|
||||
|
||||
for (int i=0; i<size; ++i) {
|
||||
int ofs = offset + i;
|
||||
int vid = indices[ofs];
|
||||
if (weights) addWithWeight( &v, src, vid, weights[ofs]);
|
||||
if (duWeights) addWithWeight(&vdu, src, vid, duWeights[ofs]);
|
||||
if (dvWeights) addWithWeight(&vdv, src, vid, dvWeights[ofs]);
|
||||
if (duuWeights) addWithWeight(&vduu, src, vid, duuWeights[ofs]);
|
||||
if (duvWeights) addWithWeight(&vduv, src, vid, duvWeights[ofs]);
|
||||
if (dvvWeights) addWithWeight(&vdvv, src, vid, dvvWeights[ofs]);
|
||||
}
|
||||
|
||||
if (dst) writeVertex (dst, current, &v);
|
||||
if (du) writeVertexStride(du, current, &vdu, duStride);
|
||||
if (dv) writeVertexStride(dv, current, &vdv, dvStride);
|
||||
if (duu) writeVertexStride(duu, current, &vduu, duuStride);
|
||||
if (duv) writeVertexStride(duv, current, &vduv, duvStride);
|
||||
if (dvv) writeVertexStride(dvv, current, &vdvv, dvvStride);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
__kernel void computePatches(__global float *src, int srcOffset,
|
||||
__global float *dst, int dstOffset,
|
||||
__global float *du, int duOffset, int duStride,
|
||||
__global float *dv, int dvOffset, int dvStride,
|
||||
__global float *duu, int duuOffset, int duuStride,
|
||||
__global float *duv, int duvOffset, int duvStride,
|
||||
__global float *dvv, int dvvOffset, int dvvStride,
|
||||
__global struct OsdPatchCoord *patchCoords,
|
||||
__global struct OsdPatchArray *patchArrayBuffer,
|
||||
__global int *patchIndexBuffer,
|
||||
__global struct OsdPatchParam *patchParamBuffer) {
|
||||
int current = get_global_id(0);
|
||||
|
||||
if (src) src += srcOffset;
|
||||
if (dst) dst += dstOffset;
|
||||
if (du) du += duOffset;
|
||||
if (dv) dv += dvOffset;
|
||||
if (duu) duu += duuOffset;
|
||||
if (duv) duv += duvOffset;
|
||||
if (dvv) dvv += dvvOffset;
|
||||
|
||||
struct OsdPatchCoord coord = patchCoords[current];
|
||||
struct OsdPatchArray array = patchArrayBuffer[coord.arrayIndex];
|
||||
struct OsdPatchParam param = patchParamBuffer[coord.patchIndex];
|
||||
|
||||
int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
|
||||
|
||||
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
|
||||
int nPoints = OsdEvaluatePatchBasis(patchType, param,
|
||||
coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
|
||||
|
||||
int indexBase = array.indexBase + array.stride *
|
||||
(coord.patchIndex - array.primitiveIdBase);
|
||||
|
||||
struct Vertex v;
|
||||
clear(&v);
|
||||
for (int i = 0; i < nPoints; ++i) {
|
||||
int index = patchIndexBuffer[indexBase + i];
|
||||
addWithWeight(&v, src, index, wP[i]);
|
||||
}
|
||||
writeVertex(dst, current, &v);
|
||||
|
||||
if (du) {
|
||||
struct Vertex vdu;
|
||||
clear(&vdu);
|
||||
for (int i = 0; i < nPoints; ++i) {
|
||||
int index = patchIndexBuffer[indexBase + i];
|
||||
addWithWeight(&vdu, src, index, wDu[i]);
|
||||
}
|
||||
writeVertexStride(du, current, &vdu, duStride);
|
||||
}
|
||||
if (dv) {
|
||||
struct Vertex vdv;
|
||||
clear(&vdv);
|
||||
for (int i = 0; i < nPoints; ++i) {
|
||||
int index = patchIndexBuffer[indexBase + i];
|
||||
addWithWeight(&vdv, src, index, wDv[i]);
|
||||
}
|
||||
writeVertexStride(dv, current, &vdv, dvStride);
|
||||
}
|
||||
if (duu) {
|
||||
struct Vertex vduu;
|
||||
clear(&vduu);
|
||||
for (int i = 0; i < nPoints; ++i) {
|
||||
int index = patchIndexBuffer[indexBase + i];
|
||||
addWithWeight(&vduu, src, index, wDuu[i]);
|
||||
}
|
||||
writeVertexStride(duu, current, &vduu, duuStride);
|
||||
}
|
||||
if (duv) {
|
||||
struct Vertex vduv;
|
||||
clear(&vduv);
|
||||
for (int i = 0; i < nPoints; ++i) {
|
||||
int index = patchIndexBuffer[indexBase + i];
|
||||
addWithWeight(&vduv, src, index, wDuv[i]);
|
||||
}
|
||||
writeVertexStride(duv, current, &vduv, duvStride);
|
||||
}
|
||||
if (dvv) {
|
||||
struct Vertex vdvv;
|
||||
clear(&vdvv);
|
||||
for (int i = 0; i < nPoints; ++i) {
|
||||
int index = patchIndexBuffer[indexBase + i];
|
||||
addWithWeight(&vdvv, src, index, wDvv[i]);
|
||||
}
|
||||
writeVertexStride(dvv, current, &vdvv, dvvStride);
|
||||
}
|
||||
}
|
||||
153
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clPatchTable.cpp
vendored
Normal file
153
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clPatchTable.cpp
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/clPatchTable.h"
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/patchTable.h"
|
||||
#include "../osd/opencl.h"
|
||||
#include "../osd/cpuPatchTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CLPatchTable::CLPatchTable() :
|
||||
_patchArrays(NULL), _indexBuffer(NULL), _patchParamBuffer(NULL) {
|
||||
}
|
||||
|
||||
CLPatchTable::~CLPatchTable() {
|
||||
if (_patchArrays) clReleaseMemObject(_patchArrays);
|
||||
if (_indexBuffer) clReleaseMemObject(_indexBuffer);
|
||||
if (_patchParamBuffer) clReleaseMemObject(_patchParamBuffer);
|
||||
if (_varyingPatchArrays) clReleaseMemObject(_varyingPatchArrays);
|
||||
if (_varyingIndexBuffer) clReleaseMemObject(_varyingIndexBuffer);
|
||||
for (int fvc=0; fvc<(int)_fvarPatchArrays.size(); ++fvc) {
|
||||
if (_fvarPatchArrays[fvc]) clReleaseMemObject(_fvarPatchArrays[fvc]);
|
||||
}
|
||||
for (int fvc=0; fvc<(int)_fvarIndexBuffers.size(); ++fvc) {
|
||||
if (_fvarIndexBuffers[fvc]) clReleaseMemObject(_fvarIndexBuffers[fvc]);
|
||||
}
|
||||
for (int fvc=0; fvc<(int)_fvarParamBuffers.size(); ++fvc) {
|
||||
if (_fvarParamBuffers[fvc]) clReleaseMemObject(_fvarParamBuffers[fvc]);
|
||||
}
|
||||
}
|
||||
|
||||
CLPatchTable *
|
||||
CLPatchTable::Create(Far::PatchTable const *farPatchTable,
|
||||
cl_context clContext) {
|
||||
CLPatchTable *instance = new CLPatchTable();
|
||||
if (instance->allocate(farPatchTable, clContext)) return instance;
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
CLPatchTable::allocate(Far::PatchTable const *farPatchTable, cl_context clContext) {
|
||||
CpuPatchTable patchTable(farPatchTable);
|
||||
|
||||
size_t numPatchArrays = patchTable.GetNumPatchArrays();
|
||||
size_t indexSize = patchTable.GetPatchIndexSize();
|
||||
size_t patchParamSize = patchTable.GetPatchParamSize();
|
||||
|
||||
cl_int err = 0;
|
||||
_patchArrays = clCreateBuffer(clContext,
|
||||
CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,
|
||||
numPatchArrays * sizeof(Osd::PatchArray),
|
||||
(void*)patchTable.GetPatchArrayBuffer(),
|
||||
&err);
|
||||
if (err != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clCreateBuffer: %d", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
_indexBuffer = clCreateBuffer(clContext,
|
||||
CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,
|
||||
indexSize * sizeof(int),
|
||||
(void*)patchTable.GetPatchIndexBuffer(),
|
||||
&err);
|
||||
if (err != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clCreateBuffer: %d", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
_patchParamBuffer = clCreateBuffer(clContext,
|
||||
CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,
|
||||
patchParamSize * sizeof(Osd::PatchParam),
|
||||
(void*)patchTable.GetPatchParamBuffer(),
|
||||
&err);
|
||||
if (err != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clCreateBuffer: %d", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
_varyingPatchArrays = clCreateBuffer(clContext,
|
||||
CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,
|
||||
numPatchArrays * sizeof(Osd::PatchArray),
|
||||
(void*)patchTable.GetVaryingPatchArrayBuffer(),
|
||||
&err);
|
||||
if (err != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clCreateBuffer: %d", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
_varyingIndexBuffer = clCreateBuffer(clContext,
|
||||
CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,
|
||||
patchTable.GetVaryingPatchIndexSize() * sizeof(int),
|
||||
(void*)patchTable.GetVaryingPatchIndexBuffer(),
|
||||
&err);
|
||||
if (err != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clCreateBuffer: %d", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t numFVarChannels = patchTable.GetNumFVarChannels();
|
||||
_fvarPatchArrays.resize(numFVarChannels, 0);
|
||||
_fvarIndexBuffers.resize(numFVarChannels, 0);
|
||||
_fvarParamBuffers.resize(numFVarChannels, 0);
|
||||
for (int fvc=0; fvc<(int)numFVarChannels; ++fvc) {
|
||||
_fvarPatchArrays[fvc] = clCreateBuffer(clContext,
|
||||
CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,
|
||||
numPatchArrays * sizeof(Osd::PatchArray),
|
||||
(void*)patchTable.GetFVarPatchArrayBuffer(fvc),
|
||||
&err);
|
||||
if (err != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clCreateBuffer: %d", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
_fvarIndexBuffers[fvc] = clCreateBuffer(clContext,
|
||||
CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,
|
||||
patchTable.GetFVarPatchIndexSize(fvc) * sizeof(int),
|
||||
(void*)patchTable.GetFVarPatchIndexBuffer(fvc),
|
||||
&err);
|
||||
if (err != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clCreateBuffer: %d", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
_fvarParamBuffers[fvc] = clCreateBuffer(clContext,
|
||||
CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,
|
||||
patchTable.GetFVarPatchParamSize(fvc) * sizeof(Osd::PatchParam),
|
||||
(void*)patchTable.GetFVarPatchParamBuffer(fvc),
|
||||
&err);
|
||||
if (err != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clCreateBuffer: %d", err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
102
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clPatchTable.h
vendored
Normal file
102
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clPatchTable.h
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CL_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_OSD_CL_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/opencl.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/types.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far{
|
||||
class PatchTable;
|
||||
};
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief CL patch table
|
||||
///
|
||||
/// This class is a CL buffer representation of Far::PatchTable.
|
||||
///
|
||||
/// CLEvaluator consumes this table to evaluate on the patches.
|
||||
///
|
||||
///
|
||||
class CLPatchTable : private NonCopyable<CLPatchTable> {
|
||||
public:
|
||||
/// Creator. Returns NULL if error
|
||||
static CLPatchTable *Create(Far::PatchTable const *patchTable,
|
||||
cl_context clContext);
|
||||
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static CLPatchTable * Create(Far::PatchTable const *patchTable,
|
||||
DEVICE_CONTEXT context) {
|
||||
return Create(patchTable, context->GetContext());
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
~CLPatchTable();
|
||||
|
||||
/// Returns the CL memory of the array of Osd::PatchArray buffer
|
||||
cl_mem GetPatchArrayBuffer() const { return _patchArrays; }
|
||||
|
||||
/// Returns the CL memory of the patch control vertices
|
||||
cl_mem GetPatchIndexBuffer() const { return _indexBuffer; }
|
||||
|
||||
/// Returns the CL memory of the array of Osd::PatchParam buffer
|
||||
cl_mem GetPatchParamBuffer() const { return _patchParamBuffer; }
|
||||
|
||||
/// Returns the CL memory of the array of Osd::PatchArray buffer
|
||||
cl_mem GetVaryingPatchArrayBuffer() const { return _varyingPatchArrays; }
|
||||
|
||||
/// Returns the CL memory of the varying control vertices
|
||||
cl_mem GetVaryingPatchIndexBuffer() const { return _varyingIndexBuffer; }
|
||||
|
||||
/// Returns the number of face-varying channel buffers
|
||||
int GetNumFVarChannels() const { return (int)_fvarPatchArrays.size(); }
|
||||
|
||||
/// Returns the CL memory of the array of Osd::PatchArray buffer
|
||||
cl_mem GetFVarPatchArrayBuffer(int fvarChannel = 0) const { return _fvarPatchArrays[fvarChannel]; }
|
||||
|
||||
/// Returns the CL memory of the face-varying control vertices
|
||||
cl_mem GetFVarPatchIndexBuffer(int fvarChannel = 0) const { return _fvarIndexBuffers[fvarChannel]; }
|
||||
|
||||
/// Returns the CL memory of the array of Osd::PatchParam buffer
|
||||
cl_mem GetFVarPatchParamBuffer(int fvarChannel = 0) const { return _fvarParamBuffers[fvarChannel]; }
|
||||
|
||||
protected:
|
||||
CLPatchTable();
|
||||
|
||||
bool allocate(Far::PatchTable const *patchTable, cl_context clContext);
|
||||
|
||||
cl_mem _patchArrays;
|
||||
cl_mem _indexBuffer;
|
||||
cl_mem _patchParamBuffer;
|
||||
|
||||
cl_mem _varyingPatchArrays;
|
||||
cl_mem _varyingIndexBuffer;
|
||||
|
||||
std::vector<cl_mem> _fvarPatchArrays;
|
||||
std::vector<cl_mem> _fvarIndexBuffers;
|
||||
std::vector<cl_mem> _fvarParamBuffers;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CL_PATCH_TABLE_H
|
||||
85
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clVertexBuffer.cpp
vendored
Normal file
85
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clVertexBuffer.cpp
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/clVertexBuffer.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CLVertexBuffer::CLVertexBuffer(int numElements, int numVertices,
|
||||
cl_context /* clContext */)
|
||||
: _numElements(numElements), _numVertices(numVertices), _clMemory(NULL) {
|
||||
|
||||
}
|
||||
|
||||
CLVertexBuffer::~CLVertexBuffer() {
|
||||
|
||||
clReleaseMemObject(_clMemory);
|
||||
}
|
||||
|
||||
CLVertexBuffer *
|
||||
CLVertexBuffer::Create(int numElements, int numVertices,
|
||||
cl_context clContext) {
|
||||
CLVertexBuffer *instance =
|
||||
new CLVertexBuffer(numElements, numVertices, clContext);
|
||||
if (instance->allocate(clContext)) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
CLVertexBuffer::UpdateData(const float *src, int startVertex, int numVertices, cl_command_queue queue,
|
||||
cl_event* startEvents, unsigned int numStartEvents, cl_event* endEvent) {
|
||||
|
||||
size_t size = _numElements * numVertices * sizeof(float);
|
||||
size_t offset = startVertex * _numElements * sizeof(float);
|
||||
|
||||
cl_bool blocking = (endEvent == NULL) ? CL_TRUE : CL_FALSE;
|
||||
cl_int err = clEnqueueWriteBuffer(queue, _clMemory, blocking, offset, size, src, numStartEvents, startEvents, endEvent);
|
||||
assert(err == CL_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
CLVertexBuffer::GetNumElements() const {
|
||||
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int
|
||||
CLVertexBuffer::GetNumVertices() const {
|
||||
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLVertexBuffer::BindCLBuffer(cl_command_queue /* queue */) {
|
||||
|
||||
return _clMemory;
|
||||
}
|
||||
|
||||
bool
|
||||
CLVertexBuffer::allocate(cl_context clContext) {
|
||||
assert(clContext);
|
||||
int size = _numVertices * _numElements * sizeof(float);
|
||||
cl_int err;
|
||||
|
||||
_clMemory = clCreateBuffer(clContext, CL_MEM_READ_WRITE, size, NULL, &err);
|
||||
|
||||
if (err != CL_SUCCESS) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
82
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clVertexBuffer.h
vendored
Normal file
82
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/clVertexBuffer.h
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CL_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_CL_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../osd/opencl.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief Concrete vertex buffer class for OpenCL subdivision.
|
||||
///
|
||||
/// CLVertexBuffer implements CLVertexBufferInterface. An instance of this
|
||||
/// buffer class can be passed to CLEvaluator
|
||||
///
|
||||
class CLVertexBuffer {
|
||||
|
||||
public:
|
||||
/// Creator. Returns NULL if error.
|
||||
static CLVertexBuffer * Create(int numElements, int numVertices, cl_context clContext);
|
||||
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static CLVertexBuffer * Create(int numElements, int numVertices,
|
||||
DEVICE_CONTEXT context) {
|
||||
return Create(numElements, numVertices, context->GetContext());
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
~CLVertexBuffer();
|
||||
|
||||
/// 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 startVertex, int numVertices, cl_command_queue clQueue,
|
||||
cl_event* startEvents = NULL, unsigned int numStartEvents = 0, cl_event* endEvent = NULL);
|
||||
|
||||
template<typename DEVICE_CONTEXT>
|
||||
void UpdateData(const float *src, int startVertex, int numVertices,
|
||||
DEVICE_CONTEXT context,
|
||||
cl_event* startEvents = NULL, unsigned int numStartEvents = 0, cl_event* endEvent = NULL) {
|
||||
UpdateData(src, startVertex, numVertices, context->GetCommandQueue(), startEvents, numStartEvents, endEvent);
|
||||
}
|
||||
|
||||
/// Returns how many elements defined in this vertex buffer.
|
||||
int GetNumElements() const;
|
||||
|
||||
/// Returns how many vertices allocated in this vertex buffer.
|
||||
int GetNumVertices() const;
|
||||
|
||||
/// Returns the CL memory object.
|
||||
cl_mem BindCLBuffer(cl_command_queue queue);
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
CLVertexBuffer(int numElements, int numVertices, cl_context clContext);
|
||||
|
||||
/// Allocates CL memory for this buffer.
|
||||
/// Returns true if success.
|
||||
bool allocate(cl_context clContext);
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
cl_mem _clMemory;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CL_VERTEX_BUFFER_H
|
||||
123
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuD3D11VertexBuffer.cpp
vendored
Normal file
123
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuD3D11VertexBuffer.cpp
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/cpuD3D11VertexBuffer.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <D3D11.h>
|
||||
#include <cassert>
|
||||
#include <string.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuD3D11VertexBuffer::CpuD3D11VertexBuffer(int numElements, int numVertices)
|
||||
: _numElements(numElements), _numVertices(numVertices),
|
||||
_d3d11Buffer(NULL), _cpuBuffer(NULL) {
|
||||
}
|
||||
|
||||
CpuD3D11VertexBuffer::~CpuD3D11VertexBuffer() {
|
||||
|
||||
delete[] _cpuBuffer;
|
||||
|
||||
if (_d3d11Buffer) _d3d11Buffer->Release();
|
||||
}
|
||||
|
||||
CpuD3D11VertexBuffer *
|
||||
CpuD3D11VertexBuffer::Create(int numElements, int numVertices,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
CpuD3D11VertexBuffer *instance =
|
||||
new CpuD3D11VertexBuffer(numElements, numVertices);
|
||||
ID3D11Device *device;
|
||||
deviceContext->GetDevice(&device);
|
||||
if (instance->allocate(device)) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
CpuD3D11VertexBuffer::UpdateData(const float *src, int startVertex,
|
||||
int numVertices,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
memcpy(_cpuBuffer + startVertex * _numElements, src,
|
||||
_numElements * numVertices * sizeof(float));
|
||||
}
|
||||
|
||||
int
|
||||
CpuD3D11VertexBuffer::GetNumElements() const {
|
||||
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int
|
||||
CpuD3D11VertexBuffer::GetNumVertices() const {
|
||||
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
float*
|
||||
CpuD3D11VertexBuffer::BindCpuBuffer() {
|
||||
|
||||
return _cpuBuffer;
|
||||
}
|
||||
|
||||
ID3D11Buffer *
|
||||
CpuD3D11VertexBuffer::BindD3D11Buffer(ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
assert(deviceContext);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE resource;
|
||||
HRESULT hr = deviceContext->Map(_d3d11Buffer, 0,
|
||||
D3D11_MAP_WRITE_DISCARD, 0, &resource);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "Fail to map buffer\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int size = _numElements * _numVertices * sizeof(float);
|
||||
|
||||
memcpy(resource.pData, _cpuBuffer, size);
|
||||
|
||||
deviceContext->Unmap(_d3d11Buffer, 0);
|
||||
|
||||
return _d3d11Buffer;
|
||||
}
|
||||
|
||||
bool
|
||||
CpuD3D11VertexBuffer::allocate(ID3D11Device *device) {
|
||||
|
||||
_cpuBuffer = new float[_numElements * _numVertices];
|
||||
|
||||
// XXX: should move this constructor to factory for error handling
|
||||
D3D11_BUFFER_DESC hBufferDesc;
|
||||
hBufferDesc.ByteWidth = _numElements * _numVertices * sizeof(float);
|
||||
hBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
hBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_SHADER_RESOURCE;
|
||||
hBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
hBufferDesc.MiscFlags = 0;
|
||||
hBufferDesc.StructureByteStride = sizeof(float); // XXX ?
|
||||
|
||||
HRESULT hr;
|
||||
hr = device->CreateBuffer(&hBufferDesc, NULL, &_d3d11Buffer);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Fail in CreateBuffer\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
82
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuD3D11VertexBuffer.h
vendored
Normal file
82
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuD3D11VertexBuffer.h
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CPU_D3D11_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_CPU_D3D11_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
#include <cstddef>
|
||||
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief Concrete vertex buffer class for Cpu subdivision and DirectX drawing.
|
||||
///
|
||||
/// CpuD3D11VertexBuffer implements CpuVertexBufferInterface and
|
||||
/// D3D11VertexBufferInterface.
|
||||
///
|
||||
/// An instance of this buffer class can be passed to CpuEvaluator.
|
||||
///
|
||||
class CpuD3D11VertexBuffer {
|
||||
public:
|
||||
/// Creator. Returns NULL if error.
|
||||
static CpuD3D11VertexBuffer * Create(int numElements, int numVertices,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Destructor.
|
||||
virtual ~CpuD3D11VertexBuffer();
|
||||
|
||||
/// 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 startVertex, int numVertices,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Returns how many elements defined in this vertex buffer.
|
||||
int GetNumElements() const;
|
||||
|
||||
/// Returns how many vertices allocated in this vertex buffer.
|
||||
int GetNumVertices() const;
|
||||
|
||||
/// Returns the address of CPU buffer.
|
||||
float * BindCpuBuffer();
|
||||
|
||||
/// Returns the D3D11 buffer object.
|
||||
ID3D11Buffer *BindD3D11Buffer(ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Returns the D3D11 buffer object (for Osd::Mesh interface)
|
||||
ID3D11Buffer *BindVBO(ID3D11DeviceContext *deviceContext) {
|
||||
return BindD3D11Buffer(deviceContext);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
CpuD3D11VertexBuffer(int numElements, int numVertices);
|
||||
|
||||
bool allocate(ID3D11Device *device);
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
ID3D11Buffer *_d3d11Buffer;
|
||||
float *_cpuBuffer;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CPU_D3D11_VERTEX_BUFFER_H
|
||||
370
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuEvaluator.cpp
vendored
Normal file
370
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuEvaluator.cpp
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/cpuEvaluator.h"
|
||||
#include "../osd/cpuKernel.h"
|
||||
#include "../osd/patchBasis.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CpuEvaluator::EvalStencils(const float *src, BufferDescriptor const &srcDesc,
|
||||
float *dst, BufferDescriptor const &dstDesc,
|
||||
const int * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start, int end) {
|
||||
|
||||
if (end <= start) return true;
|
||||
if (srcDesc.length != dstDesc.length) return false;
|
||||
|
||||
// XXX: we can probably expand cpuKernel.cpp to here.
|
||||
CpuEvalStencils(src, srcDesc, dst, dstDesc,
|
||||
sizes, offsets, indices, weights, start, end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CpuEvaluator::EvalStencils(const float *src, BufferDescriptor const &srcDesc,
|
||||
float *dst, BufferDescriptor const &dstDesc,
|
||||
float *du, BufferDescriptor const &duDesc,
|
||||
float *dv, BufferDescriptor const &dvDesc,
|
||||
const int * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
const float * duWeights,
|
||||
const float * dvWeights,
|
||||
int start, int end) {
|
||||
if (end <= start) return true;
|
||||
if (srcDesc.length != dstDesc.length) return false;
|
||||
if (srcDesc.length != duDesc.length) return false;
|
||||
if (srcDesc.length != dvDesc.length) return false;
|
||||
|
||||
CpuEvalStencils(src, srcDesc,
|
||||
dst, dstDesc,
|
||||
du, duDesc,
|
||||
dv, dvDesc,
|
||||
sizes, offsets, indices,
|
||||
weights, duWeights, dvWeights,
|
||||
start, end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CpuEvaluator::EvalStencils(const float *src, BufferDescriptor const &srcDesc,
|
||||
float *dst, BufferDescriptor const &dstDesc,
|
||||
float *du, BufferDescriptor const &duDesc,
|
||||
float *dv, BufferDescriptor const &dvDesc,
|
||||
float *duu, BufferDescriptor const &duuDesc,
|
||||
float *duv, BufferDescriptor const &duvDesc,
|
||||
float *dvv, BufferDescriptor const &dvvDesc,
|
||||
const int * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
const float * duWeights,
|
||||
const float * dvWeights,
|
||||
const float * duuWeights,
|
||||
const float * duvWeights,
|
||||
const float * dvvWeights,
|
||||
int start, int end) {
|
||||
if (end <= start) return true;
|
||||
if (srcDesc.length != dstDesc.length) return false;
|
||||
if (srcDesc.length != duDesc.length) return false;
|
||||
if (srcDesc.length != dvDesc.length) return false;
|
||||
if (srcDesc.length != duuDesc.length) return false;
|
||||
if (srcDesc.length != duvDesc.length) return false;
|
||||
if (srcDesc.length != dvvDesc.length) return false;
|
||||
|
||||
CpuEvalStencils(src, srcDesc,
|
||||
dst, dstDesc,
|
||||
du, duDesc,
|
||||
dv, dvDesc,
|
||||
duu, duuDesc,
|
||||
duv, duvDesc,
|
||||
dvv, dvvDesc,
|
||||
sizes, offsets, indices,
|
||||
weights, duWeights, dvWeights,
|
||||
duuWeights, duvWeights, dvvWeights,
|
||||
start, end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct BufferAdapter {
|
||||
BufferAdapter(T *p, int length, int stride) :
|
||||
_p(p), _length(length), _stride(stride) { }
|
||||
void Clear() {
|
||||
for (int i = 0; i < _length; ++i) _p[i] = 0;
|
||||
}
|
||||
void AddWithWeight(T const *src, float w) {
|
||||
if (_p) {
|
||||
for (int i = 0; i < _length; ++i) {
|
||||
_p[i] += src[i] * w;
|
||||
}
|
||||
}
|
||||
}
|
||||
const T *operator[] (int index) const {
|
||||
return _p + _stride * index;
|
||||
}
|
||||
BufferAdapter<T> & operator ++() {
|
||||
if (_p) {
|
||||
_p += _stride;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
T *_p;
|
||||
int _length;
|
||||
int _stride;
|
||||
};
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CpuEvaluator::EvalPatches(const float *src, BufferDescriptor const &srcDesc,
|
||||
float *dst, BufferDescriptor const &dstDesc,
|
||||
int numPatchCoords,
|
||||
const PatchCoord *patchCoords,
|
||||
const PatchArray *patchArrays,
|
||||
const int *patchIndexBuffer,
|
||||
const PatchParam *patchParamBuffer) {
|
||||
if (src) {
|
||||
src += srcDesc.offset;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (dst) {
|
||||
dst += dstDesc.offset;
|
||||
if (srcDesc.length != dstDesc.length) return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
BufferAdapter<const float> srcT(src, srcDesc.length, srcDesc.stride);
|
||||
BufferAdapter<float> dstT(dst, dstDesc.length, dstDesc.stride);
|
||||
|
||||
float wP[20];
|
||||
|
||||
for (int i = 0; i < numPatchCoords; ++i) {
|
||||
PatchCoord const &coord = patchCoords[i];
|
||||
PatchArray const &array = patchArrays[coord.handle.arrayIndex];
|
||||
|
||||
Osd::PatchParam const & paramStruct =
|
||||
patchParamBuffer[coord.handle.patchIndex];
|
||||
OsdPatchParam param = OsdPatchParamInit(
|
||||
paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
|
||||
|
||||
int patchType = OsdPatchParamIsRegular(param)
|
||||
? array.GetPatchTypeRegular()
|
||||
: array.GetPatchTypeIrregular();
|
||||
|
||||
int nPoints = OsdEvaluatePatchBasis(patchType, param,
|
||||
coord.s, coord.t, wP, 0, 0, 0, 0, 0);
|
||||
|
||||
int indexBase = array.GetIndexBase() + array.GetStride() *
|
||||
(coord.handle.patchIndex - array.GetPrimitiveIdBase());
|
||||
|
||||
const int *cvs = &patchIndexBuffer[indexBase];
|
||||
|
||||
dstT.Clear();
|
||||
for (int j = 0; j < nPoints; ++j) {
|
||||
dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
|
||||
}
|
||||
++dstT;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CpuEvaluator::EvalPatches(const float *src, BufferDescriptor const &srcDesc,
|
||||
float *dst, BufferDescriptor const &dstDesc,
|
||||
float *du, BufferDescriptor const &duDesc,
|
||||
float *dv, BufferDescriptor const &dvDesc,
|
||||
int numPatchCoords,
|
||||
const PatchCoord *patchCoords,
|
||||
const PatchArray *patchArrays,
|
||||
const int *patchIndexBuffer,
|
||||
const PatchParam *patchParamBuffer) {
|
||||
if (src) {
|
||||
src += srcDesc.offset;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (dst) {
|
||||
if (srcDesc.length != dstDesc.length) return false;
|
||||
dst += dstDesc.offset;
|
||||
}
|
||||
if (du) {
|
||||
du += duDesc.offset;
|
||||
if (srcDesc.length != duDesc.length) return false;
|
||||
}
|
||||
if (dv) {
|
||||
dv += dvDesc.offset;
|
||||
if (srcDesc.length != dvDesc.length) return false;
|
||||
}
|
||||
|
||||
BufferAdapter<const float> srcT(src, srcDesc.length, srcDesc.stride);
|
||||
BufferAdapter<float> dstT(dst, dstDesc.length, dstDesc.stride);
|
||||
BufferAdapter<float> duT(du, duDesc.length, duDesc.stride);
|
||||
BufferAdapter<float> dvT(dv, dvDesc.length, dvDesc.stride);
|
||||
|
||||
float wP[20], wDs[20], wDt[20];
|
||||
|
||||
for (int i = 0; i < numPatchCoords; ++i) {
|
||||
PatchCoord const &coord = patchCoords[i];
|
||||
PatchArray const &array = patchArrays[coord.handle.arrayIndex];
|
||||
|
||||
Osd::PatchParam const & paramStruct =
|
||||
patchParamBuffer[coord.handle.patchIndex];
|
||||
OsdPatchParam param = OsdPatchParamInit(
|
||||
paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
|
||||
|
||||
int patchType = OsdPatchParamIsRegular(param)
|
||||
? array.GetPatchTypeRegular()
|
||||
: array.GetPatchTypeIrregular();
|
||||
|
||||
int nPoints = OsdEvaluatePatchBasis(patchType, param,
|
||||
coord.s, coord.t, wP, wDs, wDt, 0, 0, 0);
|
||||
|
||||
int indexBase = array.GetIndexBase() + array.GetStride() *
|
||||
(coord.handle.patchIndex - array.GetPrimitiveIdBase());
|
||||
|
||||
const int *cvs = &patchIndexBuffer[indexBase];
|
||||
|
||||
dstT.Clear();
|
||||
duT.Clear();
|
||||
dvT.Clear();
|
||||
for (int j = 0; j < nPoints; ++j) {
|
||||
dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
|
||||
duT.AddWithWeight (srcT[cvs[j]], wDs[j]);
|
||||
dvT.AddWithWeight (srcT[cvs[j]], wDt[j]);
|
||||
}
|
||||
++dstT;
|
||||
++duT;
|
||||
++dvT;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CpuEvaluator::EvalPatches(const float *src, BufferDescriptor const &srcDesc,
|
||||
float *dst, BufferDescriptor const &dstDesc,
|
||||
float *du, BufferDescriptor const &duDesc,
|
||||
float *dv, BufferDescriptor const &dvDesc,
|
||||
float *duu, BufferDescriptor const &duuDesc,
|
||||
float *duv, BufferDescriptor const &duvDesc,
|
||||
float *dvv, BufferDescriptor const &dvvDesc,
|
||||
int numPatchCoords,
|
||||
const PatchCoord *patchCoords,
|
||||
const PatchArray *patchArrays,
|
||||
const int *patchIndexBuffer,
|
||||
const PatchParam *patchParamBuffer) {
|
||||
if (src) {
|
||||
src += srcDesc.offset;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (dst) {
|
||||
if (srcDesc.length != dstDesc.length) return false;
|
||||
dst += dstDesc.offset;
|
||||
}
|
||||
if (du) {
|
||||
du += duDesc.offset;
|
||||
if (srcDesc.length != duDesc.length) return false;
|
||||
}
|
||||
if (dv) {
|
||||
dv += dvDesc.offset;
|
||||
if (srcDesc.length != dvDesc.length) return false;
|
||||
}
|
||||
if (duu) {
|
||||
duu += duuDesc.offset;
|
||||
if (srcDesc.length != duuDesc.length) return false;
|
||||
}
|
||||
if (duv) {
|
||||
duv += duvDesc.offset;
|
||||
if (srcDesc.length != duvDesc.length) return false;
|
||||
}
|
||||
if (dvv) {
|
||||
dvv += dvvDesc.offset;
|
||||
if (srcDesc.length != dvvDesc.length) return false;
|
||||
}
|
||||
|
||||
BufferAdapter<const float> srcT(src, srcDesc.length, srcDesc.stride);
|
||||
BufferAdapter<float> dstT(dst, dstDesc.length, dstDesc.stride);
|
||||
BufferAdapter<float> duT(du, duDesc.length, duDesc.stride);
|
||||
BufferAdapter<float> dvT(dv, dvDesc.length, dvDesc.stride);
|
||||
BufferAdapter<float> duuT(duu, duuDesc.length, duuDesc.stride);
|
||||
BufferAdapter<float> duvT(duv, duvDesc.length, duvDesc.stride);
|
||||
BufferAdapter<float> dvvT(dvv, dvvDesc.length, dvvDesc.stride);
|
||||
|
||||
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
|
||||
|
||||
for (int i = 0; i < numPatchCoords; ++i) {
|
||||
PatchCoord const &coord = patchCoords[i];
|
||||
PatchArray const &array = patchArrays[coord.handle.arrayIndex];
|
||||
|
||||
Osd::PatchParam const & paramStruct =
|
||||
patchParamBuffer[coord.handle.patchIndex];
|
||||
OsdPatchParam param = OsdPatchParamInit(
|
||||
paramStruct.field0, paramStruct.field1, paramStruct.sharpness);
|
||||
|
||||
int patchType = OsdPatchParamIsRegular(param)
|
||||
? array.GetPatchTypeRegular()
|
||||
: array.GetPatchTypeIrregular();
|
||||
|
||||
int nPoints = OsdEvaluatePatchBasis(patchType, param,
|
||||
coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
|
||||
|
||||
int indexBase = array.GetIndexBase() + array.GetStride() *
|
||||
(coord.handle.patchIndex - array.GetPrimitiveIdBase());
|
||||
|
||||
const int *cvs = &patchIndexBuffer[indexBase];
|
||||
|
||||
dstT.Clear();
|
||||
duT.Clear();
|
||||
dvT.Clear();
|
||||
duuT.Clear();
|
||||
duvT.Clear();
|
||||
dvvT.Clear();
|
||||
for (int j = 0; j < nPoints; ++j) {
|
||||
dstT.AddWithWeight(srcT[cvs[j]], wP[j]);
|
||||
duT.AddWithWeight (srcT[cvs[j]], wDu[j]);
|
||||
dvT.AddWithWeight (srcT[cvs[j]], wDv[j]);
|
||||
duuT.AddWithWeight (srcT[cvs[j]], wDuu[j]);
|
||||
duvT.AddWithWeight (srcT[cvs[j]], wDuv[j]);
|
||||
dvvT.AddWithWeight (srcT[cvs[j]], wDvv[j]);
|
||||
}
|
||||
++dstT;
|
||||
++duT;
|
||||
++dvT;
|
||||
++duuT;
|
||||
++duvT;
|
||||
++dvvT;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
1224
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuEvaluator.h
vendored
Normal file
1224
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuEvaluator.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
106
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuGLVertexBuffer.cpp
vendored
Normal file
106
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuGLVertexBuffer.cpp
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "glLoader.h"
|
||||
|
||||
#include "../osd/cpuGLVertexBuffer.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuGLVertexBuffer::CpuGLVertexBuffer(int numElements, int numVertices)
|
||||
: _numElements(numElements), _numVertices(numVertices),
|
||||
_vbo(0), _cpuBuffer(0), _dataDirty(true) {
|
||||
|
||||
// Initialize internal OpenGL loader library if necessary
|
||||
OpenSubdiv::internal::GLLoader::libraryInitializeGL();
|
||||
}
|
||||
|
||||
CpuGLVertexBuffer::~CpuGLVertexBuffer() {
|
||||
|
||||
delete[] _cpuBuffer;
|
||||
|
||||
if (_vbo) {
|
||||
glDeleteBuffers(1, &_vbo);
|
||||
}
|
||||
}
|
||||
|
||||
CpuGLVertexBuffer *
|
||||
CpuGLVertexBuffer::Create(int numElements, int numVertices, void *) {
|
||||
CpuGLVertexBuffer *instance =
|
||||
new CpuGLVertexBuffer(numElements, numVertices);
|
||||
if (instance->allocate()) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
CpuGLVertexBuffer::UpdateData(const float *src,
|
||||
int startVertex, int numVertices,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
memcpy(_cpuBuffer + startVertex * GetNumElements(), src,
|
||||
GetNumElements() * numVertices * sizeof(float));
|
||||
_dataDirty = true;
|
||||
}
|
||||
|
||||
int
|
||||
CpuGLVertexBuffer::GetNumElements() const {
|
||||
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int
|
||||
CpuGLVertexBuffer::GetNumVertices() const {
|
||||
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
float*
|
||||
CpuGLVertexBuffer::BindCpuBuffer() {
|
||||
|
||||
_dataDirty = true; // caller might modify data
|
||||
return _cpuBuffer;
|
||||
}
|
||||
|
||||
CpuGLVertexBuffer::ID
|
||||
CpuGLVertexBuffer::BindVBO(void * /*deviceContext*/) {
|
||||
|
||||
if (! _dataDirty)
|
||||
return _vbo;
|
||||
|
||||
int size = GetNumElements() * GetNumVertices() * (int) sizeof(float);
|
||||
|
||||
if (! _vbo) {
|
||||
glGenBuffers(1, &_vbo);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, _cpuBuffer, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
_dataDirty = false;
|
||||
return _vbo;
|
||||
}
|
||||
|
||||
bool
|
||||
CpuGLVertexBuffer::allocate() {
|
||||
|
||||
_cpuBuffer = new float[GetNumElements() * GetNumVertices()];
|
||||
_dataDirty = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
81
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuGLVertexBuffer.h
vendored
Normal file
81
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuGLVertexBuffer.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CPU_GL_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_CPU_GL_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief Concrete vertex buffer class for cpu subdivision and OpenGL drawing.
|
||||
///
|
||||
/// CpuGLVertexBuffer implements CpuVertexBufferInterface and
|
||||
/// GLVertexBufferInterface.
|
||||
///
|
||||
/// The buffer interop between Cpu and GL is handled automatically when a
|
||||
/// client calls BindCpuBuffer and BindVBO methods.
|
||||
///
|
||||
class CpuGLVertexBuffer {
|
||||
public:
|
||||
using ID = unsigned int; // GLuint resource ID
|
||||
|
||||
/// Creator. Returns NULL if error.
|
||||
static CpuGLVertexBuffer * Create(int numElements, int numVertices,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Destructor.
|
||||
~CpuGLVertexBuffer();
|
||||
|
||||
/// 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 startVertex, int numVertices,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Returns how many elements defined in this vertex buffer.
|
||||
int GetNumElements() const;
|
||||
|
||||
/// Returns how many vertices allocated in this vertex buffer.
|
||||
int GetNumVertices() const;
|
||||
|
||||
/// Returns cpu memory. GL buffer will be mapped to cpu address
|
||||
/// if necessary.
|
||||
float * BindCpuBuffer();
|
||||
|
||||
/// Returns the name of GL buffer object. If the buffer is mapped
|
||||
/// to cpu address, it will be unmapped back to GL.
|
||||
ID BindVBO(void *deviceContext = NULL);
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
CpuGLVertexBuffer(int numElements, int numVertices);
|
||||
|
||||
/// Allocates VBO for this buffer. Returns true if success.
|
||||
bool allocate();
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
ID _vbo;
|
||||
float *_cpuBuffer;
|
||||
bool _dataDirty;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CPU_GL_VERTEX_BUFFER_H
|
||||
228
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuKernel.cpp
vendored
Normal file
228
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuKernel.cpp
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/cpuKernel.h"
|
||||
#include "../osd/bufferDescriptor.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
template <class T> T *
|
||||
elementAtIndex(T * src, int index, BufferDescriptor const &desc) {
|
||||
|
||||
return src + index * desc.stride;
|
||||
}
|
||||
|
||||
static inline void
|
||||
clear(float *dst, BufferDescriptor const &desc) {
|
||||
|
||||
assert(dst);
|
||||
memset(dst, 0, desc.length*sizeof(float));
|
||||
}
|
||||
|
||||
static inline void
|
||||
addWithWeight(float *dst, const float *src, int srcIndex, float weight,
|
||||
BufferDescriptor const &desc) {
|
||||
|
||||
assert(src && dst);
|
||||
src = elementAtIndex(src, srcIndex, desc);
|
||||
for (int k = 0; k < desc.length; ++k) {
|
||||
dst[k] += src[k] * weight;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
copy(float *dst, int dstIndex, const float *src, BufferDescriptor const &desc) {
|
||||
|
||||
assert(src && dst);
|
||||
|
||||
dst = elementAtIndex(dst, dstIndex, desc);
|
||||
memcpy(dst, src, desc.length*sizeof(float));
|
||||
}
|
||||
|
||||
void
|
||||
CpuEvalStencils(float const * src, BufferDescriptor const &srcDesc,
|
||||
float * dst, BufferDescriptor const &dstDesc,
|
||||
int const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end) {
|
||||
|
||||
assert(start>=0 && start<end);
|
||||
|
||||
if (start>0) {
|
||||
sizes += start;
|
||||
indices += offsets[start];
|
||||
weights += offsets[start];
|
||||
}
|
||||
|
||||
src += srcDesc.offset;
|
||||
dst += dstDesc.offset;
|
||||
|
||||
if (srcDesc.length == 4 && dstDesc.length == 4 &&
|
||||
srcDesc.stride == 4 && dstDesc.stride == 4) {
|
||||
|
||||
// SIMD fast path for aligned primvar data (4 floats)
|
||||
ComputeStencilKernel<4>(src, dst,
|
||||
sizes, indices, weights, start, end);
|
||||
|
||||
} else if (srcDesc.length == 8 && dstDesc.length == 8 &&
|
||||
srcDesc.stride == 8 && dstDesc.stride == 8) {
|
||||
|
||||
// SIMD fast path for aligned primvar data (8 floats)
|
||||
ComputeStencilKernel<8>(src, dst,
|
||||
sizes, indices, weights, start, end);
|
||||
} else {
|
||||
|
||||
// Slow path for non-aligned data
|
||||
|
||||
float * result = (float*)alloca(srcDesc.length * sizeof(float));
|
||||
|
||||
int nstencils = end-start;
|
||||
for (int i=0; i<nstencils; ++i, ++sizes) {
|
||||
|
||||
clear(result, srcDesc);
|
||||
|
||||
for (int j=0; j<*sizes; ++j) {
|
||||
addWithWeight(result, src, *indices++, *weights++, srcDesc);
|
||||
}
|
||||
|
||||
copy(dst, i, result, dstDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CpuEvalStencils(float const * src, BufferDescriptor const &srcDesc,
|
||||
float * dst, BufferDescriptor const &dstDesc,
|
||||
float * dstDu, BufferDescriptor const &dstDuDesc,
|
||||
float * dstDv, BufferDescriptor const &dstDvDesc,
|
||||
int const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
float const * duWeights,
|
||||
float const * dvWeights,
|
||||
int start, int end) {
|
||||
if (start > 0) {
|
||||
sizes += start;
|
||||
indices += offsets[start];
|
||||
weights += offsets[start];
|
||||
duWeights += offsets[start];
|
||||
dvWeights += offsets[start];
|
||||
}
|
||||
|
||||
src += srcDesc.offset;
|
||||
dst += dstDesc.offset;
|
||||
dstDu += dstDuDesc.offset;
|
||||
dstDv += dstDvDesc.offset;
|
||||
|
||||
int nOutLength = dstDesc.length + dstDuDesc.length + dstDvDesc.length;
|
||||
float * result = (float*)alloca(nOutLength * sizeof(float));
|
||||
float * resultDu = result + dstDesc.length;
|
||||
float * resultDv = resultDu + dstDuDesc.length;
|
||||
|
||||
int nStencils = end - start;
|
||||
for (int i = 0; i < nStencils; ++i, ++sizes) {
|
||||
|
||||
// clear
|
||||
memset(result, 0, nOutLength * sizeof(float));
|
||||
|
||||
for (int j=0; j<*sizes; ++j) {
|
||||
addWithWeight(result, src, *indices, *weights++, srcDesc);
|
||||
addWithWeight(resultDu, src, *indices, *duWeights++, srcDesc);
|
||||
addWithWeight(resultDv, src, *indices, *dvWeights++, srcDesc);
|
||||
++indices;
|
||||
}
|
||||
copy(dst, i, result, dstDesc);
|
||||
copy(dstDu, i, resultDu, dstDuDesc);
|
||||
copy(dstDv, i, resultDv, dstDvDesc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CpuEvalStencils(float const * src, BufferDescriptor const &srcDesc,
|
||||
float * dst, BufferDescriptor const &dstDesc,
|
||||
float * dstDu, BufferDescriptor const &dstDuDesc,
|
||||
float * dstDv, BufferDescriptor const &dstDvDesc,
|
||||
float * dstDuu, BufferDescriptor const &dstDuuDesc,
|
||||
float * dstDuv, BufferDescriptor const &dstDuvDesc,
|
||||
float * dstDvv, BufferDescriptor const &dstDvvDesc,
|
||||
int const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
float const * duWeights,
|
||||
float const * dvWeights,
|
||||
float const * duuWeights,
|
||||
float const * duvWeights,
|
||||
float const * dvvWeights,
|
||||
int start, int end) {
|
||||
if (start > 0) {
|
||||
sizes += start;
|
||||
indices += offsets[start];
|
||||
weights += offsets[start];
|
||||
duWeights += offsets[start];
|
||||
dvWeights += offsets[start];
|
||||
duuWeights += offsets[start];
|
||||
duvWeights += offsets[start];
|
||||
dvvWeights += offsets[start];
|
||||
}
|
||||
|
||||
src += srcDesc.offset;
|
||||
dst += dstDesc.offset;
|
||||
dstDu += dstDuDesc.offset;
|
||||
dstDv += dstDvDesc.offset;
|
||||
dstDuu += dstDuuDesc.offset;
|
||||
dstDuv += dstDuvDesc.offset;
|
||||
dstDvv += dstDvvDesc.offset;
|
||||
|
||||
int nOutLength = dstDesc.length + dstDuDesc.length + dstDvDesc.length
|
||||
+ dstDuuDesc.length + dstDuvDesc.length + dstDvvDesc.length;
|
||||
float * result = (float*)alloca(nOutLength * sizeof(float));
|
||||
float * resultDu = result + dstDesc.length;
|
||||
float * resultDv = resultDu + dstDuDesc.length;
|
||||
float * resultDuu = resultDv + dstDvDesc.length;
|
||||
float * resultDuv = resultDuu + dstDuuDesc.length;
|
||||
float * resultDvv = resultDuv + dstDuvDesc.length;
|
||||
|
||||
int nStencils = end - start;
|
||||
for (int i = 0; i < nStencils; ++i, ++sizes) {
|
||||
|
||||
// clear
|
||||
memset(result, 0, nOutLength * sizeof(float));
|
||||
|
||||
for (int j=0; j<*sizes; ++j) {
|
||||
addWithWeight(result, src, *indices, *weights++, srcDesc);
|
||||
addWithWeight(resultDu, src, *indices, *duWeights++, srcDesc);
|
||||
addWithWeight(resultDv, src, *indices, *dvWeights++, srcDesc);
|
||||
addWithWeight(resultDuu, src, *indices, *duuWeights++, srcDesc);
|
||||
addWithWeight(resultDuv, src, *indices, *duvWeights++, srcDesc);
|
||||
addWithWeight(resultDvv, src, *indices, *dvvWeights++, srcDesc);
|
||||
++indices;
|
||||
}
|
||||
copy(dst, i, result, dstDesc);
|
||||
copy(dstDu, i, resultDu, dstDuDesc);
|
||||
copy(dstDv, i, resultDv, dstDvDesc);
|
||||
copy(dstDuu, i, resultDuu, dstDuuDesc);
|
||||
copy(dstDuv, i, resultDuv, dstDuvDesc);
|
||||
copy(dstDvv, i, resultDvv, dstDvvDesc);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
133
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuKernel.h
vendored
Normal file
133
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuKernel.h
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CPU_KERNEL_H
|
||||
#define OPENSUBDIV3_OSD_CPU_KERNEL_H
|
||||
|
||||
#include "../version.h"
|
||||
#include <cstring>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
struct BufferDescriptor;
|
||||
|
||||
void
|
||||
CpuEvalStencils(float const * src, BufferDescriptor const &srcDesc,
|
||||
float * dst, BufferDescriptor const &dstDesc,
|
||||
int const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end);
|
||||
|
||||
void
|
||||
CpuEvalStencils(float const * src, BufferDescriptor const &srcDesc,
|
||||
float * dst, BufferDescriptor const &dstDesc,
|
||||
float * dstDu, BufferDescriptor const &dstDuDesc,
|
||||
float * dstDv, BufferDescriptor const &dstDvDesc,
|
||||
int const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
float const * duWeights,
|
||||
float const * dvWeights,
|
||||
int start, int end);
|
||||
|
||||
void
|
||||
CpuEvalStencils(float const * src, BufferDescriptor const &srcDesc,
|
||||
float * dst, BufferDescriptor const &dstDesc,
|
||||
float * dstDu, BufferDescriptor const &dstDuDesc,
|
||||
float * dstDv, BufferDescriptor const &dstDvDesc,
|
||||
float * dstDuu, BufferDescriptor const &dstDuuDesc,
|
||||
float * dstDuv, BufferDescriptor const &dstDuvDesc,
|
||||
float * dstDvv, BufferDescriptor const &dstDvvDesc,
|
||||
int const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
float const * duWeights,
|
||||
float const * dvWeights,
|
||||
float const * duuWeights,
|
||||
float const * duvWeights,
|
||||
float const * dvvWeights,
|
||||
int start, int end);
|
||||
|
||||
//
|
||||
// SIMD ICC optimization of the stencil kernel
|
||||
//
|
||||
|
||||
#if defined ( __INTEL_COMPILER ) || defined ( __ICC )
|
||||
#define __ALIGN_DATA __declspec(align(32))
|
||||
#else
|
||||
#define __ALIGN_DATA
|
||||
#endif
|
||||
|
||||
// Note : this function is re-used in the TBB Compute kernel
|
||||
template <int numElems> void
|
||||
ComputeStencilKernel(float const * vertexSrc,
|
||||
float * vertexDst,
|
||||
int const * sizes,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start,
|
||||
int end) {
|
||||
|
||||
__ALIGN_DATA float result[numElems],
|
||||
result1[numElems];
|
||||
|
||||
float const * src;
|
||||
float * dst, weight;
|
||||
|
||||
for (int i=start; i<end; ++i) {
|
||||
|
||||
// Clear
|
||||
#if defined ( __INTEL_COMPILER ) || defined ( __ICC )
|
||||
#pragma simd
|
||||
#pragma vector aligned
|
||||
#endif
|
||||
for (int k = 0; k<numElems; ++k)
|
||||
result[k] = 0.0f;
|
||||
|
||||
for (int j=0; j<sizes[i]; ++j, ++indices, ++weights) {
|
||||
|
||||
src = vertexSrc + (*indices)*numElems;
|
||||
weight = *weights;
|
||||
|
||||
// AddWithWeight
|
||||
#if defined ( __INTEL_COMPILER ) || defined ( __ICC )
|
||||
#pragma simd
|
||||
#pragma vector aligned
|
||||
#endif
|
||||
for (int k=0; k<numElems; ++k) {
|
||||
result[k] += src[k] * weight;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined ( __INTEL_COMPILER ) || defined ( __ICC )
|
||||
#pragma simd
|
||||
#pragma vector aligned
|
||||
#endif
|
||||
for (int k=0; k<numElems; ++k) {
|
||||
result1[k] = result[k];
|
||||
}
|
||||
|
||||
dst = vertexDst + i*numElems;
|
||||
memcpy(dst, result1, numElems*sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CPU_KERNEL_H
|
||||
147
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuPatchTable.cpp
vendored
Normal file
147
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuPatchTable.cpp
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/cpuPatchTable.h"
|
||||
#include "../far/patchDescriptor.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuPatchTable::CpuPatchTable(const Far::PatchTable *farPatchTable) {
|
||||
int nPatchArrays = farPatchTable->GetNumPatchArrays();
|
||||
|
||||
// count
|
||||
int numPatches = 0;
|
||||
int numIndices = 0;
|
||||
for (int j = 0; j < nPatchArrays; ++j) {
|
||||
int nPatch = farPatchTable->GetNumPatches(j);
|
||||
int nCV = farPatchTable->GetPatchArrayDescriptor(j).GetNumControlVertices();
|
||||
numPatches += nPatch;
|
||||
numIndices += nPatch * nCV;
|
||||
}
|
||||
_patchArrays.reserve(nPatchArrays);
|
||||
_indexBuffer.reserve(numIndices);
|
||||
|
||||
_varyingPatchArrays.reserve(nPatchArrays);
|
||||
_varyingIndexBuffer.reserve(
|
||||
numPatches*farPatchTable->GetVaryingPatchDescriptor().GetNumControlVertices());
|
||||
|
||||
_fvarPatchArrays.resize(farPatchTable->GetNumFVarChannels());
|
||||
_fvarIndexBuffers.resize(farPatchTable->GetNumFVarChannels());
|
||||
_fvarParamBuffers.resize(farPatchTable->GetNumFVarChannels());
|
||||
for (int fvc=0; fvc<farPatchTable->GetNumFVarChannels(); ++fvc) {
|
||||
_fvarPatchArrays[fvc].reserve(nPatchArrays);
|
||||
_fvarIndexBuffers[fvc].reserve(
|
||||
numPatches * farPatchTable->GetFVarValueStride(fvc));
|
||||
_fvarParamBuffers[fvc].reserve(numPatches);
|
||||
}
|
||||
_patchParamBuffer.reserve(numPatches);
|
||||
|
||||
// for each patchArray
|
||||
for (int j = 0; j < nPatchArrays; ++j) {
|
||||
int numPatchesThisArray = farPatchTable->GetNumPatches(j);
|
||||
|
||||
// create vertex array and append indices to buffer:
|
||||
PatchArray patchArray(
|
||||
farPatchTable->GetPatchArrayDescriptor(j),
|
||||
numPatchesThisArray,
|
||||
(int)_indexBuffer.size(), (int)_patchParamBuffer.size());
|
||||
_patchArrays.push_back(patchArray);
|
||||
|
||||
Far::ConstIndexArray indices = farPatchTable->GetPatchArrayVertices(j);
|
||||
_indexBuffer.insert(_indexBuffer.end(), indices.begin(), indices.end());
|
||||
|
||||
// create varying array and append indices to buffer:
|
||||
PatchArray varyingPatchArray(
|
||||
farPatchTable->GetVaryingPatchDescriptor(),
|
||||
numPatchesThisArray,
|
||||
(int)_varyingIndexBuffer.size(), (int)_patchParamBuffer.size());
|
||||
_varyingPatchArrays.push_back(varyingPatchArray);
|
||||
|
||||
Far::ConstIndexArray
|
||||
varyingIndices = farPatchTable->GetPatchArrayVaryingVertices(j);
|
||||
_varyingIndexBuffer.insert(_varyingIndexBuffer.end(),
|
||||
varyingIndices.begin(), varyingIndices.end());
|
||||
|
||||
// create face-varying arrays for each channel:
|
||||
for (int fvc=0; fvc<farPatchTable->GetNumFVarChannels(); ++fvc) {
|
||||
// create face-varying array and append indices to buffer:
|
||||
PatchArray fvarPatchArray(
|
||||
farPatchTable->GetFVarPatchDescriptorRegular(fvc),
|
||||
farPatchTable->GetFVarPatchDescriptorIrregular(fvc),
|
||||
numPatchesThisArray,
|
||||
(int)_fvarIndexBuffers[fvc].size(), (int)_fvarParamBuffers[fvc].size());
|
||||
_fvarPatchArrays[fvc].push_back(fvarPatchArray);
|
||||
|
||||
Far::ConstIndexArray
|
||||
fvarIndices = farPatchTable->GetPatchArrayFVarValues(j, fvc);
|
||||
_fvarIndexBuffers[fvc].insert(_fvarIndexBuffers[fvc].end(),
|
||||
fvarIndices.begin(), fvarIndices.end());
|
||||
|
||||
// append face-varying patch params (converting Far PatchParams to Osd)
|
||||
Far::ConstPatchParamArray
|
||||
fvarParam = farPatchTable->GetPatchArrayFVarPatchParams(j, fvc);
|
||||
|
||||
for (int k = 0; k < numPatchesThisArray; ++k) {
|
||||
PatchParam param;
|
||||
//param.patchParam = patchParamTable[patchIndex];
|
||||
param.field0 = fvarParam[k].field0;
|
||||
param.field1 = fvarParam[k].field1;
|
||||
param.sharpness = 0.0f;
|
||||
_fvarParamBuffers[fvc].push_back(param);
|
||||
}
|
||||
}
|
||||
|
||||
// patchParams bundling
|
||||
// XXX: this process won't be needed if Far::PatchParam includes
|
||||
// sharpness.
|
||||
#if 0
|
||||
// XXX: we need sharpness interface for patcharray or put sharpness
|
||||
// into patchParam.
|
||||
Far::ConstPatchParamArray patchParams =
|
||||
farPatchTable->GetPatchParams(j);
|
||||
for (int k = 0; k < patchParams.size(); ++k) {
|
||||
float sharpness = 0.0;
|
||||
_patchParamBuffer.push_back(patchParams[k].field0);
|
||||
_patchParamBuffer.push_back(patchParams[k].field1);
|
||||
_patchParamBuffer.push_back(*((unsigned int *)&sharpness));
|
||||
}
|
||||
#else
|
||||
// XXX: workaround. GetPatchParamTable() will be deprecated though.
|
||||
Far::PatchParamTable const & patchParamTable =
|
||||
farPatchTable->GetPatchParamTable();
|
||||
std::vector<Far::Index> const &sharpnessIndexTable =
|
||||
farPatchTable->GetSharpnessIndexTable();
|
||||
int numPatchesJ = farPatchTable->GetNumPatches(j);
|
||||
for (int k = 0; k < numPatchesJ; ++k) {
|
||||
float sharpness = 0.0;
|
||||
int patchIndex = (int)_patchParamBuffer.size();
|
||||
if (patchIndex < (int)sharpnessIndexTable.size()) {
|
||||
int sharpnessIndex = sharpnessIndexTable[patchIndex];
|
||||
if (sharpnessIndex >= 0)
|
||||
sharpness = farPatchTable->GetSharpnessValues()[sharpnessIndex];
|
||||
}
|
||||
PatchParam param;
|
||||
//param.patchParam = patchParamTable[patchIndex];
|
||||
param.field0 = patchParamTable[patchIndex].field0;
|
||||
param.field1 = patchParamTable[patchIndex].field1;
|
||||
param.sharpness = sharpness;
|
||||
_patchParamBuffer.push_back(param);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
128
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuPatchTable.h
vendored
Normal file
128
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuPatchTable.h
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CPU_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_OSD_CPU_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <vector>
|
||||
#include "../far/patchDescriptor.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/types.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far{
|
||||
class PatchTable;
|
||||
};
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Cpu patch table
|
||||
///
|
||||
/// XXX: We can use just Far::PatchTable for typical CpuEval use cases.
|
||||
///
|
||||
/// Currently this class exists because of the template resolution
|
||||
/// for the CpuEvaluator's generic interface functions
|
||||
/// (glEvalLimit example uses), and
|
||||
/// device-specific patch tables such as GLPatchTables internally use
|
||||
/// as a staging buffer to splice patcharray and interleave sharpnesses.
|
||||
///
|
||||
/// Ideally Far::PatchTables should have the same data representation
|
||||
/// and accessors so that we don't have to copy data unnecessarily.
|
||||
///
|
||||
class CpuPatchTable {
|
||||
public:
|
||||
static CpuPatchTable *Create(const Far::PatchTable *patchTable,
|
||||
void *deviceContext = NULL) {
|
||||
(void)deviceContext; // unused
|
||||
return new CpuPatchTable(patchTable);
|
||||
}
|
||||
|
||||
explicit CpuPatchTable(const Far::PatchTable *patchTable);
|
||||
~CpuPatchTable() {}
|
||||
|
||||
const PatchArray *GetPatchArrayBuffer() const {
|
||||
return &_patchArrays[0];
|
||||
}
|
||||
const int *GetPatchIndexBuffer() const {
|
||||
return &_indexBuffer[0];
|
||||
}
|
||||
const PatchParam *GetPatchParamBuffer() const {
|
||||
return &_patchParamBuffer[0];
|
||||
}
|
||||
|
||||
size_t GetNumPatchArrays() const {
|
||||
return _patchArrays.size();
|
||||
}
|
||||
size_t GetPatchIndexSize() const {
|
||||
return _indexBuffer.size();
|
||||
}
|
||||
size_t GetPatchParamSize() const {
|
||||
return _patchParamBuffer.size();
|
||||
}
|
||||
|
||||
const PatchArray *GetVaryingPatchArrayBuffer() const {
|
||||
if (_varyingPatchArrays.empty()) {
|
||||
return NULL;
|
||||
}
|
||||
return &_varyingPatchArrays[0];
|
||||
}
|
||||
const int *GetVaryingPatchIndexBuffer() const {
|
||||
if (_varyingIndexBuffer.empty()) {
|
||||
return NULL;
|
||||
}
|
||||
return &_varyingIndexBuffer[0];
|
||||
}
|
||||
size_t GetVaryingPatchIndexSize() const {
|
||||
return _varyingIndexBuffer.size();
|
||||
}
|
||||
|
||||
int GetNumFVarChannels() const {
|
||||
return (int)_fvarPatchArrays.size();
|
||||
}
|
||||
const PatchArray *GetFVarPatchArrayBuffer(int fvarChannel = 0) const {
|
||||
return &_fvarPatchArrays[fvarChannel][0];
|
||||
}
|
||||
const int *GetFVarPatchIndexBuffer(int fvarChannel = 0) const {
|
||||
return &_fvarIndexBuffers[fvarChannel][0];
|
||||
}
|
||||
size_t GetFVarPatchIndexSize(int fvarChannel = 0) const {
|
||||
return _fvarIndexBuffers[fvarChannel].size();
|
||||
}
|
||||
const PatchParam *GetFVarPatchParamBuffer(int fvarChannel= 0) const {
|
||||
return &_fvarParamBuffers[fvarChannel][0];
|
||||
}
|
||||
size_t GetFVarPatchParamSize(int fvarChannel = 0) const {
|
||||
return _fvarParamBuffers[fvarChannel].size();
|
||||
}
|
||||
|
||||
protected:
|
||||
PatchArrayVector _patchArrays;
|
||||
std::vector<int> _indexBuffer;
|
||||
PatchParamVector _patchParamBuffer;
|
||||
|
||||
PatchArrayVector _varyingPatchArrays;
|
||||
std::vector<int> _varyingIndexBuffer;
|
||||
|
||||
std::vector< PatchArrayVector > _fvarPatchArrays;
|
||||
std::vector< std::vector<int> > _fvarIndexBuffers;
|
||||
std::vector< PatchParamVector > _fvarParamBuffers;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CPU_PATCH_TABLE_H
|
||||
67
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuVertexBuffer.cpp
vendored
Normal file
67
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuVertexBuffer.cpp
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/cpuVertexBuffer.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuVertexBuffer::CpuVertexBuffer(int numElements, int numVertices)
|
||||
: _numElements(numElements),
|
||||
_numVertices(numVertices),
|
||||
_cpuBuffer(NULL) {
|
||||
|
||||
_cpuBuffer = new float[numElements * numVertices];
|
||||
}
|
||||
|
||||
CpuVertexBuffer::~CpuVertexBuffer() {
|
||||
|
||||
delete[] _cpuBuffer;
|
||||
}
|
||||
|
||||
CpuVertexBuffer *
|
||||
CpuVertexBuffer::Create(int numElements, int numVertices,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
return new CpuVertexBuffer(numElements, numVertices);
|
||||
}
|
||||
|
||||
void
|
||||
CpuVertexBuffer::UpdateData(const float *src, int startVertex, int numVertices,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
memcpy(_cpuBuffer + startVertex * _numElements,
|
||||
src, GetNumElements() * numVertices * sizeof(float));
|
||||
}
|
||||
|
||||
int
|
||||
CpuVertexBuffer::GetNumElements() const {
|
||||
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int
|
||||
CpuVertexBuffer::GetNumVertices() const {
|
||||
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
float*
|
||||
CpuVertexBuffer::BindCpuBuffer() {
|
||||
|
||||
return _cpuBuffer;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
66
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuVertexBuffer.h
vendored
Normal file
66
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cpuVertexBuffer.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CPU_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_CPU_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Concrete vertex buffer class for CPU subdivision.
|
||||
///
|
||||
/// CpuVertexBuffer implements the VertexBufferInterface. An instance
|
||||
/// of this buffer class can be passed to CpuEvaluator
|
||||
///
|
||||
class CpuVertexBuffer {
|
||||
public:
|
||||
/// Creator. Returns NULL if error.
|
||||
static CpuVertexBuffer * Create(int numElements, int numVertices,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Destructor.
|
||||
~CpuVertexBuffer();
|
||||
|
||||
/// 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 startVertex, int numVertices,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Returns how many elements defined in this vertex buffer.
|
||||
int GetNumElements() const;
|
||||
|
||||
/// Returns how many vertices allocated in this vertex buffer.
|
||||
int GetNumVertices() const;
|
||||
|
||||
/// Returns the address of CPU buffer
|
||||
float * BindCpuBuffer();
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
CpuVertexBuffer(int numElements, int numVertices);
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
float *_cpuBuffer;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CPU_VERTEX_BUFFER_H
|
||||
134
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaD3D11VertexBuffer.cpp
vendored
Normal file
134
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaD3D11VertexBuffer.cpp
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/cudaD3D11VertexBuffer.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <D3D11.h>
|
||||
#include <cuda_runtime.h>
|
||||
#include <cuda_d3d11_interop.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CudaD3D11VertexBuffer::CudaD3D11VertexBuffer(int numElements, int numVertices)
|
||||
: _numElements(numElements), _numVertices(numVertices),
|
||||
_d3d11Buffer(NULL), _cudaBuffer(NULL), _cudaResource(NULL) {
|
||||
}
|
||||
|
||||
CudaD3D11VertexBuffer::~CudaD3D11VertexBuffer() {
|
||||
|
||||
unmap();
|
||||
cudaGraphicsUnregisterResource(_cudaResource);
|
||||
_d3d11Buffer->Release();
|
||||
}
|
||||
|
||||
CudaD3D11VertexBuffer *
|
||||
CudaD3D11VertexBuffer::Create(int numElements, int numVertices,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
CudaD3D11VertexBuffer *instance =
|
||||
new CudaD3D11VertexBuffer(numElements, numVertices);
|
||||
|
||||
ID3D11Device *device;
|
||||
deviceContext->GetDevice(&device);
|
||||
if (instance->allocate(device)) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
CudaD3D11VertexBuffer::UpdateData(const float *src,
|
||||
int startVertex, int numVertices,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
map();
|
||||
cudaMemcpy((float*)_cudaBuffer + _numElements * startVertex,
|
||||
src, _numElements * numVertices * sizeof(float),
|
||||
cudaMemcpyHostToDevice);
|
||||
}
|
||||
|
||||
int
|
||||
CudaD3D11VertexBuffer::GetNumElements() const {
|
||||
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int
|
||||
CudaD3D11VertexBuffer::GetNumVertices() const {
|
||||
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
float *
|
||||
CudaD3D11VertexBuffer::BindCudaBuffer() {
|
||||
|
||||
map();
|
||||
return (float*)_cudaBuffer;
|
||||
}
|
||||
|
||||
ID3D11Buffer *
|
||||
CudaD3D11VertexBuffer::BindD3D11Buffer(ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
unmap();
|
||||
return _d3d11Buffer;
|
||||
}
|
||||
|
||||
bool
|
||||
CudaD3D11VertexBuffer::allocate(ID3D11Device *device) {
|
||||
|
||||
D3D11_BUFFER_DESC hBufferDesc;
|
||||
hBufferDesc.ByteWidth = _numElements * _numVertices * sizeof(float);
|
||||
hBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
hBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_SHADER_RESOURCE;
|
||||
hBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
hBufferDesc.MiscFlags = 0;
|
||||
hBufferDesc.StructureByteStride = sizeof(float);
|
||||
|
||||
HRESULT hr;
|
||||
hr = device->CreateBuffer(&hBufferDesc, NULL, &_d3d11Buffer);
|
||||
if(FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Fail in CreateBuffer\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// register d3d11buffer as cuda resource
|
||||
cudaError_t err = cudaGraphicsD3D11RegisterResource(
|
||||
&_cudaResource, _d3d11Buffer, cudaGraphicsRegisterFlagsNone);
|
||||
|
||||
if (err != cudaSuccess) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CudaD3D11VertexBuffer::map() {
|
||||
|
||||
if (_cudaBuffer) return;
|
||||
size_t num_bytes;
|
||||
void *ptr;
|
||||
|
||||
cudaGraphicsMapResources(1, &_cudaResource, 0);
|
||||
cudaGraphicsResourceGetMappedPointer(&ptr, &num_bytes, _cudaResource);
|
||||
_cudaBuffer = ptr;
|
||||
}
|
||||
|
||||
void
|
||||
CudaD3D11VertexBuffer::unmap() {
|
||||
|
||||
if (_cudaBuffer == NULL) return;
|
||||
cudaGraphicsUnmapResources(1, &_cudaResource, 0);
|
||||
_cudaBuffer = NULL;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
92
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaD3D11VertexBuffer.h
vendored
Normal file
92
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaD3D11VertexBuffer.h
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CUDA_D3D11_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_CUDA_D3D11_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
struct cudaGraphicsResource;
|
||||
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Concrete vertex buffer class for cuda subdivision and D3D11 drawing.
|
||||
///
|
||||
/// CudaD3D11VertexBuffer implements CudaVertexBufferInterface and
|
||||
/// D3D11VertexBufferInterface.
|
||||
///
|
||||
/// The buffer interop between Cuda and D3D is handled automatically when a
|
||||
/// client calls BindCudaBuffer and BindVBO methods.
|
||||
///
|
||||
class CudaD3D11VertexBuffer {
|
||||
public:
|
||||
/// Creator. Returns NULL if error.
|
||||
static CudaD3D11VertexBuffer * Create(int numElements,
|
||||
int numVertices,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Destructor.
|
||||
virtual ~CudaD3D11VertexBuffer();
|
||||
|
||||
/// 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 startVertex, int numVertices,
|
||||
void * /*deviceContext*/);
|
||||
|
||||
/// Returns how many elements defined in this vertex buffer.
|
||||
int GetNumElements() const;
|
||||
|
||||
/// Returns how many vertices allocated in this vertex buffer.
|
||||
int GetNumVertices() const;
|
||||
|
||||
/// Returns cuda memory. DX buffer will be mapped to cuda resource
|
||||
/// if necessary.
|
||||
float * BindCudaBuffer();
|
||||
|
||||
/// Returns the D3D11 buffer object.
|
||||
ID3D11Buffer *BindD3D11Buffer(ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Returns the D3D11 buffer object (for Osd::Mesh interface)
|
||||
ID3D11Buffer *BindVBO(ID3D11DeviceContext *deviceContext) {
|
||||
return BindD3D11Buffer(deviceContext);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
CudaD3D11VertexBuffer(int numElements, int numVertices);
|
||||
|
||||
bool allocate(ID3D11Device *device);
|
||||
|
||||
// Acquires a cuda resource from DX11
|
||||
void map();
|
||||
|
||||
// Releases a cuda resource to DX11
|
||||
void unmap();
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
ID3D11Buffer *_d3d11Buffer;
|
||||
void *_cudaBuffer;
|
||||
cudaGraphicsResource *_cudaResource;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CUDA_D3D11_VERTEX_BUFFER_H
|
||||
368
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaEvaluator.cpp
vendored
Normal file
368
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaEvaluator.cpp
vendored
Normal file
@@ -0,0 +1,368 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/cudaEvaluator.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <vector>
|
||||
|
||||
#include "../far/stencilTable.h"
|
||||
#include "../osd/types.h"
|
||||
|
||||
extern "C" {
|
||||
void CudaEvalStencils(const float *src,
|
||||
float *dst,
|
||||
int length,
|
||||
int srcStride,
|
||||
int dstStride,
|
||||
const int * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end);
|
||||
|
||||
void CudaEvalPatches(
|
||||
const float *src, float *dst,
|
||||
int length, int srcStride, int dstStride,
|
||||
int numPatchCoords,
|
||||
const void *patchCoords,
|
||||
const void *patchArrays,
|
||||
const int *patchIndices,
|
||||
const void *patchParams);
|
||||
|
||||
void CudaEvalPatchesWithDerivatives(
|
||||
const float *src, float *dst,
|
||||
float *du, float *dv,
|
||||
float *duu, float *duv, float *dvv,
|
||||
int length, int srcStride, int dstStride,
|
||||
int duStride, int dvStride,
|
||||
int duuStride, int duvStride, int dvvStride,
|
||||
int numPatchCoords,
|
||||
const void *patchCoords,
|
||||
const void *patchArrays,
|
||||
const int *patchIndices,
|
||||
const void *patchParams);
|
||||
|
||||
}
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
template <class T> void *
|
||||
createCudaBuffer(std::vector<T> const & src) {
|
||||
if (src.empty()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * devicePtr = 0;
|
||||
|
||||
size_t size = src.size()*sizeof(T);
|
||||
|
||||
cudaError_t err = cudaMalloc(&devicePtr, size);
|
||||
if (err != cudaSuccess) {
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
err = cudaMemcpy(devicePtr, &src.at(0), size, cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess) {
|
||||
cudaFree(devicePtr);
|
||||
return 0;
|
||||
}
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CudaStencilTable::CudaStencilTable(Far::StencilTable const *stencilTable) {
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCudaBuffer(stencilTable->GetSizes());
|
||||
_offsets = createCudaBuffer(stencilTable->GetOffsets());
|
||||
_indices = createCudaBuffer(stencilTable->GetControlIndices());
|
||||
_weights = createCudaBuffer(stencilTable->GetWeights());
|
||||
_duWeights = _dvWeights = NULL;
|
||||
_duuWeights = _duvWeights = _dvvWeights = NULL;
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
_duWeights = _dvWeights = NULL;
|
||||
_duuWeights = _duvWeights = _dvvWeights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CudaStencilTable::CudaStencilTable(Far::LimitStencilTable const *limitStencilTable) {
|
||||
_numStencils = limitStencilTable->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCudaBuffer(limitStencilTable->GetSizes());
|
||||
_offsets = createCudaBuffer(limitStencilTable->GetOffsets());
|
||||
_indices = createCudaBuffer(limitStencilTable->GetControlIndices());
|
||||
_weights = createCudaBuffer(limitStencilTable->GetWeights());
|
||||
_duWeights = createCudaBuffer(limitStencilTable->GetDuWeights());
|
||||
_dvWeights = createCudaBuffer(limitStencilTable->GetDvWeights());
|
||||
_duuWeights = createCudaBuffer(limitStencilTable->GetDuuWeights());
|
||||
_duvWeights = createCudaBuffer(limitStencilTable->GetDuvWeights());
|
||||
_dvvWeights = createCudaBuffer(limitStencilTable->GetDvvWeights());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
_duWeights = _dvWeights = NULL;
|
||||
_duuWeights = _duvWeights = _dvvWeights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CudaStencilTable::~CudaStencilTable() {
|
||||
if (_sizes) cudaFree(_sizes);
|
||||
if (_offsets) cudaFree(_offsets);
|
||||
if (_indices) cudaFree(_indices);
|
||||
if (_weights) cudaFree(_weights);
|
||||
if (_duWeights) cudaFree(_duWeights);
|
||||
if (_dvWeights) cudaFree(_dvWeights);
|
||||
if (_duuWeights) cudaFree(_duuWeights);
|
||||
if (_duvWeights) cudaFree(_duvWeights);
|
||||
if (_dvvWeights) cudaFree(_dvvWeights);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CudaEvaluator::EvalStencils(const float *src, BufferDescriptor const &srcDesc,
|
||||
float *dst, BufferDescriptor const &dstDesc,
|
||||
const int * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end) {
|
||||
if (dst == NULL) return false;
|
||||
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
dst + dstDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
dstDesc.stride,
|
||||
sizes, offsets, indices, weights,
|
||||
start, end);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CudaEvaluator::EvalStencils(const float *src, BufferDescriptor const &srcDesc,
|
||||
float *dst, BufferDescriptor const &dstDesc,
|
||||
float *du, BufferDescriptor const &duDesc,
|
||||
float *dv, BufferDescriptor const &dvDesc,
|
||||
const int * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
const float * duWeights,
|
||||
const float * dvWeights,
|
||||
int start,
|
||||
int end) {
|
||||
// PERFORMANCE: need to combine 3 launches together
|
||||
if (dst) {
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
dst + dstDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
dstDesc.stride,
|
||||
sizes, offsets, indices, weights,
|
||||
start, end);
|
||||
}
|
||||
if (du) {
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
du + duDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
duDesc.stride,
|
||||
sizes, offsets, indices, duWeights,
|
||||
start, end);
|
||||
}
|
||||
if (dv) {
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
dv + dvDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
dvDesc.stride,
|
||||
sizes, offsets, indices, dvWeights,
|
||||
start, end);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CudaEvaluator::EvalStencils(const float *src, BufferDescriptor const &srcDesc,
|
||||
float *dst, BufferDescriptor const &dstDesc,
|
||||
float *du, BufferDescriptor const &duDesc,
|
||||
float *dv, BufferDescriptor const &dvDesc,
|
||||
float *duu, BufferDescriptor const &duuDesc,
|
||||
float *duv, BufferDescriptor const &duvDesc,
|
||||
float *dvv, BufferDescriptor const &dvvDesc,
|
||||
const int * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
const float * duWeights,
|
||||
const float * dvWeights,
|
||||
const float * duuWeights,
|
||||
const float * duvWeights,
|
||||
const float * dvvWeights,
|
||||
int start,
|
||||
int end) {
|
||||
// PERFORMANCE: need to combine 3 launches together
|
||||
if (dst) {
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
dst + dstDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
dstDesc.stride,
|
||||
sizes, offsets, indices, weights,
|
||||
start, end);
|
||||
}
|
||||
if (du) {
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
du + duDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
duDesc.stride,
|
||||
sizes, offsets, indices, duWeights,
|
||||
start, end);
|
||||
}
|
||||
if (dv) {
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
dv + dvDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
dvDesc.stride,
|
||||
sizes, offsets, indices, dvWeights,
|
||||
start, end);
|
||||
}
|
||||
if (duu) {
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
duu + duuDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
duuDesc.stride,
|
||||
sizes, offsets, indices, duuWeights,
|
||||
start, end);
|
||||
}
|
||||
if (duv) {
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
duv + duvDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
duvDesc.stride,
|
||||
sizes, offsets, indices, duvWeights,
|
||||
start, end);
|
||||
}
|
||||
if (dvv) {
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
dvv + dvvDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
dvvDesc.stride,
|
||||
sizes, offsets, indices, dvvWeights,
|
||||
start, end);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CudaEvaluator::EvalPatches(const float *src,
|
||||
BufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
BufferDescriptor const &dstDesc,
|
||||
int numPatchCoords,
|
||||
const PatchCoord *patchCoords,
|
||||
const PatchArray *patchArrays,
|
||||
const int *patchIndices,
|
||||
const PatchParam *patchParams) {
|
||||
if (src) src += srcDesc.offset;
|
||||
if (dst) dst += dstDesc.offset;
|
||||
|
||||
CudaEvalPatches(src, dst,
|
||||
srcDesc.length, srcDesc.stride, dstDesc.stride,
|
||||
numPatchCoords, patchCoords, patchArrays, patchIndices, patchParams);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CudaEvaluator::EvalPatches(
|
||||
const float *src, BufferDescriptor const &srcDesc,
|
||||
float *dst, BufferDescriptor const &dstDesc,
|
||||
float *du, BufferDescriptor const &duDesc,
|
||||
float *dv, BufferDescriptor const &dvDesc,
|
||||
int numPatchCoords,
|
||||
const PatchCoord *patchCoords,
|
||||
const PatchArray *patchArrays,
|
||||
const int *patchIndices,
|
||||
const PatchParam *patchParams) {
|
||||
|
||||
if (src) src += srcDesc.offset;
|
||||
if (dst) dst += dstDesc.offset;
|
||||
if (du) du += duDesc.offset;
|
||||
if (dv) dv += dvDesc.offset;
|
||||
|
||||
CudaEvalPatchesWithDerivatives(
|
||||
src, dst, du, dv, NULL, NULL, NULL,
|
||||
srcDesc.length, srcDesc.stride, dstDesc.stride,
|
||||
duDesc.stride, dvDesc.stride, 0, 0, 0,
|
||||
numPatchCoords, patchCoords, patchArrays, patchIndices, patchParams);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CudaEvaluator::EvalPatches(
|
||||
const float *src, BufferDescriptor const &srcDesc,
|
||||
float *dst, BufferDescriptor const &dstDesc,
|
||||
float *du, BufferDescriptor const &duDesc,
|
||||
float *dv, BufferDescriptor const &dvDesc,
|
||||
float *duu, BufferDescriptor const &duuDesc,
|
||||
float *duv, BufferDescriptor const &duvDesc,
|
||||
float *dvv, BufferDescriptor const &dvvDesc,
|
||||
int numPatchCoords,
|
||||
const PatchCoord *patchCoords,
|
||||
const PatchArray *patchArrays,
|
||||
const int *patchIndices,
|
||||
const PatchParam *patchParams) {
|
||||
|
||||
if (src) src += srcDesc.offset;
|
||||
if (dst) dst += dstDesc.offset;
|
||||
if (du) du += duDesc.offset;
|
||||
if (dv) dv += dvDesc.offset;
|
||||
if (duu) duu += duuDesc.offset;
|
||||
if (duv) duv += duvDesc.offset;
|
||||
if (dvv) dvv += dvvDesc.offset;
|
||||
|
||||
CudaEvalPatchesWithDerivatives(
|
||||
src, dst, du, dv, duu, duv, dvv,
|
||||
srcDesc.length, srcDesc.stride, dstDesc.stride,
|
||||
duDesc.stride, dvDesc.stride,
|
||||
duuDesc.stride, duvDesc.stride, dvvDesc.stride,
|
||||
numPatchCoords, patchCoords, patchArrays, patchIndices, patchParams);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* static */
|
||||
void
|
||||
CudaEvaluator::Synchronize(void * /*deviceContext*/) {
|
||||
cudaThreadSynchronize();
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
1256
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaEvaluator.h
vendored
Normal file
1256
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaEvaluator.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
156
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaGLVertexBuffer.cpp
vendored
Normal file
156
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaGLVertexBuffer.cpp
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "glLoader.h"
|
||||
|
||||
#include "../osd/cudaGLVertexBuffer.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <cuda_gl_interop.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CudaGLVertexBuffer::CudaGLVertexBuffer(int numElements, int numVertices)
|
||||
: _numElements(numElements), _numVertices(numVertices),
|
||||
_vbo(0), _devicePtr(0), _cudaResource(0) {
|
||||
|
||||
// Initialize internal OpenGL loader library if necessary
|
||||
OpenSubdiv::internal::GLLoader::libraryInitializeGL();
|
||||
}
|
||||
|
||||
CudaGLVertexBuffer::~CudaGLVertexBuffer() {
|
||||
|
||||
unmap();
|
||||
cudaGraphicsUnregisterResource(_cudaResource);
|
||||
glDeleteBuffers(1, &_vbo);
|
||||
}
|
||||
|
||||
CudaGLVertexBuffer *
|
||||
CudaGLVertexBuffer::Create(int numElements, int numVertices, void *) {
|
||||
CudaGLVertexBuffer *instance =
|
||||
new CudaGLVertexBuffer(numElements, numVertices);
|
||||
if (instance->allocate()) return instance;
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "CudaGLVertexBuffer::Create failed.\n");
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
CudaGLVertexBuffer::UpdateData(const float *src,
|
||||
int startVertex, int numVertices,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
map();
|
||||
cudaError_t err = cudaMemcpy((float*)_devicePtr + _numElements * startVertex,
|
||||
src,
|
||||
_numElements * numVertices * sizeof(float),
|
||||
cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess)
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"CudaGLVertexBuffer::UpdateData failed. : %s\n",
|
||||
cudaGetErrorString(err));
|
||||
}
|
||||
|
||||
int
|
||||
CudaGLVertexBuffer::GetNumElements() const {
|
||||
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int
|
||||
CudaGLVertexBuffer::GetNumVertices() const {
|
||||
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
float *
|
||||
CudaGLVertexBuffer::BindCudaBuffer() {
|
||||
|
||||
map();
|
||||
return static_cast<float*>(_devicePtr);
|
||||
}
|
||||
|
||||
CudaGLVertexBuffer::ID
|
||||
CudaGLVertexBuffer::BindVBO(void * /*deviceContext*/) {
|
||||
|
||||
unmap();
|
||||
return _vbo;
|
||||
}
|
||||
|
||||
bool
|
||||
CudaGLVertexBuffer::allocate() {
|
||||
|
||||
int size = _numElements * _numVertices * sizeof(float);
|
||||
|
||||
|
||||
#if defined(GL_ARB_direct_state_access)
|
||||
if (OSD_OPENGL_HAS(ARB_direct_state_access)) {
|
||||
glCreateBuffers(1, &_vbo);
|
||||
glNamedBufferData(_vbo, size, 0, GL_DYNAMIC_DRAW);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLint prev = 0;
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev);
|
||||
glGenBuffers(1, &_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, prev);
|
||||
}
|
||||
|
||||
// register vbo as cuda resource
|
||||
cudaError_t err = cudaGraphicsGLRegisterBuffer(
|
||||
&_cudaResource, _vbo, cudaGraphicsMapFlagsWriteDiscard);
|
||||
|
||||
if (err != cudaSuccess) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CudaGLVertexBuffer::map() {
|
||||
|
||||
if (_devicePtr) return;
|
||||
size_t num_bytes;
|
||||
void *ptr;
|
||||
|
||||
cudaError_t err = cudaGraphicsMapResources(1, &_cudaResource, 0);
|
||||
if (err != cudaSuccess)
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"CudaGLVertexBuffer::map failed.\n%s\n",
|
||||
cudaGetErrorString(err));
|
||||
err = cudaGraphicsResourceGetMappedPointer(&ptr, &num_bytes, _cudaResource);
|
||||
if (err != cudaSuccess)
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"CudaGLVertexBuffer::map failed.\n%s\n",
|
||||
cudaGetErrorString(err));
|
||||
_devicePtr = ptr;
|
||||
}
|
||||
|
||||
void
|
||||
CudaGLVertexBuffer::unmap() {
|
||||
|
||||
if (_devicePtr == NULL) return;
|
||||
cudaError_t err = cudaGraphicsUnmapResources(1, &_cudaResource, 0);
|
||||
if (err != cudaSuccess)
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"CudaGLVertexBuffer::unmap failed.\n%s\n",
|
||||
cudaGetErrorString(err));
|
||||
_devicePtr = NULL;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
91
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaGLVertexBuffer.h
vendored
Normal file
91
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaGLVertexBuffer.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CUDA_GL_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_CUDA_GL_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
#include <cuda_gl_interop.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Concrete vertex buffer class for cuda subdivision and OpenGL drawing.
|
||||
///
|
||||
/// CudaGLVertexBuffer implements CudaVertexBufferInterface and
|
||||
/// GLVertexBufferInterface.
|
||||
///
|
||||
/// The buffer interop between Cuda and GL is handled automatically when a
|
||||
/// client calls BindCudaBuffer and BindVBO methods.
|
||||
///
|
||||
class CudaGLVertexBuffer {
|
||||
public:
|
||||
using ID = unsigned int; // GLuint resource ID
|
||||
|
||||
/// Creator. Returns NULL if error.
|
||||
static CudaGLVertexBuffer * Create(int numElements, int numVertices,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Destructor.
|
||||
~CudaGLVertexBuffer();
|
||||
|
||||
/// 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 startVertex, int numVertices,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Returns how many elements defined in this vertex buffer.
|
||||
int GetNumElements() const;
|
||||
|
||||
/// Returns how many vertices allocated in this vertex buffer.
|
||||
int GetNumVertices() const;
|
||||
|
||||
/// Returns cuda memory. GL buffer will be mapped to cuda resource
|
||||
/// if necessary.
|
||||
float * BindCudaBuffer();
|
||||
|
||||
/// Returns the GL buffer object. If the buffer is mapped as a cuda
|
||||
/// resource, it will be unmapped back to GL.
|
||||
ID BindVBO(void *deviceContext = NULL);
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
CudaGLVertexBuffer(int numElements, int numVertices);
|
||||
|
||||
/// Allocates VBO for this buffer and register as a cuda resource.
|
||||
/// Returns true if success.
|
||||
bool allocate();
|
||||
|
||||
/// Acquire a cuda resource from GL.
|
||||
void map();
|
||||
|
||||
/// Release a cuda resource to GL.
|
||||
void unmap();
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
ID _vbo;
|
||||
void *_devicePtr;
|
||||
struct cudaGraphicsResource *_cudaResource;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CUDA_GL_VERTEX_BUFFER_H
|
||||
409
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaKernel.cu
vendored
Normal file
409
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaKernel.cu
vendored
Normal file
@@ -0,0 +1,409 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#define OSD_PATCH_BASIS_CUDA
|
||||
#include "../osd/patchBasisTypes.h"
|
||||
#include "../osd/patchBasis.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
template<int N> struct DeviceVertex {
|
||||
|
||||
float v[N];
|
||||
|
||||
__device__ void addWithWeight(DeviceVertex<N> const & src, float weight) {
|
||||
#pragma unroll
|
||||
for(int i = 0; i < N; ++i){
|
||||
v[i] += src.v[i] * weight;
|
||||
}
|
||||
}
|
||||
|
||||
__device__ void clear() {
|
||||
#pragma unroll
|
||||
for(int i = 0; i < N; ++i){
|
||||
v[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Specialize DeviceVertex for N=0 to avoid compile error:
|
||||
// "flexible array member in otherwise empty struct"
|
||||
template<> struct DeviceVertex<0> {
|
||||
__device__ void addWithWeight(DeviceVertex<0> &src, float weight) {}
|
||||
__device__ void clear() {}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
__device__ void clear(float *dst, int count)
|
||||
{
|
||||
for(int i = 0; i < count; ++i) dst[i] = 0;
|
||||
}
|
||||
|
||||
__device__ void addWithWeight(float *dst, float const *src, float weight, int count)
|
||||
{
|
||||
for(int i = 0; i < count; ++i) dst[i] += src[i] * weight;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
template <int NUM_ELEMENTS> __global__ void
|
||||
computeStencils(float const * cvs, float * vbuffer,
|
||||
int const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end) {
|
||||
|
||||
DeviceVertex<NUM_ELEMENTS> const * src =
|
||||
(DeviceVertex<NUM_ELEMENTS> const *)cvs;
|
||||
|
||||
DeviceVertex<NUM_ELEMENTS> * verts =
|
||||
(DeviceVertex<NUM_ELEMENTS> *)vbuffer;
|
||||
|
||||
int first = start + threadIdx.x + blockIdx.x*blockDim.x;
|
||||
|
||||
for (int i=first; i<end; i += blockDim.x * gridDim.x) {
|
||||
|
||||
int const * lindices = indices + offsets[i];
|
||||
float const * lweights = weights + offsets[i];
|
||||
|
||||
DeviceVertex<NUM_ELEMENTS> dst;
|
||||
dst.clear();
|
||||
|
||||
for (int j=0; j<sizes[i]; ++j) {
|
||||
dst.addWithWeight(src[lindices[j]], lweights[j]);
|
||||
}
|
||||
verts[i] = dst;
|
||||
}
|
||||
}
|
||||
|
||||
__global__ void
|
||||
computeStencils(float const * cvs, float * dst,
|
||||
int length,
|
||||
int srcStride,
|
||||
int dstStride,
|
||||
int const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end) {
|
||||
|
||||
int first = start + threadIdx.x + blockIdx.x*blockDim.x;
|
||||
|
||||
for (int i=first; i<end; i += blockDim.x * gridDim.x) {
|
||||
|
||||
int const * lindices = indices + offsets[i];
|
||||
float const * lweights = weights + offsets[i];
|
||||
|
||||
float * dstVert = dst + i*dstStride;
|
||||
clear(dstVert, length);
|
||||
|
||||
for (int j=0; j<sizes[i]; ++j) {
|
||||
|
||||
float const * srcVert = cvs + lindices[j]*srcStride;
|
||||
|
||||
addWithWeight(dstVert, srcVert, lweights[j], length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define USE_NVIDIA_OPTIMIZATION
|
||||
#ifdef USE_NVIDIA_OPTIMIZATION
|
||||
|
||||
template< int NUM_ELEMENTS, int NUM_THREADS_PER_BLOCK >
|
||||
__global__ void computeStencilsNv(float const *__restrict cvs,
|
||||
float * vbuffer,
|
||||
int const *__restrict sizes,
|
||||
int const *__restrict offsets,
|
||||
int const *__restrict indices,
|
||||
float const *__restrict weights,
|
||||
int start,
|
||||
int end)
|
||||
{
|
||||
// Shared memory to stage indices/weights.
|
||||
__shared__ int smem_indices_buffer[NUM_THREADS_PER_BLOCK];
|
||||
__shared__ float smem_weights_buffer[NUM_THREADS_PER_BLOCK];
|
||||
|
||||
// The size of a single warp.
|
||||
const int WARP_SIZE = 32;
|
||||
// The number of warps per block.
|
||||
const int NUM_WARPS_PER_BLOCK = NUM_THREADS_PER_BLOCK / WARP_SIZE;
|
||||
// The number of outputs computed by a single warp.
|
||||
const int NUM_OUTPUTS_PER_WARP = WARP_SIZE / NUM_ELEMENTS;
|
||||
// The number of outputs computed by a block of threads.
|
||||
const int NUM_OUTPUTS_PER_BLOCK = NUM_OUTPUTS_PER_WARP*NUM_WARPS_PER_BLOCK;
|
||||
// The number of active threads in a warp.
|
||||
const int NUM_ACTIVE_THREADS_PER_WARP = NUM_OUTPUTS_PER_WARP * NUM_ELEMENTS;
|
||||
|
||||
// The number of the warp inside the block.
|
||||
const int warpId = threadIdx.x / WARP_SIZE;
|
||||
const int laneId = threadIdx.x % WARP_SIZE;
|
||||
|
||||
// We use NUM_ELEMENTS threads per output. Find which output/element a thread works on.
|
||||
int outputIdx = warpId*NUM_OUTPUTS_PER_WARP + laneId/NUM_ELEMENTS, elementIdx = laneId%NUM_ELEMENTS;
|
||||
|
||||
// Each output corresponds to a section of shared memory.
|
||||
volatile int *smem_indices = &smem_indices_buffer[warpId*WARP_SIZE + (laneId/NUM_ELEMENTS)*NUM_ELEMENTS];
|
||||
volatile float *smem_weights = &smem_weights_buffer[warpId*WARP_SIZE + (laneId/NUM_ELEMENTS)*NUM_ELEMENTS];
|
||||
|
||||
// Disable threads that have nothing to do inside the warp.
|
||||
int i = end;
|
||||
if( laneId < NUM_ACTIVE_THREADS_PER_WARP )
|
||||
i = start + blockIdx.x*NUM_OUTPUTS_PER_BLOCK + outputIdx;
|
||||
|
||||
// Iterate over the vertices.
|
||||
for( ; i < end ; i += gridDim.x*NUM_OUTPUTS_PER_BLOCK )
|
||||
{
|
||||
// Each thread computes an element of the final vertex.
|
||||
float x = 0.f;
|
||||
|
||||
// Load the offset and the size for each vertex. We have NUM_THREADS_PER_VERTEX threads loading the same value.
|
||||
const int offset_i = offsets[i], size_i = sizes[i];
|
||||
|
||||
// Iterate over the stencil.
|
||||
for( int j = offset_i, j_end = offset_i+size_i ; j < j_end ; )
|
||||
{
|
||||
int j_it = j + elementIdx;
|
||||
|
||||
// Load some indices and some weights. The transaction is coalesced.
|
||||
smem_indices[elementIdx] = j_it < j_end ? indices[j_it] : 0;
|
||||
smem_weights[elementIdx] = j_it < j_end ? weights[j_it] : 0.f;
|
||||
|
||||
// Thread now collaborates to load the vertices.
|
||||
#pragma unroll
|
||||
for( int k = 0 ; k < NUM_ELEMENTS ; ++k, ++j )
|
||||
if( j < j_end )
|
||||
x += smem_weights[k] * cvs[smem_indices[k]*NUM_ELEMENTS + elementIdx];
|
||||
}
|
||||
|
||||
// Store the vertex.
|
||||
vbuffer[NUM_ELEMENTS*i + elementIdx] = x;
|
||||
}
|
||||
}
|
||||
|
||||
template< int NUM_THREADS_PER_BLOCK >
|
||||
__global__ void computeStencilsNv_v4(float const *__restrict cvs,
|
||||
float * vbuffer,
|
||||
int const *__restrict sizes,
|
||||
int const *__restrict offsets,
|
||||
int const *__restrict indices,
|
||||
float const *__restrict weights,
|
||||
int start,
|
||||
int end)
|
||||
{
|
||||
// Iterate over the vertices.
|
||||
for( int i = start + blockIdx.x*NUM_THREADS_PER_BLOCK + threadIdx.x ; i < end ; i += gridDim.x*NUM_THREADS_PER_BLOCK )
|
||||
{
|
||||
// Each thread computes an element of the final vertex.
|
||||
float4 x = make_float4(0.f, 0.f, 0.f, 0.f);
|
||||
|
||||
// Iterate over the stencil.
|
||||
for( int j = offsets[i], j_end = offsets[i]+sizes[i] ; j < j_end ; ++j )
|
||||
{
|
||||
float w = weights[j];
|
||||
float4 tmp = reinterpret_cast<const float4 *>(cvs)[indices[j]];
|
||||
x.x += w*tmp.x;
|
||||
x.y += w*tmp.y;
|
||||
x.z += w*tmp.z;
|
||||
x.w += w*tmp.w;
|
||||
}
|
||||
|
||||
// Store the vertex.
|
||||
reinterpret_cast<float4*>(vbuffer)[i] = x;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_NVIDIA_OPTIMIZATION
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
__global__ void
|
||||
computePatches(const float *src, float *dst,
|
||||
float *dstDu, float *dstDv,
|
||||
float *dstDuu, float *dstDuv, float *dstDvv,
|
||||
int length, int srcStride, int dstStride,
|
||||
int dstDuStride, int dstDvStride,
|
||||
int dstDuuStride, int dstDuvStride, int dstDvvStride,
|
||||
int numPatchCoords, const OsdPatchCoord *patchCoords,
|
||||
const OsdPatchArray *patchArrayBuffer,
|
||||
const int *patchIndexBuffer,
|
||||
const OsdPatchParam *patchParamBuffer) {
|
||||
|
||||
int first = threadIdx.x + blockIdx.x * blockDim.x;
|
||||
|
||||
// PERFORMANCE: not yet optimized
|
||||
|
||||
for (int i = first; i < numPatchCoords; i += blockDim.x * gridDim.x) {
|
||||
|
||||
OsdPatchCoord const &coord = patchCoords[i];
|
||||
int arrayIndex = coord.arrayIndex;
|
||||
int patchIndex = coord.patchIndex;
|
||||
|
||||
OsdPatchArray const &array = patchArrayBuffer[arrayIndex];
|
||||
OsdPatchParam const ¶m = patchParamBuffer[patchIndex];
|
||||
|
||||
int patchType = OsdPatchParamIsRegular(param)
|
||||
? array.regDesc : array.desc;
|
||||
|
||||
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
|
||||
int nPoints = OsdEvaluatePatchBasis(patchType, param,
|
||||
coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
|
||||
|
||||
int indexBase = array.indexBase + array.stride *
|
||||
(patchIndex - array.primitiveIdBase);
|
||||
|
||||
const int *cvs = patchIndexBuffer + indexBase;
|
||||
|
||||
float * dstVert = dst + i * dstStride;
|
||||
clear(dstVert, length);
|
||||
for (int j = 0; j < nPoints; ++j) {
|
||||
const float * srcVert = src + cvs[j] * srcStride;
|
||||
addWithWeight(dstVert, srcVert, wP[j], length);
|
||||
}
|
||||
if (dstDu) {
|
||||
float *d = dstDu + i * dstDuStride;
|
||||
clear(d, length);
|
||||
for (int j = 0; j < nPoints; ++j) {
|
||||
const float * srcVert = src + cvs[j] * srcStride;
|
||||
addWithWeight(d, srcVert, wDu[j], length);
|
||||
}
|
||||
}
|
||||
if (dstDv) {
|
||||
float *d = dstDv + i * dstDvStride;
|
||||
clear(d, length);
|
||||
for (int j = 0; j < nPoints; ++j) {
|
||||
const float * srcVert = src + cvs[j] * srcStride;
|
||||
addWithWeight(d, srcVert, wDv[j], length);
|
||||
}
|
||||
}
|
||||
if (dstDuu) {
|
||||
float *d = dstDuu + i * dstDuuStride;
|
||||
clear(d, length);
|
||||
for (int j = 0; j < nPoints; ++j) {
|
||||
const float * srcVert = src + cvs[j] * srcStride;
|
||||
addWithWeight(d, srcVert, wDuu[j], length);
|
||||
}
|
||||
}
|
||||
if (dstDuv) {
|
||||
float *d = dstDuv + i * dstDuvStride;
|
||||
clear(d, length);
|
||||
for (int j = 0; j < nPoints; ++j) {
|
||||
const float * srcVert = src + cvs[j] * srcStride;
|
||||
addWithWeight(d, srcVert, wDuv[j], length);
|
||||
}
|
||||
}
|
||||
if (dstDvv) {
|
||||
float *d = dstDvv + i * dstDvvStride;
|
||||
clear(d, length);
|
||||
for (int j = 0; j < nPoints; ++j) {
|
||||
const float * srcVert = src + cvs[j] * srcStride;
|
||||
addWithWeight(d, srcVert, wDvv[j], length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#define OPT_KERNEL(NUM_ELEMENTS, KERNEL, X, Y, ARG) \
|
||||
if (length==NUM_ELEMENTS && srcStride==length && dstStride==length) { \
|
||||
KERNEL<NUM_ELEMENTS><<<X,Y>>>ARG; \
|
||||
return; \
|
||||
}
|
||||
|
||||
#ifdef USE_NVIDIA_OPTIMIZATION
|
||||
#define OPT_KERNEL_NVIDIA(NUM_ELEMENTS, KERNEL, X, Y, ARG) \
|
||||
if (length==NUM_ELEMENTS && srcStride==length && dstStride==length) { \
|
||||
int gridDim = min(X, (end-start+Y-1)/Y); \
|
||||
KERNEL<NUM_ELEMENTS, Y><<<gridDim, Y>>>ARG; \
|
||||
return; \
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
void CudaEvalStencils(
|
||||
const float *src, float *dst,
|
||||
int length, int srcStride, int dstStride,
|
||||
const int * sizes, const int * offsets, const int * indices,
|
||||
const float * weights,
|
||||
int start, int end) {
|
||||
if (length == 0 || srcStride == 0 || dstStride == 0 || (end <= start)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_NVIDIA_OPTIMIZATION
|
||||
OPT_KERNEL_NVIDIA(3, computeStencilsNv, 2048, 256,
|
||||
(src, dst, sizes, offsets, indices, weights, start, end));
|
||||
//OPT_KERNEL_NVIDIA(4, computeStencilsNv, 2048, 256,
|
||||
// (cvs, dst, sizes, offsets, indices, weights, start, end));
|
||||
if (length == 4 && srcStride == length && dstStride == length) {
|
||||
int gridDim = min(2048, (end-start+256-1)/256);
|
||||
computeStencilsNv_v4<256><<<gridDim, 256>>>(
|
||||
src, dst, sizes, offsets, indices, weights, start, end);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
OPT_KERNEL(3, computeStencils, 512, 32,
|
||||
(src, dst, sizes, offsets, indices, weights, start, end));
|
||||
OPT_KERNEL(4, computeStencils, 512, 32,
|
||||
(src, dst, sizes, offsets, indices, weights, start, end));
|
||||
#endif
|
||||
|
||||
// generic case (slow)
|
||||
computeStencils <<<512, 32>>>(
|
||||
src, dst, length, srcStride, dstStride,
|
||||
sizes, offsets, indices, weights, start, end);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void CudaEvalPatches(
|
||||
const float *src, float *dst,
|
||||
int length, int srcStride, int dstStride,
|
||||
int numPatchCoords, const OsdPatchCoord *patchCoords,
|
||||
const OsdPatchArray *patchArrayBuffer,
|
||||
const int *patchIndexBuffer,
|
||||
const OsdPatchParam *patchParamBuffer) {
|
||||
|
||||
// PERFORMANCE: not optimized at all
|
||||
|
||||
computePatches <<<512, 32>>>(
|
||||
src, dst, NULL, NULL, NULL, NULL, NULL,
|
||||
length, srcStride, dstStride, 0, 0, 0, 0, 0,
|
||||
numPatchCoords, patchCoords,
|
||||
patchArrayBuffer, patchIndexBuffer, patchParamBuffer);
|
||||
}
|
||||
|
||||
void CudaEvalPatchesWithDerivatives(
|
||||
const float *src, float *dst,
|
||||
float *dstDu, float *dstDv,
|
||||
float *dstDuu, float *dstDuv, float *dstDvv,
|
||||
int length, int srcStride, int dstStride,
|
||||
int dstDuStride, int dstDvStride,
|
||||
int dstDuuStride, int dstDuvStride, int dstDvvStride,
|
||||
int numPatchCoords, const OsdPatchCoord *patchCoords,
|
||||
const OsdPatchArray *patchArrayBuffer,
|
||||
const int *patchIndexBuffer,
|
||||
const OsdPatchParam *patchParamBuffer) {
|
||||
|
||||
// PERFORMANCE: not optimized at all
|
||||
|
||||
computePatches <<<512, 32>>>(
|
||||
src, dst, dstDu, dstDv, dstDuu, dstDuv, dstDvv,
|
||||
length, srcStride, dstStride,
|
||||
dstDuStride, dstDvStride, dstDuuStride, dstDuvStride, dstDvvStride,
|
||||
numPatchCoords, patchCoords,
|
||||
patchArrayBuffer, patchIndexBuffer, patchParamBuffer);
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
152
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaPatchTable.cpp
vendored
Normal file
152
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaPatchTable.cpp
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/cudaPatchTable.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
#include "../far/patchTable.h"
|
||||
#include "../osd/cpuPatchTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CudaPatchTable::CudaPatchTable() :
|
||||
_patchArrays(NULL), _indexBuffer(NULL), _patchParamBuffer(NULL),
|
||||
_varyingPatchArrays(NULL), _varyingIndexBuffer(NULL) {
|
||||
}
|
||||
|
||||
CudaPatchTable::~CudaPatchTable() {
|
||||
if (_patchArrays) cudaFree(_patchArrays);
|
||||
if (_indexBuffer) cudaFree(_indexBuffer);
|
||||
if (_patchParamBuffer) cudaFree(_patchParamBuffer);
|
||||
if (_varyingPatchArrays) cudaFree(_varyingPatchArrays);
|
||||
if (_varyingIndexBuffer) cudaFree(_varyingIndexBuffer);
|
||||
for (int fvc=0; fvc<(int)_fvarPatchArrays.size(); ++fvc) {
|
||||
if (_fvarPatchArrays[fvc]) cudaFree(_fvarPatchArrays[fvc]);
|
||||
}
|
||||
for (int fvc=0; fvc<(int)_fvarIndexBuffers.size(); ++fvc) {
|
||||
if (_fvarIndexBuffers[fvc]) cudaFree(_fvarIndexBuffers[fvc]);
|
||||
}
|
||||
for (int fvc=0; fvc<(int)_fvarParamBuffers.size(); ++fvc) {
|
||||
if (_fvarParamBuffers[fvc]) cudaFree(_fvarParamBuffers[fvc]);
|
||||
}
|
||||
}
|
||||
|
||||
CudaPatchTable *
|
||||
CudaPatchTable::Create(Far::PatchTable const *farPatchTable,
|
||||
void * /*deviceContext*/) {
|
||||
CudaPatchTable *instance = new CudaPatchTable();
|
||||
if (instance->allocate(farPatchTable)) return instance;
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
CudaPatchTable::allocate(Far::PatchTable const *farPatchTable) {
|
||||
CpuPatchTable patchTable(farPatchTable);
|
||||
|
||||
size_t numPatchArrays = patchTable.GetNumPatchArrays();
|
||||
size_t indexSize = patchTable.GetPatchIndexSize();
|
||||
size_t patchParamSize = patchTable.GetPatchParamSize();
|
||||
|
||||
cudaError_t err;
|
||||
err = cudaMalloc(&_patchArrays, numPatchArrays * sizeof(Osd::PatchArray));
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
err = cudaMalloc(&_indexBuffer, indexSize * sizeof(int));
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
err = cudaMalloc(&_patchParamBuffer, patchParamSize * sizeof(Osd::PatchParam));
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
err = cudaMalloc(&_varyingPatchArrays, numPatchArrays * sizeof(Osd::PatchArray));
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
size_t varyingIndexSize = patchTable.GetVaryingPatchIndexSize();
|
||||
err = cudaMalloc(&_varyingIndexBuffer, varyingIndexSize * sizeof(int));
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
size_t numFVarChannels = patchTable.GetNumFVarChannels();
|
||||
_fvarPatchArrays.resize(numFVarChannels, 0);
|
||||
_fvarIndexBuffers.resize(numFVarChannels, 0);
|
||||
_fvarParamBuffers.resize(numFVarChannels, 0);
|
||||
for (int fvc=0; fvc<(int)numFVarChannels; ++fvc) {
|
||||
err = cudaMalloc(&_fvarPatchArrays[fvc], numPatchArrays * sizeof(Osd::PatchArray));
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
err = cudaMemcpy(_fvarPatchArrays[fvc],
|
||||
patchTable.GetFVarPatchArrayBuffer(fvc),
|
||||
numPatchArrays * sizeof(Osd::PatchArray),
|
||||
cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
size_t fvarIndexSize = patchTable.GetFVarPatchIndexSize(fvc);
|
||||
err = cudaMalloc(&_fvarIndexBuffers[fvc], fvarIndexSize * sizeof(int));
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
err = cudaMemcpy(_fvarIndexBuffers[fvc],
|
||||
patchTable.GetFVarPatchIndexBuffer(fvc),
|
||||
fvarIndexSize * sizeof(int),
|
||||
cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
size_t fvarParamSize = patchTable.GetFVarPatchParamSize(fvc);
|
||||
err = cudaMalloc(&_fvarParamBuffers[fvc], fvarParamSize * sizeof(Osd::PatchParam));
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
err = cudaMemcpy(_fvarParamBuffers[fvc],
|
||||
patchTable.GetFVarPatchParamBuffer(fvc),
|
||||
patchParamSize * sizeof(PatchParam),
|
||||
cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess) return false;
|
||||
}
|
||||
|
||||
// copy patch array
|
||||
err = cudaMemcpy(_patchArrays,
|
||||
patchTable.GetPatchArrayBuffer(),
|
||||
numPatchArrays * sizeof(Osd::PatchArray),
|
||||
cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
// copy index buffer
|
||||
err = cudaMemcpy(_indexBuffer,
|
||||
patchTable.GetPatchIndexBuffer(),
|
||||
indexSize * sizeof(int),
|
||||
cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
// patch param buffer
|
||||
err = cudaMemcpy(_patchParamBuffer,
|
||||
patchTable.GetPatchParamBuffer(),
|
||||
patchParamSize * sizeof(Osd::PatchParam),
|
||||
cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
// copy varying patch arrays and index buffer
|
||||
err = cudaMemcpy(_varyingPatchArrays,
|
||||
patchTable.GetVaryingPatchArrayBuffer(),
|
||||
numPatchArrays * sizeof(Osd::PatchArray),
|
||||
cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess) return false;
|
||||
err = cudaMemcpy(_varyingIndexBuffer,
|
||||
patchTable.GetVaryingPatchIndexBuffer(),
|
||||
varyingIndexSize * sizeof(int),
|
||||
cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
102
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaPatchTable.h
vendored
Normal file
102
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaPatchTable.h
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CUDA_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_OSD_CUDA_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/types.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far{
|
||||
class PatchTable;
|
||||
};
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief CUDA patch table
|
||||
///
|
||||
/// This class is a cuda buffer representation of Far::PatchTable.
|
||||
///
|
||||
/// CudaEvaluator consumes this table to evaluate on the patches.
|
||||
///
|
||||
///
|
||||
class CudaPatchTable : private NonCopyable<CudaPatchTable> {
|
||||
public:
|
||||
/// Creator. Returns NULL if error
|
||||
static CudaPatchTable *Create(Far::PatchTable const *patchTable,
|
||||
void *deviceContext = NULL);
|
||||
/// Destructor
|
||||
~CudaPatchTable();
|
||||
|
||||
/// Returns the cuda memory of the array of Osd::PatchArray buffer
|
||||
void *GetPatchArrayBuffer() const { return _patchArrays; }
|
||||
|
||||
/// Returns the cuda memory of the patch control vertices
|
||||
void *GetPatchIndexBuffer() const { return _indexBuffer; }
|
||||
|
||||
/// Returns the cuda memory of the array of Osd::PatchParam buffer
|
||||
void *GetPatchParamBuffer() const { return _patchParamBuffer; }
|
||||
|
||||
/// Returns the cuda memory of the array of Osd::PatchArray buffer
|
||||
void *GetVaryingPatchArrayBuffer() const {
|
||||
return _varyingPatchArrays;
|
||||
}
|
||||
/// Returns the cuda memory of the array of varying control vertices
|
||||
void *GetVaryingPatchIndexBuffer() const {
|
||||
return _varyingIndexBuffer;
|
||||
}
|
||||
|
||||
/// Returns the number of face-varying channels buffers
|
||||
int GetNumFVarChannels() const { return (int)_fvarPatchArrays.size(); }
|
||||
|
||||
/// Returns the cuda memory of the array of Osd::PatchArray buffer
|
||||
void *GetFVarPatchArrayBuffer(int fvarChannel) const {
|
||||
return _fvarPatchArrays[fvarChannel];
|
||||
}
|
||||
|
||||
/// Returns the cuda memory of the array of face-varying control vertices
|
||||
void *GetFVarPatchIndexBuffer(int fvarChannel = 0) const {
|
||||
return _fvarIndexBuffers[fvarChannel];
|
||||
}
|
||||
|
||||
/// Returns the cuda memory of the array of face-varying param
|
||||
void *GetFVarPatchParamBuffer(int fvarChannel = 0) const {
|
||||
return _fvarParamBuffers[fvarChannel];
|
||||
}
|
||||
|
||||
protected:
|
||||
CudaPatchTable();
|
||||
|
||||
bool allocate(Far::PatchTable const *patchTable);
|
||||
|
||||
void *_patchArrays;
|
||||
void *_indexBuffer;
|
||||
void *_patchParamBuffer;
|
||||
|
||||
void *_varyingPatchArrays;
|
||||
void *_varyingIndexBuffer;
|
||||
|
||||
std::vector<void *> _fvarPatchArrays;
|
||||
std::vector<void *> _fvarIndexBuffers;
|
||||
std::vector<void *> _fvarParamBuffers;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CUDA_PATCH_TABLE_H
|
||||
80
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaVertexBuffer.cpp
vendored
Normal file
80
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaVertexBuffer.cpp
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/cudaVertexBuffer.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CudaVertexBuffer::CudaVertexBuffer(int numElements, int numVertices)
|
||||
: _numElements(numElements),
|
||||
_numVertices(numVertices),
|
||||
_cudaMem(0) {
|
||||
}
|
||||
|
||||
CudaVertexBuffer::~CudaVertexBuffer() {
|
||||
if (_cudaMem) cudaFree(_cudaMem);
|
||||
}
|
||||
|
||||
CudaVertexBuffer *
|
||||
CudaVertexBuffer::Create(int numElements, int numVertices,
|
||||
void * /*deviceContext */) {
|
||||
CudaVertexBuffer *instance =
|
||||
new CudaVertexBuffer(numElements, numVertices);
|
||||
if (instance->allocate()) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
CudaVertexBuffer::UpdateData(const float *src, int startVertex, int numVertices,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
size_t size = _numElements * numVertices * sizeof(float);
|
||||
|
||||
cudaMemcpy((float*)_cudaMem + _numElements * startVertex,
|
||||
src, size, cudaMemcpyHostToDevice);
|
||||
}
|
||||
|
||||
int
|
||||
CudaVertexBuffer::GetNumElements() const {
|
||||
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int
|
||||
CudaVertexBuffer::GetNumVertices() const {
|
||||
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
float *
|
||||
CudaVertexBuffer::BindCudaBuffer() {
|
||||
|
||||
return static_cast<float*>(_cudaMem);
|
||||
}
|
||||
|
||||
bool
|
||||
CudaVertexBuffer::allocate() {
|
||||
int size = _numElements * _numVertices * sizeof(float);
|
||||
|
||||
cudaError_t err = cudaMalloc(&_cudaMem, size);
|
||||
|
||||
if (err != cudaSuccess) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
71
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaVertexBuffer.h
vendored
Normal file
71
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/cudaVertexBuffer.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_CUDA_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_CUDA_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Concrete vertex buffer class for Cuda subdivision.
|
||||
///
|
||||
/// CudaVertexBuffer implements CudaVertexBufferInterface.
|
||||
/// An instance of this buffer class can be passed to CudaEvaluator
|
||||
///
|
||||
class CudaVertexBuffer {
|
||||
|
||||
public:
|
||||
/// Creator. Returns NULL if error.
|
||||
static CudaVertexBuffer * Create(int numElements, int numVertices,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Destructor.
|
||||
~CudaVertexBuffer();
|
||||
|
||||
/// 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 startVertex, int numVertices,
|
||||
void *deviceContext=NULL);
|
||||
|
||||
/// Returns how many elements defined in this vertex buffer.
|
||||
int GetNumElements() const;
|
||||
|
||||
/// Returns how many vertices allocated in this vertex buffer.
|
||||
int GetNumVertices() const;
|
||||
|
||||
/// Returns cuda memory.
|
||||
float * BindCudaBuffer();
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
CudaVertexBuffer(int numElements, int numVertices);
|
||||
|
||||
/// Allocates Cuda memory for this buffer.
|
||||
/// Returns true if success.
|
||||
bool allocate();
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
void *_cudaMem;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_CUDA_VERTEX_BUFFER_H
|
||||
381
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11ComputeEvaluator.cpp
vendored
Normal file
381
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11ComputeEvaluator.cpp
vendored
Normal file
@@ -0,0 +1,381 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/d3d11ComputeEvaluator.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define INITGUID // for IID_ID3D11ShaderReflection
|
||||
#include <D3D11.h>
|
||||
#include <D3D11shader.h>
|
||||
#include <D3Dcompiler.h>
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
||||
|
||||
static const char *shaderSource =
|
||||
#include "../osd/hlslComputeKernel.gen.h"
|
||||
;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// must match constant buffer declaration in hlslComputeKernel.hlsl
|
||||
__declspec(align(16))
|
||||
|
||||
struct KernelUniformArgs {
|
||||
|
||||
int start; // batch
|
||||
int end;
|
||||
|
||||
int srcOffset;
|
||||
int dstOffset;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
static ID3D11Buffer *createBuffer(std::vector<T> const &src,
|
||||
ID3D11Device *device) {
|
||||
|
||||
size_t size = src.size()*sizeof(T);
|
||||
|
||||
ID3D11Buffer *buffer = NULL;
|
||||
D3D11_BUFFER_DESC bd;
|
||||
bd.ByteWidth = (unsigned int)size;
|
||||
bd.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
bd.CPUAccessFlags = 0;
|
||||
bd.MiscFlags = 0;
|
||||
bd.StructureByteStride = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
initData.pSysMem = &src.at(0);
|
||||
|
||||
HRESULT hr = device->CreateBuffer(&bd, &initData, &buffer);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Error creating compute table buffer\n");
|
||||
return NULL;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static ID3D11ShaderResourceView *createSRV(ID3D11Buffer *buffer,
|
||||
DXGI_FORMAT format,
|
||||
ID3D11Device *device,
|
||||
size_t size) {
|
||||
ID3D11ShaderResourceView *srv = NULL;
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
|
||||
ZeroMemory(&srvd, sizeof(srvd));
|
||||
srvd.Format = format;
|
||||
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
srvd.Buffer.FirstElement = 0;
|
||||
srvd.Buffer.NumElements = (unsigned int)size;
|
||||
|
||||
HRESULT hr = device->CreateShaderResourceView(buffer, &srvd, &srv);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Error creating compute table shader resource view\n");
|
||||
return NULL;
|
||||
}
|
||||
return srv;
|
||||
}
|
||||
|
||||
D3D11StencilTable::D3D11StencilTable(Far::StencilTable const *stencilTable,
|
||||
ID3D11DeviceContext *deviceContext)
|
||||
{
|
||||
ID3D11Device *device = NULL;
|
||||
deviceContext->GetDevice(&device);
|
||||
assert(device);
|
||||
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
std::vector<int> const &sizes = stencilTable->GetSizes();
|
||||
|
||||
_sizesBuffer = createBuffer(sizes, device);
|
||||
_offsetsBuffer = createBuffer(stencilTable->GetOffsets(), device);
|
||||
_indicesBuffer = createBuffer(stencilTable->GetControlIndices(), device);
|
||||
_weightsBuffer = createBuffer(stencilTable->GetWeights(), device);
|
||||
|
||||
_sizes = createSRV(_sizesBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTable->GetSizes().size());
|
||||
_offsets = createSRV(_offsetsBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTable->GetOffsets().size());
|
||||
_indices = createSRV(_indicesBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTable->GetControlIndices().size());
|
||||
_weights= createSRV(_weightsBuffer, DXGI_FORMAT_R32_FLOAT, device,
|
||||
stencilTable->GetWeights().size());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
_sizesBuffer = _offsetsBuffer = _indicesBuffer = _weightsBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11StencilTable::~D3D11StencilTable() {
|
||||
SAFE_RELEASE(_sizes);
|
||||
SAFE_RELEASE(_sizesBuffer);
|
||||
SAFE_RELEASE(_offsets);
|
||||
SAFE_RELEASE(_offsetsBuffer);
|
||||
SAFE_RELEASE(_indices);
|
||||
SAFE_RELEASE(_indicesBuffer);
|
||||
SAFE_RELEASE(_weights);
|
||||
SAFE_RELEASE(_weightsBuffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
D3D11ComputeEvaluator::D3D11ComputeEvaluator() :
|
||||
_computeShader(NULL),
|
||||
_classLinkage(NULL),
|
||||
_singleBufferKernel(NULL),
|
||||
_separateBufferKernel(NULL),
|
||||
_uniformArgs(NULL),
|
||||
_workGroupSize(64) {
|
||||
|
||||
}
|
||||
|
||||
D3D11ComputeEvaluator *
|
||||
D3D11ComputeEvaluator::Create(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
return Create(srcDesc, dstDesc, duDesc, dvDesc,
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
deviceContext);
|
||||
}
|
||||
|
||||
D3D11ComputeEvaluator *
|
||||
D3D11ComputeEvaluator::Create(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
(void)deviceContext; // not used
|
||||
|
||||
// TODO: implements derivatives
|
||||
(void)duDesc;
|
||||
(void)dvDesc;
|
||||
|
||||
D3D11ComputeEvaluator *instance = new D3D11ComputeEvaluator();
|
||||
if (instance->Compile(srcDesc, dstDesc, deviceContext)) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D3D11ComputeEvaluator::~D3D11ComputeEvaluator() {
|
||||
SAFE_RELEASE(_computeShader);
|
||||
SAFE_RELEASE(_classLinkage);
|
||||
SAFE_RELEASE(_singleBufferKernel);
|
||||
SAFE_RELEASE(_separateBufferKernel);
|
||||
SAFE_RELEASE(_uniformArgs);
|
||||
}
|
||||
|
||||
bool
|
||||
D3D11ComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
if (srcDesc.length > dstDesc.length) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"srcDesc length must be less than or equal to "
|
||||
"dstDesc length.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
|
||||
#if defined(D3D10_SHADER_RESOURCES_MAY_ALIAS)
|
||||
dwShaderFlags |= D3D10_SHADER_RESOURCES_MAY_ALIAS;
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
dwShaderFlags |= D3DCOMPILE_DEBUG;
|
||||
#endif
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << srcDesc.length; std::string lengthValue(ss.str()); ss.str("");
|
||||
ss << srcDesc.stride; std::string srcStrideValue(ss.str()); ss.str("");
|
||||
ss << dstDesc.stride; std::string dstStrideValue(ss.str()); ss.str("");
|
||||
ss << _workGroupSize; std::string workgroupSizeValue(ss.str()); ss.str("");
|
||||
|
||||
D3D_SHADER_MACRO defines[] =
|
||||
{ { "LENGTH", lengthValue.c_str() },
|
||||
{ "SRC_STRIDE", srcStrideValue.c_str() },
|
||||
{ "DST_STRIDE", dstStrideValue.c_str() },
|
||||
{ "WORK_GROUP_SIZE", workgroupSizeValue.c_str() },
|
||||
{ 0, 0 } };
|
||||
|
||||
ID3DBlob * computeShaderBuffer = NULL;
|
||||
ID3DBlob * errorBuffer = NULL;
|
||||
|
||||
HRESULT hr = D3DCompile(shaderSource, strlen(shaderSource),
|
||||
NULL, &defines[0], NULL,
|
||||
"cs_main", "cs_5_0",
|
||||
dwShaderFlags, 0,
|
||||
&computeShaderBuffer, &errorBuffer);
|
||||
if (FAILED(hr)) {
|
||||
if (errorBuffer != NULL) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Error compiling HLSL shader: %s\n",
|
||||
(CHAR*)errorBuffer->GetBufferPointer());
|
||||
errorBuffer->Release();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11Device *device = NULL;
|
||||
deviceContext->GetDevice(&device);
|
||||
assert(device);
|
||||
|
||||
device->CreateClassLinkage(&_classLinkage);
|
||||
assert(_classLinkage);
|
||||
|
||||
device->CreateComputeShader(computeShaderBuffer->GetBufferPointer(),
|
||||
computeShaderBuffer->GetBufferSize(),
|
||||
_classLinkage,
|
||||
&_computeShader);
|
||||
assert(_computeShader);
|
||||
|
||||
ID3D11ShaderReflection *reflector;
|
||||
D3DReflect(computeShaderBuffer->GetBufferPointer(),
|
||||
computeShaderBuffer->GetBufferSize(),
|
||||
IID_ID3D11ShaderReflection, (void**) &reflector);
|
||||
assert(reflector);
|
||||
|
||||
assert(reflector->GetNumInterfaceSlots() == 1);
|
||||
reflector->Release();
|
||||
|
||||
computeShaderBuffer->Release();
|
||||
|
||||
_classLinkage->GetClassInstance("singleBufferCompute", 0, &_singleBufferKernel);
|
||||
assert(_singleBufferKernel);
|
||||
_classLinkage->GetClassInstance("separateBufferCompute", 0, &_separateBufferKernel);
|
||||
assert(_separateBufferKernel);
|
||||
|
||||
D3D11_BUFFER_DESC cbDesc;
|
||||
ZeroMemory(&cbDesc, sizeof(cbDesc));
|
||||
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
cbDesc.MiscFlags = 0;
|
||||
cbDesc.ByteWidth = sizeof(KernelUniformArgs);
|
||||
device->CreateBuffer(&cbDesc, NULL, &_uniformArgs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
D3D11ComputeEvaluator::Synchronize(ID3D11DeviceContext *deviceContext) {
|
||||
// XXX: this is currently just for the performance measuring purpose.
|
||||
|
||||
// XXXFIXME!
|
||||
ID3D11Query *query = NULL;
|
||||
|
||||
ID3D11Device *device = NULL;
|
||||
deviceContext->GetDevice(&device);
|
||||
assert(device);
|
||||
|
||||
D3D11_QUERY_DESC desc;
|
||||
desc.Query = D3D11_QUERY_EVENT;
|
||||
desc.MiscFlags = 0;
|
||||
device->CreateQuery(&desc, &query);
|
||||
|
||||
deviceContext->Flush();
|
||||
deviceContext->End(query);
|
||||
while (S_OK != deviceContext->GetData(query, NULL, 0, 0));
|
||||
|
||||
SAFE_RELEASE(query);
|
||||
}
|
||||
|
||||
bool
|
||||
D3D11ComputeEvaluator::EvalStencils(ID3D11UnorderedAccessView *srcUAV,
|
||||
BufferDescriptor const &srcDesc,
|
||||
ID3D11UnorderedAccessView *dstUAV,
|
||||
BufferDescriptor const &dstDesc,
|
||||
ID3D11ShaderResourceView *sizesSRV,
|
||||
ID3D11ShaderResourceView *offsetsSRV,
|
||||
ID3D11ShaderResourceView *indicesSRV,
|
||||
ID3D11ShaderResourceView *weightsSRV,
|
||||
int start,
|
||||
int end,
|
||||
ID3D11DeviceContext *deviceContext) const {
|
||||
assert(deviceContext);
|
||||
|
||||
int count = end - start;
|
||||
if (count <= 0) return true;
|
||||
|
||||
KernelUniformArgs args;
|
||||
args.start = start;
|
||||
args.end = end;
|
||||
args.srcOffset = srcDesc.offset;
|
||||
args.dstOffset = dstDesc.offset;
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
deviceContext->Map(_uniformArgs, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
CopyMemory(mappedResource.pData, &args, sizeof(KernelUniformArgs));
|
||||
|
||||
deviceContext->Unmap(_uniformArgs, 0);
|
||||
deviceContext->CSSetConstantBuffers(0, 1, &_uniformArgs); // b0
|
||||
|
||||
// Unbind the vertexBuffer from the input assembler
|
||||
ID3D11Buffer *NULLBuffer = 0;
|
||||
UINT voffset = 0, vstride = 0;
|
||||
deviceContext->IASetVertexBuffers(0, 1, &NULLBuffer, &voffset, &vstride);
|
||||
ID3D11ShaderResourceView *NULLSRV = 0;
|
||||
deviceContext->VSSetShaderResources(0, 1, &NULLSRV);
|
||||
|
||||
// bind UAV
|
||||
ID3D11UnorderedAccessView *UAViews[] = { srcUAV, dstUAV };
|
||||
ID3D11ShaderResourceView *SRViews[] = {
|
||||
sizesSRV, offsetsSRV, indicesSRV, weightsSRV };
|
||||
|
||||
// bind source vertex and stencil table
|
||||
deviceContext->CSSetShaderResources(1, 4, SRViews); // t1-t4
|
||||
|
||||
if (srcUAV == dstUAV) {
|
||||
deviceContext->CSSetUnorderedAccessViews(0, 1, UAViews, 0); // u0
|
||||
// Dispatch src == dst buffer
|
||||
deviceContext->CSSetShader(_computeShader, &_singleBufferKernel, 1);
|
||||
deviceContext->Dispatch((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
} else {
|
||||
deviceContext->CSSetUnorderedAccessViews(0, 2, UAViews, 0); // u0, u1
|
||||
// Dispatch src != dst buffer
|
||||
deviceContext->CSSetShader(_computeShader, &_separateBufferKernel, 1);
|
||||
deviceContext->Dispatch((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
}
|
||||
|
||||
// unbind stencil table and vertexbuffers
|
||||
SRViews[0] = SRViews[1] = SRViews[2] = SRViews[3] = NULL;
|
||||
deviceContext->CSSetShaderResources(1, 4, SRViews);
|
||||
|
||||
UAViews[0] = UAViews[1] = NULL;
|
||||
deviceContext->CSSetUnorderedAccessViews(0, 2, UAViews, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
221
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11ComputeEvaluator.h
vendored
Normal file
221
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11ComputeEvaluator.h
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_D3D11_COMPUTE_EVALUATOR_H
|
||||
#define OPENSUBDIV3_OSD_D3D11_COMPUTE_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
struct ID3D11DeviceContext;
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11ComputeShader;
|
||||
struct ID3D11ClassLinkage;
|
||||
struct ID3D11ClassInstance;
|
||||
struct ID3D11ShaderResourceView;
|
||||
struct ID3D11UnorderedAccessView;
|
||||
|
||||
#include "../osd/bufferDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTable;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief D3D11 stencil table
|
||||
///
|
||||
/// This class is a D3D11 Shader Resource View representation of
|
||||
/// Far::StencilTable.
|
||||
///
|
||||
/// D3D11ComputeEvaluator consumes this table to apply stencils
|
||||
///
|
||||
class D3D11StencilTable {
|
||||
public:
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static D3D11StencilTable *Create(Far::StencilTable const *stencilTable,
|
||||
DEVICE_CONTEXT context) {
|
||||
return new D3D11StencilTable(stencilTable, context->GetDeviceContext());
|
||||
}
|
||||
|
||||
static D3D11StencilTable *Create(Far::StencilTable const *stencilTable,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
return new D3D11StencilTable(stencilTable, deviceContext);
|
||||
}
|
||||
|
||||
D3D11StencilTable(Far::StencilTable const *stencilTable,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
~D3D11StencilTable();
|
||||
|
||||
// interfaces needed for D3D11ComputeEvaluator
|
||||
ID3D11ShaderResourceView *GetSizesSRV() const { return _sizes; }
|
||||
ID3D11ShaderResourceView *GetOffsetsSRV() const { return _offsets; }
|
||||
ID3D11ShaderResourceView *GetIndicesSRV() const { return _indices; }
|
||||
ID3D11ShaderResourceView *GetWeightsSRV() const { return _weights; }
|
||||
int GetNumStencils() const { return _numStencils; }
|
||||
|
||||
private:
|
||||
ID3D11ShaderResourceView *_sizes;
|
||||
ID3D11ShaderResourceView *_offsets;
|
||||
ID3D11ShaderResourceView *_indices;
|
||||
ID3D11ShaderResourceView *_weights;
|
||||
ID3D11Buffer *_sizesBuffer;
|
||||
ID3D11Buffer *_offsetsBuffer;
|
||||
ID3D11Buffer *_indicesBuffer;
|
||||
ID3D11Buffer *_weightsBuffer;
|
||||
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class D3D11ComputeEvaluator {
|
||||
public:
|
||||
using Instantiatable = bool; // Enable compiled kernel evaluator cache
|
||||
|
||||
static D3D11ComputeEvaluator * Create(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
static D3D11ComputeEvaluator * Create(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Constructor.
|
||||
D3D11ComputeEvaluator();
|
||||
|
||||
/// Destructor.
|
||||
~D3D11ComputeEvaluator();
|
||||
|
||||
/// \brief Generic static compute function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently from OsdMesh template interface.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBO() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTable stencil table to be applied. The table must have
|
||||
/// SSBO interfaces.
|
||||
///
|
||||
/// @param instance cached compiled instance. Clients are supposed to
|
||||
/// pre-compile an instance of this class and provide
|
||||
/// to this function. If it's null the kernel still
|
||||
/// compute by instantiating on-demand kernel although
|
||||
/// it may cause a performance problem.
|
||||
///
|
||||
/// @param deviceContext ID3D11DeviceContext.
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
D3D11ComputeEvaluator const *instance,
|
||||
ID3D11DeviceContext * deviceContext) {
|
||||
if (instance) {
|
||||
return instance->EvalStencils(srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
stencilTable,
|
||||
deviceContext);
|
||||
} else {
|
||||
// Create an instance on demand (slow)
|
||||
(void)deviceContext; // unused
|
||||
instance = Create(srcDesc, dstDesc,
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
deviceContext);
|
||||
if (instance) {
|
||||
bool r = instance->EvalStencils(srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
stencilTable,
|
||||
deviceContext);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatch the DX compute kernel on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
|
||||
bool EvalStencils(
|
||||
SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
ID3D11DeviceContext *deviceContext) const {
|
||||
return EvalStencils(srcBuffer->BindD3D11UAV(deviceContext), srcDesc,
|
||||
dstBuffer->BindD3D11UAV(deviceContext), dstDesc,
|
||||
stencilTable->GetSizesSRV(),
|
||||
stencilTable->GetOffsetsSRV(),
|
||||
stencilTable->GetIndicesSRV(),
|
||||
stencilTable->GetWeightsSRV(),
|
||||
/* start = */ 0,
|
||||
/* end = */ stencilTable->GetNumStencils(),
|
||||
deviceContext);
|
||||
}
|
||||
|
||||
/// Dispatch the DX compute kernel on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
bool EvalStencils(ID3D11UnorderedAccessView *srcSRV,
|
||||
BufferDescriptor const &srcDesc,
|
||||
ID3D11UnorderedAccessView *dstUAV,
|
||||
BufferDescriptor const &dstDesc,
|
||||
ID3D11ShaderResourceView *sizesSRV,
|
||||
ID3D11ShaderResourceView *offsetsSRV,
|
||||
ID3D11ShaderResourceView *indicesSRV,
|
||||
ID3D11ShaderResourceView *weightsSRV,
|
||||
int start,
|
||||
int end,
|
||||
ID3D11DeviceContext *deviceContext) const;
|
||||
|
||||
/// Configure DX kernel. Returns false if it fails to compile the kernel.
|
||||
bool Compile(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Wait the dispatched kernel finishes.
|
||||
static void Synchronize(ID3D11DeviceContext *deviceContext);
|
||||
|
||||
private:
|
||||
ID3D11ComputeShader * _computeShader;
|
||||
ID3D11ClassLinkage * _classLinkage;
|
||||
ID3D11ClassInstance * _singleBufferKernel;
|
||||
ID3D11ClassInstance * _separateBufferKernel;
|
||||
ID3D11Buffer * _uniformArgs; // uniform parameters for kernels
|
||||
|
||||
int _workGroupSize;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_D3D11_COMPUTE_EVALUATOR_H
|
||||
148
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11LegacyGregoryPatchTable.cpp
vendored
Normal file
148
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11LegacyGregoryPatchTable.cpp
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/d3d11LegacyGregoryPatchTable.h"
|
||||
|
||||
#include <D3D11.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
D3D11LegacyGregoryPatchTable::D3D11LegacyGregoryPatchTable() :
|
||||
_vertexValenceBuffer(0), _quadOffsetsBuffer(0),
|
||||
_vertexSRV(0), _vertexValenceSRV(0), _quadOffsetsSRV(0) {
|
||||
_quadOffsetsBase[0] = _quadOffsetsBase[1] = 0;
|
||||
}
|
||||
|
||||
D3D11LegacyGregoryPatchTable::~D3D11LegacyGregoryPatchTable() {
|
||||
if (_vertexValenceBuffer) _vertexValenceBuffer->Release();
|
||||
if (_quadOffsetsBuffer) _quadOffsetsBuffer->Release();
|
||||
if (_vertexSRV) _vertexSRV->Release();
|
||||
if (_vertexValenceSRV) _vertexValenceSRV->Release();
|
||||
if (_quadOffsetsSRV) _quadOffsetsSRV->Release();
|
||||
}
|
||||
|
||||
D3D11LegacyGregoryPatchTable *
|
||||
D3D11LegacyGregoryPatchTable::Create(Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *pd3d11DeviceContext) {
|
||||
ID3D11Device *pd3d11Device = NULL;
|
||||
pd3d11DeviceContext->GetDevice(&pd3d11Device);
|
||||
assert(pd3d11Device);
|
||||
|
||||
D3D11LegacyGregoryPatchTable *result = new D3D11LegacyGregoryPatchTable();
|
||||
|
||||
Far::PatchTable::VertexValenceTable const &
|
||||
valenceTable = farPatchTable->GetVertexValenceTable();
|
||||
Far::PatchTable::QuadOffsetsTable const &
|
||||
quadOffsetsTable = farPatchTable->GetQuadOffsetsTable();
|
||||
|
||||
if (! valenceTable.empty()) {
|
||||
D3D11_BUFFER_DESC bd;
|
||||
bd.ByteWidth = UINT(valenceTable.size() * sizeof(unsigned int));
|
||||
bd.Usage = D3D11_USAGE_DEFAULT;
|
||||
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
bd.CPUAccessFlags = 0;
|
||||
bd.MiscFlags = 0;
|
||||
bd.StructureByteStride = sizeof(unsigned int);
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
initData.pSysMem = &valenceTable[0];
|
||||
HRESULT hr = pd3d11Device->CreateBuffer(&bd, &initData,
|
||||
&result->_vertexValenceBuffer);
|
||||
if (FAILED(hr)) {
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
|
||||
ZeroMemory(&srvd, sizeof(srvd));
|
||||
srvd.Format = DXGI_FORMAT_R32_SINT;
|
||||
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
srvd.Buffer.FirstElement = 0;
|
||||
srvd.Buffer.NumElements = UINT(valenceTable.size());
|
||||
hr = pd3d11Device->CreateShaderResourceView(
|
||||
result->_vertexValenceBuffer, &srvd,
|
||||
&result->_vertexValenceSRV);
|
||||
if (FAILED(hr)) {
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (! quadOffsetsTable.empty()) {
|
||||
D3D11_BUFFER_DESC bd;
|
||||
bd.ByteWidth = UINT(quadOffsetsTable.size() * sizeof(unsigned int));
|
||||
bd.Usage = D3D11_USAGE_DEFAULT;
|
||||
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
bd.CPUAccessFlags = 0;
|
||||
bd.MiscFlags = 0;
|
||||
bd.StructureByteStride = sizeof(unsigned int);
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
initData.pSysMem = &quadOffsetsTable[0];
|
||||
HRESULT hr = pd3d11Device->CreateBuffer(&bd, &initData,
|
||||
&result->_quadOffsetsBuffer);
|
||||
if (FAILED(hr)) {
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
|
||||
ZeroMemory(&srvd, sizeof(srvd));
|
||||
srvd.Format = DXGI_FORMAT_R32_SINT;
|
||||
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
srvd.Buffer.FirstElement = 0;
|
||||
srvd.Buffer.NumElements = UINT(quadOffsetsTable.size());
|
||||
hr = pd3d11Device->CreateShaderResourceView(
|
||||
result->_quadOffsetsBuffer, &srvd, &result->_quadOffsetsSRV);
|
||||
if (FAILED(hr)) {
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
result->_quadOffsetsBase[0] = 0;
|
||||
result->_quadOffsetsBase[1] = 0;
|
||||
|
||||
// scan patchtable to find quadOffsetsBase.
|
||||
for (int i = 0; i < farPatchTable->GetNumPatchArrays(); ++i) {
|
||||
// GREGORY_BOUNDARY's quadoffsets come after GREGORY's.
|
||||
if (farPatchTable->GetPatchArrayDescriptor(i) ==
|
||||
Far::PatchDescriptor::GREGORY) {
|
||||
result->_quadOffsetsBase[1] = farPatchTable->GetNumPatches(i) * 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
D3D11LegacyGregoryPatchTable::UpdateVertexBuffer(
|
||||
ID3D11Buffer *vbo, int numVertices, int numVertexElements,
|
||||
ID3D11DeviceContext *pd3d11DeviceContext) {
|
||||
ID3D11Device *pd3d11Device = NULL;
|
||||
pd3d11DeviceContext->GetDevice(&pd3d11Device);
|
||||
assert(pd3d11Device);
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
|
||||
ZeroMemory(&srvd, sizeof(srvd));
|
||||
srvd.Format = DXGI_FORMAT_R32_FLOAT;
|
||||
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
srvd.Buffer.FirstElement = 0;
|
||||
srvd.Buffer.NumElements = numVertices * numVertexElements;
|
||||
HRESULT hr = pd3d11Device->CreateShaderResourceView(vbo, &srvd,
|
||||
&_vertexSRV);
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
85
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11LegacyGregoryPatchTable.h
vendored
Normal file
85
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11LegacyGregoryPatchTable.h
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_D3D11_LEGACY_GREGORY_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_OSD_D3D11_LEGACY_GREGORY_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/patchTable.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11ShaderResourceView;
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class D3D11LegacyGregoryPatchTable
|
||||
: private NonCopyable<D3D11LegacyGregoryPatchTable> {
|
||||
public:
|
||||
~D3D11LegacyGregoryPatchTable();
|
||||
|
||||
template<typename DEVICE_CONTEXT>
|
||||
static D3D11LegacyGregoryPatchTable *Create(
|
||||
Far::PatchTable const *farPatchTable, DEVICE_CONTEXT context) {
|
||||
return Create(farPatchTable, context->GetDeviceContext());
|
||||
}
|
||||
|
||||
static D3D11LegacyGregoryPatchTable *Create(
|
||||
Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
void UpdateVertexBuffer(ID3D11Buffer *vbo,
|
||||
int numVertices, int numVertexElements,
|
||||
ID3D11DeviceContext *pd3d11DeviceContext);
|
||||
|
||||
ID3D11ShaderResourceView* GetVertexSRV() const {
|
||||
return _vertexSRV;
|
||||
}
|
||||
|
||||
ID3D11ShaderResourceView* GetVertexValenceSRV() const {
|
||||
return _vertexValenceSRV;
|
||||
}
|
||||
|
||||
ID3D11ShaderResourceView* GetQuadOffsetsSRV() const {
|
||||
return _quadOffsetsSRV;
|
||||
}
|
||||
|
||||
int GetQuadOffsetsBase(Far::PatchDescriptor::Type type) {
|
||||
if (type == Far::PatchDescriptor::GREGORY_BOUNDARY) {
|
||||
return _quadOffsetsBase[1];
|
||||
}
|
||||
return _quadOffsetsBase[0];
|
||||
}
|
||||
|
||||
protected:
|
||||
D3D11LegacyGregoryPatchTable();
|
||||
|
||||
private:
|
||||
ID3D11Buffer* _vertexValenceBuffer;
|
||||
ID3D11Buffer* _quadOffsetsBuffer;
|
||||
ID3D11ShaderResourceView* _vertexSRV;
|
||||
ID3D11ShaderResourceView* _vertexValenceSRV;
|
||||
ID3D11ShaderResourceView* _quadOffsetsSRV;
|
||||
int _quadOffsetsBase[2]; // gregory, boundaryGregory
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_D3D11_LEGACY_GREGORY_PATCH_TABLE_H
|
||||
31
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11Mesh.h
vendored
Normal file
31
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11Mesh.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_D3D11MESH_H
|
||||
#define OPENSUBDIV3_OSD_D3D11MESH_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/mesh.h"
|
||||
#include "../osd/d3d11PatchTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
typedef MeshInterface<D3D11PatchTable> D3D11MeshInterface;
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_D3D11MESH_H
|
||||
127
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11PatchTable.cpp
vendored
Normal file
127
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11PatchTable.cpp
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/d3d11PatchTable.h"
|
||||
|
||||
#include <D3D11.h>
|
||||
#include "../far/patchTable.h"
|
||||
#include "../osd/cpuPatchTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
D3D11PatchTable::D3D11PatchTable() :
|
||||
_indexBuffer(0), _patchParamBuffer(0), _patchParamBufferSRV(0) {
|
||||
}
|
||||
|
||||
D3D11PatchTable::~D3D11PatchTable() {
|
||||
if (_indexBuffer) _indexBuffer->Release();
|
||||
if (_patchParamBuffer) _patchParamBuffer->Release();
|
||||
if (_patchParamBufferSRV) _patchParamBufferSRV->Release();
|
||||
}
|
||||
|
||||
D3D11PatchTable *
|
||||
D3D11PatchTable::Create(Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *pd3d11DeviceContext) {
|
||||
D3D11PatchTable *instance = new D3D11PatchTable();
|
||||
if (instance->allocate(farPatchTable, pd3d11DeviceContext))
|
||||
return instance;
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
D3D11PatchTable::allocate(Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *pd3d11DeviceContext) {
|
||||
ID3D11Device *pd3d11Device = NULL;
|
||||
pd3d11DeviceContext->GetDevice(&pd3d11Device);
|
||||
assert(pd3d11Device);
|
||||
|
||||
CpuPatchTable patchTable(farPatchTable);
|
||||
|
||||
size_t numPatchArrays = patchTable.GetNumPatchArrays();
|
||||
size_t indexSize = patchTable.GetPatchIndexSize();
|
||||
size_t patchParamSize = patchTable.GetPatchParamSize();
|
||||
|
||||
// copy patch array
|
||||
_patchArrays.assign(patchTable.GetPatchArrayBuffer(),
|
||||
patchTable.GetPatchArrayBuffer() + numPatchArrays);
|
||||
|
||||
// index buffer
|
||||
D3D11_BUFFER_DESC bd;
|
||||
ZeroMemory(&bd, sizeof(bd));
|
||||
bd.ByteWidth = (int)indexSize * sizeof(int);
|
||||
bd.Usage = D3D11_USAGE_DYNAMIC;
|
||||
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
bd.MiscFlags = 0;
|
||||
bd.StructureByteStride = sizeof(int);
|
||||
HRESULT hr = pd3d11Device->CreateBuffer(&bd, NULL, &_indexBuffer);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
hr = pd3d11DeviceContext->Map(_indexBuffer, 0,
|
||||
D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
unsigned int * indexBuffer = (unsigned int *) mappedResource.pData;
|
||||
memcpy(indexBuffer,
|
||||
patchTable.GetPatchIndexBuffer(),
|
||||
indexSize * sizeof(unsigned int));
|
||||
|
||||
pd3d11DeviceContext->Unmap(_indexBuffer, 0);
|
||||
|
||||
// patchparam buffer
|
||||
ZeroMemory(&bd, sizeof(bd));
|
||||
bd.ByteWidth = (int)patchParamSize * sizeof(PatchParam);
|
||||
bd.Usage = D3D11_USAGE_DYNAMIC;
|
||||
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
bd.MiscFlags = 0;
|
||||
bd.StructureByteStride = sizeof(PatchParam);
|
||||
hr = pd3d11Device->CreateBuffer(&bd, NULL, &_patchParamBuffer);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
|
||||
ZeroMemory(&srvd, sizeof(srvd));
|
||||
srvd.Format = DXGI_FORMAT_R32G32B32_UINT;
|
||||
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
srvd.Buffer.FirstElement = 0;
|
||||
srvd.Buffer.NumElements = (int)patchParamSize;
|
||||
hr = pd3d11Device->CreateShaderResourceView(
|
||||
_patchParamBuffer, &srvd, &_patchParamBufferSRV);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
hr = pd3d11DeviceContext->Map(_patchParamBuffer, 0,
|
||||
D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
unsigned int *dst = (unsigned int *) mappedResource.pData;
|
||||
memcpy(dst,
|
||||
patchTable.GetPatchParamBuffer(),
|
||||
patchParamSize * sizeof(PatchParam));
|
||||
|
||||
pd3d11DeviceContext->Unmap(_patchParamBuffer, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
82
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11PatchTable.h
vendored
Normal file
82
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11PatchTable.h
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_GL_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_OSD_GL_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <vector>
|
||||
#include "../far/patchDescriptor.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/types.h"
|
||||
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11ShaderResourceView;
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far{
|
||||
class PatchTable;
|
||||
};
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class D3D11PatchTable : private NonCopyable<D3D11PatchTable> {
|
||||
public:
|
||||
using VertexBufferBinding = ID3D11Buffer*; // buffer binding type
|
||||
|
||||
D3D11PatchTable();
|
||||
~D3D11PatchTable();
|
||||
|
||||
template<typename DEVICE_CONTEXT>
|
||||
static D3D11PatchTable *Create(Far::PatchTable const *farPatchTable,
|
||||
DEVICE_CONTEXT context) {
|
||||
return Create(farPatchTable, context->GetDeviceContext());
|
||||
}
|
||||
|
||||
static D3D11PatchTable *Create(Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
PatchArrayVector const &GetPatchArrays() const {
|
||||
return _patchArrays;
|
||||
}
|
||||
|
||||
/// Returns the index buffer containing the patch control vertices
|
||||
ID3D11Buffer* GetPatchIndexBuffer() const {
|
||||
return _indexBuffer;
|
||||
}
|
||||
|
||||
/// Returns the SRV containing the patch parameter
|
||||
ID3D11ShaderResourceView* GetPatchParamSRV() const {
|
||||
return _patchParamBufferSRV;
|
||||
}
|
||||
|
||||
protected:
|
||||
// allocate buffers from patchTable
|
||||
bool allocate(Far::PatchTable const *farPatchTable,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
PatchArrayVector _patchArrays;
|
||||
|
||||
ID3D11Buffer *_indexBuffer;
|
||||
ID3D11Buffer *_patchParamBuffer;
|
||||
ID3D11ShaderResourceView *_patchParamBufferSRV;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_GL_PATCH_TABLE_H
|
||||
147
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11VertexBuffer.cpp
vendored
Normal file
147
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11VertexBuffer.cpp
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/d3d11VertexBuffer.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <D3D11.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
||||
|
||||
D3D11VertexBuffer::D3D11VertexBuffer(int numElements, int numVertices)
|
||||
: _numElements(numElements), _numVertices(numVertices), _buffer(0),
|
||||
_uploadBuffer(0), _uav(0) {
|
||||
}
|
||||
|
||||
D3D11VertexBuffer::~D3D11VertexBuffer() {
|
||||
|
||||
SAFE_RELEASE(_buffer);
|
||||
SAFE_RELEASE(_uploadBuffer);
|
||||
SAFE_RELEASE(_uav);
|
||||
}
|
||||
|
||||
D3D11VertexBuffer*
|
||||
D3D11VertexBuffer::Create(int numElements, int numVertices,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
D3D11VertexBuffer *instance =
|
||||
new D3D11VertexBuffer(numElements, numVertices);
|
||||
|
||||
ID3D11Device *device;
|
||||
deviceContext->GetDevice(&device);
|
||||
if (instance->allocate(device)) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
D3D11VertexBuffer::UpdateData(const float *src, int startVertex, int numVertices,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
assert(deviceContext);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE resource;
|
||||
HRESULT hr = deviceContext->Map(_uploadBuffer, 0,
|
||||
D3D11_MAP_WRITE_DISCARD, 0, &resource);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "Failed to map buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int size = GetNumElements() * numVertices * sizeof(float);
|
||||
|
||||
memcpy((float*)resource.pData + startVertex * _numElements, src, size);
|
||||
|
||||
deviceContext->Unmap(_uploadBuffer, 0);
|
||||
|
||||
D3D11_BOX srcBox = { 0, 0, 0, size, 1, 1 };
|
||||
deviceContext->CopySubresourceRegion(_buffer, 0, 0, 0, 0,
|
||||
_uploadBuffer, 0, &srcBox);
|
||||
}
|
||||
|
||||
int
|
||||
D3D11VertexBuffer::GetNumElements() const {
|
||||
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int
|
||||
D3D11VertexBuffer::GetNumVertices() const {
|
||||
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
ID3D11Buffer *
|
||||
D3D11VertexBuffer::BindD3D11Buffer(ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
ID3D11UnorderedAccessView *
|
||||
D3D11VertexBuffer::BindD3D11UAV(ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
return _uav;
|
||||
}
|
||||
|
||||
bool
|
||||
D3D11VertexBuffer::allocate(ID3D11Device *device) {
|
||||
|
||||
D3D11_BUFFER_DESC hBufferDesc;
|
||||
hBufferDesc.ByteWidth = _numElements * _numVertices * sizeof(float);
|
||||
hBufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
hBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
|
||||
hBufferDesc.CPUAccessFlags = 0;
|
||||
hBufferDesc.MiscFlags = 0;
|
||||
hBufferDesc.StructureByteStride = sizeof(float);
|
||||
|
||||
HRESULT hr = device->CreateBuffer(&hBufferDesc, NULL, &_buffer);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Failed to create vertex buffer\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
hBufferDesc.ByteWidth = _numElements * _numVertices * sizeof(float);
|
||||
hBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
hBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_SHADER_RESOURCE;
|
||||
hBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
hBufferDesc.MiscFlags = 0;
|
||||
hBufferDesc.StructureByteStride = sizeof(float);
|
||||
|
||||
hr = device->CreateBuffer(&hBufferDesc, NULL, &_uploadBuffer);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Failed to create upload vertex buffer\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC uavd;
|
||||
ZeroMemory(&uavd, sizeof(uavd));
|
||||
uavd.Format = DXGI_FORMAT_R32_FLOAT;
|
||||
uavd.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
|
||||
uavd.Buffer.FirstElement = 0;
|
||||
uavd.Buffer.NumElements = _numElements * _numVertices;
|
||||
hr = device->CreateUnorderedAccessView(_buffer, &uavd, &_uav);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Failed to create unordered access resource view\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
82
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11VertexBuffer.h
vendored
Normal file
82
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/d3d11VertexBuffer.h
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_D3D11_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_D3D11_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
struct ID3D11UnorderedAccessView;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief Concrete vertex buffer class for DirectX subdivision and DirectX drawing.
|
||||
///
|
||||
/// D3D11VertexBuffer implements D3D11VertexBufferInterface. An instance
|
||||
/// of this buffer class can be passed to D3D11ComputeEvaluator.
|
||||
///
|
||||
class D3D11VertexBuffer {
|
||||
public:
|
||||
/// Creator. Returns NULL if error.
|
||||
static D3D11VertexBuffer * Create(int numElements, int numVertices,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Destructor.
|
||||
virtual ~D3D11VertexBuffer();
|
||||
|
||||
/// 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 startVertex, int numVertices,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Returns how many elements defined in this vertex buffer.
|
||||
int GetNumElements() const;
|
||||
|
||||
/// Returns how many vertices allocated in this vertex buffer.
|
||||
int GetNumVertices() const;
|
||||
|
||||
/// Returns the D3D11 buffer object.
|
||||
ID3D11Buffer *BindD3D11Buffer(ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Returns the D3D11 buffer object (for Osd::Mesh interface)
|
||||
ID3D11Buffer *BindVBO(ID3D11DeviceContext *deviceContext) {
|
||||
return BindD3D11Buffer(deviceContext);
|
||||
}
|
||||
|
||||
/// Returns the D3D11 UAV
|
||||
ID3D11UnorderedAccessView *BindD3D11UAV(ID3D11DeviceContext *deviceContext);
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
D3D11VertexBuffer(int numElements, int numVertices);
|
||||
|
||||
// Allocates D3D11 buffer
|
||||
bool allocate(ID3D11Device *device);
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
ID3D11Buffer *_buffer;
|
||||
ID3D11Buffer *_uploadBuffer;
|
||||
ID3D11UnorderedAccessView *_uav;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_D3D11_VERTEX_BUFFER_H
|
||||
556
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glComputeEvaluator.cpp
vendored
Normal file
556
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glComputeEvaluator.cpp
vendored
Normal file
@@ -0,0 +1,556 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "glLoader.h"
|
||||
|
||||
#include "../osd/glComputeEvaluator.h"
|
||||
#include "../osd/glslPatchShaderSource.h"
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTable.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static const char *shaderSource =
|
||||
#include "../osd/glslComputeKernel.gen.h"
|
||||
;
|
||||
|
||||
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 (OSD_OPENGL_HAS(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(
|
||||
Far::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(
|
||||
Far::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) {
|
||||
std::memset((void*) &_stencilKernel, 0, sizeof(_stencilKernel));
|
||||
std::memset((void*) &_patchKernel, 0, sizeof(_patchKernel));
|
||||
|
||||
// Initialize internal OpenGL loader library if necessary
|
||||
OpenSubdiv::internal::GLLoader::libraryInitializeGL();
|
||||
}
|
||||
|
||||
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 =
|
||||
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", 0, 0, 0};
|
||||
|
||||
shaderSources[1] = defineStr.c_str();
|
||||
shaderSources[2] = patchBasisShaderSource.c_str();
|
||||
shaderSources[3] = shaderSource;
|
||||
glShaderSource(shader, 4, shaderSources, NULL);
|
||||
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, NULL, buffer);
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, buffer);
|
||||
|
||||
glGetProgramInfoLog(program, 1024, NULL, buffer);
|
||||
Far::Error(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();
|
||||
}
|
||||
|
||||
bool
|
||||
GLComputeEvaluator::EvalStencils(
|
||||
ID srcBuffer, BufferDescriptor const &srcDesc,
|
||||
ID dstBuffer, BufferDescriptor const &dstDesc,
|
||||
ID duBuffer, BufferDescriptor const &duDesc,
|
||||
ID dvBuffer, BufferDescriptor const &dvDesc,
|
||||
ID sizesBuffer,
|
||||
ID offsetsBuffer,
|
||||
ID indicesBuffer,
|
||||
ID weightsBuffer,
|
||||
ID duWeightsBuffer,
|
||||
ID 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(
|
||||
ID srcBuffer, BufferDescriptor const &srcDesc,
|
||||
ID dstBuffer, BufferDescriptor const &dstDesc,
|
||||
ID duBuffer, BufferDescriptor const &duDesc,
|
||||
ID dvBuffer, BufferDescriptor const &dvDesc,
|
||||
ID duuBuffer, BufferDescriptor const &duuDesc,
|
||||
ID duvBuffer, BufferDescriptor const &duvDesc,
|
||||
ID dvvBuffer, BufferDescriptor const &dvvDesc,
|
||||
ID sizesBuffer,
|
||||
ID offsetsBuffer,
|
||||
ID indicesBuffer,
|
||||
ID weightsBuffer,
|
||||
ID duWeightsBuffer,
|
||||
ID dvWeightsBuffer,
|
||||
ID duuWeightsBuffer,
|
||||
ID duvWeightsBuffer,
|
||||
ID 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);
|
||||
}
|
||||
|
||||
glDispatchCompute((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
|
||||
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(
|
||||
ID srcBuffer, BufferDescriptor const &srcDesc,
|
||||
ID dstBuffer, BufferDescriptor const &dstDesc,
|
||||
ID duBuffer, BufferDescriptor const &duDesc,
|
||||
ID dvBuffer, BufferDescriptor const &dvDesc,
|
||||
int numPatchCoords,
|
||||
ID patchCoordsBuffer,
|
||||
const PatchArrayVector &patchArrays,
|
||||
ID patchIndexBuffer,
|
||||
ID 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(
|
||||
ID srcBuffer, BufferDescriptor const &srcDesc,
|
||||
ID dstBuffer, BufferDescriptor const &dstDesc,
|
||||
ID duBuffer, BufferDescriptor const &duDesc,
|
||||
ID dvBuffer, BufferDescriptor const &dvDesc,
|
||||
ID duuBuffer, BufferDescriptor const &duuDesc,
|
||||
ID duvBuffer, BufferDescriptor const &duvDesc,
|
||||
ID dvvBuffer, BufferDescriptor const &dvvDesc,
|
||||
int numPatchCoords,
|
||||
ID patchCoordsBuffer,
|
||||
const PatchArrayVector &patchArrays,
|
||||
ID patchIndexBuffer,
|
||||
ID 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, NULL, 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);
|
||||
}
|
||||
|
||||
glDispatchCompute((numPatchCoords + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
2101
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glComputeEvaluator.h
vendored
Normal file
2101
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glComputeEvaluator.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
100
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glLegacyGregoryPatchTable.cpp
vendored
Normal file
100
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glLegacyGregoryPatchTable.cpp
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "glLoader.h"
|
||||
|
||||
#include "../osd/glLegacyGregoryPatchTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
GLLegacyGregoryPatchTable::GLLegacyGregoryPatchTable() :
|
||||
_vertexTextureBuffer(0), _vertexValenceTextureBuffer(0),
|
||||
_quadOffsetsTextureBuffer(0) {
|
||||
_quadOffsetsBase[0] = _quadOffsetsBase[1] = 0;
|
||||
|
||||
// Initialize internal OpenGL loader library if necessary
|
||||
OpenSubdiv::internal::GLLoader::libraryInitializeGL();
|
||||
}
|
||||
|
||||
GLLegacyGregoryPatchTable::~GLLegacyGregoryPatchTable() {
|
||||
if (_vertexTextureBuffer)
|
||||
glDeleteTextures(1, &_vertexTextureBuffer);
|
||||
if (_vertexValenceTextureBuffer)
|
||||
glDeleteTextures(1, &_vertexValenceTextureBuffer);
|
||||
if (_quadOffsetsTextureBuffer)
|
||||
glDeleteTextures(1, &_quadOffsetsTextureBuffer);
|
||||
}
|
||||
|
||||
GLLegacyGregoryPatchTable *
|
||||
GLLegacyGregoryPatchTable::Create(Far::PatchTable const *farPatchTable) {
|
||||
|
||||
GLLegacyGregoryPatchTable *result = new GLLegacyGregoryPatchTable();
|
||||
glGenTextures(1, &result->_vertexTextureBuffer);
|
||||
glGenTextures(1, &result->_vertexValenceTextureBuffer);
|
||||
glGenTextures(1, &result->_quadOffsetsTextureBuffer);
|
||||
|
||||
Far::PatchTable::VertexValenceTable const &
|
||||
valenceTable = farPatchTable->GetVertexValenceTable();
|
||||
Far::PatchTable::QuadOffsetsTable const &
|
||||
quadOffsetsTable = farPatchTable->GetQuadOffsetsTable();
|
||||
|
||||
if (! valenceTable.empty()) {
|
||||
GLuint buffer;
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, valenceTable.size() * sizeof(int),
|
||||
&valenceTable[0], GL_STATIC_DRAW);
|
||||
|
||||
glBindTexture(GL_TEXTURE_BUFFER, result->_vertexValenceTextureBuffer);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
|
||||
if (! quadOffsetsTable.empty()) {
|
||||
GLuint buffer;
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, quadOffsetsTable.size() * sizeof(int),
|
||||
&quadOffsetsTable[0], GL_STATIC_DRAW);
|
||||
|
||||
glBindTexture(GL_TEXTURE_BUFFER, result->_quadOffsetsTextureBuffer);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
|
||||
result->_quadOffsetsBase[0] = 0;
|
||||
result->_quadOffsetsBase[1] = 0;
|
||||
// scan patchtable to find quadOffsetsBase.
|
||||
for (int i = 0; i < farPatchTable->GetNumPatchArrays(); ++i) {
|
||||
// GREGORY_BOUNDARY's quadoffsets come after GREGORY's.
|
||||
if (farPatchTable->GetPatchArrayDescriptor(i) ==
|
||||
Far::PatchDescriptor::GREGORY) {
|
||||
result->_quadOffsetsBase[1] = farPatchTable->GetNumPatches(i) * 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
GLLegacyGregoryPatchTable::UpdateVertexBuffer(ID vbo) {
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _vertexTextureBuffer);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, vbo);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
70
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glLegacyGregoryPatchTable.h
vendored
Normal file
70
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glLegacyGregoryPatchTable.h
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_GL_LEGACY_GREGORY_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_OSD_GL_LEGACY_GREGORY_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/patchTable.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class GLLegacyGregoryPatchTable
|
||||
: private NonCopyable<GLLegacyGregoryPatchTable> {
|
||||
public:
|
||||
using ID = unsigned int; // GLuint resource ID
|
||||
|
||||
~GLLegacyGregoryPatchTable();
|
||||
|
||||
static GLLegacyGregoryPatchTable *Create(Far::PatchTable const *patchTable);
|
||||
|
||||
void UpdateVertexBuffer(ID vbo);
|
||||
|
||||
ID GetVertexTextureBuffer() const {
|
||||
return _vertexTextureBuffer;
|
||||
}
|
||||
|
||||
ID GetVertexValenceTextureBuffer() const {
|
||||
return _vertexValenceTextureBuffer;
|
||||
}
|
||||
|
||||
ID GetQuadOffsetsTextureBuffer() const {
|
||||
return _quadOffsetsTextureBuffer;
|
||||
}
|
||||
|
||||
ID GetQuadOffsetsBase(Far::PatchDescriptor::Type type) {
|
||||
if (type == Far::PatchDescriptor::GREGORY_BOUNDARY) {
|
||||
return _quadOffsetsBase[1];
|
||||
}
|
||||
return _quadOffsetsBase[0];
|
||||
}
|
||||
|
||||
protected:
|
||||
GLLegacyGregoryPatchTable();
|
||||
|
||||
private:
|
||||
ID _vertexTextureBuffer;
|
||||
ID _vertexValenceTextureBuffer;
|
||||
ID _quadOffsetsTextureBuffer;
|
||||
ID _quadOffsetsBase[2]; // gregory, boundaryGregory
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_GL_LEGACY_GREGORY_PATCH_TABLE_H
|
||||
31
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glMesh.h
vendored
Normal file
31
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glMesh.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_GL_MESH_H
|
||||
#define OPENSUBDIV3_OSD_GL_MESH_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/mesh.h"
|
||||
#include "../osd/glPatchTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
typedef MeshInterface<GLPatchTable> GLMeshInterface;
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_GL_MESH_H
|
||||
155
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glPatchTable.cpp
vendored
Normal file
155
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glPatchTable.cpp
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "glLoader.h"
|
||||
|
||||
#include "../osd/glPatchTable.h"
|
||||
|
||||
#include "../far/patchTable.h"
|
||||
#include "../osd/cpuPatchTable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
GLPatchTable::GLPatchTable() :
|
||||
_patchIndexBuffer(0), _patchParamBuffer(0),
|
||||
_patchIndexTexture(0), _patchParamTexture(0) {
|
||||
|
||||
// Initialize internal OpenGL loader library if necessary
|
||||
OpenSubdiv::internal::GLLoader::libraryInitializeGL();
|
||||
}
|
||||
|
||||
GLPatchTable::~GLPatchTable() {
|
||||
if (_patchIndexBuffer) glDeleteBuffers(1, &_patchIndexBuffer);
|
||||
if (_patchParamBuffer) glDeleteBuffers(1, &_patchParamBuffer);
|
||||
if (_patchIndexTexture) glDeleteTextures(1, &_patchIndexTexture);
|
||||
if (_patchParamTexture) glDeleteTextures(1, &_patchParamTexture);
|
||||
if (_varyingIndexBuffer) glDeleteBuffers(1, &_varyingIndexBuffer);
|
||||
if (_varyingIndexTexture) glDeleteTextures(1, &_varyingIndexTexture);
|
||||
for (int fvc=0; fvc<(int)_fvarIndexBuffers.size(); ++fvc) {
|
||||
if (_fvarIndexBuffers[fvc]) glDeleteBuffers(1, &_fvarIndexBuffers[fvc]);
|
||||
}
|
||||
for (int fvc=0; fvc<(int)_fvarIndexTextures.size(); ++fvc) {
|
||||
if (_fvarIndexTextures[fvc]) glDeleteTextures(1, &_fvarIndexTextures[fvc]);
|
||||
}
|
||||
}
|
||||
|
||||
GLPatchTable *
|
||||
GLPatchTable::Create(Far::PatchTable const *farPatchTable,
|
||||
void * /*deviceContext*/) {
|
||||
GLPatchTable *instance = new GLPatchTable();
|
||||
if (instance->allocate(farPatchTable)) return instance;
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
GLPatchTable::allocate(Far::PatchTable const *farPatchTable) {
|
||||
glGenBuffers(1, &_patchIndexBuffer);
|
||||
glGenBuffers(1, &_patchParamBuffer);
|
||||
|
||||
CpuPatchTable patchTable(farPatchTable);
|
||||
|
||||
size_t numPatchArrays = patchTable.GetNumPatchArrays();
|
||||
GLsizei indexSize = (GLsizei)patchTable.GetPatchIndexSize();
|
||||
GLsizei patchParamSize = (GLsizei)patchTable.GetPatchParamSize();
|
||||
|
||||
// copy patch array
|
||||
_patchArrays.assign(patchTable.GetPatchArrayBuffer(),
|
||||
patchTable.GetPatchArrayBuffer() + numPatchArrays);
|
||||
|
||||
// copy index buffer
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _patchIndexBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
indexSize * sizeof(GLint),
|
||||
patchTable.GetPatchIndexBuffer(),
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
// copy patchparam buffer
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _patchParamBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
patchParamSize * sizeof(PatchParam),
|
||||
patchTable.GetPatchParamBuffer(),
|
||||
GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
// make both buffer as texture buffers too.
|
||||
glGenTextures(1, &_patchIndexTexture);
|
||||
glGenTextures(1, &_patchParamTexture);
|
||||
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _patchIndexTexture);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, _patchIndexBuffer);
|
||||
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _patchParamTexture);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32I, _patchParamBuffer);
|
||||
|
||||
// varying
|
||||
_varyingPatchArrays.assign(
|
||||
patchTable.GetVaryingPatchArrayBuffer(),
|
||||
patchTable.GetVaryingPatchArrayBuffer() + numPatchArrays);
|
||||
|
||||
glGenBuffers(1, &_varyingIndexBuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _varyingIndexBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
patchTable.GetVaryingPatchIndexSize() * sizeof(GLint),
|
||||
patchTable.GetVaryingPatchIndexBuffer(),
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
glGenTextures(1, &_varyingIndexTexture);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _varyingIndexTexture);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, _varyingIndexBuffer);
|
||||
|
||||
// face-varying
|
||||
int numFVarChannels = patchTable.GetNumFVarChannels();
|
||||
_fvarPatchArrays.resize(numFVarChannels);
|
||||
_fvarIndexBuffers.resize(numFVarChannels);
|
||||
_fvarIndexTextures.resize(numFVarChannels);
|
||||
_fvarParamBuffers.resize(numFVarChannels);
|
||||
_fvarParamTextures.resize(numFVarChannels);
|
||||
for (int fvc=0; fvc<numFVarChannels; ++fvc) {
|
||||
_fvarPatchArrays[fvc].assign(
|
||||
patchTable.GetFVarPatchArrayBuffer(fvc),
|
||||
patchTable.GetFVarPatchArrayBuffer(fvc) + numPatchArrays);
|
||||
|
||||
glGenBuffers(1, &_fvarIndexBuffers[fvc]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _fvarIndexBuffers[fvc]);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
patchTable.GetFVarPatchIndexSize(fvc) * sizeof(GLint),
|
||||
patchTable.GetFVarPatchIndexBuffer(fvc),
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
glGenTextures(1, &_fvarIndexTextures[fvc]);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _fvarIndexTextures[fvc]);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, _fvarIndexBuffers[fvc]);
|
||||
|
||||
glGenBuffers(1, &_fvarParamBuffers[fvc]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _fvarParamBuffers[fvc]);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
patchTable.GetFVarPatchParamSize(fvc) * sizeof(PatchParam),
|
||||
patchTable.GetFVarPatchParamBuffer(fvc),
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
glGenTextures(1, &_fvarParamTextures[fvc]);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _fvarParamTextures[fvc]);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32I, _fvarParamBuffers[fvc]);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
139
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glPatchTable.h
vendored
Normal file
139
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glPatchTable.h
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_GL_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_OSD_GL_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/types.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far{
|
||||
class PatchTable;
|
||||
};
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class GLPatchTable : private NonCopyable<GLPatchTable> {
|
||||
public:
|
||||
using ID = unsigned int; // GLuint resource ID
|
||||
using VertexBufferBinding = ID; // buffer binding type
|
||||
|
||||
~GLPatchTable();
|
||||
|
||||
static GLPatchTable *Create(Far::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
|
||||
ID GetPatchIndexBuffer() const {
|
||||
return _patchIndexBuffer;
|
||||
}
|
||||
|
||||
/// Returns the GL index buffer containing the patch parameter
|
||||
ID GetPatchParamBuffer() const {
|
||||
return _patchParamBuffer;
|
||||
}
|
||||
|
||||
/// Returns the GL texture buffer containing the patch control vertices
|
||||
ID GetPatchIndexTextureBuffer() const {
|
||||
return _patchIndexTexture;
|
||||
}
|
||||
|
||||
/// Returns the GL texture buffer containing the patch parameter
|
||||
ID GetPatchParamTextureBuffer() const {
|
||||
return _patchParamTexture;
|
||||
}
|
||||
|
||||
/// 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
|
||||
ID GetVaryingPatchIndexBuffer() const {
|
||||
return _varyingIndexBuffer;
|
||||
}
|
||||
|
||||
/// Returns the GL texture buffer containing the varying control vertices
|
||||
ID GetVaryingPatchIndexTextureBuffer() const {
|
||||
return _varyingIndexTexture;
|
||||
}
|
||||
|
||||
/// 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
|
||||
ID GetFVarPatchIndexBuffer(int fvarChannel = 0) const {
|
||||
return _fvarIndexBuffers[fvarChannel];
|
||||
}
|
||||
|
||||
/// Returns the GL texture buffer containing face-varying control vertices
|
||||
ID GetFVarPatchIndexTextureBuffer(int fvarChannel = 0) const {
|
||||
return _fvarIndexTextures[fvarChannel];
|
||||
}
|
||||
|
||||
/// Returns the GL index buffer containing face-varying patch params
|
||||
ID GetFVarPatchParamBuffer(int fvarChannel = 0) const {
|
||||
return _fvarParamBuffers[fvarChannel];
|
||||
}
|
||||
|
||||
/// Returns the GL texture buffer containing face-varying patch params
|
||||
ID GetFVarPatchParamTextureBuffer(int fvarChannel = 0) const {
|
||||
return _fvarParamTextures[fvarChannel];
|
||||
}
|
||||
|
||||
protected:
|
||||
GLPatchTable();
|
||||
|
||||
// allocate buffers from patchTable
|
||||
bool allocate(Far::PatchTable const *farPatchTable);
|
||||
|
||||
PatchArrayVector _patchArrays;
|
||||
|
||||
ID _patchIndexBuffer;
|
||||
ID _patchParamBuffer;
|
||||
|
||||
ID _patchIndexTexture;
|
||||
ID _patchParamTexture;
|
||||
|
||||
PatchArrayVector _varyingPatchArrays;
|
||||
ID _varyingIndexBuffer;
|
||||
ID _varyingIndexTexture;
|
||||
|
||||
std::vector<PatchArrayVector> _fvarPatchArrays;
|
||||
std::vector<ID> _fvarIndexBuffers;
|
||||
std::vector<ID> _fvarIndexTextures;
|
||||
|
||||
std::vector<ID> _fvarParamBuffers;
|
||||
std::vector<ID> _fvarParamTextures;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_GL_PATCH_TABLE_H
|
||||
107
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glVertexBuffer.cpp
vendored
Normal file
107
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glVertexBuffer.cpp
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "glLoader.h"
|
||||
|
||||
#include "../osd/glVertexBuffer.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
GLVertexBuffer::GLVertexBuffer(int numElements, int numVertices)
|
||||
: _numElements(numElements),
|
||||
_numVertices(numVertices),
|
||||
_vbo(0) {
|
||||
|
||||
// Initialize internal OpenGL loader library if necessary
|
||||
OpenSubdiv::internal::GLLoader::libraryInitializeGL();
|
||||
}
|
||||
|
||||
GLVertexBuffer::~GLVertexBuffer() {
|
||||
|
||||
glDeleteBuffers(1, &_vbo);
|
||||
}
|
||||
|
||||
GLVertexBuffer *
|
||||
GLVertexBuffer::Create(int numElements, int numVertices, void *) {
|
||||
|
||||
GLVertexBuffer *instance =
|
||||
new GLVertexBuffer(numElements, numVertices);
|
||||
if (instance->allocate()) return instance;
|
||||
delete instance;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
GLVertexBuffer::UpdateData(const float *src, int startVertex, int numVertices,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
int size = numVertices * _numElements * (int) sizeof(float);
|
||||
#if defined(GL_ARB_direct_state_access)
|
||||
if (OSD_OPENGL_HAS(ARB_direct_state_access)) {
|
||||
glNamedBufferSubData(_vbo,
|
||||
startVertex * _numElements * sizeof(float),
|
||||
size, src);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
glBufferSubData(GL_ARRAY_BUFFER,
|
||||
startVertex * _numElements * sizeof(float), size, src);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
GLVertexBuffer::GetNumElements() const {
|
||||
|
||||
return _numElements;
|
||||
}
|
||||
|
||||
int
|
||||
GLVertexBuffer::GetNumVertices() const {
|
||||
|
||||
return _numVertices;
|
||||
}
|
||||
|
||||
GLVertexBuffer::ID
|
||||
GLVertexBuffer::BindVBO(void * /*deviceContext*/) {
|
||||
|
||||
return _vbo;
|
||||
}
|
||||
|
||||
bool
|
||||
GLVertexBuffer::allocate() {
|
||||
|
||||
int size = _numElements * _numVertices * (int) sizeof(float);
|
||||
|
||||
|
||||
#if defined(GL_ARB_direct_state_access)
|
||||
if (OSD_OPENGL_HAS(ARB_direct_state_access)) {
|
||||
glCreateBuffers(1, &_vbo);
|
||||
glNamedBufferDataEXT(_vbo, size, 0, GL_DYNAMIC_DRAW);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLint prev = 0;
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev);
|
||||
glGenBuffers(1, &_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, prev);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
72
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glVertexBuffer.h
vendored
Normal file
72
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glVertexBuffer.h
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_GL_VERTEX_BUFFER_H
|
||||
#define OPENSUBDIV3_OSD_GL_VERTEX_BUFFER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief Concrete vertex buffer class for GLSL subdivision and OpenGL drawing.
|
||||
///
|
||||
/// GLVertexBuffer implements GLVertexBufferInterface. An instance
|
||||
/// of this buffer class can be passed to OsdGLComputeEvaluator.
|
||||
///
|
||||
class GLVertexBuffer {
|
||||
public:
|
||||
using ID = unsigned int; // GLuint resource ID
|
||||
|
||||
/// Creator. Returns NULL if error.
|
||||
static GLVertexBuffer * Create(int numElements, int numVertices,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Destructor.
|
||||
~GLVertexBuffer();
|
||||
|
||||
/// 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 startVertex, int numVertices,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Returns how many elements defined in this vertex buffer.
|
||||
int GetNumElements() const;
|
||||
|
||||
/// Returns how many vertices allocated in this vertex buffer.
|
||||
int GetNumVertices() const;
|
||||
|
||||
/// Returns the GL buffer object.
|
||||
ID BindVBO(void *deviceContext = NULL);
|
||||
|
||||
protected:
|
||||
/// Constructor.
|
||||
GLVertexBuffer(int numElements, int numVertices);
|
||||
|
||||
/// Allocates VBO for this buffer.
|
||||
/// Returns true if success.
|
||||
bool allocate();
|
||||
|
||||
private:
|
||||
int _numElements;
|
||||
int _numVertices;
|
||||
ID _vbo;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_GL_VERTEX_BUFFER_H
|
||||
947
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glXFBEvaluator.cpp
vendored
Normal file
947
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glXFBEvaluator.cpp
vendored
Normal file
@@ -0,0 +1,947 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "glLoader.h"
|
||||
|
||||
#include "../osd/glXFBEvaluator.h"
|
||||
#include "../osd/glslPatchShaderSource.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTable.h"
|
||||
|
||||
#if _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static const char *shaderSource =
|
||||
#include "../osd/glslXFBKernel.gen.h"
|
||||
;
|
||||
|
||||
template <class T> GLuint
|
||||
createGLTextureBuffer(std::vector<T> const & src, GLenum type) {
|
||||
if (src.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLint size = static_cast<int>(src.size()*sizeof(T));
|
||||
void const * ptr = &src.at(0);
|
||||
|
||||
GLuint buffer = 0;
|
||||
GLuint devicePtr = 0;
|
||||
|
||||
#if defined(GL_ARB_direct_state_access)
|
||||
if (OSD_OPENGL_HAS(ARB_direct_state_access)) {
|
||||
glCreateBuffers(1, &buffer);
|
||||
glNamedBufferData(buffer, size, ptr, GL_STATIC_DRAW);
|
||||
glCreateTextures(GL_TEXTURE_BUFFER, 1, &devicePtr);
|
||||
glTextureBuffer(devicePtr, type, buffer);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLint prev = 0;
|
||||
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev);
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, ptr, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, prev);
|
||||
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_BUFFER, &prev);
|
||||
glGenTextures(1, &devicePtr);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, devicePtr);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, type, buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, prev);
|
||||
}
|
||||
|
||||
glDeleteBuffers(1, &buffer);
|
||||
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
GLStencilTableTBO::GLStencilTableTBO(
|
||||
Far::StencilTable const *stencilTable) {
|
||||
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createGLTextureBuffer(stencilTable->GetSizes(), GL_R32UI);
|
||||
_offsets = createGLTextureBuffer(
|
||||
stencilTable->GetOffsets(), GL_R32I);
|
||||
_indices = createGLTextureBuffer(
|
||||
stencilTable->GetControlIndices(), GL_R32I);
|
||||
_weights = createGLTextureBuffer(stencilTable->GetWeights(), GL_R32F);
|
||||
_duWeights = _dvWeights = 0;
|
||||
_duuWeights = _duvWeights = _dvvWeights = 0;
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = 0;
|
||||
_duWeights = _dvWeights = 0;
|
||||
_duuWeights = _duvWeights = _dvvWeights = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLStencilTableTBO::GLStencilTableTBO(
|
||||
Far::LimitStencilTable const *limitStencilTable) {
|
||||
|
||||
_numStencils = limitStencilTable->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createGLTextureBuffer(
|
||||
limitStencilTable->GetSizes(), GL_R32UI);
|
||||
_offsets = createGLTextureBuffer(
|
||||
limitStencilTable->GetOffsets(), GL_R32I);
|
||||
_indices = createGLTextureBuffer(
|
||||
limitStencilTable->GetControlIndices(), GL_R32I);
|
||||
_weights = createGLTextureBuffer(
|
||||
limitStencilTable->GetWeights(), GL_R32F);
|
||||
_duWeights = createGLTextureBuffer(
|
||||
limitStencilTable->GetDuWeights(), GL_R32F);
|
||||
_dvWeights = createGLTextureBuffer(
|
||||
limitStencilTable->GetDvWeights(), GL_R32F);
|
||||
_duuWeights = createGLTextureBuffer(
|
||||
limitStencilTable->GetDuuWeights(), GL_R32F);
|
||||
_duvWeights = createGLTextureBuffer(
|
||||
limitStencilTable->GetDuvWeights(), GL_R32F);
|
||||
_dvvWeights = createGLTextureBuffer(
|
||||
limitStencilTable->GetDvvWeights(), GL_R32F);
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = 0;
|
||||
_duWeights = _dvWeights = 0;
|
||||
_duuWeights = _duvWeights = _dvvWeights = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLStencilTableTBO::~GLStencilTableTBO() {
|
||||
if (_sizes) glDeleteTextures(1, &_sizes);
|
||||
if (_offsets) glDeleteTextures(1, &_offsets);
|
||||
if (_indices) glDeleteTextures(1, &_indices);
|
||||
if (_weights) glDeleteTextures(1, &_weights);
|
||||
if (_duWeights) glDeleteTextures(1, &_duWeights);
|
||||
if (_dvWeights) glDeleteTextures(1, &_dvWeights);
|
||||
if (_duuWeights) glDeleteTextures(1, &_duuWeights);
|
||||
if (_duvWeights) glDeleteTextures(1, &_duvWeights);
|
||||
if (_dvvWeights) glDeleteTextures(1, &_dvvWeights);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
GLXFBEvaluator::GLXFBEvaluator(bool interleavedDerivativeBuffers)
|
||||
: _srcBufferTexture(0),
|
||||
_patchArraysUBO(0),
|
||||
_interleavedDerivativeBuffers(interleavedDerivativeBuffers) {
|
||||
|
||||
// Initialize internal OpenGL loader library if necessary
|
||||
OpenSubdiv::internal::GLLoader::libraryInitializeGL();
|
||||
}
|
||||
|
||||
GLXFBEvaluator::~GLXFBEvaluator() {
|
||||
if (_srcBufferTexture) {
|
||||
glDeleteTextures(1, &_srcBufferTexture);
|
||||
}
|
||||
if (_patchArraysUBO) {
|
||||
glDeleteBuffers(1, &_patchArraysUBO);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
bool interleavedDerivativeBuffers) {
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
|
||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
|
||||
std::string patchBasisShaderSource =
|
||||
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 VERTEX_SHADER\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_XFB_USE_1ST_DERIVATIVES\n";
|
||||
if (interleavedDerivativeBuffers) {
|
||||
defines <<
|
||||
"#define OPENSUBDIV_GLSL_XFB_INTERLEAVED_1ST_DERIVATIVE_BUFFERS\n";
|
||||
}
|
||||
}
|
||||
if (deriv2) {
|
||||
defines << "#define OPENSUBDIV_GLSL_XFB_USE_2ND_DERIVATIVES\n";
|
||||
if (interleavedDerivativeBuffers) {
|
||||
defines <<
|
||||
"#define OPENSUBDIV_GLSL_XFB_INTERLEAVED_2ND_DERIVATIVE_BUFFERS\n";
|
||||
}
|
||||
}
|
||||
|
||||
std::string defineStr = defines.str();
|
||||
|
||||
const char *shaderSources[4] = {"#version 410\n", NULL, NULL, NULL};
|
||||
|
||||
shaderSources[1] = defineStr.c_str();
|
||||
shaderSources[2] = patchBasisShaderSource.c_str();
|
||||
shaderSources[3] = shaderSource;
|
||||
glShaderSource(vertexShader, 4, shaderSources, NULL);
|
||||
glCompileShader(vertexShader);
|
||||
glAttachShader(program, vertexShader);
|
||||
|
||||
std::vector<std::string> outputs;
|
||||
char attrName[32];
|
||||
{
|
||||
// vertex data (may include custom vertex data) and varying data
|
||||
// are stored into the same buffer, interleaved.
|
||||
//
|
||||
// (gl_SkipComponents1)
|
||||
// outVertexData[0]
|
||||
// outVertexData[1]
|
||||
// outVertexData[2]
|
||||
// (gl_SkipComponents1)
|
||||
//
|
||||
// note that "primvarOffset" in shader is still needed to read
|
||||
// interleaved components even if gl_SkipComponents is used.
|
||||
//
|
||||
int primvarOffset = (dstDesc.offset % dstDesc.stride);
|
||||
for (int i = 0; i < primvarOffset; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
for (int i = 0; i < dstDesc.length; ++i) {
|
||||
snprintf(attrName, sizeof(attrName), "outVertexBuffer[%d]", i);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
for (int i = primvarOffset + dstDesc.length; i < dstDesc.stride; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
}
|
||||
//
|
||||
// For derivatives, we use another buffer bindings so gl_NextBuffer
|
||||
// is inserted here to switch the destination of transform feedback.
|
||||
//
|
||||
// Note that the destination buffers may or may not be interleaved between
|
||||
// vertex and each derivatives. gl_NextBuffer seems still works well
|
||||
// in either case.
|
||||
//
|
||||
// If we know that the buffers for derivatives are interleaved, then we
|
||||
// can use fewer buffer bindings. This can be important, since most GL
|
||||
// implementations will support only up to 4 transform feedback bindings.
|
||||
//
|
||||
if (deriv1 && interleavedDerivativeBuffers) {
|
||||
outputs.push_back("gl_NextBuffer");
|
||||
|
||||
int primvar1Offset = (duDesc.offset % duDesc.stride);
|
||||
int primvar2Offset = (dvDesc.offset % dvDesc.stride);
|
||||
|
||||
for (int i = 0; i < primvar1Offset; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
for (int i = 0; i < duDesc.length; ++i) {
|
||||
snprintf(attrName, sizeof(attrName), "outDeriv1Buffer[%d]", i);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
for (int i = primvar1Offset + duDesc.length; i < primvar2Offset; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
for (int i = 0; i < dvDesc.length; ++i) {
|
||||
snprintf(attrName, sizeof(attrName), "outDeriv1Buffer[%d]", i+duDesc.length);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
for (int i = primvar2Offset + dvDesc.length; i < dvDesc.stride; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
} else {
|
||||
if (duDesc.length) {
|
||||
outputs.push_back("gl_NextBuffer");
|
||||
int primvarOffset = (duDesc.offset % duDesc.stride);
|
||||
for (int i = 0; i < primvarOffset; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
for (int i = 0; i < duDesc.length; ++i) {
|
||||
snprintf(attrName, sizeof(attrName), "outDuBuffer[%d]", i);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
for (int i = primvarOffset + duDesc.length; i < duDesc.stride; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
}
|
||||
if (dvDesc.length) {
|
||||
outputs.push_back("gl_NextBuffer");
|
||||
int primvarOffset = (dvDesc.offset % dvDesc.stride);
|
||||
for (int i = 0; i < primvarOffset; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
for (int i = 0; i < dvDesc.length; ++i) {
|
||||
snprintf(attrName, sizeof(attrName), "outDvBuffer[%d]", i);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
for (int i = primvarOffset + dvDesc.length; i < dvDesc.stride; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (deriv2 && interleavedDerivativeBuffers) {
|
||||
outputs.push_back("gl_NextBuffer");
|
||||
|
||||
int primvar1Offset = (duuDesc.offset % duuDesc.stride);
|
||||
int primvar2Offset = (duvDesc.offset % duvDesc.stride);
|
||||
int primvar3Offset = (dvvDesc.offset % dvvDesc.stride);
|
||||
|
||||
for (int i = 0; i < primvar1Offset; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
for (int i = 0; i < duuDesc.length; ++i) {
|
||||
snprintf(attrName, sizeof(attrName), "outDeriv2Buffer[%d]", i);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
|
||||
for (int i = primvar1Offset + duuDesc.length; i < primvar2Offset; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
for (int i = 0; i < duvDesc.length; ++i) {
|
||||
snprintf(attrName, sizeof(attrName), "outDeriv2Buffer[%d]", i+duuDesc.length);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
|
||||
for (int i = primvar2Offset + duvDesc.length; i < primvar3Offset; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
for (int i = 0; i < dvvDesc.length; ++i) {
|
||||
snprintf(attrName, sizeof(attrName), "outDeriv2Buffer[%d]", i+duuDesc.length+duvDesc.length);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
|
||||
for (int i = primvar3Offset + dvvDesc.length; i < dvvDesc.stride; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
} else {
|
||||
if (duuDesc.length) {
|
||||
outputs.push_back("gl_NextBuffer");
|
||||
int primvarOffset = (duuDesc.offset % duuDesc.stride);
|
||||
for (int i = 0; i < primvarOffset; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
for (int i = 0; i < duuDesc.length; ++i) {
|
||||
snprintf(attrName, sizeof(attrName), "outDuuBuffer[%d]", i);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
for (int i = primvarOffset + duuDesc.length; i < duuDesc.stride; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
}
|
||||
if (duvDesc.length) {
|
||||
outputs.push_back("gl_NextBuffer");
|
||||
int primvarOffset = (duvDesc.offset % duvDesc.stride);
|
||||
for (int i = 0; i < primvarOffset; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
for (int i = 0; i < duvDesc.length; ++i) {
|
||||
snprintf(attrName, sizeof(attrName), "outDuvBuffer[%d]", i);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
for (int i = primvarOffset + duvDesc.length; i < duvDesc.stride; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
}
|
||||
if (dvvDesc.length) {
|
||||
outputs.push_back("gl_NextBuffer");
|
||||
int primvarOffset = (dvvDesc.offset % dvvDesc.stride);
|
||||
for (int i = 0; i < primvarOffset; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
for (int i = 0; i < dvvDesc.length; ++i) {
|
||||
snprintf(attrName, sizeof(attrName), "outDvvBuffer[%d]", i);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
for (int i = primvarOffset + dvvDesc.length; i < dvvDesc.stride; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
}
|
||||
}
|
||||
// convert to char* array
|
||||
std::vector<const char *> pOutputs;
|
||||
for (size_t i = 0; i < outputs.size(); ++i) {
|
||||
pOutputs.push_back(&outputs[i][0]);
|
||||
}
|
||||
|
||||
glTransformFeedbackVaryings(program, (GLsizei)outputs.size(),
|
||||
&pOutputs[0], GL_INTERLEAVED_ATTRIBS);
|
||||
|
||||
GLint linked = 0;
|
||||
glLinkProgram(program);
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &linked);
|
||||
|
||||
if (linked == GL_FALSE) {
|
||||
char buffer[1024];
|
||||
glGetShaderInfoLog(vertexShader, 1024, NULL, buffer);
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, buffer);
|
||||
|
||||
glGetProgramInfoLog(program, 1024, NULL, buffer);
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, buffer);
|
||||
|
||||
glDeleteProgram(program);
|
||||
program = 0;
|
||||
}
|
||||
|
||||
glDeleteShader(vertexShader);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
bool
|
||||
GLXFBEvaluator::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
|
||||
_stencilKernel.Compile(srcDesc, dstDesc, duDesc, dvDesc,
|
||||
duuDesc, duvDesc, dvvDesc,
|
||||
_interleavedDerivativeBuffers);
|
||||
|
||||
// create a patch kernel
|
||||
_patchKernel.Compile(srcDesc, dstDesc, duDesc, dvDesc,
|
||||
duuDesc, duvDesc, dvvDesc,
|
||||
_interleavedDerivativeBuffers);
|
||||
|
||||
// create a texture for input buffer
|
||||
if (!_srcBufferTexture) {
|
||||
glGenTextures(1, &_srcBufferTexture);
|
||||
}
|
||||
if (!_patchArraysUBO) {
|
||||
glGenBuffers(1, &_patchArraysUBO);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
GLXFBEvaluator::Synchronize(void * /*kernel*/) {
|
||||
// XXX: this is currently just for the test purpose.
|
||||
// need to be reimplemented by fence and sync.
|
||||
glFinish();
|
||||
}
|
||||
|
||||
static void
|
||||
bindTexture(GLint sampler, GLuint texture, int unit) {
|
||||
if (sampler == -1) {
|
||||
return;
|
||||
}
|
||||
glUniform1i(sampler, unit);
|
||||
glActiveTexture(GL_TEXTURE0 + unit);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, texture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
bool
|
||||
GLXFBEvaluator::EvalStencils(
|
||||
ID srcBuffer, BufferDescriptor const &srcDesc,
|
||||
ID dstBuffer, BufferDescriptor const &dstDesc,
|
||||
ID duBuffer, BufferDescriptor const &duDesc,
|
||||
ID dvBuffer, BufferDescriptor const &dvDesc,
|
||||
ID sizesBuffer,
|
||||
ID offsetsBuffer,
|
||||
ID indicesBuffer,
|
||||
ID weightsBuffer,
|
||||
ID duWeightsBuffer,
|
||||
ID 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
|
||||
GLXFBEvaluator::EvalStencils(
|
||||
ID srcBuffer, BufferDescriptor const &srcDesc,
|
||||
ID dstBuffer, BufferDescriptor const &dstDesc,
|
||||
ID duBuffer, BufferDescriptor const &duDesc,
|
||||
ID dvBuffer, BufferDescriptor const &dvDesc,
|
||||
ID duuBuffer, BufferDescriptor const &duuDesc,
|
||||
ID duvBuffer, BufferDescriptor const &duvDesc,
|
||||
ID dvvBuffer, BufferDescriptor const &dvvDesc,
|
||||
ID sizesTexture,
|
||||
ID offsetsTexture,
|
||||
ID indicesTexture,
|
||||
ID weightsTexture,
|
||||
ID duWeightsTexture,
|
||||
ID dvWeightsTexture,
|
||||
ID duuWeightsTexture,
|
||||
ID duvWeightsTexture,
|
||||
ID dvvWeightsTexture,
|
||||
int start, int end) const {
|
||||
|
||||
if (!_stencilKernel.program) return false;
|
||||
int count = end - start;
|
||||
if (count <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// bind vertex array
|
||||
// always create new one, to be safe with multiple contexts (slow though)
|
||||
GLuint vao = 0;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
glEnable(GL_RASTERIZER_DISCARD);
|
||||
glUseProgram(_stencilKernel.program);
|
||||
|
||||
// Set input VBO as a texture buffer.
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _srcBufferTexture);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, srcBuffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
|
||||
bindTexture(_stencilKernel.uniformSrcBufferTexture, _srcBufferTexture, 0);
|
||||
|
||||
// bind stencil table textures.
|
||||
bindTexture(_stencilKernel.uniformSizesTexture, sizesTexture, 1);
|
||||
bindTexture(_stencilKernel.uniformOffsetsTexture, offsetsTexture, 2);
|
||||
bindTexture(_stencilKernel.uniformIndicesTexture, indicesTexture, 3);
|
||||
bindTexture(_stencilKernel.uniformWeightsTexture, weightsTexture, 4);
|
||||
if (_stencilKernel.uniformDuWeightsTexture >= 0 && duWeightsTexture)
|
||||
bindTexture(_stencilKernel.uniformDuWeightsTexture, duWeightsTexture, 5);
|
||||
if (_stencilKernel.uniformDvWeightsTexture >= 0 && dvWeightsTexture)
|
||||
bindTexture(_stencilKernel.uniformDvWeightsTexture, dvWeightsTexture, 6);
|
||||
if (_stencilKernel.uniformDuuWeightsTexture >= 0 && duuWeightsTexture)
|
||||
bindTexture(_stencilKernel.uniformDuuWeightsTexture, duuWeightsTexture, 7);
|
||||
if (_stencilKernel.uniformDuvWeightsTexture >= 0 && duvWeightsTexture)
|
||||
bindTexture(_stencilKernel.uniformDuvWeightsTexture, duvWeightsTexture, 8);
|
||||
if (_stencilKernel.uniformDvvWeightsTexture >= 0 && dvvWeightsTexture)
|
||||
bindTexture(_stencilKernel.uniformDvvWeightsTexture, dvvWeightsTexture, 9);
|
||||
|
||||
// set batch range
|
||||
glUniform1i(_stencilKernel.uniformStart, start);
|
||||
glUniform1i(_stencilKernel.uniformEnd, end);
|
||||
glUniform1i(_stencilKernel.uniformSrcOffset, srcDesc.offset);
|
||||
|
||||
// The destination buffer is bound at vertex boundary.
|
||||
//
|
||||
// Example: When we have a batched and interleaved vertex buffer
|
||||
//
|
||||
// Obj X | Obj Y |
|
||||
// -----------+-------------------------------------------+-------
|
||||
// | vtx 0 | vtx 1 | |
|
||||
// -----------+---------------+---------------+-----------+-------
|
||||
// | x y z r g b a | x y z r g b a | .... |
|
||||
// -----------+---------------+---------------+-----------+-------
|
||||
// ^
|
||||
// srcDesc.offset for Obj Y color
|
||||
//
|
||||
// ^-------------------------------------------^
|
||||
// XFB destination buffer range
|
||||
// S S S * * * *
|
||||
// k k k
|
||||
// i i i
|
||||
// p p p
|
||||
//
|
||||
// We use gl_SkipComponents to skip the first 3 XYZ so the
|
||||
// buffer itself needs to be bound for entire section of ObjY.
|
||||
//
|
||||
// Note that for the source buffer (texture) we bind the whole
|
||||
// buffer (all VBO range) and use srcOffset=srcDesc.offset for
|
||||
// indexing.
|
||||
//
|
||||
int dstBufferBindOffset = dstDesc.stride ?
|
||||
(dstDesc.offset - (dstDesc.offset % dstDesc.stride)) : 0;
|
||||
int duBufferBindOffset = duDesc.stride ?
|
||||
(duDesc.offset - (duDesc.offset % duDesc.stride)) : 0;
|
||||
int dvBufferBindOffset = dvDesc.stride ?
|
||||
(dvDesc.offset - (dvDesc.offset % dvDesc.stride)) : 0;
|
||||
int duuBufferBindOffset = duuDesc.stride ?
|
||||
(duuDesc.offset - (duuDesc.offset % duuDesc.stride)) : 0;
|
||||
int duvBufferBindOffset = duvDesc.stride ?
|
||||
(duvDesc.offset - (duvDesc.offset % duvDesc.stride)) : 0;
|
||||
int dvvBufferBindOffset = dvvDesc.stride ?
|
||||
(dvvDesc.offset - (dvvDesc.offset % dvvDesc.stride)) : 0;
|
||||
|
||||
// bind destination buffer
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
0, dstBuffer,
|
||||
dstBufferBindOffset * sizeof(float),
|
||||
count * dstDesc.stride * sizeof(float));
|
||||
|
||||
if ((duDesc.length > 0) && _interleavedDerivativeBuffers) {
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
1, duBuffer,
|
||||
duBufferBindOffset * sizeof(float),
|
||||
count * duDesc.stride * sizeof(float));
|
||||
} else {
|
||||
if (duDesc.length > 0) {
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
1, duBuffer,
|
||||
duBufferBindOffset * sizeof(float),
|
||||
count * duDesc.stride * sizeof(float));
|
||||
}
|
||||
|
||||
if (dvDesc.length > 0) {
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
2, dvBuffer,
|
||||
dvBufferBindOffset * sizeof(float),
|
||||
count * dvDesc.stride * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
if ((duuDesc.length > 0) && _interleavedDerivativeBuffers) {
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
2, duuBuffer,
|
||||
duuBufferBindOffset * sizeof(float),
|
||||
count * duuDesc.stride * sizeof(float));
|
||||
} else {
|
||||
if (duuDesc.length > 0) {
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
3, duuBuffer,
|
||||
duuBufferBindOffset * sizeof(float),
|
||||
count * duuDesc.stride * sizeof(float));
|
||||
}
|
||||
|
||||
if (duvDesc.length > 0) {
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
4, duvBuffer,
|
||||
duvBufferBindOffset * sizeof(float),
|
||||
count * duvDesc.stride * sizeof(float));
|
||||
}
|
||||
|
||||
if (dvvDesc.length > 0) {
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
5, dvvBuffer,
|
||||
dvvBufferBindOffset * sizeof(float),
|
||||
count * dvvDesc.stride * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
glBeginTransformFeedback(GL_POINTS);
|
||||
glDrawArrays(GL_POINTS, 0, count);
|
||||
glEndTransformFeedback();
|
||||
|
||||
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
}
|
||||
|
||||
glDisable(GL_RASTERIZER_DISCARD);
|
||||
glUseProgram(0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// revert vao
|
||||
glBindVertexArray(0);
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GLXFBEvaluator::EvalPatches(
|
||||
ID srcBuffer, BufferDescriptor const &srcDesc,
|
||||
ID dstBuffer, BufferDescriptor const &dstDesc,
|
||||
ID duBuffer, BufferDescriptor const &duDesc,
|
||||
ID dvBuffer, BufferDescriptor const &dvDesc,
|
||||
int numPatchCoords,
|
||||
ID patchCoordsBuffer,
|
||||
const PatchArrayVector &patchArrays,
|
||||
ID patchIndexTexture,
|
||||
ID patchParamTexture) const {
|
||||
|
||||
return EvalPatches(srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
duBuffer, duDesc,
|
||||
dvBuffer, dvDesc,
|
||||
0, BufferDescriptor(),
|
||||
0, BufferDescriptor(),
|
||||
0, BufferDescriptor(),
|
||||
numPatchCoords,
|
||||
patchCoordsBuffer, patchArrays,
|
||||
patchIndexTexture,
|
||||
patchParamTexture);
|
||||
}
|
||||
|
||||
bool
|
||||
GLXFBEvaluator::EvalPatches(
|
||||
ID srcBuffer, BufferDescriptor const &srcDesc,
|
||||
ID dstBuffer, BufferDescriptor const &dstDesc,
|
||||
ID duBuffer, BufferDescriptor const &duDesc,
|
||||
ID dvBuffer, BufferDescriptor const &dvDesc,
|
||||
ID duuBuffer, BufferDescriptor const &duuDesc,
|
||||
ID duvBuffer, BufferDescriptor const &duvDesc,
|
||||
ID dvvBuffer, BufferDescriptor const &dvvDesc,
|
||||
int numPatchCoords,
|
||||
ID patchCoordsBuffer,
|
||||
const PatchArrayVector &patchArrays,
|
||||
ID patchIndexTexture,
|
||||
ID patchParamTexture) const {
|
||||
|
||||
bool deriv1 = (duDesc.length > 0 || dvDesc.length > 0);
|
||||
bool deriv2 = (duuDesc.length > 0 || duvDesc.length > 0 || dvvDesc.length > 0);
|
||||
|
||||
if (!_patchKernel.program) return false;
|
||||
|
||||
// bind vertex array
|
||||
// always create new one, to be safe with multiple contexts (slow though)
|
||||
GLuint vao = 0;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
glEnable(GL_RASTERIZER_DISCARD);
|
||||
glUseProgram(_patchKernel.program);
|
||||
|
||||
// Set input VBO as a texture buffer.
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _srcBufferTexture);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, srcBuffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
|
||||
bindTexture(_patchKernel.uniformSrcBufferTexture, _srcBufferTexture, 0);
|
||||
|
||||
// bind patch index and patch param textures.
|
||||
bindTexture(_patchKernel.uniformPatchParamTexture, patchParamTexture, 1);
|
||||
bindTexture(_patchKernel.uniformPatchIndexTexture, patchIndexTexture, 2);
|
||||
|
||||
// bind patch arrays UBO (std140 struct size padded to vec4 alignment)
|
||||
int patchArraySize =
|
||||
sizeof(GLint) * ((sizeof(PatchArray)/sizeof(GLint) + 3) & ~3);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, _patchArraysUBO);
|
||||
glBufferData(GL_UNIFORM_BUFFER,
|
||||
patchArrays.size()*patchArraySize, NULL, GL_STATIC_DRAW);
|
||||
for (int i=0; i<(int)patchArrays.size(); ++i) {
|
||||
glBufferSubData(GL_UNIFORM_BUFFER,
|
||||
i*patchArraySize, sizeof(PatchArray), &patchArrays[i]);
|
||||
}
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER,
|
||||
_patchKernel.uniformPatchArraysUBOBinding, _patchArraysUBO);
|
||||
|
||||
// set other uniforms
|
||||
glUniform1i(_patchKernel.uniformSrcOffset, srcDesc.offset);
|
||||
|
||||
// input patchcoords
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
int stride = sizeof(int) * 5; // patchcoord = int*5 struct
|
||||
glBindBuffer(GL_ARRAY_BUFFER, patchCoordsBuffer);
|
||||
glVertexAttribIPointer(0, 3, GL_UNSIGNED_INT, stride, (void*)0);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (void*)(sizeof(int)*3));
|
||||
|
||||
int dstBufferBindOffset =
|
||||
dstDesc.offset - (dstDesc.offset % dstDesc.stride);
|
||||
int duBufferBindOffset = duDesc.stride
|
||||
? (duDesc.offset - (duDesc.offset % duDesc.stride))
|
||||
: 0;
|
||||
int dvBufferBindOffset = dvDesc.stride
|
||||
? (dvDesc.offset - (dvDesc.offset % dvDesc.stride))
|
||||
: 0;
|
||||
int duuBufferBindOffset = duuDesc.stride
|
||||
? (duuDesc.offset - (duuDesc.offset % duuDesc.stride))
|
||||
: 0;
|
||||
int duvBufferBindOffset = duvDesc.stride
|
||||
? (duvDesc.offset - (duvDesc.offset % duvDesc.stride))
|
||||
: 0;
|
||||
int dvvBufferBindOffset = dvvDesc.stride
|
||||
? (dvvDesc.offset - (dvvDesc.offset % dvvDesc.stride))
|
||||
: 0;
|
||||
|
||||
// bind destination buffer
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
0, dstBuffer,
|
||||
dstBufferBindOffset * sizeof(float),
|
||||
numPatchCoords * dstDesc.stride * sizeof(float));
|
||||
|
||||
if (deriv1 && _interleavedDerivativeBuffers) {
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
1, duBuffer,
|
||||
duBufferBindOffset * sizeof(float),
|
||||
numPatchCoords * duDesc.stride * sizeof(float));
|
||||
} else if (deriv1) {
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
1, duBuffer,
|
||||
duBufferBindOffset * sizeof(float),
|
||||
numPatchCoords * duDesc.stride * sizeof(float));
|
||||
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
2, dvBuffer,
|
||||
dvBufferBindOffset * sizeof(float),
|
||||
numPatchCoords * dvDesc.stride * sizeof(float));
|
||||
}
|
||||
if (deriv2 && _interleavedDerivativeBuffers) {
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
2, duuBuffer,
|
||||
duuBufferBindOffset * sizeof(float),
|
||||
numPatchCoords * duuDesc.stride * sizeof(float));
|
||||
} else if (deriv2) {
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
3, duuBuffer,
|
||||
duuBufferBindOffset * sizeof(float),
|
||||
numPatchCoords * duuDesc.stride * sizeof(float));
|
||||
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
4, duvBuffer,
|
||||
duvBufferBindOffset * sizeof(float),
|
||||
numPatchCoords * duvDesc.stride * sizeof(float));
|
||||
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
5, dvvBuffer,
|
||||
dvvBufferBindOffset * sizeof(float),
|
||||
numPatchCoords * dvvDesc.stride * sizeof(float));
|
||||
}
|
||||
|
||||
glBeginTransformFeedback(GL_POINTS);
|
||||
glDrawArrays(GL_POINTS, 0, numPatchCoords);
|
||||
glEndTransformFeedback();
|
||||
|
||||
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
|
||||
|
||||
// unbind textures
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
}
|
||||
|
||||
// unbind UBO
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER,
|
||||
_patchKernel.uniformPatchArraysUBOBinding, 0);
|
||||
|
||||
glDisable(GL_RASTERIZER_DISCARD);
|
||||
glUseProgram(0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
|
||||
// revert vao
|
||||
glBindVertexArray(0);
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
GLXFBEvaluator::_StencilKernel::_StencilKernel() : program(0) {
|
||||
}
|
||||
GLXFBEvaluator::_StencilKernel::~_StencilKernel() {
|
||||
if (program) {
|
||||
glDeleteProgram(program);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GLXFBEvaluator::_StencilKernel::Compile(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
bool interleavedDerivativeBuffers) {
|
||||
// create stencil kernel
|
||||
if (program) {
|
||||
glDeleteProgram(program);
|
||||
}
|
||||
|
||||
const char * kernelDefines =
|
||||
"#define OPENSUBDIV_GLSL_XFB_KERNEL_EVAL_STENCILS\n";
|
||||
|
||||
program = compileKernel(srcDesc, dstDesc, duDesc, dvDesc,
|
||||
duuDesc, duvDesc, dvvDesc,
|
||||
kernelDefines, interleavedDerivativeBuffers);
|
||||
if (program == 0) return false;
|
||||
|
||||
// cache uniform locations (TODO: use uniform block)
|
||||
uniformSrcBufferTexture = glGetUniformLocation(program, "vertexBuffer");
|
||||
uniformSrcOffset = glGetUniformLocation(program, "srcOffset");
|
||||
uniformSizesTexture = glGetUniformLocation(program, "sizes");
|
||||
uniformOffsetsTexture = glGetUniformLocation(program, "offsets");
|
||||
uniformIndicesTexture = glGetUniformLocation(program, "indices");
|
||||
uniformWeightsTexture = glGetUniformLocation(program, "weights");
|
||||
uniformDuWeightsTexture = glGetUniformLocation(program, "duWeights");
|
||||
uniformDvWeightsTexture = glGetUniformLocation(program, "dvWeights");
|
||||
uniformDuuWeightsTexture = glGetUniformLocation(program, "duuWeights");
|
||||
uniformDuvWeightsTexture = glGetUniformLocation(program, "duvWeights");
|
||||
uniformDvvWeightsTexture = glGetUniformLocation(program, "dvvWeights");
|
||||
uniformStart = glGetUniformLocation(program, "batchStart");
|
||||
uniformEnd = glGetUniformLocation(program, "batchEnd");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
GLXFBEvaluator::_PatchKernel::_PatchKernel() : program(0) {
|
||||
}
|
||||
GLXFBEvaluator::_PatchKernel::~_PatchKernel() {
|
||||
if (program) {
|
||||
glDeleteProgram(program);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GLXFBEvaluator::_PatchKernel::Compile(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
bool interleavedDerivativeBuffers) {
|
||||
// create stencil kernel
|
||||
if (program) {
|
||||
glDeleteProgram(program);
|
||||
}
|
||||
|
||||
const char * kernelDefines =
|
||||
"#define OPENSUBDIV_GLSL_XFB_KERNEL_EVAL_PATCHES\n";
|
||||
|
||||
program = compileKernel(srcDesc, dstDesc, duDesc, dvDesc,
|
||||
duuDesc, duvDesc, dvvDesc,
|
||||
kernelDefines, interleavedDerivativeBuffers);
|
||||
if (program == 0) return false;
|
||||
|
||||
// cache uniform locations
|
||||
uniformSrcBufferTexture = glGetUniformLocation(program, "vertexBuffer");
|
||||
uniformSrcOffset = glGetUniformLocation(program, "srcOffset");
|
||||
uniformPatchParamTexture = glGetUniformLocation(program, "patchParamBuffer");
|
||||
uniformPatchIndexTexture = glGetUniformLocation(program, "patchIndexBuffer");
|
||||
|
||||
uniformPatchArraysUBOBinding = 1;
|
||||
int uboIndex = glGetUniformBlockIndex(program, "PatchArrays");
|
||||
glUniformBlockBinding(program, uboIndex , uniformPatchArraysUBOBinding);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
2179
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glXFBEvaluator.h
vendored
Normal file
2179
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glXFBEvaluator.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
294
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslComputeKernel.glsl
vendored
Normal file
294
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslComputeKernel.glsl
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
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
|
||||
|
||||
#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];
|
||||
}
|
||||
|
||||
OsdPatchArray GetPatchArray(int arrayIndex)
|
||||
{
|
||||
return patchArrayBuffer[arrayIndex];
|
||||
}
|
||||
|
||||
OsdPatchParam GetPatchParam(int patchIndex)
|
||||
{
|
||||
return patchParamBuffer[patchIndex];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct Vertex {
|
||||
float vertexData[LENGTH];
|
||||
};
|
||||
|
||||
void clear(out Vertex v) {
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vertex readVertex(int index) {
|
||||
Vertex v;
|
||||
int vertexIndex = srcOffset + index * SRC_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] = srcVertexBuffer[vertexIndex + i];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void writeVertex(int index, Vertex v) {
|
||||
int vertexIndex = dstOffset + index * DST_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dstVertexBuffer[vertexIndex + i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void addWithWeight(inout Vertex v, const Vertex src, float weight) {
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] += weight * src.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
|
||||
void writeDu(int index, Vertex du) {
|
||||
int duIndex = duDesc.x + index * duDesc.z;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
duBuffer[duIndex + i] = du.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDv(int index, Vertex dv) {
|
||||
int dvIndex = dvDesc.x + index * dvDesc.z;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dvBuffer[dvIndex + i] = dv.vertexData[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
|
||||
void writeDuu(int index, Vertex duu) {
|
||||
int duuIndex = duuDesc.x + index * duuDesc.z;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
duuBuffer[duuIndex + i] = duu.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDuv(int index, Vertex duv) {
|
||||
int duvIndex = duvDesc.x + index * duvDesc.z;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
duvBuffer[duvIndex + i] = duv.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDvv(int index, Vertex dvv) {
|
||||
int dvvIndex = dvvDesc.x + index * dvvDesc.z;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dvvBuffer[dvvIndex + i] = dvv.vertexData[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS)
|
||||
|
||||
void main() {
|
||||
|
||||
int current = int(gl_GlobalInvocationID.x) + batchStart;
|
||||
|
||||
if (current>=batchEnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vertex dst;
|
||||
clear(dst);
|
||||
|
||||
int offset = _offsets[current],
|
||||
size = _sizes[current];
|
||||
|
||||
for (int stencil = 0; stencil < size; ++stencil) {
|
||||
int vindex = offset + stencil;
|
||||
addWithWeight(
|
||||
dst, readVertex(_indices[vindex]), _weights[vindex]);
|
||||
}
|
||||
|
||||
writeVertex(current, dst);
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
|
||||
Vertex du, dv;
|
||||
clear(du);
|
||||
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]);
|
||||
}
|
||||
|
||||
if (duDesc.y > 0) { // length
|
||||
writeDu(current, du);
|
||||
}
|
||||
if (dvDesc.y > 0) {
|
||||
writeDv(current, dv);
|
||||
}
|
||||
#endif
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
|
||||
Vertex duu, duv, dvv;
|
||||
clear(duu);
|
||||
clear(duv);
|
||||
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]);
|
||||
}
|
||||
|
||||
if (duuDesc.y > 0) { // length
|
||||
writeDuu(current, duu);
|
||||
}
|
||||
if (duvDesc.y > 0) {
|
||||
writeDuv(current, duv);
|
||||
}
|
||||
if (dvvDesc.y > 0) {
|
||||
writeDvv(current, dvv);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES)
|
||||
|
||||
// PERFORMANCE: stride could be constant, but not as significant as length
|
||||
|
||||
void main() {
|
||||
|
||||
int current = int(gl_GlobalInvocationID.x);
|
||||
|
||||
OsdPatchCoord coord = GetPatchCoord(current);
|
||||
OsdPatchArray array = GetPatchArray(coord.arrayIndex);
|
||||
OsdPatchParam param = GetPatchParam(coord.patchIndex);
|
||||
|
||||
int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
|
||||
|
||||
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
|
||||
int nPoints = OsdEvaluatePatchBasis(patchType, param,
|
||||
coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
|
||||
|
||||
Vertex dst, du, dv, duu, duv, dvv;
|
||||
clear(dst);
|
||||
clear(du);
|
||||
clear(dv);
|
||||
clear(duu);
|
||||
clear(duv);
|
||||
clear(dvv);
|
||||
|
||||
int indexBase = array.indexBase + array.stride *
|
||||
(coord.patchIndex - array.primitiveIdBase);
|
||||
|
||||
for (int cv = 0; cv < nPoints; ++cv) {
|
||||
int index = patchIndexBuffer[indexBase + cv];
|
||||
addWithWeight(dst, readVertex(index), wP[cv]);
|
||||
addWithWeight(du, readVertex(index), wDu[cv]);
|
||||
addWithWeight(dv, readVertex(index), wDv[cv]);
|
||||
addWithWeight(duu, readVertex(index), wDuu[cv]);
|
||||
addWithWeight(duv, readVertex(index), wDuv[cv]);
|
||||
addWithWeight(dvv, readVertex(index), wDvv[cv]);
|
||||
}
|
||||
writeVertex(current, dst);
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
|
||||
if (duDesc.y > 0) { // length
|
||||
writeDu(current, du);
|
||||
}
|
||||
if (dvDesc.y > 0) {
|
||||
writeDv(current, dv);
|
||||
}
|
||||
#endif
|
||||
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
|
||||
if (duuDesc.y > 0) { // length
|
||||
writeDuu(current, duu);
|
||||
}
|
||||
if (duvDesc.y > 0) { // length
|
||||
writeDuv(current, duv);
|
||||
}
|
||||
if (dvvDesc.y > 0) {
|
||||
writeDvv(current, dvv);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
174
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchBSpline.glsl
vendored
Normal file
174
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchBSpline.glsl
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexBSpline
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_VERTEX_BSPLINE_SHADER
|
||||
|
||||
layout(location = 0) in vec4 position;
|
||||
OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
|
||||
out block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
outpt.v.position = position;
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(position);
|
||||
OSD_USER_VARYING_PER_VERTEX();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessControlBSpline
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER
|
||||
|
||||
patch out vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OsdPerPatchVertexBezier v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt[16];
|
||||
|
||||
layout(vertices = 16) out;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 cv[16];
|
||||
for (int i=0; i<16; ++i) {
|
||||
cv[i] = inpt[i].v.position.xyz;
|
||||
}
|
||||
|
||||
ivec3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(gl_PrimitiveID));
|
||||
OsdComputePerPatchVertexBSpline(patchParam, gl_InvocationID, cv, outpt[gl_InvocationID].v);
|
||||
|
||||
OSD_USER_VARYING_PER_CONTROL_POINT(gl_InvocationID, gl_InvocationID);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Wait for all basis conversion to be finished
|
||||
barrier();
|
||||
#endif
|
||||
if (gl_InvocationID == 0) {
|
||||
vec4 tessLevelOuter = vec4(0);
|
||||
vec2 tessLevelInner = vec2(0);
|
||||
|
||||
OSD_PATCH_CULL(16);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
OsdPerPatchVertexBezier cpBezier[16];
|
||||
cpBezier[0] = outpt[0].v;
|
||||
cpBezier[1] = outpt[1].v;
|
||||
cpBezier[2] = outpt[2].v;
|
||||
cpBezier[3] = outpt[3].v;
|
||||
cpBezier[4] = outpt[4].v;
|
||||
cpBezier[5] = outpt[5].v;
|
||||
cpBezier[6] = outpt[6].v;
|
||||
cpBezier[7] = outpt[7].v;
|
||||
cpBezier[8] = outpt[8].v;
|
||||
cpBezier[9] = outpt[9].v;
|
||||
cpBezier[10] = outpt[10].v;
|
||||
cpBezier[11] = outpt[11].v;
|
||||
cpBezier[12] = outpt[12].v;
|
||||
cpBezier[13] = outpt[13].v;
|
||||
cpBezier[14] = outpt[14].v;
|
||||
cpBezier[15] = outpt[15].v;
|
||||
|
||||
OsdEvalPatchBezierTessLevels(cpBezier, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(patchParam, tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
gl_TessLevelOuter[0] = tessLevelOuter[0];
|
||||
gl_TessLevelOuter[1] = tessLevelOuter[1];
|
||||
gl_TessLevelOuter[2] = tessLevelOuter[2];
|
||||
gl_TessLevelOuter[3] = tessLevelOuter[3];
|
||||
|
||||
gl_TessLevelInner[0] = tessLevelInner[0];
|
||||
gl_TessLevelInner[1] = tessLevelInner[1];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessEvalBSpline
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_EVAL_BSPLINE_SHADER
|
||||
|
||||
layout(quads) in;
|
||||
layout(OSD_SPACING) in;
|
||||
|
||||
patch in vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
OsdPerPatchVertexBezier v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
vec2 vSegments;
|
||||
#endif
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 P = vec3(0), dPu = vec3(0), dPv = vec3(0);
|
||||
vec3 N = vec3(0), dNu = vec3(0), dNv = vec3(0);
|
||||
|
||||
OsdPerPatchVertexBezier cv[16];
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
cv[i] = inpt[i].v;
|
||||
}
|
||||
|
||||
vec2 UV = OsdGetTessParameterization(gl_TessCoord.xy,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
ivec3 patchParam = inpt[0].v.patchParam;
|
||||
OsdEvalPatchBezier(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
outpt.v.position = OsdModelViewMatrix() * vec4(P, 1.0f);
|
||||
outpt.v.normal = (OsdModelViewMatrix() * vec4(N, 0.0f)).xyz;
|
||||
outpt.v.tangent = (OsdModelViewMatrix() * vec4(dPu, 0.0f)).xyz;
|
||||
outpt.v.bitangent = (OsdModelViewMatrix() * vec4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
outpt.v.Nu = dNu;
|
||||
outpt.v.Nv = dNv;
|
||||
#endif
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
outpt.vSegments = cv[0].vSegments;
|
||||
#endif
|
||||
|
||||
outpt.v.tessCoord = UV;
|
||||
outpt.v.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
|
||||
OSD_USER_VARYING_PER_EVAL_POINT(UV, 5, 6, 9, 10);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
gl_Position = OsdProjectionMatrix() * outpt.v.position;
|
||||
}
|
||||
|
||||
#endif
|
||||
156
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchBoxSplineTriangle.glsl
vendored
Normal file
156
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchBoxSplineTriangle.glsl
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
//
|
||||
// Copyright 2018 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexBoxSplineTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_VERTEX_BOX_SPLINE_TRIANGLE_SHADER
|
||||
|
||||
layout(location = 0) in vec4 position;
|
||||
OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
|
||||
out block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
outpt.v.position = position;
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(position);
|
||||
OSD_USER_VARYING_PER_VERTEX();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessControlBoxSplineTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_CONTROL_BOX_SPLINE_TRIANGLE_SHADER
|
||||
|
||||
patch out vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OsdPerPatchVertexBezier v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt[15];
|
||||
|
||||
layout(vertices = 15) out;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 cv[12];
|
||||
for (int i=0; i<12; ++i) {
|
||||
cv[i] = inpt[i].v.position.xyz;
|
||||
}
|
||||
|
||||
ivec3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(gl_PrimitiveID));
|
||||
OsdComputePerPatchVertexBoxSplineTriangle(
|
||||
patchParam, gl_InvocationID, cv, outpt[gl_InvocationID].v);
|
||||
|
||||
OSD_USER_VARYING_PER_CONTROL_POINT(gl_InvocationID, gl_InvocationID);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Wait for all basis conversion to be finished
|
||||
barrier();
|
||||
#endif
|
||||
if (gl_InvocationID == 0) {
|
||||
vec4 tessLevelOuter = vec4(0);
|
||||
vec2 tessLevelInner = vec2(0);
|
||||
|
||||
OSD_PATCH_CULL(12);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
vec3 bezcv[15];
|
||||
for (int i=0; i<15; ++i) {
|
||||
bezcv[i] = outpt[i].v.P;
|
||||
}
|
||||
OsdEvalPatchBezierTriangleTessLevels(
|
||||
bezcv, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniformTriangle(patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
#endif
|
||||
|
||||
gl_TessLevelOuter[0] = tessLevelOuter[0];
|
||||
gl_TessLevelOuter[1] = tessLevelOuter[1];
|
||||
gl_TessLevelOuter[2] = tessLevelOuter[2];
|
||||
|
||||
gl_TessLevelInner[0] = tessLevelInner[0];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessEvalBoxSplineTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_EVAL_BOX_SPLINE_TRIANGLE_SHADER
|
||||
|
||||
layout(triangles) in;
|
||||
layout(OSD_SPACING) in;
|
||||
|
||||
patch in vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
OsdPerPatchVertexBezier v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 P = vec3(0), dPu = vec3(0), dPv = vec3(0);
|
||||
vec3 N = vec3(0), dNu = vec3(0), dNv = vec3(0);
|
||||
|
||||
OsdPerPatchVertexBezier cv[15];
|
||||
for (int i = 0; i < 15; ++i) {
|
||||
cv[i] = inpt[i].v;
|
||||
}
|
||||
|
||||
vec2 UV = OsdGetTessParameterizationTriangle(gl_TessCoord.xyz,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
ivec3 patchParam = inpt[0].v.patchParam;
|
||||
OsdEvalPatchBezierTriangle(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
outpt.v.position = OsdModelViewMatrix() * vec4(P, 1.0f);
|
||||
outpt.v.normal = (OsdModelViewMatrix() * vec4(N, 0.0f)).xyz;
|
||||
outpt.v.tangent = (OsdModelViewMatrix() * vec4(dPu, 0.0f)).xyz;
|
||||
outpt.v.bitangent = (OsdModelViewMatrix() * vec4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
outpt.v.Nu = dNu;
|
||||
outpt.v.Nv = dNv;
|
||||
#endif
|
||||
|
||||
outpt.v.tessCoord = UV;
|
||||
outpt.v.patchCoord = OsdInterpolatePatchCoordTriangle(UV, patchParam);
|
||||
|
||||
OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE(UV, 4, 5, 8);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
gl_Position = OsdProjectionMatrix() * outpt.v.position;
|
||||
}
|
||||
|
||||
#endif
|
||||
1107
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchCommon.glsl
vendored
Normal file
1107
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchCommon.glsl
vendored
Normal file
File diff suppressed because it is too large
Load Diff
715
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchCommonTess.glsl
vendored
Normal file
715
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchCommonTess.glsl
vendored
Normal file
@@ -0,0 +1,715 @@
|
||||
//
|
||||
// Copyright 2013-2018 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Tessellation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// For now, fractional spacing is supported only with screen space tessellation
|
||||
#ifndef OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
#undef OSD_FRACTIONAL_EVEN_SPACING
|
||||
#undef OSD_FRACTIONAL_ODD_SPACING
|
||||
#endif
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
#define OSD_SPACING fractional_even_spacing
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
#define OSD_SPACING fractional_odd_spacing
|
||||
#else
|
||||
#define OSD_SPACING equal_spacing
|
||||
#endif
|
||||
|
||||
//
|
||||
// Organization of B-spline and Bezier control points.
|
||||
//
|
||||
// Each patch is defined by 16 control points (labeled 0-15).
|
||||
//
|
||||
// The patch will be evaluated across the domain from (0,0) at
|
||||
// the lower-left to (1,1) at the upper-right. When computing
|
||||
// adaptive tessellation metrics, we consider refined vertex-vertex
|
||||
// and edge-vertex points along the transition edges of the patch
|
||||
// (labeled vv* and ev* respectively).
|
||||
//
|
||||
// The two segments of each transition edge are labeled Lo and Hi,
|
||||
// with the Lo segment occurring before the Hi segment along the
|
||||
// transition edge's domain parameterization. These Lo and Hi segment
|
||||
// tessellation levels determine how domain evaluation coordinates
|
||||
// are remapped along transition edges. The Hi segment value will
|
||||
// be zero for a non-transition edge.
|
||||
//
|
||||
// (0,1) (1,1)
|
||||
//
|
||||
// vv3 ev23 vv2
|
||||
// | Lo3 | Hi3 |
|
||||
// --O-----------O-----+-----O-----------O--
|
||||
// | 12 | 13 14 | 15 |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// Hi0 | | | | Hi2
|
||||
// | | | |
|
||||
// O-----------O-----------O-----------O
|
||||
// | 8 | 9 10 | 11 |
|
||||
// | | | |
|
||||
// ev03 --+ | | +-- ev12
|
||||
// | | | |
|
||||
// | 4 | 5 6 | 7 |
|
||||
// O-----------O-----------O-----------O
|
||||
// | | | |
|
||||
// Lo0 | | | | Lo2
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | 0 | 1 2 | 3 |
|
||||
// --O-----------O-----+-----O-----------O--
|
||||
// | Lo1 | Hi1 |
|
||||
// vv0 ev01 vv1
|
||||
//
|
||||
// (0,0) (1,0)
|
||||
//
|
||||
|
||||
#define OSD_MAX_TESS_LEVEL gl_MaxTessGenLevel
|
||||
|
||||
float OsdComputePostProjectionSphereExtent(vec3 center, float diameter)
|
||||
{
|
||||
vec4 p = OsdProjectionMatrix() * vec4(center, 1.0);
|
||||
return abs(diameter * OsdProjectionMatrix()[1][1] / p.w);
|
||||
}
|
||||
|
||||
float OsdComputeTessLevel(vec3 p0, vec3 p1)
|
||||
{
|
||||
// Adaptive factor can be any computation that depends only on arg values.
|
||||
// Project the diameter of the edge's bounding sphere instead of using the
|
||||
// length of the projected edge itself to avoid problems near silhouettes.
|
||||
p0 = (OsdModelViewMatrix() * vec4(p0, 1.0)).xyz;
|
||||
p1 = (OsdModelViewMatrix() * vec4(p1, 1.0)).xyz;
|
||||
vec3 center = (p0 + p1) / 2.0;
|
||||
float diameter = distance(p0, p1);
|
||||
float projLength = OsdComputePostProjectionSphereExtent(center, diameter);
|
||||
float tessLevel = max(1.0, OsdTessLevel() * projLength);
|
||||
|
||||
// We restrict adaptive tessellation levels to half of the device
|
||||
// supported maximum because transition edges are split into two
|
||||
// halves and the sum of the two corresponding levels must not exceed
|
||||
// the device maximum. We impose this limit even for non-transition
|
||||
// edges because a non-transition edge must be able to match up with
|
||||
// one half of the transition edge of an adjacent transition patch.
|
||||
return min(tessLevel, OSD_MAX_TESS_LEVEL / 2);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniform(ivec3 patchParam,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// Uniform factors are simple powers of two for each level.
|
||||
// The maximum here can be increased if we know the maximum
|
||||
// refinement level of the mesh:
|
||||
// min(OSD_MAX_TESS_LEVEL, pow(2, MaximumRefinementLevel-1)
|
||||
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
|
||||
float tessLevel = min(OsdTessLevel(), OSD_MAX_TESS_LEVEL) /
|
||||
pow(2, refinementLevel-1);
|
||||
|
||||
// tessLevels of transition edge should be clamped to 2.
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
vec4 tessLevelMin = vec4(1) + vec4(((transitionMask & 8) >> 3),
|
||||
((transitionMask & 1) >> 0),
|
||||
((transitionMask & 2) >> 1),
|
||||
((transitionMask & 4) >> 2));
|
||||
|
||||
tessOuterLo = max(vec4(tessLevel), tessLevelMin);
|
||||
tessOuterHi = vec4(0);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniformTriangle(ivec3 patchParam,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// Uniform factors are simple powers of two for each level.
|
||||
// The maximum here can be increased if we know the maximum
|
||||
// refinement level of the mesh:
|
||||
// min(OSD_MAX_TESS_LEVEL, pow(2, MaximumRefinementLevel-1)
|
||||
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
|
||||
float tessLevel = min(OsdTessLevel(), OSD_MAX_TESS_LEVEL) /
|
||||
pow(2, refinementLevel-1);
|
||||
|
||||
// tessLevels of transition edge should be clamped to 2.
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
vec4 tessLevelMin = vec4(1) + vec4(((transitionMask & 4) >> 2),
|
||||
((transitionMask & 1) >> 0),
|
||||
((transitionMask & 2) >> 1),
|
||||
0);
|
||||
|
||||
tessOuterLo = max(vec4(tessLevel), tessLevelMin);
|
||||
tessOuterHi = vec4(0);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsRefinedPoints(vec3 cp[16], ivec3 patchParam,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. We compute the corresponding
|
||||
// vertex-vertex and edge-vertex refined points along the edges of the
|
||||
// patch using Catmull-Clark subdivision stencil weights.
|
||||
// For simplicity, we let the optimizer discard unused computation.
|
||||
|
||||
vec3 vv0 = (cp[0] + cp[2] + cp[8] + cp[10]) * 0.015625 +
|
||||
(cp[1] + cp[4] + cp[6] + cp[9]) * 0.09375 + cp[5] * 0.5625;
|
||||
vec3 ev01 = (cp[1] + cp[2] + cp[9] + cp[10]) * 0.0625 +
|
||||
(cp[5] + cp[6]) * 0.375;
|
||||
|
||||
vec3 vv1 = (cp[1] + cp[3] + cp[9] + cp[11]) * 0.015625 +
|
||||
(cp[2] + cp[5] + cp[7] + cp[10]) * 0.09375 + cp[6] * 0.5625;
|
||||
vec3 ev12 = (cp[5] + cp[7] + cp[9] + cp[11]) * 0.0625 +
|
||||
(cp[6] + cp[10]) * 0.375;
|
||||
|
||||
vec3 vv2 = (cp[5] + cp[7] + cp[13] + cp[15]) * 0.015625 +
|
||||
(cp[6] + cp[9] + cp[11] + cp[14]) * 0.09375 + cp[10] * 0.5625;
|
||||
vec3 ev23 = (cp[5] + cp[6] + cp[13] + cp[14]) * 0.0625 +
|
||||
(cp[9] + cp[10]) * 0.375;
|
||||
|
||||
vec3 vv3 = (cp[4] + cp[6] + cp[12] + cp[14]) * 0.015625 +
|
||||
(cp[5] + cp[8] + cp[10] + cp[13]) * 0.09375 + cp[9] * 0.5625;
|
||||
vec3 ev03 = (cp[4] + cp[6] + cp[8] + cp[10]) * 0.0625 +
|
||||
(cp[5] + cp[9]) * 0.375;
|
||||
|
||||
tessOuterLo = vec4(0);
|
||||
tessOuterHi = vec4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 8) != 0) {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(vv0, ev03);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(vv3, ev03);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cp[5], cp[9]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(vv0, ev01);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(vv1, ev01);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cp[5], cp[6]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(vv1, ev12);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(vv2, ev12);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cp[6], cp[10]);
|
||||
}
|
||||
if ((transitionMask & 4) != 0) {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(vv3, ev23);
|
||||
tessOuterHi[3] = OsdComputeTessLevel(vv2, ev23);
|
||||
} else {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(cp[9], cp[10]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Patch boundary corners are ordered counter-clockwise from the first
|
||||
// corner while patch boundary edges and their midpoints are similarly
|
||||
// ordered counter-clockwise beginning at the edge preceding corner[0].
|
||||
//
|
||||
void
|
||||
Osd_GetTessLevelsFromPatchBoundaries4(vec3 corners[4], vec3 midpoints[4],
|
||||
ivec3 patchParam, out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
tessOuterLo = vec4(0);
|
||||
tessOuterHi = vec4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 8) != 0) {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(corners[0], midpoints[0]);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(corners[3], midpoints[0]);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(corners[0], corners[3]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(corners[0], midpoints[1]);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(corners[1], midpoints[1]);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(corners[0], corners[1]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(corners[1], midpoints[2]);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(corners[2], midpoints[2]);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(corners[1], corners[2]);
|
||||
}
|
||||
if ((transitionMask & 4) != 0) {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(corners[3], midpoints[3]);
|
||||
tessOuterHi[3] = OsdComputeTessLevel(corners[2], midpoints[3]);
|
||||
} else {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(corners[3], corners[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Osd_GetTessLevelsFromPatchBoundaries3(vec3 corners[3], vec3 midpoints[3],
|
||||
ivec3 patchParam, out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
tessOuterLo = vec4(0);
|
||||
tessOuterHi = vec4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 4) != 0) {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(corners[0], midpoints[0]);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(corners[2], midpoints[0]);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(corners[0], corners[2]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(corners[0], midpoints[1]);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(corners[1], midpoints[1]);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(corners[0], corners[1]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(corners[2], midpoints[2]);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(corners[1], midpoints[2]);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(corners[1], corners[2]);
|
||||
}
|
||||
}
|
||||
|
||||
vec3
|
||||
Osd_EvalBezierCurveMidPoint(vec3 p0, vec3 p1, vec3 p2, vec3 p3)
|
||||
{
|
||||
// Coefficients for the midpoint are { 1/8, 3/8, 3/8, 1/8 }:
|
||||
return 0.125 * (p0 + p3) + 0.375 * (p1 + p2);
|
||||
}
|
||||
|
||||
vec3
|
||||
Osd_EvalQuarticBezierCurveMidPoint(vec3 p0, vec3 p1, vec3 p2, vec3 p3, vec3 p4)
|
||||
{
|
||||
// Coefficients for the midpoint are { 1/16, 1/4, 3/8, 1/4, 1/16 }:
|
||||
return 0.0625 * (p0 + p4) + 0.25 * (p1 + p3) + 0.375 * p2;
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTessLevels(OsdPerPatchVertexBezier cpBezier[16],
|
||||
ivec3 patchParam, out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. When the patch control
|
||||
// points have been converted to the Bezier basis, the control points
|
||||
// at the four corners are on the limit surface (since a Bezier patch
|
||||
// interpolates its corner control points). We can compute an adaptive
|
||||
// tessellation level for transition edges on the limit surface by
|
||||
// evaluating a limit position at the mid point of each transition edge.
|
||||
|
||||
tessOuterLo = vec4(0);
|
||||
tessOuterHi = vec4(0);
|
||||
|
||||
vec3 corners[4];
|
||||
vec3 midpoints[4];
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
corners[0] = OsdEvalBezier(cpBezier, patchParam, vec2(0.0, 0.0));
|
||||
corners[1] = OsdEvalBezier(cpBezier, patchParam, vec2(1.0, 0.0));
|
||||
corners[2] = OsdEvalBezier(cpBezier, patchParam, vec2(1.0, 1.0));
|
||||
corners[3] = OsdEvalBezier(cpBezier, patchParam, vec2(0.0, 1.0));
|
||||
|
||||
midpoints[0] = ((transitionMask & 8) == 0) ? vec3(0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, vec2(0.0, 0.5));
|
||||
midpoints[1] = ((transitionMask & 1) == 0) ? vec3(0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, vec2(0.5, 0.0));
|
||||
midpoints[2] = ((transitionMask & 2) == 0) ? vec3(0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, vec2(1.0, 0.5));
|
||||
midpoints[3] = ((transitionMask & 4) == 0) ? vec3(0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, vec2(0.5, 1.0));
|
||||
#else
|
||||
corners[0] = cpBezier[ 0].P;
|
||||
corners[1] = cpBezier[ 3].P;
|
||||
corners[2] = cpBezier[15].P;
|
||||
corners[3] = cpBezier[12].P;
|
||||
|
||||
midpoints[0] = ((transitionMask & 8) == 0) ? vec3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[0].P, cpBezier[4].P, cpBezier[8].P, cpBezier[12].P);
|
||||
midpoints[1] = ((transitionMask & 1) == 0) ? vec3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[0].P, cpBezier[1].P, cpBezier[2].P, cpBezier[3].P);
|
||||
midpoints[2] = ((transitionMask & 2) == 0) ? vec3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[3].P, cpBezier[7].P, cpBezier[11].P, cpBezier[15].P);
|
||||
midpoints[3] = ((transitionMask & 4) == 0) ? vec3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[12].P, cpBezier[13].P, cpBezier[14].P, cpBezier[15].P);
|
||||
#endif
|
||||
|
||||
Osd_GetTessLevelsFromPatchBoundaries4(corners, midpoints,
|
||||
patchParam, tessOuterLo, tessOuterHi);
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTriangleTessLevels(vec3 cv[15],
|
||||
ivec3 patchParam, out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. When the patch control
|
||||
// points have been converted to the Bezier basis, the control points
|
||||
// at the corners are on the limit surface (since a Bezier patch
|
||||
// interpolates its corner control points). We can compute an adaptive
|
||||
// tessellation level for transition edges on the limit surface by
|
||||
// evaluating a limit position at the mid point of each transition edge.
|
||||
|
||||
tessOuterLo = vec4(0);
|
||||
tessOuterHi = vec4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
vec3 corners[3];
|
||||
corners[0] = cv[0];
|
||||
corners[1] = cv[4];
|
||||
corners[2] = cv[14];
|
||||
|
||||
vec3 midpoints[3];
|
||||
midpoints[0] = ((transitionMask & 4) == 0) ? vec3(0) :
|
||||
Osd_EvalQuarticBezierCurveMidPoint(cv[0], cv[5], cv[9], cv[12], cv[14]);
|
||||
midpoints[1] = ((transitionMask & 1) == 0) ? vec3(0) :
|
||||
Osd_EvalQuarticBezierCurveMidPoint(cv[0], cv[1], cv[2], cv[3], cv[4]);
|
||||
midpoints[2] = ((transitionMask & 2) == 0) ? vec3(0) :
|
||||
Osd_EvalQuarticBezierCurveMidPoint(cv[4], cv[8], cv[11], cv[13], cv[14]);
|
||||
|
||||
Osd_GetTessLevelsFromPatchBoundaries3(corners, midpoints,
|
||||
patchParam, tessOuterLo, tessOuterHi);
|
||||
}
|
||||
|
||||
// Round up to the nearest even integer
|
||||
float OsdRoundUpEven(float x) {
|
||||
return 2*ceil(x/2);
|
||||
}
|
||||
|
||||
// Round up to the nearest odd integer
|
||||
float OsdRoundUpOdd(float x) {
|
||||
return 2*ceil((x+1)/2)-1;
|
||||
}
|
||||
|
||||
// Compute outer and inner tessellation levels taking into account the
|
||||
// current tessellation spacing mode.
|
||||
void
|
||||
OsdComputeTessLevels(inout vec4 tessOuterLo, inout vec4 tessOuterHi,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner)
|
||||
{
|
||||
// Outer levels are the sum of the Lo and Hi segments where the Hi
|
||||
// segments will have lengths of zero for non-transition edges.
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
// Combine fractional outer transition edge levels before rounding.
|
||||
vec4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
|
||||
// Round the segments of transition edges separately. We will recover the
|
||||
// fractional parameterization of transition edges after tessellation.
|
||||
|
||||
tessLevelOuter = combinedOuter;
|
||||
if (tessOuterHi[0] > 0) {
|
||||
tessLevelOuter[0] =
|
||||
OsdRoundUpEven(tessOuterLo[0]) + OsdRoundUpEven(tessOuterHi[0]);
|
||||
}
|
||||
if (tessOuterHi[1] > 0) {
|
||||
tessLevelOuter[1] =
|
||||
OsdRoundUpEven(tessOuterLo[1]) + OsdRoundUpEven(tessOuterHi[1]);
|
||||
}
|
||||
if (tessOuterHi[2] > 0) {
|
||||
tessLevelOuter[2] =
|
||||
OsdRoundUpEven(tessOuterLo[2]) + OsdRoundUpEven(tessOuterHi[2]);
|
||||
}
|
||||
if (tessOuterHi[3] > 0) {
|
||||
tessLevelOuter[3] =
|
||||
OsdRoundUpEven(tessOuterLo[3]) + OsdRoundUpEven(tessOuterHi[3]);
|
||||
}
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
// Combine fractional outer transition edge levels before rounding.
|
||||
vec4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
|
||||
// Round the segments of transition edges separately. We will recover the
|
||||
// fractional parameterization of transition edges after tessellation.
|
||||
//
|
||||
// The sum of the two outer odd segment lengths will be an even number
|
||||
// which the tessellator will increase by +1 so that there will be a
|
||||
// total odd number of segments. We clamp the combinedOuter tess levels
|
||||
// (used to compute the inner tess levels) so that the outer transition
|
||||
// edges will be sampled without degenerate triangles.
|
||||
|
||||
tessLevelOuter = combinedOuter;
|
||||
if (tessOuterHi[0] > 0) {
|
||||
tessLevelOuter[0] =
|
||||
OsdRoundUpOdd(tessOuterLo[0]) + OsdRoundUpOdd(tessOuterHi[0]);
|
||||
combinedOuter = max(vec4(3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[1] > 0) {
|
||||
tessLevelOuter[1] =
|
||||
OsdRoundUpOdd(tessOuterLo[1]) + OsdRoundUpOdd(tessOuterHi[1]);
|
||||
combinedOuter = max(vec4(3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[2] > 0) {
|
||||
tessLevelOuter[2] =
|
||||
OsdRoundUpOdd(tessOuterLo[2]) + OsdRoundUpOdd(tessOuterHi[2]);
|
||||
combinedOuter = max(vec4(3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[3] > 0) {
|
||||
tessLevelOuter[3] =
|
||||
OsdRoundUpOdd(tessOuterLo[3]) + OsdRoundUpOdd(tessOuterHi[3]);
|
||||
combinedOuter = max(vec4(3), combinedOuter);
|
||||
}
|
||||
#else
|
||||
// Round equally spaced transition edge levels before combining.
|
||||
tessOuterLo = round(tessOuterLo);
|
||||
tessOuterHi = round(tessOuterHi);
|
||||
|
||||
vec4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
tessLevelOuter = combinedOuter;
|
||||
#endif
|
||||
|
||||
// Inner levels are the averages the corresponding outer levels.
|
||||
tessLevelInner[0] = (combinedOuter[1] + combinedOuter[3]) * 0.5;
|
||||
tessLevelInner[1] = (combinedOuter[0] + combinedOuter[2]) * 0.5;
|
||||
}
|
||||
|
||||
void
|
||||
OsdComputeTessLevelsTriangle(inout vec4 tessOuterLo, inout vec4 tessOuterHi,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner)
|
||||
{
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
|
||||
// Inner level is the max of the three outer levels.
|
||||
tessLevelInner[0] = max(max(tessLevelOuter[0],
|
||||
tessLevelOuter[1]),
|
||||
tessLevelOuter[2]);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniform(ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsUniform(patchParam, tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniformTriangle(ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsUniformTriangle(patchParam, tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevelsTriangle(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTessLevels(OsdPerPatchVertexBezier cpBezier[16],
|
||||
ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
OsdEvalPatchBezierTessLevels(cpBezier, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTriangleTessLevels(vec3 cv[15],
|
||||
ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
OsdEvalPatchBezierTriangleTessLevels(cv, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevelsTriangle(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsAdaptiveRefinedPoints(vec3 cpRefined[16], ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsRefinedPoints(cpRefined, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
// Deprecated -- prefer use of newer Bezier patch equivalent:
|
||||
void
|
||||
OsdGetTessLevelsLimitPoints(OsdPerPatchVertexBezier cpBezier[16],
|
||||
ivec3 patchParam, out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
OsdEvalPatchBezierTessLevels(cpBezier, patchParam, tessOuterLo, tessOuterHi);
|
||||
}
|
||||
|
||||
// Deprecated -- prefer use of newer Bezier patch equivalent:
|
||||
void
|
||||
OsdGetTessLevelsAdaptiveLimitPoints(OsdPerPatchVertexBezier cpBezier[16],
|
||||
ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsLimitPoints(cpBezier, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
// Deprecated -- prefer use of newer Bezier patch equivalent:
|
||||
void
|
||||
OsdGetTessLevels(vec3 cp0, vec3 cp1, vec3 cp2, vec3 cp3,
|
||||
ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner)
|
||||
{
|
||||
vec4 tessOuterLo = vec4(0);
|
||||
vec4 tessOuterHi = vec4(0);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cp0, cp1);
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cp0, cp3);
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cp2, cp3);
|
||||
tessOuterLo[3] = OsdComputeTessLevel(cp1, cp2);
|
||||
tessOuterHi = vec4(0);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(patchParam, tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING || defined OSD_FRACTIONAL_ODD_SPACING
|
||||
float
|
||||
OsdGetTessFractionalSplit(float t, float level, float levelUp)
|
||||
{
|
||||
// Fractional tessellation of an edge will produce n segments where n
|
||||
// is the tessellation level of the edge (level) rounded up to the
|
||||
// nearest even or odd integer (levelUp). There will be n-2 segments of
|
||||
// equal length (dx1) and two additional segments of equal length (dx0)
|
||||
// that are typically shorter than the other segments. The two additional
|
||||
// segments should be placed symmetrically on opposite sides of the
|
||||
// edge (offset).
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
if (level <= 2) return t;
|
||||
|
||||
float base = pow(2.0,floor(log2(levelUp)));
|
||||
float offset = 1.0/(int(2*base-levelUp)/2 & int(base/2-1));
|
||||
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
if (level <= 1) return t;
|
||||
|
||||
float base = pow(2.0,floor(log2(levelUp)));
|
||||
float offset = 1.0/(((int(2*base-levelUp)/2+1) & int(base/2-1))+1);
|
||||
#endif
|
||||
|
||||
float dx0 = (1.0 - (levelUp-level)/2) / levelUp;
|
||||
float dx1 = (1.0 - 2.0*dx0) / (levelUp - 2.0*ceil(dx0));
|
||||
|
||||
if (t < 0.5) {
|
||||
float x = levelUp/2 - round(t*levelUp);
|
||||
return 0.5 - (x*dx1 + int(x*offset > 1) * (dx0 - dx1));
|
||||
} else if (t > 0.5) {
|
||||
float x = round(t*levelUp) - levelUp/2;
|
||||
return 0.5 + (x*dx1 + int(x*offset > 1) * (dx0 - dx1));
|
||||
} else {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
float
|
||||
OsdGetTessTransitionSplit(float t, float lo, float hi)
|
||||
{
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
float loRoundUp = OsdRoundUpEven(lo);
|
||||
float hiRoundUp = OsdRoundUpEven(hi);
|
||||
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
float ti = round(t * (loRoundUp + hiRoundUp));
|
||||
|
||||
if (ti <= loRoundUp) {
|
||||
float t0 = ti / loRoundUp;
|
||||
return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5;
|
||||
} else {
|
||||
float t1 = (ti - loRoundUp) / hiRoundUp;
|
||||
return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5;
|
||||
}
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
float loRoundUp = OsdRoundUpOdd(lo);
|
||||
float hiRoundUp = OsdRoundUpOdd(hi);
|
||||
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
// The +1 below is to account for the extra segment produced by the
|
||||
// tessellator since the sum of two odd tess levels will be rounded
|
||||
// up by one to the next odd integer tess level.
|
||||
float ti = round(t * (loRoundUp + hiRoundUp + 1));
|
||||
|
||||
if (ti <= loRoundUp) {
|
||||
float t0 = ti / loRoundUp;
|
||||
return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5;
|
||||
} else if (ti > (loRoundUp+1)) {
|
||||
float t1 = (ti - (loRoundUp+1)) / hiRoundUp;
|
||||
return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5;
|
||||
} else {
|
||||
return 0.5;
|
||||
}
|
||||
#else
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
float ti = round(t * (lo + hi));
|
||||
|
||||
if (ti <= lo) {
|
||||
return (ti / lo) * 0.5;
|
||||
} else {
|
||||
return ((ti - lo) / hi) * 0.5 + 0.5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
vec2
|
||||
OsdGetTessParameterization(vec2 p, vec4 tessOuterLo, vec4 tessOuterHi)
|
||||
{
|
||||
vec2 UV = p;
|
||||
if (p.x == 0 && tessOuterHi[0] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[0], tessOuterHi[0]);
|
||||
} else
|
||||
if (p.y == 0 && tessOuterHi[1] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[1], tessOuterHi[1]);
|
||||
} else
|
||||
if (p.x == 1 && tessOuterHi[2] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[2], tessOuterHi[2]);
|
||||
} else
|
||||
if (p.y == 1 && tessOuterHi[3] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[3], tessOuterHi[3]);
|
||||
}
|
||||
return UV;
|
||||
}
|
||||
|
||||
vec2
|
||||
OsdGetTessParameterizationTriangle(vec3 p, vec4 tessOuterLo, vec4 tessOuterHi)
|
||||
{
|
||||
vec2 UV = p.xy;
|
||||
if (p.x == 0 && tessOuterHi[0] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[0], tessOuterHi[0]);
|
||||
} else
|
||||
if (p.y == 0 && tessOuterHi[1] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[1], tessOuterHi[1]);
|
||||
} else
|
||||
if (p.z == 0 && tessOuterHi[2] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[2], tessOuterHi[2]);
|
||||
UV.y = 1.0 - UV.x;
|
||||
}
|
||||
return UV;
|
||||
}
|
||||
188
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchGregory.glsl
vendored
Normal file
188
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchGregory.glsl
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexGregory
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_VERTEX_GREGORY_SHADER
|
||||
|
||||
layout (location=0) in vec4 position;
|
||||
OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
|
||||
out block {
|
||||
OsdPerVertexGregory v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
OsdComputePerVertexGregory(gl_VertexID, position.xyz, outpt.v);
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(position);
|
||||
OSD_USER_VARYING_PER_VERTEX();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessControlGregory
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_CONTROL_GREGORY_SHADER
|
||||
|
||||
patch out vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
OsdPerVertexGregory v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OsdPerPatchVertexGregory v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt[4];
|
||||
|
||||
layout(vertices = 4) out;
|
||||
|
||||
void main()
|
||||
{
|
||||
OsdPerVertexGregory cv[4];
|
||||
for (int i=0; i<4; ++i) {
|
||||
cv[i] = inpt[i].v;
|
||||
}
|
||||
|
||||
ivec3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(gl_PrimitiveID));
|
||||
OsdComputePerPatchVertexGregory(patchParam, gl_InvocationID, gl_PrimitiveID, cv, outpt[gl_InvocationID].v);
|
||||
|
||||
OSD_USER_VARYING_PER_CONTROL_POINT(gl_InvocationID, gl_InvocationID);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Wait for all basis conversion to be finished
|
||||
barrier();
|
||||
#endif
|
||||
if (gl_InvocationID == 0) {
|
||||
vec4 tessLevelOuter = vec4(0);
|
||||
vec2 tessLevelInner = vec2(0);
|
||||
|
||||
OSD_PATCH_CULL(4);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
OsdPerPatchVertexBezier bezcv[16];
|
||||
bezcv[ 0].P = outpt[0].v.P;
|
||||
bezcv[ 1].P = outpt[0].v.Ep;
|
||||
bezcv[ 2].P = outpt[1].v.Em;
|
||||
bezcv[ 3].P = outpt[1].v.P;
|
||||
bezcv[ 4].P = outpt[0].v.Em;
|
||||
bezcv[ 5].P = outpt[0].v.Fp;
|
||||
bezcv[ 6].P = outpt[1].v.Fm;
|
||||
bezcv[ 7].P = outpt[1].v.Ep;
|
||||
bezcv[ 8].P = outpt[3].v.Ep;
|
||||
bezcv[ 9].P = outpt[3].v.Fm;
|
||||
bezcv[10].P = outpt[2].v.Fp;
|
||||
bezcv[11].P = outpt[2].v.Em;
|
||||
bezcv[12].P = outpt[3].v.P;
|
||||
bezcv[13].P = outpt[3].v.Em;
|
||||
bezcv[14].P = outpt[2].v.Ep;
|
||||
bezcv[15].P = outpt[2].v.P;
|
||||
|
||||
OsdEvalPatchBezierTessLevels(bezcv, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(patchParam, tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
gl_TessLevelOuter[0] = tessLevelOuter[0];
|
||||
gl_TessLevelOuter[1] = tessLevelOuter[1];
|
||||
gl_TessLevelOuter[2] = tessLevelOuter[2];
|
||||
gl_TessLevelOuter[3] = tessLevelOuter[3];
|
||||
|
||||
gl_TessLevelInner[0] = tessLevelInner[0];
|
||||
gl_TessLevelInner[1] = tessLevelInner[1];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessEvalGregory
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_EVAL_GREGORY_SHADER
|
||||
|
||||
layout(quads) in;
|
||||
layout(OSD_SPACING) in;
|
||||
|
||||
patch in vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
OsdPerPatchVertexGregory v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 P = vec3(0), dPu = vec3(0), dPv = vec3(0);
|
||||
vec3 N = vec3(0), dNu = vec3(0), dNv = vec3(0);
|
||||
|
||||
vec3 cv[20];
|
||||
cv[0] = inpt[0].v.P;
|
||||
cv[1] = inpt[0].v.Ep;
|
||||
cv[2] = inpt[0].v.Em;
|
||||
cv[3] = inpt[0].v.Fp;
|
||||
cv[4] = inpt[0].v.Fm;
|
||||
|
||||
cv[5] = inpt[1].v.P;
|
||||
cv[6] = inpt[1].v.Ep;
|
||||
cv[7] = inpt[1].v.Em;
|
||||
cv[8] = inpt[1].v.Fp;
|
||||
cv[9] = inpt[1].v.Fm;
|
||||
|
||||
cv[10] = inpt[2].v.P;
|
||||
cv[11] = inpt[2].v.Ep;
|
||||
cv[12] = inpt[2].v.Em;
|
||||
cv[13] = inpt[2].v.Fp;
|
||||
cv[14] = inpt[2].v.Fm;
|
||||
|
||||
cv[15] = inpt[3].v.P;
|
||||
cv[16] = inpt[3].v.Ep;
|
||||
cv[17] = inpt[3].v.Em;
|
||||
cv[18] = inpt[3].v.Fp;
|
||||
cv[19] = inpt[3].v.Fm;
|
||||
|
||||
vec2 UV = OsdGetTessParameterization(gl_TessCoord.xy,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
ivec3 patchParam = inpt[0].v.patchParam;
|
||||
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
outpt.v.position = OsdModelViewMatrix() * vec4(P, 1.0f);
|
||||
outpt.v.normal = (OsdModelViewMatrix() * vec4(N, 0.0f)).xyz;
|
||||
outpt.v.tangent = (OsdModelViewMatrix() * vec4(dPu, 0.0f)).xyz;
|
||||
outpt.v.bitangent = (OsdModelViewMatrix() * vec4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
outpt.v.Nu = dNu;
|
||||
outpt.v.Nv = dNv;
|
||||
#endif
|
||||
|
||||
outpt.v.tessCoord = UV;
|
||||
outpt.v.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
|
||||
OSD_USER_VARYING_PER_EVAL_POINT(UV, 0, 1, 3, 2);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
gl_Position = OsdProjectionMatrix() * outpt.v.position;
|
||||
}
|
||||
|
||||
#endif
|
||||
165
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchGregoryBasis.glsl
vendored
Normal file
165
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchGregoryBasis.glsl
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexGregoryBasis
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_VERTEX_GREGORY_BASIS_SHADER
|
||||
|
||||
layout(location = 0) in vec4 position;
|
||||
OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
|
||||
out block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
outpt.v.position = position;
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(position);
|
||||
OSD_USER_VARYING_PER_VERTEX();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessControlGregoryBasis
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_CONTROL_GREGORY_BASIS_SHADER
|
||||
|
||||
patch out vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OsdPerPatchVertexGregoryBasis v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt[20];
|
||||
|
||||
layout(vertices = 20) out;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 cv = inpt[gl_InvocationID].v.position.xyz;
|
||||
|
||||
ivec3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(gl_PrimitiveID));
|
||||
OsdComputePerPatchVertexGregoryBasis(
|
||||
patchParam, gl_InvocationID, cv, outpt[gl_InvocationID].v);
|
||||
|
||||
OSD_USER_VARYING_PER_CONTROL_POINT(gl_InvocationID, gl_InvocationID);
|
||||
|
||||
if (gl_InvocationID == 0) {
|
||||
vec4 tessLevelOuter = vec4(0);
|
||||
vec2 tessLevelInner = vec2(0);
|
||||
|
||||
OSD_PATCH_CULL(20);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
OsdPerPatchVertexBezier bezcv[16];
|
||||
bezcv[ 0].P = inpt[ 0].v.position.xyz;
|
||||
bezcv[ 1].P = inpt[ 1].v.position.xyz;
|
||||
bezcv[ 2].P = inpt[ 7].v.position.xyz;
|
||||
bezcv[ 3].P = inpt[ 5].v.position.xyz;
|
||||
bezcv[ 4].P = inpt[ 2].v.position.xyz;
|
||||
bezcv[ 5].P = inpt[ 3].v.position.xyz;
|
||||
bezcv[ 6].P = inpt[ 8].v.position.xyz;
|
||||
bezcv[ 7].P = inpt[ 6].v.position.xyz;
|
||||
bezcv[ 8].P = inpt[16].v.position.xyz;
|
||||
bezcv[ 9].P = inpt[18].v.position.xyz;
|
||||
bezcv[10].P = inpt[13].v.position.xyz;
|
||||
bezcv[11].P = inpt[12].v.position.xyz;
|
||||
bezcv[12].P = inpt[15].v.position.xyz;
|
||||
bezcv[13].P = inpt[17].v.position.xyz;
|
||||
bezcv[14].P = inpt[11].v.position.xyz;
|
||||
bezcv[15].P = inpt[10].v.position.xyz;
|
||||
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
bezcv, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(
|
||||
patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
gl_TessLevelOuter[0] = tessLevelOuter[0];
|
||||
gl_TessLevelOuter[1] = tessLevelOuter[1];
|
||||
gl_TessLevelOuter[2] = tessLevelOuter[2];
|
||||
gl_TessLevelOuter[3] = tessLevelOuter[3];
|
||||
|
||||
gl_TessLevelInner[0] = tessLevelInner[0];
|
||||
gl_TessLevelInner[1] = tessLevelInner[1];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessEvalGregoryBasis
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_EVAL_GREGORY_BASIS_SHADER
|
||||
|
||||
layout(quads) in;
|
||||
layout(OSD_SPACING) in;
|
||||
|
||||
patch in vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
OsdPerPatchVertexGregoryBasis v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 P = vec3(0), dPu = vec3(0), dPv = vec3(0);
|
||||
vec3 N = vec3(0), dNu = vec3(0), dNv = vec3(0);
|
||||
|
||||
vec3 cv[20];
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
cv[i] = inpt[i].v.P;
|
||||
}
|
||||
|
||||
vec2 UV = OsdGetTessParameterization(gl_TessCoord.xy,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
ivec3 patchParam = inpt[0].v.patchParam;
|
||||
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
outpt.v.position = OsdModelViewMatrix() * vec4(P, 1.0f);
|
||||
outpt.v.normal = (OsdModelViewMatrix() * vec4(N, 0.0f)).xyz;
|
||||
outpt.v.tangent = (OsdModelViewMatrix() * vec4(dPu, 0.0f)).xyz;
|
||||
outpt.v.bitangent = (OsdModelViewMatrix() * vec4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
outpt.v.Nu = dNu;
|
||||
outpt.v.Nv = dNv;
|
||||
#endif
|
||||
|
||||
outpt.v.tessCoord = UV;
|
||||
outpt.v.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
|
||||
OSD_USER_VARYING_PER_EVAL_POINT(UV, 0, 5, 15, 10);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
gl_Position = OsdProjectionMatrix() * outpt.v.position;
|
||||
}
|
||||
|
||||
#endif
|
||||
162
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchGregoryTriangle.glsl
vendored
Normal file
162
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchGregoryTriangle.glsl
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
//
|
||||
// Copyright 2018 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexGregoryTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_VERTEX_GREGORY_TRIANGLE_SHADER
|
||||
|
||||
layout(location = 0) in vec4 position;
|
||||
OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
|
||||
out block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
outpt.v.position = position;
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(position);
|
||||
OSD_USER_VARYING_PER_VERTEX();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessControlGregoryTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_CONTROL_GREGORY_TRIANGLE_SHADER
|
||||
|
||||
patch out vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OsdPerPatchVertexGregoryBasis v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt[18];
|
||||
|
||||
layout(vertices = 18) out;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 cv = inpt[gl_InvocationID].v.position.xyz;
|
||||
|
||||
ivec3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(gl_PrimitiveID));
|
||||
OsdComputePerPatchVertexGregoryBasis(
|
||||
patchParam, gl_InvocationID, cv, outpt[gl_InvocationID].v);
|
||||
|
||||
OSD_USER_VARYING_PER_CONTROL_POINT(gl_InvocationID, gl_InvocationID);
|
||||
|
||||
if (gl_InvocationID == 0) {
|
||||
vec4 tessLevelOuter = vec4(0);
|
||||
vec2 tessLevelInner = vec2(0);
|
||||
|
||||
OSD_PATCH_CULL(18);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
vec3 cv[15];
|
||||
cv[ 0] = inpt[ 0].v.position.xyz;
|
||||
cv[ 1] = inpt[ 1].v.position.xyz;
|
||||
cv[ 2] = inpt[15].v.position.xyz;
|
||||
cv[ 3] = inpt[ 7].v.position.xyz;
|
||||
cv[ 4] = inpt[ 5].v.position.xyz;
|
||||
cv[ 5] = inpt[ 2].v.position.xyz;
|
||||
cv[ 6] = inpt[ 3].v.position.xyz;
|
||||
cv[ 7] = inpt[ 8].v.position.xyz;
|
||||
cv[ 8] = inpt[ 6].v.position.xyz;
|
||||
cv[ 9] = inpt[17].v.position.xyz;
|
||||
cv[10] = inpt[13].v.position.xyz;
|
||||
cv[11] = inpt[16].v.position.xyz;
|
||||
cv[12] = inpt[11].v.position.xyz;
|
||||
cv[13] = inpt[12].v.position.xyz;
|
||||
cv[14] = inpt[10].v.position.xyz;
|
||||
|
||||
OsdEvalPatchBezierTriangleTessLevels(
|
||||
cv, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniformTriangle(
|
||||
patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
gl_TessLevelOuter[0] = tessLevelOuter[0];
|
||||
gl_TessLevelOuter[1] = tessLevelOuter[1];
|
||||
gl_TessLevelOuter[2] = tessLevelOuter[2];
|
||||
|
||||
gl_TessLevelInner[0] = tessLevelInner[0];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessEvalGregoryTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_EVAL_GREGORY_TRIANGLE_SHADER
|
||||
|
||||
layout(triangles) in;
|
||||
layout(OSD_SPACING) in;
|
||||
|
||||
patch in vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
OsdPerPatchVertexGregoryBasis v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 P = vec3(0), dPu = vec3(0), dPv = vec3(0);
|
||||
vec3 N = vec3(0), dNu = vec3(0), dNv = vec3(0);
|
||||
|
||||
vec3 cv[18];
|
||||
for (int i = 0; i < 18; ++i) {
|
||||
cv[i] = inpt[i].v.P;
|
||||
}
|
||||
|
||||
vec2 UV = OsdGetTessParameterizationTriangle(gl_TessCoord.xyz,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
ivec3 patchParam = inpt[0].v.patchParam;
|
||||
OsdEvalPatchGregoryTriangle(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
outpt.v.position = OsdModelViewMatrix() * vec4(P, 1.0f);
|
||||
outpt.v.normal = (OsdModelViewMatrix() * vec4(N, 0.0f)).xyz;
|
||||
outpt.v.tangent = (OsdModelViewMatrix() * vec4(dPu, 0.0f)).xyz;
|
||||
outpt.v.bitangent = (OsdModelViewMatrix() * vec4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
outpt.v.Nu = dNu;
|
||||
outpt.v.Nv = dNv;
|
||||
#endif
|
||||
|
||||
outpt.v.tessCoord = UV;
|
||||
outpt.v.patchCoord = OsdInterpolatePatchCoordTriangle(UV, patchParam);
|
||||
|
||||
OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE(UV, 0, 5, 10);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
gl_Position = OsdProjectionMatrix() * outpt.v.position;
|
||||
}
|
||||
|
||||
#endif
|
||||
616
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchLegacy.glsl
vendored
Normal file
616
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchLegacy.glsl
vendored
Normal file
@@ -0,0 +1,616 @@
|
||||
//
|
||||
// Copyright 2013-2018 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Common
|
||||
//----------------------------------------------------------
|
||||
|
||||
// XXXdyu all handling of varying data can be managed by client code
|
||||
#ifndef OSD_USER_VARYING_DECLARE
|
||||
#define OSD_USER_VARYING_DECLARE
|
||||
// type var;
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
#define OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
// layout(location = loc) in type var;
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_VERTEX
|
||||
#define OSD_USER_VARYING_PER_VERTEX()
|
||||
// output.var = var;
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_CONTROL_POINT
|
||||
#define OSD_USER_VARYING_PER_CONTROL_POINT(ID_OUT, ID_IN)
|
||||
// output[ID_OUT].var = input[ID_IN].var
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_EVAL_POINT
|
||||
#define OSD_USER_VARYING_PER_EVAL_POINT(UV, a, b, c, d)
|
||||
// output.var =
|
||||
// mix(mix(input[a].var, input[b].var, UV.x),
|
||||
// mix(input[c].var, input[d].var, UV.x), UV.y)
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE
|
||||
#define OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE(UV, a, b, c)
|
||||
// output.var =
|
||||
// input[a].var * (1.0f-UV.x-UV.y) +
|
||||
// input[b].var * UV.x +
|
||||
// input[c].var * UV.y;
|
||||
#endif
|
||||
|
||||
#if __VERSION__ < 420
|
||||
#define centroid
|
||||
#endif
|
||||
|
||||
struct ControlVertex {
|
||||
vec4 position;
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
ivec3 clipFlag;
|
||||
#endif
|
||||
};
|
||||
|
||||
// XXXdyu all downstream data can be handled by client code
|
||||
struct OutputVertex {
|
||||
vec4 position;
|
||||
vec3 normal;
|
||||
vec3 tangent;
|
||||
vec3 bitangent;
|
||||
vec4 patchCoord; // u, v, faceLevel, faceId
|
||||
vec2 tessCoord; // tesscoord.st
|
||||
#if defined OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
vec3 Nu;
|
||||
vec3 Nv;
|
||||
#endif
|
||||
};
|
||||
|
||||
mat4 OsdModelViewProjectionMatrix();
|
||||
int OsdGregoryQuadOffsetBase();
|
||||
int OsdPrimitiveIdBase();
|
||||
int OsdBaseVertex();
|
||||
|
||||
#ifndef OSD_DISPLACEMENT_CALLBACK
|
||||
#define OSD_DISPLACEMENT_CALLBACK
|
||||
#endif
|
||||
|
||||
// These are stored in OsdPatchParamBuffer indexed by the value returned
|
||||
// from OsdGetPatchIndex() which is a function of the current PrimitiveID
|
||||
// along with an optional client provided offset.
|
||||
|
||||
uniform isamplerBuffer OsdPatchParamBuffer;
|
||||
|
||||
int OsdGetPatchIndex(int primitiveId)
|
||||
{
|
||||
return (primitiveId + OsdPrimitiveIdBase());
|
||||
}
|
||||
|
||||
ivec3 OsdGetPatchParam(int patchIndex)
|
||||
{
|
||||
return texelFetch(OsdPatchParamBuffer, patchIndex).xyz;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// patch culling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P) \
|
||||
vec4 clipPos = OsdModelViewProjectionMatrix() * P; \
|
||||
bvec3 clip0 = lessThan(clipPos.xyz, vec3(clipPos.w)); \
|
||||
bvec3 clip1 = greaterThan(clipPos.xyz, -vec3(clipPos.w)); \
|
||||
outpt.v.clipFlag = ivec3(clip0) + 2*ivec3(clip1); \
|
||||
|
||||
#define OSD_PATCH_CULL(N) \
|
||||
ivec3 clipFlag = ivec3(0); \
|
||||
for(int i = 0; i < N; ++i) { \
|
||||
clipFlag |= inpt[i].v.clipFlag; \
|
||||
} \
|
||||
if (clipFlag != ivec3(3) ) { \
|
||||
gl_TessLevelInner[0] = 0; \
|
||||
gl_TessLevelInner[1] = 0; \
|
||||
gl_TessLevelOuter[0] = 0; \
|
||||
gl_TessLevelOuter[1] = 0; \
|
||||
gl_TessLevelOuter[2] = 0; \
|
||||
gl_TessLevelOuter[3] = 0; \
|
||||
return; \
|
||||
}
|
||||
|
||||
#else
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P)
|
||||
#define OSD_PATCH_CULL(N)
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Legacy Gregory
|
||||
// ----------------------------------------------------------------------------
|
||||
#if defined(OSD_PATCH_GREGORY) || defined(OSD_PATCH_GREGORY_BOUNDARY)
|
||||
|
||||
#define M_PI 3.14159265359f
|
||||
|
||||
// precomputed catmark coefficient table up to valence 29
|
||||
uniform float OsdCatmarkCoefficient[30] = float[](
|
||||
0, 0, 0, 0.812816, 0.500000, 0.363644, 0.287514,
|
||||
0.238688, 0.204544, 0.179229, 0.159657,
|
||||
0.144042, 0.131276, 0.120632, 0.111614,
|
||||
0.103872, 0.09715, 0.0912559, 0.0860444,
|
||||
0.0814022, 0.0772401, 0.0734867, 0.0700842,
|
||||
0.0669851, 0.0641504, 0.0615475, 0.0591488,
|
||||
0.0569311, 0.0548745, 0.0529621
|
||||
);
|
||||
|
||||
float
|
||||
OsdComputeCatmarkCoefficient(int valence)
|
||||
{
|
||||
#if OSD_MAX_VALENCE < 30
|
||||
return OsdCatmarkCoefficient[valence];
|
||||
#else
|
||||
if (valence < 30) {
|
||||
return OsdCatmarkCoefficient[valence];
|
||||
} else {
|
||||
float t = 2.0f * float(M_PI) / float(valence);
|
||||
return 1.0f / (valence * (cos(t) + 5.0f +
|
||||
sqrt((cos(t) + 9) * (cos(t) + 1)))/16.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float cosfn(int n, int j) {
|
||||
return cos((2.0f * M_PI * j)/float(n));
|
||||
}
|
||||
|
||||
float sinfn(int n, int j) {
|
||||
return sin((2.0f * M_PI * j)/float(n));
|
||||
}
|
||||
|
||||
#if !defined OSD_MAX_VALENCE || OSD_MAX_VALENCE < 1
|
||||
#undef OSD_MAX_VALENCE
|
||||
#define OSD_MAX_VALENCE 4
|
||||
#endif
|
||||
|
||||
struct OsdPerVertexGregory {
|
||||
vec3 P;
|
||||
ivec3 clipFlag;
|
||||
int valence;
|
||||
vec3 e0;
|
||||
vec3 e1;
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
int zerothNeighbor;
|
||||
vec3 org;
|
||||
#endif
|
||||
vec3 r[OSD_MAX_VALENCE];
|
||||
};
|
||||
|
||||
struct OsdPerPatchVertexGregory {
|
||||
ivec3 patchParam;
|
||||
vec3 P;
|
||||
vec3 Ep;
|
||||
vec3 Em;
|
||||
vec3 Fp;
|
||||
vec3 Fm;
|
||||
};
|
||||
|
||||
#ifndef OSD_NUM_ELEMENTS
|
||||
#define OSD_NUM_ELEMENTS 3
|
||||
#endif
|
||||
|
||||
uniform samplerBuffer OsdVertexBuffer;
|
||||
uniform isamplerBuffer OsdValenceBuffer;
|
||||
|
||||
vec3 OsdReadVertex(int vertexIndex)
|
||||
{
|
||||
int index = int(OSD_NUM_ELEMENTS * (vertexIndex + OsdBaseVertex()));
|
||||
return vec3(texelFetch(OsdVertexBuffer, index).x,
|
||||
texelFetch(OsdVertexBuffer, index+1).x,
|
||||
texelFetch(OsdVertexBuffer, index+2).x);
|
||||
}
|
||||
|
||||
int OsdReadVertexValence(int vertexID)
|
||||
{
|
||||
int index = int(vertexID * (2 * OSD_MAX_VALENCE + 1));
|
||||
return texelFetch(OsdValenceBuffer, index).x;
|
||||
}
|
||||
|
||||
int OsdReadVertexIndex(int vertexID, int valenceVertex)
|
||||
{
|
||||
int index = int(vertexID * (2 * OSD_MAX_VALENCE + 1) + 1 + valenceVertex);
|
||||
return texelFetch(OsdValenceBuffer, index).x;
|
||||
}
|
||||
|
||||
uniform isamplerBuffer OsdQuadOffsetBuffer;
|
||||
|
||||
int OsdReadQuadOffset(int primitiveID, int offsetVertex)
|
||||
{
|
||||
int index = int(4*primitiveID+OsdGregoryQuadOffsetBase() + offsetVertex);
|
||||
return texelFetch(OsdQuadOffsetBuffer, index).x;
|
||||
}
|
||||
|
||||
void
|
||||
OsdComputePerVertexGregory(int vID, vec3 P, out OsdPerVertexGregory v)
|
||||
{
|
||||
v.clipFlag = ivec3(0);
|
||||
|
||||
int ivalence = OsdReadVertexValence(vID);
|
||||
v.valence = ivalence;
|
||||
int valence = abs(ivalence);
|
||||
|
||||
vec3 f[OSD_MAX_VALENCE];
|
||||
vec3 pos = P;
|
||||
vec3 opos = vec3(0);
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
v.org = pos;
|
||||
int boundaryEdgeNeighbors[2];
|
||||
int currNeighbor = 0;
|
||||
int ibefore = 0;
|
||||
int zerothNeighbor = 0;
|
||||
#endif
|
||||
|
||||
for (int i=0; i<valence; ++i) {
|
||||
int im = (i+valence-1)%valence;
|
||||
int ip = (i+1)%valence;
|
||||
|
||||
int idx_neighbor = OsdReadVertexIndex(vID, 2*i);
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
bool isBoundaryNeighbor = false;
|
||||
int valenceNeighbor = OsdReadVertexValence(idx_neighbor);
|
||||
|
||||
if (valenceNeighbor < 0) {
|
||||
isBoundaryNeighbor = true;
|
||||
if (currNeighbor<2) {
|
||||
boundaryEdgeNeighbors[currNeighbor] = idx_neighbor;
|
||||
}
|
||||
currNeighbor++;
|
||||
if (currNeighbor == 1) {
|
||||
ibefore = i;
|
||||
zerothNeighbor = i;
|
||||
} else {
|
||||
if (i-ibefore == 1) {
|
||||
int tmp = boundaryEdgeNeighbors[0];
|
||||
boundaryEdgeNeighbors[0] = boundaryEdgeNeighbors[1];
|
||||
boundaryEdgeNeighbors[1] = tmp;
|
||||
zerothNeighbor = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vec3 neighbor = OsdReadVertex(idx_neighbor);
|
||||
|
||||
int idx_diagonal = OsdReadVertexIndex(vID, 2*i + 1);
|
||||
vec3 diagonal = OsdReadVertex(idx_diagonal);
|
||||
|
||||
int idx_neighbor_p = OsdReadVertexIndex(vID, 2*ip);
|
||||
vec3 neighbor_p = OsdReadVertex(idx_neighbor_p);
|
||||
|
||||
int idx_neighbor_m = OsdReadVertexIndex(vID, 2*im);
|
||||
vec3 neighbor_m = OsdReadVertex(idx_neighbor_m);
|
||||
|
||||
int idx_diagonal_m = OsdReadVertexIndex(vID, 2*im + 1);
|
||||
vec3 diagonal_m = OsdReadVertex(idx_diagonal_m);
|
||||
|
||||
f[i] = (pos * float(valence) + (neighbor_p + neighbor)*2.0f + diagonal) / (float(valence)+5.0f);
|
||||
|
||||
opos += f[i];
|
||||
v.r[i] = (neighbor_p-neighbor_m)/3.0f + (diagonal - diagonal_m)/6.0f;
|
||||
}
|
||||
|
||||
opos /= valence;
|
||||
v.P = vec4(opos, 1.0f).xyz;
|
||||
|
||||
vec3 e;
|
||||
v.e0 = vec3(0);
|
||||
v.e1 = vec3(0);
|
||||
|
||||
for(int i=0; i<valence; ++i) {
|
||||
int im = (i + valence -1) % valence;
|
||||
e = 0.5f * (f[i] + f[im]);
|
||||
v.e0 += cosfn(valence, i)*e;
|
||||
v.e1 += sinfn(valence, i)*e;
|
||||
}
|
||||
float ef = OsdComputeCatmarkCoefficient(valence);
|
||||
v.e0 *= ef;
|
||||
v.e1 *= ef;
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
v.zerothNeighbor = zerothNeighbor;
|
||||
if (currNeighbor == 1) {
|
||||
boundaryEdgeNeighbors[1] = boundaryEdgeNeighbors[0];
|
||||
}
|
||||
|
||||
if (ivalence < 0) {
|
||||
if (valence > 2) {
|
||||
v.P = (OsdReadVertex(boundaryEdgeNeighbors[0]) +
|
||||
OsdReadVertex(boundaryEdgeNeighbors[1]) +
|
||||
4.0f * pos)/6.0f;
|
||||
} else {
|
||||
v.P = pos;
|
||||
}
|
||||
|
||||
v.e0 = (OsdReadVertex(boundaryEdgeNeighbors[0]) -
|
||||
OsdReadVertex(boundaryEdgeNeighbors[1]))/6.0;
|
||||
|
||||
float k = float(float(valence) - 1.0f); //k is the number of faces
|
||||
float c = cos(M_PI/k);
|
||||
float s = sin(M_PI/k);
|
||||
float gamma = -(4.0f*s)/(3.0f*k+c);
|
||||
float alpha_0k = -((1.0f+2.0f*c)*sqrt(1.0f+c))/((3.0f*k+c)*sqrt(1.0f-c));
|
||||
float beta_0 = s/(3.0f*k + c);
|
||||
|
||||
int idx_diagonal = OsdReadVertexIndex(vID, 2*zerothNeighbor + 1);
|
||||
vec3 diagonal = OsdReadVertex(idx_diagonal);
|
||||
|
||||
v.e1 = gamma * pos +
|
||||
alpha_0k * OsdReadVertex(boundaryEdgeNeighbors[0]) +
|
||||
alpha_0k * OsdReadVertex(boundaryEdgeNeighbors[1]) +
|
||||
beta_0 * diagonal;
|
||||
|
||||
for (int x=1; x<valence - 1; ++x) {
|
||||
int curri = ((x + zerothNeighbor)%valence);
|
||||
float alpha = (4.0f*sin((M_PI * float(x))/k))/(3.0f*k+c);
|
||||
float beta = (sin((M_PI * float(x))/k) + sin((M_PI * float(x+1))/k))/(3.0f*k+c);
|
||||
|
||||
int idx_neighbor = OsdReadVertexIndex(vID, 2*curri);
|
||||
vec3 neighbor = OsdReadVertex(idx_neighbor);
|
||||
|
||||
idx_diagonal = OsdReadVertexIndex(vID, 2*curri + 1);
|
||||
diagonal = OsdReadVertex(idx_diagonal);
|
||||
|
||||
v.e1 += alpha * neighbor + beta * diagonal;
|
||||
}
|
||||
|
||||
v.e1 /= 3.0f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
OsdComputePerPatchVertexGregory(ivec3 patchParam, int ID, int primitiveID,
|
||||
in OsdPerVertexGregory v[4],
|
||||
out OsdPerPatchVertexGregory result)
|
||||
{
|
||||
result.patchParam = patchParam;
|
||||
result.P = v[ID].P;
|
||||
|
||||
int i = ID;
|
||||
int ip = (i+1)%4;
|
||||
int im = (i+3)%4;
|
||||
int valence = abs(v[i].valence);
|
||||
int n = valence;
|
||||
|
||||
int start = OsdReadQuadOffset(primitiveID, i) & 0xff;
|
||||
int prev = (OsdReadQuadOffset(primitiveID, i) >> 8) & 0xff;
|
||||
|
||||
int start_m = OsdReadQuadOffset(primitiveID, im) & 0xff;
|
||||
int prev_p = (OsdReadQuadOffset(primitiveID, ip) >> 8) & 0xff;
|
||||
|
||||
int np = abs(v[ip].valence);
|
||||
int nm = abs(v[im].valence);
|
||||
|
||||
// Control Vertices based on :
|
||||
// "Approximating Subdivision Surfaces with Gregory Patches
|
||||
// for Hardware Tessellation"
|
||||
// Loop, Schaefer, Ni, Castano (ACM ToG Siggraph Asia 2009)
|
||||
//
|
||||
// P3 e3- e2+ P2
|
||||
// O--------O--------O--------O
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | f3- | f2+ |
|
||||
// | O O |
|
||||
// e3+ O------O O------O e2-
|
||||
// | f3+ f2- |
|
||||
// | |
|
||||
// | |
|
||||
// | f0- f1+ |
|
||||
// e0- O------O O------O e1+
|
||||
// | O O |
|
||||
// | | f0+ | f1- |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// O--------O--------O--------O
|
||||
// P0 e0+ e1- P1
|
||||
//
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
vec3 Em_ip;
|
||||
if (v[ip].valence < -2) {
|
||||
int j = (np + prev_p - v[ip].zerothNeighbor) % np;
|
||||
Em_ip = v[ip].P + cos((M_PI*j)/float(np-1))*v[ip].e0 + sin((M_PI*j)/float(np-1))*v[ip].e1;
|
||||
} else {
|
||||
Em_ip = v[ip].P + v[ip].e0*cosfn(np, prev_p ) + v[ip].e1*sinfn(np, prev_p);
|
||||
}
|
||||
|
||||
vec3 Ep_im;
|
||||
if (v[im].valence < -2) {
|
||||
int j = (nm + start_m - v[im].zerothNeighbor) % nm;
|
||||
Ep_im = v[im].P + cos((M_PI*j)/float(nm-1))*v[im].e0 + sin((M_PI*j)/float(nm-1))*v[im].e1;
|
||||
} else {
|
||||
Ep_im = v[im].P + v[im].e0*cosfn(nm, start_m) + v[im].e1*sinfn(nm, start_m);
|
||||
}
|
||||
|
||||
if (v[i].valence < 0) {
|
||||
n = (n-1)*2;
|
||||
}
|
||||
if (v[im].valence < 0) {
|
||||
nm = (nm-1)*2;
|
||||
}
|
||||
if (v[ip].valence < 0) {
|
||||
np = (np-1)*2;
|
||||
}
|
||||
|
||||
if (v[i].valence > 2) {
|
||||
result.Ep = v[i].P + v[i].e0*cosfn(n, start) + v[i].e1*sinfn(n, start);
|
||||
result.Em = v[i].P + v[i].e0*cosfn(n, prev ) + v[i].e1*sinfn(n, prev);
|
||||
|
||||
float s1=3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2=2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
|
||||
} else if (v[i].valence < -2) {
|
||||
int j = (valence + start - v[i].zerothNeighbor) % valence;
|
||||
|
||||
result.Ep = v[i].P + cos((M_PI*j)/float(valence-1))*v[i].e0 + sin((M_PI*j)/float(valence-1))*v[i].e1;
|
||||
j = (valence + prev - v[i].zerothNeighbor) % valence;
|
||||
result.Em = v[i].P + cos((M_PI*j)/float(valence-1))*v[i].e0 + sin((M_PI*j)/float(valence-1))*v[i].e1;
|
||||
|
||||
vec3 Rp = ((-2.0f * v[i].org - 1.0f * v[im].org) + (2.0f * v[ip].org + 1.0f * v[(i+2)%4].org))/3.0f;
|
||||
vec3 Rm = ((-2.0f * v[i].org - 1.0f * v[ip].org) + (2.0f * v[im].org + 1.0f * v[(i+2)%4].org))/3.0f;
|
||||
|
||||
float s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2 = 2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
|
||||
if (v[im].valence < 0) {
|
||||
s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
result.Fp = result.Fm = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
} else if (v[ip].valence < 0) {
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/n)-cos(2.0f*M_PI/nm);
|
||||
result.Fm = result.Fp = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
}
|
||||
|
||||
} else if (v[i].valence == -2) {
|
||||
result.Ep = (2.0f * v[i].org + v[ip].org)/3.0f;
|
||||
result.Em = (2.0f * v[i].org + v[im].org)/3.0f;
|
||||
result.Fp = result.Fm = (4.0f * v[i].org + v[(i+2)%n].org + 2.0f * v[ip].org + 2.0f * v[im].org)/9.0f;
|
||||
}
|
||||
|
||||
#else // not OSD_PATCH_GREGORY_BOUNDARY
|
||||
|
||||
result.Ep = v[i].P + v[i].e0 * cosfn(n, start) + v[i].e1*sinfn(n, start);
|
||||
result.Em = v[i].P + v[i].e0 * cosfn(n, prev ) + v[i].e1*sinfn(n, prev);
|
||||
|
||||
vec3 Em_ip = v[ip].P + v[ip].e0 * cosfn(np, prev_p ) + v[ip].e1*sinfn(np, prev_p);
|
||||
vec3 Ep_im = v[im].P + v[im].e0 * cosfn(nm, start_m) + v[im].e1*sinfn(nm, start_m);
|
||||
|
||||
float s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2 = 2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Legacy Face-varying
|
||||
// ----------------------------------------------------------------------------
|
||||
uniform samplerBuffer OsdFVarDataBuffer;
|
||||
|
||||
#ifndef OSD_FVAR_WIDTH
|
||||
#define OSD_FVAR_WIDTH 0
|
||||
#endif
|
||||
|
||||
// ------ extract from quads (catmark, bilinear) ---------
|
||||
// XXX: only linear interpolation is supported
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_1(result, fvarOffset, tessCoord) \
|
||||
{ \
|
||||
float v[4]; \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 4; \
|
||||
for (int i = 0; i < 4; ++i) { \
|
||||
int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
v[i] = texelFetch(OsdFVarDataBuffer, index).s \
|
||||
} \
|
||||
result = mix(mix(v[0], v[1], tessCoord.s), \
|
||||
mix(v[3], v[2], tessCoord.s), \
|
||||
tessCoord.t); \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_2(result, fvarOffset, tessCoord) \
|
||||
{ \
|
||||
vec2 v[4]; \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 4; \
|
||||
for (int i = 0; i < 4; ++i) { \
|
||||
int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
v[i] = vec2(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s); \
|
||||
} \
|
||||
result = mix(mix(v[0], v[1], tessCoord.s), \
|
||||
mix(v[3], v[2], tessCoord.s), \
|
||||
tessCoord.t); \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_3(result, fvarOffset, tessCoord) \
|
||||
{ \
|
||||
vec3 v[4]; \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 4; \
|
||||
for (int i = 0; i < 4; ++i) { \
|
||||
int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
v[i] = vec3(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 2).s); \
|
||||
} \
|
||||
result = mix(mix(v[0], v[1], tessCoord.s), \
|
||||
mix(v[3], v[2], tessCoord.s), \
|
||||
tessCoord.t); \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_4(result, fvarOffset, tessCoord) \
|
||||
{ \
|
||||
vec4 v[4]; \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 4; \
|
||||
for (int i = 0; i < 4; ++i) { \
|
||||
int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
v[i] = vec4(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 2).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 3).s); \
|
||||
} \
|
||||
result = mix(mix(v[0], v[1], tessCoord.s), \
|
||||
mix(v[3], v[2], tessCoord.s), \
|
||||
tessCoord.t); \
|
||||
}
|
||||
|
||||
// ------ extract from triangles barycentric (loop) ---------
|
||||
// XXX: no interpolation supported
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_TRI_1(result, fvarOffset, triVert) \
|
||||
{ \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 3; \
|
||||
int index = (primOffset+triVert)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
result = texelFetch(OsdFVarDataBuffer, index).s; \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_TRI_2(result, fvarOffset, triVert) \
|
||||
{ \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 3; \
|
||||
int index = (primOffset+triVert)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
result = vec2(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s); \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_TRI_3(result, fvarOffset, triVert) \
|
||||
{ \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 3; \
|
||||
int index = (primOffset+triVert)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
result = vec3(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 2).s); \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_TRI_4(result, fvarOffset, triVert) \
|
||||
{ \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 3; \
|
||||
int index = (primOffset+triVert)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
result = vec4(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 2).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 3).s); \
|
||||
}
|
||||
|
||||
206
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchShaderSource.cpp
vendored
Normal file
206
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchShaderSource.cpp
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/glslPatchShaderSource.h"
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static const char *commonShaderSource =
|
||||
#include "glslPatchCommon.gen.h"
|
||||
;
|
||||
static const char *commonTessShaderSource =
|
||||
#include "glslPatchCommonTess.gen.h"
|
||||
;
|
||||
static const char *patchLegacyShaderSource =
|
||||
#include "glslPatchLegacy.gen.h"
|
||||
;
|
||||
static const char *patchBasisTypesShaderSource =
|
||||
#include "patchBasisTypes.gen.h"
|
||||
;
|
||||
static const char *patchBasisShaderSource =
|
||||
#include "patchBasis.gen.h"
|
||||
;
|
||||
static const char *boxSplineTriangleShaderSource =
|
||||
#include "glslPatchBoxSplineTriangle.gen.h"
|
||||
;
|
||||
static const char *bsplineShaderSource =
|
||||
#include "glslPatchBSpline.gen.h"
|
||||
;
|
||||
static const char *gregoryShaderSource =
|
||||
#include "glslPatchGregory.gen.h"
|
||||
;
|
||||
static const char *gregoryBasisShaderSource =
|
||||
#include "glslPatchGregoryBasis.gen.h"
|
||||
;
|
||||
static const char *gregoryTriangleShaderSource =
|
||||
#include "glslPatchGregoryTriangle.gen.h"
|
||||
;
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
GLSLPatchShaderSource::GetPatchDrawingShaderSource() {
|
||||
std::stringstream ss;
|
||||
ss << std::string(commonShaderSource);
|
||||
ss << std::string(commonTessShaderSource);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
GLSLPatchShaderSource::GetCommonShaderSource() {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchDrawingShaderSource();
|
||||
ss << std::string(patchLegacyShaderSource);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
GLSLPatchShaderSource::GetPatchBasisShaderSource() {
|
||||
std::stringstream ss;
|
||||
#if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES)
|
||||
ss << "#define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES\n";
|
||||
#endif
|
||||
ss << std::string(patchBasisTypesShaderSource);
|
||||
ss << std::string(patchBasisShaderSource);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
GLSLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type) {
|
||||
std::stringstream ss;
|
||||
switch (type) {
|
||||
case Far::PatchDescriptor::REGULAR:
|
||||
ss << "#define OSD_PATCH_BSPLINE\n"
|
||||
<< "#define OSD_PATCH_VERTEX_BSPLINE_SHADER\n"
|
||||
<< bsplineShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::LOOP:
|
||||
ss << "#define OSD_PATCH_BOX_SPLINE_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_VERTEX_BOX_SPLINE_TRIANGLE_SHADER\n"
|
||||
<< boxSplineTriangleShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
ss << "#define OSD_PATCH_GREGORY\n"
|
||||
<< "#define OSD_PATCH_VERTEX_GREGORY_SHADER\n"
|
||||
<< gregoryShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY:
|
||||
ss << "#define OSD_PATCH_GREGORY_BOUNDARY\n"
|
||||
<< "#define OSD_PATCH_VERTEX_GREGORY_SHADER\n"
|
||||
<< gregoryShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||
ss << "#define OSD_PATCH_GREGORY_BASIS\n"
|
||||
<< "#define OSD_PATCH_VERTEX_GREGORY_BASIS_SHADER\n"
|
||||
<< gregoryBasisShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_TRIANGLE:
|
||||
ss << "#define OSD_PATCH_GREGORY_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_VERTEX_GREGORY_TRIANGLE_SHADER\n"
|
||||
<< gregoryTriangleShaderSource;
|
||||
break;
|
||||
default:
|
||||
break; // returns empty (points, lines, quads, ...)
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
GLSLPatchShaderSource::GetTessControlShaderSource(
|
||||
Far::PatchDescriptor::Type type) {
|
||||
std::stringstream ss;
|
||||
switch (type) {
|
||||
case Far::PatchDescriptor::REGULAR:
|
||||
ss << "#define OSD_PATCH_BSPLINE\n"
|
||||
<< "#define OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER\n"
|
||||
<< bsplineShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::LOOP:
|
||||
ss << "#define OSD_PATCH_BOX_SPLINE_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_TESS_CONTROL_BOX_SPLINE_TRIANGLE_SHADER\n"
|
||||
<< boxSplineTriangleShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
ss << "#define OSD_PATCH_GREGORY\n"
|
||||
<< "#define OSD_PATCH_TESS_CONTROL_GREGORY_SHADER\n"
|
||||
<< gregoryShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY:
|
||||
ss << "#define OSD_PATCH_GREGORY_BOUNDARY\n"
|
||||
<< "#define OSD_PATCH_TESS_CONTROL_GREGORY_SHADER\n"
|
||||
<< gregoryShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||
ss << "#define OSD_PATCH_GREGORY_BASIS\n"
|
||||
<< "#define OSD_PATCH_TESS_CONTROL_GREGORY_BASIS_SHADER\n"
|
||||
<< gregoryBasisShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_TRIANGLE:
|
||||
ss << "#define OSD_PATCH_GREGORY_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_TESS_CONTROL_GREGORY_TRIANGLE_SHADER\n"
|
||||
<< gregoryTriangleShaderSource;
|
||||
break;
|
||||
default:
|
||||
break; // returns empty (points, lines, quads, ...)
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
GLSLPatchShaderSource::GetTessEvalShaderSource(
|
||||
Far::PatchDescriptor::Type type) {
|
||||
std::stringstream ss;
|
||||
switch (type) {
|
||||
case Far::PatchDescriptor::REGULAR:
|
||||
ss << "#define OSD_PATCH_BSPLINE\n"
|
||||
<< "#define OSD_PATCH_TESS_EVAL_BSPLINE_SHADER\n"
|
||||
<< bsplineShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::LOOP:
|
||||
ss << "#define OSD_PATCH_BOX_SPLINE_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_TESS_EVAL_BOX_SPLINE_TRIANGLE_SHADER\n"
|
||||
<< boxSplineTriangleShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
ss << "#define OSD_PATCH_GREGORY\n"
|
||||
<< "#define OSD_PATCH_TESS_EVAL_GREGORY_SHADER\n"
|
||||
<< gregoryShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY:
|
||||
ss << "#define OSD_PATCH_GREGORY_BOUNDARY\n"
|
||||
<< "#define OSD_PATCH_TESS_EVAL_GREGORY_SHADER\n"
|
||||
<< gregoryShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||
ss << "#define OSD_PATCH_GREGORY_BASIS\n"
|
||||
<< "#define OSD_PATCH_TESS_EVAL_GREGORY_BASIS_SHADER\n"
|
||||
<< gregoryBasisShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_TRIANGLE:
|
||||
ss << "#define OSD_PATCH_GREGORY_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_TESS_EVAL_GREGORY_TRIANGLE_SHADER\n"
|
||||
<< gregoryTriangleShaderSource;
|
||||
break;
|
||||
default:
|
||||
break; // returns empty (points, lines, quads, ...)
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
64
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchShaderSource.h
vendored
Normal file
64
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslPatchShaderSource.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_GLSL_PATCH_SHADER_SOURCE_H
|
||||
#define OPENSUBDIV3_OSD_GLSL_PATCH_SHADER_SOURCE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/patchDescriptor.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Provides shader source which can be used by client code.
|
||||
class GLSLPatchShaderSource {
|
||||
public:
|
||||
/// \brief Returns shader source which can be used to evaluate
|
||||
/// position and first and second derivatives on piecewise parametric
|
||||
/// patches resulting from subdivision refinement.
|
||||
static std::string GetPatchBasisShaderSource();
|
||||
|
||||
/// \brief Returns shader source which can be used while drawing
|
||||
/// piecewise parametric patches resulting from subdivision refinement,
|
||||
/// e.g. while using GPU HW tessellation.
|
||||
static std::string GetPatchDrawingShaderSource();
|
||||
|
||||
/// \name Alternative methods
|
||||
/// \{
|
||||
/// These methods return shader source which can be used
|
||||
/// while drawing. Unlike the methods above, the source returned
|
||||
/// by these methods includes support for legacy patch types along
|
||||
/// with dependencies on specific resource bindings and interstage
|
||||
/// shader variable declarations.
|
||||
|
||||
static std::string GetCommonShaderSource();
|
||||
|
||||
static std::string GetVertexShaderSource(
|
||||
Far::PatchDescriptor::Type type);
|
||||
|
||||
static std::string GetTessControlShaderSource(
|
||||
Far::PatchDescriptor::Type type);
|
||||
|
||||
static std::string GetTessEvalShaderSource(
|
||||
Far::PatchDescriptor::Type type);
|
||||
|
||||
/// \}
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_GLSL_PATCH_SHADER_SOURCE
|
||||
277
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslXFBKernel.glsl
vendored
Normal file
277
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/glslXFBKernel.glsl
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
uniform samplerBuffer vertexBuffer;
|
||||
uniform int srcOffset = 0;
|
||||
out float outVertexBuffer[LENGTH];
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct Vertex {
|
||||
float vertexData[LENGTH];
|
||||
};
|
||||
|
||||
void clear(out Vertex v) {
|
||||
for (int i = 0; i < LENGTH; i++) {
|
||||
v.vertexData[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void addWithWeight(inout Vertex v, Vertex src, float weight) {
|
||||
for(int j = 0; j < LENGTH; j++) {
|
||||
v.vertexData[j] += weight * src.vertexData[j];
|
||||
}
|
||||
}
|
||||
|
||||
Vertex readVertex(int index) {
|
||||
Vertex v;
|
||||
int vertexIndex = srcOffset + index * SRC_STRIDE;
|
||||
for(int j = 0; j < LENGTH; j++) {
|
||||
v.vertexData[j] = texelFetch(vertexBuffer, vertexIndex+j).x;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void writeVertex(Vertex v) {
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
outVertexBuffer[i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_USE_1ST_DERIVATIVES) && \
|
||||
defined(OPENSUBDIV_GLSL_XFB_INTERLEAVED_1ST_DERIVATIVE_BUFFERS)
|
||||
out float outDeriv1Buffer[2*LENGTH];
|
||||
|
||||
void writeDu(Vertex v) {
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
outDeriv1Buffer[i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDv(Vertex v) {
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
outDeriv1Buffer[i+LENGTH] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
#elif defined(OPENSUBDIV_GLSL_XFB_USE_1ST_DERIVATIVES)
|
||||
out float outDuBuffer[LENGTH];
|
||||
out float outDvBuffer[LENGTH];
|
||||
|
||||
void writeDu(Vertex v) {
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
outDuBuffer[i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDv(Vertex v) {
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
outDvBuffer[i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_USE_2ND_DERIVATIVES) && \
|
||||
defined(OPENSUBDIV_GLSL_XFB_INTERLEAVED_2ND_DERIVATIVE_BUFFERS)
|
||||
out float outDeriv2Buffer[3*LENGTH];
|
||||
|
||||
void writeDuu(Vertex v) {
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
outDeriv2Buffer[i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDuv(Vertex v) {
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
outDeriv2Buffer[i+LENGTH] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDvv(Vertex v) {
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
outDeriv2Buffer[i+2*LENGTH] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
#elif defined(OPENSUBDIV_GLSL_XFB_USE_2ND_DERIVATIVES)
|
||||
out float outDuuBuffer[LENGTH];
|
||||
out float outDuvBuffer[LENGTH];
|
||||
out float outDvvBuffer[LENGTH];
|
||||
|
||||
void writeDuu(Vertex v) {
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
outDuuBuffer[i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDuv(Vertex v) {
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
outDuvBuffer[i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDvv(Vertex v) {
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
outDvvBuffer[i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_KERNEL_EVAL_STENCILS)
|
||||
|
||||
uniform usamplerBuffer sizes;
|
||||
uniform isamplerBuffer offsets;
|
||||
uniform isamplerBuffer indices;
|
||||
uniform samplerBuffer weights;
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_USE_1ST_DERIVATIVES)
|
||||
uniform samplerBuffer duWeights;
|
||||
uniform samplerBuffer dvWeights;
|
||||
#endif
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_USE_2ND_DERIVATIVES)
|
||||
uniform samplerBuffer duuWeights;
|
||||
uniform samplerBuffer duvWeights;
|
||||
uniform samplerBuffer dvvWeights;
|
||||
#endif
|
||||
|
||||
uniform int batchStart = 0;
|
||||
uniform int batchEnd = 0;
|
||||
|
||||
void main() {
|
||||
int current = gl_VertexID + batchStart;
|
||||
|
||||
if (current>=batchEnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vertex dst, du, dv, duu, duv, dvv;
|
||||
clear(dst);
|
||||
clear(du);
|
||||
clear(dv);
|
||||
clear(duu);
|
||||
clear(duv);
|
||||
clear(dvv);
|
||||
|
||||
int offset = texelFetch(offsets, current).x;
|
||||
uint size = texelFetch(sizes, current).x;
|
||||
|
||||
for (int stencil=0; stencil<size; ++stencil) {
|
||||
int index = texelFetch(indices, offset+stencil).x;
|
||||
float weight = texelFetch(weights, offset+stencil).x;
|
||||
addWithWeight(dst, readVertex( index ), weight);
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_USE_1ST_DERIVATIVES)
|
||||
float duWeight = texelFetch(duWeights, offset+stencil).x;
|
||||
float dvWeight = texelFetch(dvWeights, offset+stencil).x;
|
||||
addWithWeight(du, readVertex(index), duWeight);
|
||||
addWithWeight(dv, readVertex(index), dvWeight);
|
||||
#endif
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_USE_2ND_DERIVATIVES)
|
||||
float duuWeight = texelFetch(duuWeights, offset+stencil).x;
|
||||
float duvWeight = texelFetch(duvWeights, offset+stencil).x;
|
||||
float dvvWeight = texelFetch(dvvWeights, offset+stencil).x;
|
||||
addWithWeight(duu, readVertex(index), duuWeight);
|
||||
addWithWeight(duv, readVertex(index), duvWeight);
|
||||
addWithWeight(dvv, readVertex(index), dvvWeight);
|
||||
#endif
|
||||
}
|
||||
writeVertex(dst);
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_USE_1ST_DERIVATIVES)
|
||||
writeDu(du);
|
||||
writeDv(dv);
|
||||
#endif
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_USE_2ND_DERIVATIVES)
|
||||
writeDuu(duu);
|
||||
writeDuv(duv);
|
||||
writeDvv(dvv);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_KERNEL_EVAL_PATCHES)
|
||||
|
||||
layout (location = 0) in ivec3 patchHandles;
|
||||
layout (location = 1) in vec2 patchCoords;
|
||||
|
||||
layout (std140) uniform PatchArrays {
|
||||
OsdPatchArray patchArrays[2];
|
||||
};
|
||||
uniform isamplerBuffer patchParamBuffer;
|
||||
uniform isamplerBuffer patchIndexBuffer;
|
||||
|
||||
OsdPatchArray GetPatchArray(int arrayIndex) {
|
||||
return patchArrays[arrayIndex];
|
||||
}
|
||||
|
||||
OsdPatchParam GetPatchParam(int patchIndex) {
|
||||
ivec3 patchParamBits = texelFetch(patchParamBuffer, patchIndex).xyz;
|
||||
return OsdPatchParamInit(patchParamBits.x, patchParamBits.y, patchParamBits.z);
|
||||
}
|
||||
|
||||
void main() {
|
||||
int current = gl_VertexID;
|
||||
|
||||
ivec3 handle = patchHandles;
|
||||
int arrayIndex = handle.x;
|
||||
int patchIndex = handle.y;
|
||||
|
||||
vec2 coord = patchCoords;
|
||||
|
||||
OsdPatchArray array = GetPatchArray(arrayIndex);
|
||||
OsdPatchParam param = GetPatchParam(patchIndex);
|
||||
|
||||
int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
|
||||
|
||||
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
|
||||
int nPoints = OsdEvaluatePatchBasis(patchType, param,
|
||||
coord.x, coord.y, wP, wDu, wDv, wDuu, wDuv, wDvv);
|
||||
|
||||
Vertex dst, du, dv, duu, duv, dvv;
|
||||
clear(dst);
|
||||
clear(du);
|
||||
clear(dv);
|
||||
clear(duu);
|
||||
clear(duv);
|
||||
clear(dvv);
|
||||
|
||||
int indexBase = array.indexBase + array.stride *
|
||||
(patchIndex - array.primitiveIdBase);
|
||||
|
||||
for (int cv = 0; cv < nPoints; ++cv) {
|
||||
int index = texelFetch(patchIndexBuffer, indexBase + cv).x;
|
||||
addWithWeight(dst, readVertex(index), wP[cv]);
|
||||
addWithWeight(du, readVertex(index), wDu[cv]);
|
||||
addWithWeight(dv, readVertex(index), wDv[cv]);
|
||||
addWithWeight(duu, readVertex(index), wDuu[cv]);
|
||||
addWithWeight(duv, readVertex(index), wDuv[cv]);
|
||||
addWithWeight(dvv, readVertex(index), wDvv[cv]);
|
||||
}
|
||||
|
||||
writeVertex(dst);
|
||||
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_USE_1ST_DERIVATIVES)
|
||||
writeDu(du);
|
||||
writeDv(dv);
|
||||
#endif
|
||||
#if defined(OPENSUBDIV_GLSL_XFB_USE_2ND_DERIVATIVES)
|
||||
writeDuu(duu);
|
||||
writeDuv(duv);
|
||||
writeDvv(dvv);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
134
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslComputeKernel.hlsl
vendored
Normal file
134
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslComputeKernel.hlsl
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
cbuffer KernelUniformArgs : register( b0 ) {
|
||||
int batchStart;
|
||||
int batchEnd;
|
||||
int srcOffset;
|
||||
int dstOffset;
|
||||
};
|
||||
|
||||
RWBuffer<float> vertexBuffer : register( u0 );
|
||||
RWBuffer<float> dstVertexBuffer : register( u1 );
|
||||
Buffer<int> sizes : register( t1 );
|
||||
Buffer<int> offsets : register( t2 );
|
||||
Buffer<int> indices : register( t3 );
|
||||
Buffer<float> weights : register( t4 );
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
struct Vertex {
|
||||
float vertexData[LENGTH];
|
||||
};
|
||||
|
||||
void clear(out Vertex v) {
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vertex readVertex(int index) {
|
||||
Vertex v;
|
||||
int vertexIndex = srcOffset + index * SRC_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] = vertexBuffer[vertexIndex + i];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void writeVertex(int index, Vertex v) {
|
||||
int vertexIndex = dstOffset + index * DST_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
vertexBuffer[vertexIndex + i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeVertexSeparate(int index, Vertex v) {
|
||||
int vertexIndex = dstOffset + index * DST_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dstVertexBuffer[vertexIndex + i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void addWithWeight(inout Vertex v, const Vertex src, float weight) {
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] += weight * src.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
interface IComputeKernel {
|
||||
void runKernel( uint3 ID );
|
||||
};
|
||||
IComputeKernel kernel;
|
||||
|
||||
class SingleBufferCompute : IComputeKernel {
|
||||
|
||||
int placeholder;
|
||||
void runKernel(uint3 ID) {
|
||||
int current = int(ID.x) + batchStart;
|
||||
|
||||
if (current>=batchEnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vertex dst;
|
||||
clear(dst);
|
||||
|
||||
int offset = offsets[current],
|
||||
size = sizes[current];
|
||||
|
||||
for (int i=0; i<size; ++i) {
|
||||
addWithWeight(dst, readVertex( indices[offset+i] ), weights[offset+i]);
|
||||
}
|
||||
|
||||
writeVertex(current, dst);
|
||||
}
|
||||
};
|
||||
class SeparateBufferCompute : IComputeKernel {
|
||||
|
||||
int placeholder;
|
||||
void runKernel(uint3 ID) {
|
||||
int current = int(ID.x) + batchStart;
|
||||
|
||||
if (current>=batchEnd) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vertex dst;
|
||||
clear(dst);
|
||||
|
||||
int offset = offsets[current],
|
||||
size = sizes[current];
|
||||
|
||||
for (int i=0; i<size; ++i) {
|
||||
addWithWeight(dst, readVertex( indices[offset+i] ), weights[offset+i]);
|
||||
}
|
||||
|
||||
writeVertexSeparate(current, dst);
|
||||
}
|
||||
};
|
||||
|
||||
SingleBufferCompute singleBufferCompute;
|
||||
SeparateBufferCompute separateBufferCompute;
|
||||
|
||||
// Add place-holder stencil kernel or D3D11ShaderReflection::GetInterfaceSlots()
|
||||
// returns 0
|
||||
class PlaceHolder : IComputeKernel {
|
||||
int placeholder;
|
||||
void runKernel( uint3 ID ) {
|
||||
}
|
||||
};
|
||||
|
||||
[numthreads(WORK_GROUP_SIZE, 1, 1)]
|
||||
void cs_main( uint3 ID : SV_DispatchThreadID )
|
||||
{
|
||||
// call kernel
|
||||
kernel.runKernel(ID);
|
||||
}
|
||||
|
||||
137
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchBSpline.hlsl
vendored
Normal file
137
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchBSpline.hlsl
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexBSpline
|
||||
//----------------------------------------------------------
|
||||
|
||||
void vs_main_patches( in InputVertex input,
|
||||
out HullVertex output )
|
||||
{
|
||||
output.position = input.position;
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(input.position);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.HullBSpline
|
||||
//----------------------------------------------------------
|
||||
|
||||
[domain("quad")]
|
||||
[partitioning(OSD_PARTITIONING)]
|
||||
[outputtopology("triangle_cw")]
|
||||
[outputcontrolpoints(16)]
|
||||
[patchconstantfunc("HSConstFunc")]
|
||||
OsdPerPatchVertexBezier hs_main_patches(
|
||||
in InputPatch<HullVertex, 16> patch,
|
||||
uint primitiveID : SV_PrimitiveID,
|
||||
in uint ID : SV_OutputControlPointID )
|
||||
{
|
||||
OsdPerPatchVertexBezier output;
|
||||
|
||||
float3 cv[16];
|
||||
for (int i=0; i<16; ++i) {
|
||||
cv[i] = patch[i].position.xyz;
|
||||
}
|
||||
|
||||
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
||||
OsdComputePerPatchVertexBSpline(patchParam, ID, cv, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
HS_CONSTANT_FUNC_OUT
|
||||
HSConstFunc(
|
||||
InputPatch<HullVertex, 16> patch,
|
||||
OutputPatch<OsdPerPatchVertexBezier, 16> bezierPatch,
|
||||
uint primitiveID : SV_PrimitiveID)
|
||||
{
|
||||
HS_CONSTANT_FUNC_OUT output;
|
||||
|
||||
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
||||
|
||||
float4 tessLevelOuter = float4(0,0,0,0);
|
||||
float2 tessLevelInner = float2(0,0);
|
||||
float4 tessOuterLo = float4(0,0,0,0);
|
||||
float4 tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
OSD_PATCH_CULL(16);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
OsdPerPatchVertexBezier cpBezier[16];
|
||||
for (int i=0; i<16; ++i) {
|
||||
cpBezier[i] = bezierPatch[i];
|
||||
cpBezier[i].P += 0.0f;
|
||||
}
|
||||
OsdEvalPatchBezierTessLevels(cpBezier, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(patchParam, tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
output.tessLevelOuter[0] = tessLevelOuter[0];
|
||||
output.tessLevelOuter[1] = tessLevelOuter[1];
|
||||
output.tessLevelOuter[2] = tessLevelOuter[2];
|
||||
output.tessLevelOuter[3] = tessLevelOuter[3];
|
||||
|
||||
output.tessLevelInner[0] = tessLevelInner[0];
|
||||
output.tessLevelInner[1] = tessLevelInner[1];
|
||||
|
||||
output.tessOuterLo = tessOuterLo;
|
||||
output.tessOuterHi = tessOuterHi;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.DomainBSpline
|
||||
//----------------------------------------------------------
|
||||
|
||||
[domain("quad")]
|
||||
void ds_main_patches(
|
||||
in HS_CONSTANT_FUNC_OUT input,
|
||||
in OutputPatch<OsdPerPatchVertexBezier, 16> patch,
|
||||
in float2 domainCoord : SV_DomainLocation,
|
||||
out OutputVertex output )
|
||||
{
|
||||
float3 P = float3(0,0,0), dPu = float3(0,0,0), dPv = float3(0,0,0);
|
||||
float3 N = float3(0,0,0), dNu = float3(0,0,0), dNv = float3(0,0,0);
|
||||
|
||||
OsdPerPatchVertexBezier cv[16];
|
||||
for (int i=0; i<16; ++i) {
|
||||
cv[i] = patch[i];
|
||||
}
|
||||
|
||||
float2 UV = OsdGetTessParameterization(domainCoord,
|
||||
input.tessOuterLo,
|
||||
input.tessOuterHi);
|
||||
|
||||
int3 patchParam = patch[0].patchParam;
|
||||
OsdEvalPatchBezier(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
output.position = mul(OsdModelViewMatrix(), float4(P, 1.0f));
|
||||
output.normal = mul(OsdModelViewMatrix(), float4(N, 0.0f)).xyz;
|
||||
output.tangent = mul(OsdModelViewMatrix(), float4(dPu, 0.0f)).xyz;
|
||||
output.bitangent = mul(OsdModelViewMatrix(), float4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
output.vSegments = cv[0].vSegments;
|
||||
#endif
|
||||
|
||||
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
output.positionOut = mul(OsdProjectionMatrix(), output.position);
|
||||
output.edgeDistance = 0;
|
||||
}
|
||||
130
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchBoxSplineTriangle.hlsl
vendored
Normal file
130
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchBoxSplineTriangle.hlsl
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
//
|
||||
// Copyright 2019 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexBoxSplineTriangle
|
||||
//----------------------------------------------------------
|
||||
|
||||
void vs_main_patches( in InputVertex input,
|
||||
out HullVertex output )
|
||||
{
|
||||
output.position = input.position;
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(input.position);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.HullBoxSplineTriangle
|
||||
//----------------------------------------------------------
|
||||
|
||||
[domain("tri")]
|
||||
[partitioning(OSD_PARTITIONING)]
|
||||
[outputtopology("triangle_cw")]
|
||||
[outputcontrolpoints(15)]
|
||||
[patchconstantfunc("HSConstFunc")]
|
||||
OsdPerPatchVertexBezier hs_main_patches(
|
||||
in InputPatch<HullVertex, 12> patch,
|
||||
uint primitiveID : SV_PrimitiveID,
|
||||
in uint ID : SV_OutputControlPointID )
|
||||
{
|
||||
OsdPerPatchVertexBezier output;
|
||||
|
||||
float3 cv[12];
|
||||
for (int i=0; i<12; ++i) {
|
||||
cv[i] = patch[i].position.xyz;
|
||||
}
|
||||
|
||||
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
||||
OsdComputePerPatchVertexBoxSplineTriangle(patchParam, ID, cv, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
HS_CONSTANT_FUNC_TRIANGLE_OUT
|
||||
HSConstFunc(
|
||||
InputPatch<HullVertex, 12> patch,
|
||||
OutputPatch<OsdPerPatchVertexBezier, 15> bezierTrianglePatch,
|
||||
uint primitiveID : SV_PrimitiveID)
|
||||
{
|
||||
HS_CONSTANT_FUNC_TRIANGLE_OUT output;
|
||||
|
||||
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
||||
|
||||
float4 tessLevelOuter = float4(0,0,0,0);
|
||||
float2 tessLevelInner = float2(0,0);
|
||||
float4 tessOuterLo = float4(0,0,0,0);
|
||||
float4 tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
OSD_PATCH_CULL_TRIANGLE(12);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
float3 bezcv[15];
|
||||
for (int i=0; i<15; ++i) {
|
||||
bezcv[i] = bezierTrianglePatch[i].P;
|
||||
}
|
||||
OsdEvalPatchBezierTriangleTessLevels(bezcv, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniformTriangle(patchParam, tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
output.tessLevelOuter[0] = tessLevelOuter[0];
|
||||
output.tessLevelOuter[1] = tessLevelOuter[1];
|
||||
output.tessLevelOuter[2] = tessLevelOuter[2];
|
||||
|
||||
output.tessLevelInner[0] = tessLevelInner[0];
|
||||
|
||||
output.tessOuterLo = tessOuterLo;
|
||||
output.tessOuterHi = tessOuterHi;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.DomainBoxSplineTriangle
|
||||
//----------------------------------------------------------
|
||||
|
||||
[domain("tri")]
|
||||
void ds_main_patches(
|
||||
in HS_CONSTANT_FUNC_TRIANGLE_OUT input,
|
||||
in OutputPatch<OsdPerPatchVertexBezier, 15> patch,
|
||||
in float3 domainCoord : SV_DomainLocation,
|
||||
out OutputVertex output )
|
||||
{
|
||||
float3 P = float3(0,0,0), dPu = float3(0,0,0), dPv = float3(0,0,0);
|
||||
float3 N = float3(0,0,0), dNu = float3(0,0,0), dNv = float3(0,0,0);
|
||||
|
||||
OsdPerPatchVertexBezier cv[15];
|
||||
for (int i=0; i<15; ++i) {
|
||||
cv[i] = patch[i];
|
||||
}
|
||||
|
||||
float2 UV = OsdGetTessParameterizationTriangle(domainCoord,
|
||||
input.tessOuterLo,
|
||||
input.tessOuterHi);
|
||||
|
||||
int3 patchParam = patch[0].patchParam;
|
||||
OsdEvalPatchBezierTriangle(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
output.position = mul(OsdModelViewMatrix(), float4(P, 1.0f));
|
||||
output.normal = mul(OsdModelViewMatrix(), float4(N, 0.0f)).xyz;
|
||||
output.tangent = mul(OsdModelViewMatrix(), float4(dPu, 0.0f)).xyz;
|
||||
output.bitangent = mul(OsdModelViewMatrix(), float4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
|
||||
output.patchCoord = OsdInterpolatePatchCoordTriangle(UV, patchParam);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
output.positionOut = mul(OsdProjectionMatrix(), output.position);
|
||||
output.edgeDistance = 0;
|
||||
}
|
||||
1107
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchCommon.hlsl
vendored
Normal file
1107
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchCommon.hlsl
vendored
Normal file
File diff suppressed because it is too large
Load Diff
733
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchCommonTess.hlsl
vendored
Normal file
733
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchCommonTess.hlsl
vendored
Normal file
@@ -0,0 +1,733 @@
|
||||
//
|
||||
// Copyright 2013-2019 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Tessellation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// For now, fractional spacing is supported only with screen space tessellation
|
||||
#ifndef OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
#undef OSD_FRACTIONAL_EVEN_SPACING
|
||||
#undef OSD_FRACTIONAL_ODD_SPACING
|
||||
#endif
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
#define OSD_PARTITIONING "fractional_even"
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
#define OSD_PARTITIONING "fractional_odd"
|
||||
#else
|
||||
#define OSD_PARTITIONING "integer"
|
||||
#endif
|
||||
|
||||
struct HS_CONSTANT_FUNC_OUT {
|
||||
float tessLevelInner[2] : SV_InsideTessFactor;
|
||||
float tessLevelOuter[4] : SV_TessFactor;
|
||||
float4 tessOuterLo : TRANSITIONLO;
|
||||
float4 tessOuterHi : TRANSITIONHI;
|
||||
};
|
||||
|
||||
struct HS_CONSTANT_FUNC_TRIANGLE_OUT {
|
||||
float tessLevelInner[1] : SV_InsideTessFactor;
|
||||
float tessLevelOuter[3] : SV_TessFactor;
|
||||
float4 tessOuterLo : TRANSITIONLO;
|
||||
float4 tessOuterHi : TRANSITIONHI;
|
||||
};
|
||||
|
||||
//
|
||||
// Organization of B-spline and Bezier control points.
|
||||
//
|
||||
// Each patch is defined by 16 control points (labeled 0-15).
|
||||
//
|
||||
// The patch will be evaluated across the domain from (0,0) at
|
||||
// the lower-left to (1,1) at the upper-right. When computing
|
||||
// adaptive tessellation metrics, we consider refined vertex-vertex
|
||||
// and edge-vertex points along the transition edges of the patch
|
||||
// (labeled vv* and ev* respectively).
|
||||
//
|
||||
// The two segments of each transition edge are labeled Lo and Hi,
|
||||
// with the Lo segment occurring before the Hi segment along the
|
||||
// transition edge's domain parameterization. These Lo and Hi segment
|
||||
// tessellation levels determine how domain evaluation coordinates
|
||||
// are remapped along transition edges. The Hi segment value will
|
||||
// be zero for a non-transition edge.
|
||||
//
|
||||
// (0,1) (1,1)
|
||||
//
|
||||
// vv3 ev23 vv2
|
||||
// | Lo3 | Hi3 |
|
||||
// --O-----------O-----+-----O-----------O--
|
||||
// | 12 | 13 14 | 15 |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// Hi0 | | | | Hi2
|
||||
// | | | |
|
||||
// O-----------O-----------O-----------O
|
||||
// | 8 | 9 10 | 11 |
|
||||
// | | | |
|
||||
// ev03 --+ | | +-- ev12
|
||||
// | | | |
|
||||
// | 4 | 5 6 | 7 |
|
||||
// O-----------O-----------O-----------O
|
||||
// | | | |
|
||||
// Lo0 | | | | Lo2
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | 0 | 1 2 | 3 |
|
||||
// --O-----------O-----+-----O-----------O--
|
||||
// | Lo1 | Hi1 |
|
||||
// vv0 ev01 vv1
|
||||
//
|
||||
// (0,0) (1,0)
|
||||
//
|
||||
|
||||
#define OSD_MAX_TESS_LEVEL 64
|
||||
|
||||
float OsdComputePostProjectionSphereExtent(float3 center, float diameter)
|
||||
{
|
||||
float4 p = mul(OsdProjectionMatrix(), float4(center, 1.0));
|
||||
return abs(diameter * OsdProjectionMatrix()[1][1] / p.w);
|
||||
}
|
||||
|
||||
float OsdComputeTessLevel(float3 p0, float3 p1)
|
||||
{
|
||||
// Adaptive factor can be any computation that depends only on arg values.
|
||||
// Project the diameter of the edge's bounding sphere instead of using the
|
||||
// length of the projected edge itself to avoid problems near silhouettes.
|
||||
p0 = mul(OsdModelViewMatrix(), float4(p0, 1.0)).xyz;
|
||||
p1 = mul(OsdModelViewMatrix(), float4(p1, 1.0)).xyz;
|
||||
float3 center = (p0 + p1) / 2.0;
|
||||
float diameter = distance(p0, p1);
|
||||
float projLength = OsdComputePostProjectionSphereExtent(center, diameter);
|
||||
float tessLevel = max(1.0, OsdTessLevel() * projLength);
|
||||
|
||||
// We restrict adaptive tessellation levels to half of the device
|
||||
// supported maximum because transition edges are split into two
|
||||
// halves and the sum of the two corresponding levels must not exceed
|
||||
// the device maximum. We impose this limit even for non-transition
|
||||
// edges because a non-transition edge must be able to match up with
|
||||
// one half of the transition edge of an adjacent transition patch.
|
||||
return min(tessLevel, OSD_MAX_TESS_LEVEL / 2);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniform(int3 patchParam,
|
||||
out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
// Uniform factors are simple powers of two for each level.
|
||||
// The maximum here can be increased if we know the maximum
|
||||
// refinement level of the mesh:
|
||||
// min(OSD_MAX_TESS_LEVEL, pow(2, MaximumRefinementLevel-1)
|
||||
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
|
||||
float tessLevel = min(OsdTessLevel(), OSD_MAX_TESS_LEVEL) /
|
||||
pow(2, refinementLevel-1);
|
||||
|
||||
// tessLevels of transition edge should be clamped to 2.
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
float4 tessLevelMin = float4(1,1,1,1)
|
||||
+ float4(((transitionMask & 8) >> 3),
|
||||
((transitionMask & 1) >> 0),
|
||||
((transitionMask & 2) >> 1),
|
||||
((transitionMask & 4) >> 2));
|
||||
|
||||
tessOuterLo = max(float4(tessLevel,tessLevel,tessLevel,tessLevel),
|
||||
tessLevelMin);
|
||||
tessOuterHi = float4(0,0,0,0);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniformTriangle(int3 patchParam,
|
||||
out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
// Uniform factors are simple powers of two for each level.
|
||||
// The maximum here can be increased if we know the maximum
|
||||
// refinement level of the mesh:
|
||||
// min(OSD_MAX_TESS_LEVEL, pow(2, MaximumRefinementLevel-1)
|
||||
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
|
||||
float tessLevel = min(OsdTessLevel(), OSD_MAX_TESS_LEVEL) /
|
||||
pow(2, refinementLevel-1);
|
||||
|
||||
// tessLevels of transition edge should be clamped to 2.
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
float4 tessLevelMin = float4(1,1,1,1)
|
||||
+ float4(((transitionMask & 4) >> 2),
|
||||
((transitionMask & 1) >> 0),
|
||||
((transitionMask & 2) >> 1),
|
||||
0);
|
||||
|
||||
tessOuterLo = max(float4(tessLevel,tessLevel,tessLevel,tessLevel),
|
||||
tessLevelMin);
|
||||
tessOuterHi = float4(0,0,0,0);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsRefinedPoints(float3 cp[16], int3 patchParam,
|
||||
out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. We compute the corresponding
|
||||
// vertex-vertex and edge-vertex refined points along the edges of the
|
||||
// patch using Catmull-Clark subdivision stencil weights.
|
||||
// For simplicity, we let the optimizer discard unused computation.
|
||||
|
||||
float3 vv0 = (cp[0] + cp[2] + cp[8] + cp[10]) * 0.015625 +
|
||||
(cp[1] + cp[4] + cp[6] + cp[9]) * 0.09375 + cp[5] * 0.5625;
|
||||
float3 ev01 = (cp[1] + cp[2] + cp[9] + cp[10]) * 0.0625 +
|
||||
(cp[5] + cp[6]) * 0.375;
|
||||
|
||||
float3 vv1 = (cp[1] + cp[3] + cp[9] + cp[11]) * 0.015625 +
|
||||
(cp[2] + cp[5] + cp[7] + cp[10]) * 0.09375 + cp[6] * 0.5625;
|
||||
float3 ev12 = (cp[5] + cp[7] + cp[9] + cp[11]) * 0.0625 +
|
||||
(cp[6] + cp[10]) * 0.375;
|
||||
|
||||
float3 vv2 = (cp[5] + cp[7] + cp[13] + cp[15]) * 0.015625 +
|
||||
(cp[6] + cp[9] + cp[11] + cp[14]) * 0.09375 + cp[10] * 0.5625;
|
||||
float3 ev23 = (cp[5] + cp[6] + cp[13] + cp[14]) * 0.0625 +
|
||||
(cp[9] + cp[10]) * 0.375;
|
||||
|
||||
float3 vv3 = (cp[4] + cp[6] + cp[12] + cp[14]) * 0.015625 +
|
||||
(cp[5] + cp[8] + cp[10] + cp[13]) * 0.09375 + cp[9] * 0.5625;
|
||||
float3 ev03 = (cp[4] + cp[6] + cp[8] + cp[10]) * 0.0625 +
|
||||
(cp[5] + cp[9]) * 0.375;
|
||||
|
||||
tessOuterLo = float4(0,0,0,0);
|
||||
tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 8) != 0) {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(vv0, ev03);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(vv3, ev03);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cp[5], cp[9]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(vv0, ev01);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(vv1, ev01);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cp[5], cp[6]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(vv1, ev12);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(vv2, ev12);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cp[6], cp[10]);
|
||||
}
|
||||
if ((transitionMask & 4) != 0) {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(vv3, ev23);
|
||||
tessOuterHi[3] = OsdComputeTessLevel(vv2, ev23);
|
||||
} else {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(cp[9], cp[10]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Patch boundary corners are ordered counter-clockwise from the first
|
||||
// corner while patch boundary edges and their midpoints are similarly
|
||||
// ordered counter-clockwise beginning at the edge preceding corner[0].
|
||||
//
|
||||
void
|
||||
Osd_GetTessLevelsFromPatchBoundaries4(float3 corners[4], float3 midpoints[4],
|
||||
int3 patchParam, out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
tessOuterLo = float4(0,0,0,0);
|
||||
tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 8) != 0) {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(corners[0], midpoints[0]);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(corners[3], midpoints[0]);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(corners[0], corners[3]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(corners[0], midpoints[1]);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(corners[1], midpoints[1]);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(corners[0], corners[1]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(corners[1], midpoints[2]);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(corners[2], midpoints[2]);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(corners[1], corners[2]);
|
||||
}
|
||||
if ((transitionMask & 4) != 0) {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(corners[3], midpoints[3]);
|
||||
tessOuterHi[3] = OsdComputeTessLevel(corners[2], midpoints[3]);
|
||||
} else {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(corners[3], corners[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Osd_GetTessLevelsFromPatchBoundaries3(float3 corners[3], float3 midpoints[3],
|
||||
int3 patchParam, out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
tessOuterLo = float4(0,0,0,0);
|
||||
tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 4) != 0) {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(corners[0], midpoints[0]);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(corners[2], midpoints[0]);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(corners[0], corners[2]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(corners[0], midpoints[1]);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(corners[1], midpoints[1]);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(corners[0], corners[1]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(corners[2], midpoints[2]);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(corners[1], midpoints[2]);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(corners[1], corners[2]);
|
||||
}
|
||||
}
|
||||
|
||||
float3
|
||||
Osd_EvalBezierCurveMidPoint(float3 p0, float3 p1, float3 p2, float3 p3)
|
||||
{
|
||||
// Coefficients for the midpoint are { 1/8, 3/8, 3/8, 1/8 }:
|
||||
return 0.125 * (p0 + p3) + 0.375 * (p1 + p2);
|
||||
}
|
||||
|
||||
float3
|
||||
Osd_EvalQuarticBezierCurveMidPoint(float3 p0, float3 p1, float3 p2, float3 p3, float3 p4)
|
||||
{
|
||||
// Coefficients for the midpoint are { 1/16, 1/4, 3/8, 1/4, 1/16 }:
|
||||
return 0.0625 * (p0 + p4) + 0.25 * (p1 + p3) + 0.375 * p2;
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTessLevels(OsdPerPatchVertexBezier cpBezier[16],
|
||||
int3 patchParam, out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. When the patch control
|
||||
// points have been converted to the Bezier basis, the control points
|
||||
// at the four corners are on the limit surface (since a Bezier patch
|
||||
// interpolates its corner control points). We can compute an adaptive
|
||||
// tessellation level for transition edges on the limit surface by
|
||||
// evaluating a limit position at the mid point of each transition edge.
|
||||
|
||||
tessOuterLo = float4(0,0,0,0);
|
||||
tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
float3 corners[4];
|
||||
float3 midpoints[4];
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
corners[0] = OsdEvalBezier(cpBezier, patchParam, float2(0.0, 0.0));
|
||||
corners[1] = OsdEvalBezier(cpBezier, patchParam, float2(1.0, 0.0));
|
||||
corners[2] = OsdEvalBezier(cpBezier, patchParam, float2(1.0, 1.0));
|
||||
corners[3] = OsdEvalBezier(cpBezier, patchParam, float2(0.0, 1.0));
|
||||
|
||||
midpoints[0] = ((transitionMask & 8) == 0) ? float3(0,0,0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, float2(0.0, 0.5));
|
||||
midpoints[1] = ((transitionMask & 1) == 0) ? float3(0,0,0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, float2(0.5, 0.0));
|
||||
midpoints[2] = ((transitionMask & 2) == 0) ? float3(0,0,0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, float2(1.0, 0.5));
|
||||
midpoints[3] = ((transitionMask & 4) == 0) ? float3(0,0,0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, float2(0.5, 1.0));
|
||||
#else
|
||||
corners[0] = cpBezier[ 0].P;
|
||||
corners[1] = cpBezier[ 3].P;
|
||||
corners[2] = cpBezier[15].P;
|
||||
corners[3] = cpBezier[12].P;
|
||||
|
||||
midpoints[0] = ((transitionMask & 8) == 0) ? float3(0,0,0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[0].P, cpBezier[4].P, cpBezier[8].P, cpBezier[12].P);
|
||||
midpoints[1] = ((transitionMask & 1) == 0) ? float3(0,0,0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[0].P, cpBezier[1].P, cpBezier[2].P, cpBezier[3].P);
|
||||
midpoints[2] = ((transitionMask & 2) == 0) ? float3(0,0,0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[3].P, cpBezier[7].P, cpBezier[11].P, cpBezier[15].P);
|
||||
midpoints[3] = ((transitionMask & 4) == 0) ? float3(0,0,0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[12].P, cpBezier[13].P, cpBezier[14].P, cpBezier[15].P);
|
||||
#endif
|
||||
|
||||
Osd_GetTessLevelsFromPatchBoundaries4(corners, midpoints,
|
||||
patchParam, tessOuterLo, tessOuterHi);
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTriangleTessLevels(float3 cv[15],
|
||||
int3 patchParam, out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. When the patch control
|
||||
// points have been converted to the Bezier basis, the control points
|
||||
// at the corners are on the limit surface (since a Bezier patch
|
||||
// interpolates its corner control points). We can compute an adaptive
|
||||
// tessellation level for transition edges on the limit surface by
|
||||
// evaluating a limit position at the mid point of each transition edge.
|
||||
|
||||
tessOuterLo = float4(0,0,0,0);
|
||||
tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
float3 corners[3];
|
||||
corners[0] = cv[0];
|
||||
corners[1] = cv[4];
|
||||
corners[2] = cv[14];
|
||||
|
||||
float3 midpoints[3];
|
||||
midpoints[0] = ((transitionMask & 4) == 0) ? float3(0,0,0) :
|
||||
Osd_EvalQuarticBezierCurveMidPoint(cv[0], cv[5], cv[9], cv[12], cv[14]);
|
||||
midpoints[1] = ((transitionMask & 1) == 0) ? float3(0,0,0) :
|
||||
Osd_EvalQuarticBezierCurveMidPoint(cv[0], cv[1], cv[2], cv[3], cv[4]);
|
||||
midpoints[2] = ((transitionMask & 2) == 0) ? float3(0,0,0) :
|
||||
Osd_EvalQuarticBezierCurveMidPoint(cv[4], cv[8], cv[11], cv[13], cv[14]);
|
||||
|
||||
Osd_GetTessLevelsFromPatchBoundaries3(corners, midpoints,
|
||||
patchParam, tessOuterLo, tessOuterHi);
|
||||
}
|
||||
|
||||
// Round up to the nearest even integer
|
||||
float OsdRoundUpEven(float x) {
|
||||
return 2*ceil(x/2);
|
||||
}
|
||||
|
||||
// Round up to the nearest odd integer
|
||||
float OsdRoundUpOdd(float x) {
|
||||
return 2*ceil((x+1)/2)-1;
|
||||
}
|
||||
|
||||
// Compute outer and inner tessellation levels taking into account the
|
||||
// current tessellation spacing mode.
|
||||
void
|
||||
OsdComputeTessLevels(inout float4 tessOuterLo, inout float4 tessOuterHi,
|
||||
out float4 tessLevelOuter, out float2 tessLevelInner)
|
||||
{
|
||||
// Outer levels are the sum of the Lo and Hi segments where the Hi
|
||||
// segments will have lengths of zero for non-transition edges.
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
// Combine fractional outer transition edge levels before rounding.
|
||||
float4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
|
||||
// Round the segments of transition edges separately. We will recover the
|
||||
// fractional parameterization of transition edges after tessellation.
|
||||
|
||||
tessLevelOuter = combinedOuter;
|
||||
if (tessOuterHi[0] > 0) {
|
||||
tessLevelOuter[0] =
|
||||
OsdRoundUpEven(tessOuterLo[0]) + OsdRoundUpEven(tessOuterHi[0]);
|
||||
}
|
||||
if (tessOuterHi[1] > 0) {
|
||||
tessLevelOuter[1] =
|
||||
OsdRoundUpEven(tessOuterLo[1]) + OsdRoundUpEven(tessOuterHi[1]);
|
||||
}
|
||||
if (tessOuterHi[2] > 0) {
|
||||
tessLevelOuter[2] =
|
||||
OsdRoundUpEven(tessOuterLo[2]) + OsdRoundUpEven(tessOuterHi[2]);
|
||||
}
|
||||
if (tessOuterHi[3] > 0) {
|
||||
tessLevelOuter[3] =
|
||||
OsdRoundUpEven(tessOuterLo[3]) + OsdRoundUpEven(tessOuterHi[3]);
|
||||
}
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
// Combine fractional outer transition edge levels before rounding.
|
||||
float4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
|
||||
// Round the segments of transition edges separately. We will recover the
|
||||
// fractional parameterization of transition edges after tessellation.
|
||||
//
|
||||
// The sum of the two outer odd segment lengths will be an even number
|
||||
// which the tessellator will increase by +1 so that there will be a
|
||||
// total odd number of segments. We clamp the combinedOuter tess levels
|
||||
// (used to compute the inner tess levels) so that the outer transition
|
||||
// edges will be sampled without degenerate triangles.
|
||||
|
||||
tessLevelOuter = combinedOuter;
|
||||
if (tessOuterHi[0] > 0) {
|
||||
tessLevelOuter[0] =
|
||||
OsdRoundUpOdd(tessOuterLo[0]) + OsdRoundUpOdd(tessOuterHi[0]);
|
||||
combinedOuter = max(float4(3,3,3,3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[1] > 0) {
|
||||
tessLevelOuter[1] =
|
||||
OsdRoundUpOdd(tessOuterLo[1]) + OsdRoundUpOdd(tessOuterHi[1]);
|
||||
combinedOuter = max(float4(3,3,3,3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[2] > 0) {
|
||||
tessLevelOuter[2] =
|
||||
OsdRoundUpOdd(tessOuterLo[2]) + OsdRoundUpOdd(tessOuterHi[2]);
|
||||
combinedOuter = max(float4(3,3,3,3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[3] > 0) {
|
||||
tessLevelOuter[3] =
|
||||
OsdRoundUpOdd(tessOuterLo[3]) + OsdRoundUpOdd(tessOuterHi[3]);
|
||||
combinedOuter = max(float4(3,3,3,3), combinedOuter);
|
||||
}
|
||||
#else
|
||||
// Round equally spaced transition edge levels before combining.
|
||||
tessOuterLo = round(tessOuterLo);
|
||||
tessOuterHi = round(tessOuterHi);
|
||||
|
||||
float4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
tessLevelOuter = combinedOuter;
|
||||
#endif
|
||||
|
||||
// Inner levels are the averages the corresponding outer levels.
|
||||
tessLevelInner[0] = (combinedOuter[1] + combinedOuter[3]) * 0.5;
|
||||
tessLevelInner[1] = (combinedOuter[0] + combinedOuter[2]) * 0.5;
|
||||
}
|
||||
|
||||
void
|
||||
OsdComputeTessLevelsTriangle(inout float4 tessOuterLo, inout float4 tessOuterHi,
|
||||
out float4 tessLevelOuter, out float2 tessLevelInner)
|
||||
{
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
|
||||
// Inner level is the max of the three outer levels.
|
||||
tessLevelInner[0] = max(max(tessLevelOuter[0],
|
||||
tessLevelOuter[1]),
|
||||
tessLevelOuter[2]);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniform(int3 patchParam,
|
||||
out float4 tessLevelOuter, out float2 tessLevelInner,
|
||||
out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsUniform(patchParam, tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniformTriangle(int3 patchParam,
|
||||
out float4 tessLevelOuter, out float2 tessLevelInner,
|
||||
out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsUniformTriangle(patchParam, tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevelsTriangle(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTessLevels(OsdPerPatchVertexBezier cpBezier[16],
|
||||
int3 patchParam,
|
||||
out float4 tessLevelOuter, out float2 tessLevelInner,
|
||||
out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
OsdEvalPatchBezierTessLevels(cpBezier, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTriangleTessLevels(float3 cv[15],
|
||||
int3 patchParam,
|
||||
out float4 tessLevelOuter, out float2 tessLevelInner,
|
||||
out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
OsdEvalPatchBezierTriangleTessLevels(cv, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevelsTriangle(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsAdaptiveRefinedPoints(float3 cpRefined[16], int3 patchParam,
|
||||
out float4 tessLevelOuter, out float2 tessLevelInner,
|
||||
out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsRefinedPoints(cpRefined, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
// Deprecated -- prefer use of newer Bezier patch equivalend:
|
||||
void
|
||||
OsdGetTessLevelsLimitPoints(OsdPerPatchVertexBezier cpBezier[16],
|
||||
int3 patchParam, out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
OsdEvalPatchBezierTessLevels(cpBezier, patchParam, tessOuterLo, tessOuterHi);
|
||||
}
|
||||
|
||||
// Deprecated -- prefer use of newer Bezier patch equivalent:
|
||||
void
|
||||
OsdGetTessLevelsAdaptiveLimitPoints(OsdPerPatchVertexBezier cpBezier[16],
|
||||
int3 patchParam,
|
||||
out float4 tessLevelOuter, out float2 tessLevelInner,
|
||||
out float4 tessOuterLo, out float4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsLimitPoints(cpBezier, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
// Deprecated -- prefer use of newer Bezier patch equivalent:
|
||||
void
|
||||
OsdGetTessLevels(float3 cp0, float3 cp1, float3 cp2, float3 cp3,
|
||||
int3 patchParam,
|
||||
out float4 tessLevelOuter, out float2 tessLevelInner)
|
||||
{
|
||||
float4 tessOuterLo = float4(0,0,0,0);
|
||||
float4 tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cp0, cp1);
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cp0, cp3);
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cp2, cp3);
|
||||
tessOuterLo[3] = OsdComputeTessLevel(cp1, cp2);
|
||||
tessOuterHi = float4(0,0,0,0);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(patchParam, tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING || defined OSD_FRACTIONAL_ODD_SPACING
|
||||
float
|
||||
OsdGetTessFractionalSplit(float t, float level, float levelUp)
|
||||
{
|
||||
// Fractional tessellation of an edge will produce n segments where n
|
||||
// is the tessellation level of the edge (level) rounded up to the
|
||||
// nearest even or odd integer (levelUp). There will be n-2 segments of
|
||||
// equal length (dx1) and two additional segments of equal length (dx0)
|
||||
// that are typically shorter than the other segments. The two additional
|
||||
// segments should be placed symmetrically on opposite sides of the
|
||||
// edge (offset).
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
if (level <= 2) return t;
|
||||
|
||||
float base = pow(2.0,floor(log2(levelUp)));
|
||||
float offset = 1.0/(int(2*base-levelUp)/2 & int(base/2-1));
|
||||
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
if (level <= 1) return t;
|
||||
|
||||
float base = pow(2.0,floor(log2(levelUp)));
|
||||
float offset = 1.0/(((int(2*base-levelUp)/2+1) & int(base/2-1))+1);
|
||||
#endif
|
||||
|
||||
float dx0 = (1.0 - (levelUp-level)/2) / levelUp;
|
||||
float dx1 = (1.0 - 2.0*dx0) / (levelUp - 2.0*ceil(dx0));
|
||||
|
||||
if (t < 0.5) {
|
||||
float x = levelUp/2 - round(t*levelUp);
|
||||
return 0.5 - (x*dx1 + int(x*offset > 1) * (dx0 - dx1));
|
||||
} else if (t > 0.5) {
|
||||
float x = round(t*levelUp) - levelUp/2;
|
||||
return 0.5 + (x*dx1 + int(x*offset > 1) * (dx0 - dx1));
|
||||
} else {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
float
|
||||
OsdGetTessTransitionSplit(float t, float lo, float hi)
|
||||
{
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
float loRoundUp = OsdRoundUpEven(lo);
|
||||
float hiRoundUp = OsdRoundUpEven(hi);
|
||||
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
float ti = round(t * (loRoundUp + hiRoundUp));
|
||||
|
||||
if (ti <= loRoundUp) {
|
||||
float t0 = ti / loRoundUp;
|
||||
return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5;
|
||||
} else {
|
||||
float t1 = (ti - loRoundUp) / hiRoundUp;
|
||||
return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5;
|
||||
}
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
float loRoundUp = OsdRoundUpOdd(lo);
|
||||
float hiRoundUp = OsdRoundUpOdd(hi);
|
||||
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
// The +1 below is to account for the extra segment produced by the
|
||||
// tessellator since the sum of two odd tess levels will be rounded
|
||||
// up by one to the next odd integer tess level.
|
||||
float ti = round(t * (loRoundUp + hiRoundUp + 1));
|
||||
|
||||
if (ti <= loRoundUp) {
|
||||
float t0 = ti / loRoundUp;
|
||||
return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5;
|
||||
} else if (ti > (loRoundUp+1)) {
|
||||
float t1 = (ti - (loRoundUp+1)) / hiRoundUp;
|
||||
return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5;
|
||||
} else {
|
||||
return 0.5;
|
||||
}
|
||||
#else
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
float ti = round(t * (lo + hi));
|
||||
|
||||
if (ti <= lo) {
|
||||
return (ti / lo) * 0.5;
|
||||
} else {
|
||||
return ((ti - lo) / hi) * 0.5 + 0.5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float2
|
||||
OsdGetTessParameterization(float2 p, float4 tessOuterLo, float4 tessOuterHi)
|
||||
{
|
||||
float2 UV = p;
|
||||
if (p.x == 0 && tessOuterHi[0] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[0], tessOuterHi[0]);
|
||||
} else
|
||||
if (p.y == 0 && tessOuterHi[1] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[1], tessOuterHi[1]);
|
||||
} else
|
||||
if (p.x == 1 && tessOuterHi[2] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[2], tessOuterHi[2]);
|
||||
} else
|
||||
if (p.y == 1 && tessOuterHi[3] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[3], tessOuterHi[3]);
|
||||
}
|
||||
return UV;
|
||||
}
|
||||
|
||||
float2
|
||||
OsdGetTessParameterizationTriangle(float3 p, float4 tessOuterLo, float4 tessOuterHi)
|
||||
{
|
||||
float2 UV = p.xy;
|
||||
if (p.x == 0 && tessOuterHi[0] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[0], tessOuterHi[0]);
|
||||
} else
|
||||
if (p.y == 0 && tessOuterHi[1] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[1], tessOuterHi[1]);
|
||||
} else
|
||||
if (p.z == 0 && tessOuterHi[2] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[2], tessOuterHi[2]);
|
||||
UV.y = 1.0 - UV.x;
|
||||
}
|
||||
return UV;
|
||||
}
|
||||
169
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchGregory.hlsl
vendored
Normal file
169
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchGregory.hlsl
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexGregory
|
||||
//----------------------------------------------------------
|
||||
|
||||
void vs_main_patches( in InputVertex input,
|
||||
uint vID : SV_VertexID,
|
||||
out OsdPerVertexGregory output )
|
||||
{
|
||||
OsdComputePerVertexGregory(vID, input.position, output);
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(input.position);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.HullGregory
|
||||
//----------------------------------------------------------
|
||||
|
||||
[domain("quad")]
|
||||
[partitioning(OSD_PARTITIONING)]
|
||||
[outputtopology("triangle_cw")]
|
||||
[outputcontrolpoints(4)]
|
||||
[patchconstantfunc("HSConstFunc")]
|
||||
OsdPerPatchVertexGregory hs_main_patches(
|
||||
in InputPatch<OsdPerVertexGregory, 4> patch,
|
||||
uint primitiveID : SV_PrimitiveID,
|
||||
in uint ID : SV_OutputControlPointID )
|
||||
{
|
||||
OsdPerPatchVertexGregory output;
|
||||
|
||||
OsdPerVertexGregory cv[4];
|
||||
for (int i=0; i<4; ++i) {
|
||||
cv[i] = patch[i];
|
||||
}
|
||||
|
||||
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
||||
OsdComputePerPatchVertexGregory(patchParam, ID, primitiveID, cv, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
HS_CONSTANT_FUNC_OUT HSConstFunc(
|
||||
InputPatch<OsdPerVertexGregory, 4> patch,
|
||||
OutputPatch<OsdPerPatchVertexGregory, 4> gregoryPatch,
|
||||
uint primitiveID : SV_PrimitiveID)
|
||||
{
|
||||
HS_CONSTANT_FUNC_OUT output;
|
||||
|
||||
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
||||
|
||||
float4 tessLevelOuter = float4(0,0,0,0);
|
||||
float2 tessLevelInner = float2(0,0);
|
||||
float4 tessOuterLo = float4(0,0,0,0);
|
||||
float4 tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
OSD_PATCH_CULL(4);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
OsdPerPatchVertexBezier bezcv[16];
|
||||
bezcv[ 0].P = gregoryPatch[0].P;
|
||||
bezcv[ 1].P = gregoryPatch[0].Ep;
|
||||
bezcv[ 2].P = gregoryPatch[1].Em;
|
||||
bezcv[ 3].P = gregoryPatch[1].P;
|
||||
bezcv[ 4].P = gregoryPatch[0].Em;
|
||||
bezcv[ 5].P = gregoryPatch[0].Fp;
|
||||
bezcv[ 6].P = gregoryPatch[1].Fm;
|
||||
bezcv[ 7].P = gregoryPatch[1].Ep;
|
||||
bezcv[ 8].P = gregoryPatch[3].Ep;
|
||||
bezcv[ 9].P = gregoryPatch[3].Fm;
|
||||
bezcv[10].P = gregoryPatch[2].Fp;
|
||||
bezcv[11].P = gregoryPatch[2].Em;
|
||||
bezcv[12].P = gregoryPatch[3].P;
|
||||
bezcv[13].P = gregoryPatch[3].Em;
|
||||
bezcv[14].P = gregoryPatch[2].Ep;
|
||||
bezcv[15].P = gregoryPatch[2].P;
|
||||
|
||||
OsdEvalPatchBezierTessLevels(bezcv, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(patchParam, tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
#endif
|
||||
|
||||
output.tessLevelOuter[0] = tessLevelOuter[0];
|
||||
output.tessLevelOuter[1] = tessLevelOuter[1];
|
||||
output.tessLevelOuter[2] = tessLevelOuter[2];
|
||||
output.tessLevelOuter[3] = tessLevelOuter[3];
|
||||
|
||||
output.tessLevelInner[0] = tessLevelInner[0];
|
||||
output.tessLevelInner[1] = tessLevelInner[1];
|
||||
|
||||
output.tessOuterLo = tessOuterLo;
|
||||
output.tessOuterHi = tessOuterHi;
|
||||
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.DomainGregory
|
||||
//----------------------------------------------------------
|
||||
|
||||
[domain("quad")]
|
||||
void ds_main_patches(
|
||||
in HS_CONSTANT_FUNC_OUT input,
|
||||
in OutputPatch<OsdPerPatchVertexGregory, 4> patch,
|
||||
in float2 domainCoord : SV_DomainLocation,
|
||||
out OutputVertex output )
|
||||
{
|
||||
float3 P = float3(0,0,0), dPu = float3(0,0,0), dPv = float3(0,0,0);
|
||||
float3 N = float3(0,0,0), dNu = float3(0,0,0), dNv = float3(0,0,0);
|
||||
|
||||
float3 cv[20];
|
||||
cv[0] = patch[0].P;
|
||||
cv[1] = patch[0].Ep;
|
||||
cv[2] = patch[0].Em;
|
||||
cv[3] = patch[0].Fp;
|
||||
cv[4] = patch[0].Fm;
|
||||
|
||||
cv[5] = patch[1].P;
|
||||
cv[6] = patch[1].Ep;
|
||||
cv[7] = patch[1].Em;
|
||||
cv[8] = patch[1].Fp;
|
||||
cv[9] = patch[1].Fm;
|
||||
|
||||
cv[10] = patch[2].P;
|
||||
cv[11] = patch[2].Ep;
|
||||
cv[12] = patch[2].Em;
|
||||
cv[13] = patch[2].Fp;
|
||||
cv[14] = patch[2].Fm;
|
||||
|
||||
cv[15] = patch[3].P;
|
||||
cv[16] = patch[3].Ep;
|
||||
cv[17] = patch[3].Em;
|
||||
cv[18] = patch[3].Fp;
|
||||
cv[19] = patch[3].Fm;
|
||||
|
||||
float2 UV = OsdGetTessParameterization(domainCoord,
|
||||
input.tessOuterLo,
|
||||
input.tessOuterHi);
|
||||
|
||||
int3 patchParam = patch[0].patchParam;
|
||||
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
output.position = mul(OsdModelViewMatrix(), float4(P, 1.0f));
|
||||
output.normal = mul(OsdModelViewMatrix(), float4(N, 0.0f)).xyz;
|
||||
output.tangent = mul(OsdModelViewMatrix(), float4(dPu, 0.0f)).xyz;
|
||||
output.bitangent = mul(OsdModelViewMatrix(), float4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
|
||||
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
output.positionOut = mul(OsdProjectionMatrix(), output.position);
|
||||
output.edgeDistance = 0;
|
||||
}
|
||||
149
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchGregoryBasis.hlsl
vendored
Normal file
149
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchGregoryBasis.hlsl
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexGregoryBasis
|
||||
//----------------------------------------------------------
|
||||
|
||||
void vs_main_patches( in InputVertex input,
|
||||
out HullVertex output )
|
||||
{
|
||||
output.position = input.position;
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(input.position);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.HullGregoryBasis
|
||||
//----------------------------------------------------------
|
||||
|
||||
[domain("quad")]
|
||||
[partitioning(OSD_PARTITIONING)]
|
||||
[outputtopology("triangle_cw")]
|
||||
[outputcontrolpoints(20)]
|
||||
[patchconstantfunc("HSConstFunc")]
|
||||
OsdPerPatchVertexGregoryBasis hs_main_patches(
|
||||
in InputPatch<HullVertex, 20> patch,
|
||||
uint primitiveID : SV_PrimitiveID,
|
||||
in uint ID : SV_OutputControlPointID )
|
||||
{
|
||||
OsdPerPatchVertexGregoryBasis output;
|
||||
|
||||
float3 cv = patch[ID].position.xyz;
|
||||
|
||||
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
||||
OsdComputePerPatchVertexGregoryBasis(patchParam, ID, cv, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
HS_CONSTANT_FUNC_OUT
|
||||
HSConstFunc(
|
||||
InputPatch<HullVertex, 20> patch,
|
||||
uint primitiveID : SV_PrimitiveID)
|
||||
{
|
||||
HS_CONSTANT_FUNC_OUT output;
|
||||
|
||||
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
||||
|
||||
float4 tessLevelOuter = float4(0,0,0,0);
|
||||
float2 tessLevelInner = float2(0,0);
|
||||
float4 tessOuterLo = float4(0,0,0,0);
|
||||
float4 tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
OSD_PATCH_CULL(20);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
OsdPerPatchVertexBezier bezcv[16];
|
||||
bezcv[ 0].P = patch[ 0].position.xyz;
|
||||
bezcv[ 1].P = patch[ 1].position.xyz;
|
||||
bezcv[ 2].P = patch[ 7].position.xyz;
|
||||
bezcv[ 3].P = patch[ 5].position.xyz;
|
||||
bezcv[ 4].P = patch[ 2].position.xyz;
|
||||
bezcv[ 5].P = patch[ 3].position.xyz;
|
||||
bezcv[ 6].P = patch[ 8].position.xyz;
|
||||
bezcv[ 7].P = patch[ 6].position.xyz;
|
||||
bezcv[ 8].P = patch[16].position.xyz;
|
||||
bezcv[ 9].P = patch[18].position.xyz;
|
||||
bezcv[10].P = patch[13].position.xyz;
|
||||
bezcv[11].P = patch[12].position.xyz;
|
||||
bezcv[12].P = patch[15].position.xyz;
|
||||
bezcv[13].P = patch[17].position.xyz;
|
||||
bezcv[14].P = patch[11].position.xyz;
|
||||
bezcv[15].P = patch[10].position.xyz;
|
||||
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
bezcv, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(
|
||||
patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
output.tessLevelOuter[0] = tessLevelOuter[0];
|
||||
output.tessLevelOuter[1] = tessLevelOuter[1];
|
||||
output.tessLevelOuter[2] = tessLevelOuter[2];
|
||||
output.tessLevelOuter[3] = tessLevelOuter[3];
|
||||
|
||||
output.tessLevelInner[0] = tessLevelInner[0];
|
||||
output.tessLevelInner[1] = tessLevelInner[1];
|
||||
|
||||
output.tessOuterLo = tessOuterLo;
|
||||
output.tessOuterHi = tessOuterHi;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.DomainGregoryBasis
|
||||
//----------------------------------------------------------
|
||||
|
||||
[domain("quad")]
|
||||
void ds_main_patches(
|
||||
in HS_CONSTANT_FUNC_OUT input,
|
||||
in OutputPatch<OsdPerPatchVertexGregoryBasis, 20> patch,
|
||||
in float2 domainCoord : SV_DomainLocation,
|
||||
out OutputVertex output )
|
||||
{
|
||||
float3 P = float3(0,0,0), dPu = float3(0,0,0), dPv = float3(0,0,0);
|
||||
float3 N = float3(0,0,0), dNu = float3(0,0,0), dNv = float3(0,0,0);
|
||||
|
||||
float3 cv[20];
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
cv[i] = patch[i].P;
|
||||
}
|
||||
|
||||
float2 UV = OsdGetTessParameterization(domainCoord,
|
||||
input.tessOuterLo,
|
||||
input.tessOuterHi);
|
||||
|
||||
int3 patchParam = patch[0].patchParam;
|
||||
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
output.position = mul(OsdModelViewMatrix(), float4(P, 1.0f));
|
||||
output.normal = mul(OsdModelViewMatrix(), float4(N, 0.0f)).xyz;
|
||||
output.tangent = mul(OsdModelViewMatrix(), float4(dPu, 0.0f)).xyz;
|
||||
output.bitangent = mul(OsdModelViewMatrix(), float4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
output.vSegments = float2(0,0);
|
||||
#endif
|
||||
|
||||
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
output.positionOut = mul(OsdProjectionMatrix(), output.position);
|
||||
output.edgeDistance = 0;
|
||||
}
|
||||
143
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchGregoryTriangle.hlsl
vendored
Normal file
143
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchGregoryTriangle.hlsl
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
//
|
||||
// Copyright 2019 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexGregoryTriangle
|
||||
//----------------------------------------------------------
|
||||
|
||||
void vs_main_patches( in InputVertex input,
|
||||
out HullVertex output )
|
||||
{
|
||||
output.position = input.position;
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(input.position);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.HullGregoryTriangle
|
||||
//----------------------------------------------------------
|
||||
|
||||
[domain("tri")]
|
||||
[partitioning(OSD_PARTITIONING)]
|
||||
[outputtopology("triangle_cw")]
|
||||
[outputcontrolpoints(18)]
|
||||
[patchconstantfunc("HSConstFunc")]
|
||||
OsdPerPatchVertexGregoryBasis hs_main_patches(
|
||||
in InputPatch<HullVertex, 18> patch,
|
||||
uint primitiveID : SV_PrimitiveID,
|
||||
in uint ID : SV_OutputControlPointID )
|
||||
{
|
||||
OsdPerPatchVertexGregoryBasis output;
|
||||
|
||||
float3 cv = patch[ID].position.xyz;
|
||||
|
||||
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
||||
OsdComputePerPatchVertexGregoryBasis(patchParam, ID, cv, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
HS_CONSTANT_FUNC_TRIANGLE_OUT
|
||||
HSConstFunc(
|
||||
InputPatch<HullVertex, 18> patch,
|
||||
uint primitiveID : SV_PrimitiveID)
|
||||
{
|
||||
HS_CONSTANT_FUNC_TRIANGLE_OUT output;
|
||||
|
||||
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
||||
|
||||
float4 tessLevelOuter = float4(0,0,0,0);
|
||||
float2 tessLevelInner = float2(0,0);
|
||||
float4 tessOuterLo = float4(0,0,0,0);
|
||||
float4 tessOuterHi = float4(0,0,0,0);
|
||||
|
||||
OSD_PATCH_CULL_TRIANGLE(18);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
float3 cv[15];
|
||||
cv[ 0] = patch[ 0].position.xyz;
|
||||
cv[ 1] = patch[ 1].position.xyz;
|
||||
cv[ 2] = patch[15].position.xyz;
|
||||
cv[ 3] = patch[ 7].position.xyz;
|
||||
cv[ 4] = patch[ 5].position.xyz;
|
||||
cv[ 5] = patch[ 2].position.xyz;
|
||||
cv[ 6] = patch[ 3].position.xyz;
|
||||
cv[ 7] = patch[ 8].position.xyz;
|
||||
cv[ 8] = patch[ 6].position.xyz;
|
||||
cv[ 9] = patch[17].position.xyz;
|
||||
cv[10] = patch[13].position.xyz;
|
||||
cv[11] = patch[16].position.xyz;
|
||||
cv[12] = patch[11].position.xyz;
|
||||
cv[13] = patch[12].position.xyz;
|
||||
cv[14] = patch[10].position.xyz;
|
||||
|
||||
OsdEvalPatchBezierTriangleTessLevels(
|
||||
cv, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniformTriangle(
|
||||
patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
output.tessLevelOuter[0] = tessLevelOuter[0];
|
||||
output.tessLevelOuter[1] = tessLevelOuter[1];
|
||||
output.tessLevelOuter[2] = tessLevelOuter[2];
|
||||
|
||||
output.tessLevelInner[0] = tessLevelInner[0];
|
||||
|
||||
output.tessOuterLo = tessOuterLo;
|
||||
output.tessOuterHi = tessOuterHi;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.DomainGregoryTriangle
|
||||
//----------------------------------------------------------
|
||||
|
||||
[domain("tri")]
|
||||
void ds_main_patches(
|
||||
in HS_CONSTANT_FUNC_TRIANGLE_OUT input,
|
||||
in OutputPatch<OsdPerPatchVertexBezier, 18> patch,
|
||||
in float3 domainCoord : SV_DomainLocation,
|
||||
out OutputVertex output )
|
||||
{
|
||||
float3 P = float3(0,0,0), dPu = float3(0,0,0), dPv = float3(0,0,0);
|
||||
float3 N = float3(0,0,0), dNu = float3(0,0,0), dNv = float3(0,0,0);
|
||||
|
||||
float3 cv[18];
|
||||
for (int i = 0; i < 18; ++i) {
|
||||
cv[i] = patch[i].P;
|
||||
}
|
||||
|
||||
float2 UV = OsdGetTessParameterizationTriangle(domainCoord,
|
||||
input.tessOuterLo,
|
||||
input.tessOuterHi);
|
||||
|
||||
int3 patchParam = patch[0].patchParam;
|
||||
OsdEvalPatchGregoryTriangle(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
output.position = mul(OsdModelViewMatrix(), float4(P, 1.0f));
|
||||
output.normal = mul(OsdModelViewMatrix(), float4(N, 0.0f)).xyz;
|
||||
output.tangent = mul(OsdModelViewMatrix(), float4(dPu, 0.0f)).xyz;
|
||||
output.bitangent = mul(OsdModelViewMatrix(), float4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
|
||||
output.patchCoord = OsdInterpolatePatchCoordTriangle(UV, patchParam);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
output.positionOut = mul(OsdProjectionMatrix(), output.position);
|
||||
output.edgeDistance = 0;
|
||||
}
|
||||
509
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchLegacy.hlsl
vendored
Normal file
509
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchLegacy.hlsl
vendored
Normal file
@@ -0,0 +1,509 @@
|
||||
//
|
||||
// Copyright 2013-2019 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Common
|
||||
//----------------------------------------------------------
|
||||
|
||||
struct InputVertex {
|
||||
float4 position : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
};
|
||||
|
||||
struct HullVertex {
|
||||
float4 position : POSITION;
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
int3 clipFlag : CLIPFLAG;
|
||||
#endif
|
||||
};
|
||||
|
||||
// XXXdyu all downstream data can be handled by client code
|
||||
struct OutputVertex {
|
||||
float4 positionOut : SV_Position;
|
||||
float4 position : POSITION1;
|
||||
float3 normal : NORMAL;
|
||||
float3 tangent : TANGENT;
|
||||
float3 bitangent : TANGENT1;
|
||||
float4 patchCoord : PATCHCOORD; // u, v, faceLevel, faceId
|
||||
noperspective float4 edgeDistance : EDGEDISTANCE;
|
||||
#if defined(OSD_COMPUTE_NORMAL_DERIVATIVES)
|
||||
float3 Nu : TANGENT2;
|
||||
float3 Nv : TANGENT3;
|
||||
#endif
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
float2 vSegments : VSEGMENTS;
|
||||
#endif
|
||||
};
|
||||
|
||||
float4x4 OsdModelViewProjectionMatrix();
|
||||
int OsdGregoryQuadOffsetBase();
|
||||
int OsdPrimitiveIdBase();
|
||||
int OsdBaseVertex();
|
||||
|
||||
#ifndef OSD_DISPLACEMENT_CALLBACK
|
||||
#define OSD_DISPLACEMENT_CALLBACK
|
||||
#endif
|
||||
|
||||
// These are stored in OsdPatchParamBuffer indexed by the value returned
|
||||
// from OsdGetPatchIndex() which is a function of the current PrimitiveID
|
||||
// along with an optional client provided offset.
|
||||
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
Buffer<uint3> OsdPatchParamBuffer : register( t0 );
|
||||
#else
|
||||
Buffer<uint2> OsdPatchParamBuffer : register( t0 );
|
||||
#endif
|
||||
|
||||
int OsdGetPatchIndex(int primitiveId)
|
||||
{
|
||||
return (primitiveId + OsdPrimitiveIdBase());
|
||||
}
|
||||
|
||||
int3 OsdGetPatchParam(int patchIndex)
|
||||
{
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
return OsdPatchParamBuffer[patchIndex].xyz;
|
||||
#else
|
||||
uint2 p = OsdPatchParamBuffer[patchIndex].xy;
|
||||
return int3(p.x, p.y, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// patch culling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P) \
|
||||
float4 clipPos = mul(OsdModelViewProjectionMatrix(), P); \
|
||||
int3 clip0 = int3(clipPos.x < clipPos.w, \
|
||||
clipPos.y < clipPos.w, \
|
||||
clipPos.z < clipPos.w); \
|
||||
int3 clip1 = int3(clipPos.x > -clipPos.w, \
|
||||
clipPos.y > -clipPos.w, \
|
||||
clipPos.z > -clipPos.w); \
|
||||
output.clipFlag = int3(clip0) + 2*int3(clip1); \
|
||||
|
||||
#define OSD_PATCH_CULL(N) \
|
||||
int3 clipFlag = int3(0,0,0); \
|
||||
for(int i = 0; i < N; ++i) { \
|
||||
clipFlag |= patch[i].clipFlag; \
|
||||
} \
|
||||
if (any(clipFlag != int3(3,3,3))) { \
|
||||
output.tessLevelInner[0] = 0; \
|
||||
output.tessLevelInner[1] = 0; \
|
||||
output.tessLevelOuter[0] = 0; \
|
||||
output.tessLevelOuter[1] = 0; \
|
||||
output.tessLevelOuter[2] = 0; \
|
||||
output.tessLevelOuter[3] = 0; \
|
||||
output.tessOuterLo = float4(0,0,0,0); \
|
||||
output.tessOuterHi = float4(0,0,0,0); \
|
||||
return output; \
|
||||
}
|
||||
|
||||
#define OSD_PATCH_CULL_TRIANGLE(N) \
|
||||
int3 clipFlag = int3(0,0,0); \
|
||||
for(int i = 0; i < N; ++i) { \
|
||||
clipFlag |= patch[i].clipFlag; \
|
||||
} \
|
||||
if (any(clipFlag != int3(3,3,3))) { \
|
||||
output.tessLevelInner[0] = 0; \
|
||||
output.tessLevelOuter[0] = 0; \
|
||||
output.tessLevelOuter[1] = 0; \
|
||||
output.tessLevelOuter[2] = 0; \
|
||||
output.tessOuterLo = float4(0,0,0,0); \
|
||||
output.tessOuterHi = float4(0,0,0,0); \
|
||||
return output; \
|
||||
}
|
||||
|
||||
#else
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P)
|
||||
#define OSD_PATCH_CULL(N)
|
||||
#define OSD_PATCH_CULL_TRIANGLE(N)
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Legacy Gregory
|
||||
// ----------------------------------------------------------------------------
|
||||
#if defined(OSD_PATCH_GREGORY) || defined(OSD_PATCH_GREGORY_BOUNDARY)
|
||||
|
||||
#define M_PI 3.14159265359f
|
||||
|
||||
// precomputed catmark coefficient table up to valence 29
|
||||
static float OsdCatmarkCoefficient[30] = {
|
||||
0, 0, 0, 0.812816, 0.500000, 0.363644, 0.287514,
|
||||
0.238688, 0.204544, 0.179229, 0.159657,
|
||||
0.144042, 0.131276, 0.120632, 0.111614,
|
||||
0.103872, 0.09715, 0.0912559, 0.0860444,
|
||||
0.0814022, 0.0772401, 0.0734867, 0.0700842,
|
||||
0.0669851, 0.0641504, 0.0615475, 0.0591488,
|
||||
0.0569311, 0.0548745, 0.0529621
|
||||
};
|
||||
|
||||
float
|
||||
OsdComputeCatmarkCoefficient(int valence)
|
||||
{
|
||||
#if OSD_MAX_VALENCE < 30
|
||||
return OsdCatmarkCoefficient[valence];
|
||||
#else
|
||||
if (valence < 30) {
|
||||
return OsdCatmarkCoefficient[valence];
|
||||
} else {
|
||||
float t = 2.0f * float(M_PI) / float(valence);
|
||||
return 1.0f / (valence * (cos(t) + 5.0f +
|
||||
sqrt((cos(t) + 9) * (cos(t) + 1)))/16.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float cosfn(int n, int j) {
|
||||
return cos((2.0f * M_PI * j)/float(n));
|
||||
}
|
||||
|
||||
float sinfn(int n, int j) {
|
||||
return sin((2.0f * M_PI * j)/float(n));
|
||||
}
|
||||
|
||||
#if !defined OSD_MAX_VALENCE || OSD_MAX_VALENCE < 1
|
||||
#undef OSD_MAX_VALENCE
|
||||
#define OSD_MAX_VALENCE 4
|
||||
#endif
|
||||
|
||||
struct OsdPerVertexGregory {
|
||||
float3 P : POSITION0;
|
||||
int3 clipFlag : CLIPFLAG;
|
||||
int valence : BLENDINDICE0;
|
||||
float3 e0 : POSITION1;
|
||||
float3 e1 : POSITION2;
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
int zerothNeighbor : BLENDINDICE1;
|
||||
float3 org : POSITION3;
|
||||
#endif
|
||||
float3 r[OSD_MAX_VALENCE] : POSITION4;
|
||||
};
|
||||
|
||||
struct OsdPerPatchVertexGregory {
|
||||
int3 patchParam: PATCHPARAM;
|
||||
float3 P : POSITION0;
|
||||
float3 Ep : POSITION1;
|
||||
float3 Em : POSITION2;
|
||||
float3 Fp : POSITION3;
|
||||
float3 Fm : POSITION4;
|
||||
};
|
||||
|
||||
#ifndef OSD_NUM_ELEMENTS
|
||||
#define OSD_NUM_ELEMENTS 3
|
||||
#endif
|
||||
|
||||
Buffer<float> OsdVertexBuffer : register( t2 );
|
||||
Buffer<int> OsdValenceBuffer : register( t3 );
|
||||
|
||||
float3 OsdReadVertex(int vertexIndex)
|
||||
{
|
||||
int index = int(OSD_NUM_ELEMENTS * (vertexIndex /*+ OsdBaseVertex()*/));
|
||||
return float3(OsdVertexBuffer[index],
|
||||
OsdVertexBuffer[index+1],
|
||||
OsdVertexBuffer[index+2]);
|
||||
}
|
||||
|
||||
int OsdReadVertexValence(int vertexID)
|
||||
{
|
||||
int index = int(vertexID * (2 * OSD_MAX_VALENCE + 1));
|
||||
return OsdValenceBuffer[index];
|
||||
}
|
||||
|
||||
int OsdReadVertexIndex(int vertexID, int valenceVertex)
|
||||
{
|
||||
int index = int(vertexID * (2 * OSD_MAX_VALENCE + 1) + 1 + valenceVertex);
|
||||
return OsdValenceBuffer[index];
|
||||
}
|
||||
|
||||
Buffer<int> OsdQuadOffsetBuffer : register( t4 );
|
||||
|
||||
int OsdReadQuadOffset(int primitiveID, int offsetVertex)
|
||||
{
|
||||
int index = int(4*primitiveID+OsdGregoryQuadOffsetBase() + offsetVertex);
|
||||
return OsdQuadOffsetBuffer[index];
|
||||
}
|
||||
|
||||
void
|
||||
OsdComputePerVertexGregory(int vID, float3 P, out OsdPerVertexGregory v)
|
||||
{
|
||||
v.clipFlag = int3(0,0,0);
|
||||
|
||||
int ivalence = OsdReadVertexValence(vID);
|
||||
v.valence = ivalence;
|
||||
int valence = abs(ivalence);
|
||||
|
||||
float3 f[OSD_MAX_VALENCE];
|
||||
float3 pos = P;
|
||||
float3 opos = float3(0,0,0);
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
v.org = pos;
|
||||
int boundaryEdgeNeighbors[2];
|
||||
int currNeighbor = 0;
|
||||
int ibefore = 0;
|
||||
int zerothNeighbor = 0;
|
||||
#endif
|
||||
|
||||
for (int i=0; i<valence; ++i) {
|
||||
int im = (i+valence-1)%valence;
|
||||
int ip = (i+1)%valence;
|
||||
|
||||
int idx_neighbor = OsdReadVertexIndex(vID, 2*i);
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
bool isBoundaryNeighbor = false;
|
||||
int valenceNeighbor = OsdReadVertexValence(idx_neighbor);
|
||||
|
||||
if (valenceNeighbor < 0) {
|
||||
isBoundaryNeighbor = true;
|
||||
if (currNeighbor<2) {
|
||||
boundaryEdgeNeighbors[currNeighbor] = idx_neighbor;
|
||||
}
|
||||
currNeighbor++;
|
||||
if (currNeighbor == 1) {
|
||||
ibefore = i;
|
||||
zerothNeighbor = i;
|
||||
} else {
|
||||
if (i-ibefore == 1) {
|
||||
int tmp = boundaryEdgeNeighbors[0];
|
||||
boundaryEdgeNeighbors[0] = boundaryEdgeNeighbors[1];
|
||||
boundaryEdgeNeighbors[1] = tmp;
|
||||
zerothNeighbor = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
float3 neighbor = OsdReadVertex(idx_neighbor);
|
||||
|
||||
int idx_diagonal = OsdReadVertexIndex(vID, 2*i + 1);
|
||||
float3 diagonal = OsdReadVertex(idx_diagonal);
|
||||
|
||||
int idx_neighbor_p = OsdReadVertexIndex(vID, 2*ip);
|
||||
float3 neighbor_p = OsdReadVertex(idx_neighbor_p);
|
||||
|
||||
int idx_neighbor_m = OsdReadVertexIndex(vID, 2*im);
|
||||
float3 neighbor_m = OsdReadVertex(idx_neighbor_m);
|
||||
|
||||
int idx_diagonal_m = OsdReadVertexIndex(vID, 2*im + 1);
|
||||
float3 diagonal_m = OsdReadVertex(idx_diagonal_m);
|
||||
|
||||
f[i] = (pos * float(valence) + (neighbor_p + neighbor)*2.0f + diagonal) / (float(valence)+5.0f);
|
||||
|
||||
opos += f[i];
|
||||
v.r[i] = (neighbor_p-neighbor_m)/3.0f + (diagonal - diagonal_m)/6.0f;
|
||||
}
|
||||
|
||||
opos /= valence;
|
||||
v.P = float4(opos, 1.0f).xyz;
|
||||
|
||||
float3 e;
|
||||
v.e0 = float3(0,0,0);
|
||||
v.e1 = float3(0,0,0);
|
||||
|
||||
for(int iv=0; iv<valence; ++iv) {
|
||||
int im = (iv + valence -1) % valence;
|
||||
e = 0.5f * (f[iv] + f[im]);
|
||||
v.e0 += cosfn(valence, iv)*e;
|
||||
v.e1 += sinfn(valence, iv)*e;
|
||||
}
|
||||
float ef = OsdComputeCatmarkCoefficient(valence);
|
||||
v.e0 *= ef;
|
||||
v.e1 *= ef;
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
v.zerothNeighbor = zerothNeighbor;
|
||||
if (currNeighbor == 1) {
|
||||
boundaryEdgeNeighbors[1] = boundaryEdgeNeighbors[0];
|
||||
}
|
||||
|
||||
if (ivalence < 0) {
|
||||
if (valence > 2) {
|
||||
v.P = (OsdReadVertex(boundaryEdgeNeighbors[0]) +
|
||||
OsdReadVertex(boundaryEdgeNeighbors[1]) +
|
||||
4.0f * pos)/6.0f;
|
||||
} else {
|
||||
v.P = pos;
|
||||
}
|
||||
|
||||
v.e0 = (OsdReadVertex(boundaryEdgeNeighbors[0]) -
|
||||
OsdReadVertex(boundaryEdgeNeighbors[1]))/6.0;
|
||||
|
||||
float k = float(float(valence) - 1.0f); //k is the number of faces
|
||||
float c = cos(M_PI/k);
|
||||
float s = sin(M_PI/k);
|
||||
float gamma = -(4.0f*s)/(3.0f*k+c);
|
||||
float alpha_0k = -((1.0f+2.0f*c)*sqrt(1.0f+c))/((3.0f*k+c)*sqrt(1.0f-c));
|
||||
float beta_0 = s/(3.0f*k + c);
|
||||
|
||||
int idx_diagonal = OsdReadVertexIndex(vID, 2*zerothNeighbor + 1);
|
||||
float3 diagonal = OsdReadVertex(idx_diagonal);
|
||||
|
||||
v.e1 = gamma * pos +
|
||||
alpha_0k * OsdReadVertex(boundaryEdgeNeighbors[0]) +
|
||||
alpha_0k * OsdReadVertex(boundaryEdgeNeighbors[1]) +
|
||||
beta_0 * diagonal;
|
||||
|
||||
for (int x=1; x<valence - 1; ++x) {
|
||||
int curri = ((x + zerothNeighbor)%valence);
|
||||
float alpha = (4.0f*sin((M_PI * float(x))/k))/(3.0f*k+c);
|
||||
float beta = (sin((M_PI * float(x))/k) + sin((M_PI * float(x+1))/k))/(3.0f*k+c);
|
||||
|
||||
int idx_neighbor = OsdReadVertexIndex(vID, 2*curri);
|
||||
float3 neighbor = OsdReadVertex(idx_neighbor);
|
||||
|
||||
idx_diagonal = OsdReadVertexIndex(vID, 2*curri + 1);
|
||||
diagonal = OsdReadVertex(idx_diagonal);
|
||||
|
||||
v.e1 += alpha * neighbor + beta * diagonal;
|
||||
}
|
||||
|
||||
v.e1 /= 3.0f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
OsdComputePerPatchVertexGregory(int3 patchParam, int ID, int primitiveID,
|
||||
in OsdPerVertexGregory v[4],
|
||||
out OsdPerPatchVertexGregory result)
|
||||
{
|
||||
result.patchParam = patchParam;
|
||||
result.P = v[ID].P;
|
||||
|
||||
int i = ID;
|
||||
int ip = (i+1)%4;
|
||||
int im = (i+3)%4;
|
||||
int valence = abs(v[i].valence);
|
||||
int n = valence;
|
||||
|
||||
int start = OsdReadQuadOffset(primitiveID, i) & 0xff;
|
||||
int prev = (OsdReadQuadOffset(primitiveID, i) >> 8) & 0xff;
|
||||
|
||||
int start_m = OsdReadQuadOffset(primitiveID, im) & 0xff;
|
||||
int prev_p = (OsdReadQuadOffset(primitiveID, ip) >> 8) & 0xff;
|
||||
|
||||
int np = abs(v[ip].valence);
|
||||
int nm = abs(v[im].valence);
|
||||
|
||||
// Control Vertices based on :
|
||||
// "Approximating Subdivision Surfaces with Gregory Patches
|
||||
// for Hardware Tessellation"
|
||||
// Loop, Schaefer, Ni, Castano (ACM ToG Siggraph Asia 2009)
|
||||
//
|
||||
// P3 e3- e2+ P2
|
||||
// O--------O--------O--------O
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | f3- | f2+ |
|
||||
// | O O |
|
||||
// e3+ O------O O------O e2-
|
||||
// | f3+ f2- |
|
||||
// | |
|
||||
// | |
|
||||
// | f0- f1+ |
|
||||
// e0- O------O O------O e1+
|
||||
// | O O |
|
||||
// | | f0+ | f1- |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// O--------O--------O--------O
|
||||
// P0 e0+ e1- P1
|
||||
//
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
float3 Em_ip;
|
||||
if (v[ip].valence < -2) {
|
||||
int j = (np + prev_p - v[ip].zerothNeighbor) % np;
|
||||
Em_ip = v[ip].P + cos((M_PI*j)/float(np-1))*v[ip].e0 + sin((M_PI*j)/float(np-1))*v[ip].e1;
|
||||
} else {
|
||||
Em_ip = v[ip].P + v[ip].e0*cosfn(np, prev_p) + v[ip].e1*sinfn(np, prev_p);
|
||||
}
|
||||
|
||||
float3 Ep_im;
|
||||
if (v[im].valence < -2) {
|
||||
int j = (nm + start_m - v[im].zerothNeighbor) % nm;
|
||||
Ep_im = v[im].P + cos((M_PI*j)/float(nm-1))*v[im].e0 + sin((M_PI*j)/float(nm-1))*v[im].e1;
|
||||
} else {
|
||||
Ep_im = v[im].P + v[im].e0*cosfn(nm, start_m) + v[im].e1*sinfn(nm, start_m);
|
||||
}
|
||||
|
||||
if (v[i].valence < 0) {
|
||||
n = (n-1)*2;
|
||||
}
|
||||
if (v[im].valence < 0) {
|
||||
nm = (nm-1)*2;
|
||||
}
|
||||
if (v[ip].valence < 0) {
|
||||
np = (np-1)*2;
|
||||
}
|
||||
|
||||
if (v[i].valence > 2) {
|
||||
result.Ep = v[i].P + (v[i].e0*cosfn(n, start) + v[i].e1*sinfn(n, start));
|
||||
result.Em = v[i].P + (v[i].e0*cosfn(n, prev) + v[i].e1*sinfn(n, prev));
|
||||
|
||||
float s1=3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2=2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
|
||||
} else if (v[i].valence < -2) {
|
||||
int j = (valence + start - v[i].zerothNeighbor) % valence;
|
||||
|
||||
result.Ep = v[i].P + cos((M_PI*j)/float(valence-1))*v[i].e0 + sin((M_PI*j)/float(valence-1))*v[i].e1;
|
||||
j = (valence + prev - v[i].zerothNeighbor) % valence;
|
||||
result.Em = v[i].P + cos((M_PI*j)/float(valence-1))*v[i].e0 + sin((M_PI*j)/float(valence-1))*v[i].e1;
|
||||
|
||||
float3 Rp = ((-2.0f * v[i].org - 1.0f * v[im].org) + (2.0f * v[ip].org + 1.0f * v[(i+2)%4].org))/3.0f;
|
||||
float3 Rm = ((-2.0f * v[i].org - 1.0f * v[ip].org) + (2.0f * v[im].org + 1.0f * v[(i+2)%4].org))/3.0f;
|
||||
|
||||
float s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2 = 2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
|
||||
if (v[im].valence < 0) {
|
||||
s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
result.Fp = result.Fm = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
} else if (v[ip].valence < 0) {
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/n)-cos(2.0f*M_PI/nm);
|
||||
result.Fm = result.Fp = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
}
|
||||
|
||||
} else if (v[i].valence == -2) {
|
||||
result.Ep = (2.0f * v[i].org + v[ip].org)/3.0f;
|
||||
result.Em = (2.0f * v[i].org + v[im].org)/3.0f;
|
||||
result.Fp = result.Fm = (4.0f * v[i].org + v[(i+2)%n].org + 2.0f * v[ip].org + 2.0f * v[im].org)/9.0f;
|
||||
}
|
||||
|
||||
#else // not OSD_PATCH_GREGORY_BOUNDARY
|
||||
|
||||
result.Ep = v[i].P + v[i].e0 * cosfn(n, start) + v[i].e1*sinfn(n, start);
|
||||
result.Em = v[i].P + v[i].e0 * cosfn(n, prev ) + v[i].e1*sinfn(n, prev );
|
||||
|
||||
float3 Em_ip = v[ip].P + v[ip].e0*cosfn(np, prev_p) + v[ip].e1*sinfn(np, prev_p);
|
||||
float3 Ep_im = v[im].P + v[im].e0*cosfn(nm, start_m) + v[im].e1*sinfn(nm, start_m);
|
||||
|
||||
float s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2 = 2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em +s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
152
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchShaderSource.cpp
vendored
Normal file
152
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchShaderSource.cpp
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/hlslPatchShaderSource.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static const char *commonShaderSource =
|
||||
#include "hlslPatchCommon.gen.h"
|
||||
;
|
||||
static const char *commonTessShaderSource =
|
||||
#include "hlslPatchCommonTess.gen.h"
|
||||
;
|
||||
static const char *patchLegacyShaderSource =
|
||||
#include "hlslPatchLegacy.gen.h"
|
||||
;
|
||||
static const char *patchBasisTypesShaderSource =
|
||||
#include "patchBasisTypes.gen.h"
|
||||
;
|
||||
static const char *patchBasisShaderSource =
|
||||
#include "patchBasis.gen.h"
|
||||
;
|
||||
static const char *boxSplineTriangleShaderSource =
|
||||
#include "hlslPatchBoxSplineTriangle.gen.h"
|
||||
;
|
||||
static const char *bsplineShaderSource =
|
||||
#include "hlslPatchBSpline.gen.h"
|
||||
;
|
||||
static const char *gregoryShaderSource =
|
||||
#include "hlslPatchGregory.gen.h"
|
||||
;
|
||||
static const char *gregoryBasisShaderSource =
|
||||
#include "hlslPatchGregoryBasis.gen.h"
|
||||
;
|
||||
static const char *gregoryTriangleShaderSource =
|
||||
#include "hlslPatchGregoryTriangle.gen.h"
|
||||
;
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
HLSLPatchShaderSource::GetPatchDrawingShaderSource() {
|
||||
std::stringstream ss;
|
||||
ss << std::string(commonShaderSource);
|
||||
ss << std::string(commonTessShaderSource);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
HLSLPatchShaderSource::GetCommonShaderSource() {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchDrawingShaderSource();
|
||||
ss << std::string(patchLegacyShaderSource);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
HLSLPatchShaderSource::GetPatchBasisShaderSource() {
|
||||
std::stringstream ss;
|
||||
#if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES)
|
||||
ss << "#define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES\n";
|
||||
#endif
|
||||
ss << std::string(patchBasisTypesShaderSource);
|
||||
ss << std::string(patchBasisShaderSource);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
HLSLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type) {
|
||||
switch (type) {
|
||||
case Far::PatchDescriptor::REGULAR:
|
||||
return bsplineShaderSource;
|
||||
case Far::PatchDescriptor::LOOP:
|
||||
return boxSplineTriangleShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
return gregoryShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY:
|
||||
return std::string("#define OSD_PATCH_GREGORY_BOUNDRY\n")
|
||||
+ std::string(gregoryShaderSource);
|
||||
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||
return gregoryBasisShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY_TRIANGLE:
|
||||
return gregoryTriangleShaderSource;
|
||||
default:
|
||||
break; // returns empty (points, lines, quads, ...)
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
HLSLPatchShaderSource::GetHullShaderSource(Far::PatchDescriptor::Type type) {
|
||||
switch (type) {
|
||||
case Far::PatchDescriptor::REGULAR:
|
||||
return bsplineShaderSource;
|
||||
case Far::PatchDescriptor::LOOP:
|
||||
return boxSplineTriangleShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
return gregoryShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY:
|
||||
return std::string("#define OSD_PATCH_GREGORY_BOUNDRY\n")
|
||||
+ std::string(gregoryShaderSource);
|
||||
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||
return gregoryBasisShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY_TRIANGLE:
|
||||
return gregoryTriangleShaderSource;
|
||||
default:
|
||||
break; // returns empty (points, lines, quads, ...)
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
HLSLPatchShaderSource::GetDomainShaderSource(Far::PatchDescriptor::Type type) {
|
||||
switch (type) {
|
||||
case Far::PatchDescriptor::REGULAR:
|
||||
return bsplineShaderSource;
|
||||
case Far::PatchDescriptor::LOOP:
|
||||
return boxSplineTriangleShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
return gregoryShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY:
|
||||
return std::string("#define OSD_PATCH_GREGORY_BOUNDRY\n")
|
||||
+ std::string(gregoryShaderSource);
|
||||
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||
return gregoryBasisShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY_TRIANGLE:
|
||||
return gregoryTriangleShaderSource;
|
||||
default:
|
||||
break; // returns empty (points, lines, quads, ...)
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
61
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchShaderSource.h
vendored
Normal file
61
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/hlslPatchShaderSource.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_HLSL_PATCH_SHADER_SOURCE_H
|
||||
#define OPENSUBDIV3_OSD_HLSL_PATCH_SHADER_SOURCE_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/patchDescriptor.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Provides shader source which can be used by client code.
|
||||
class HLSLPatchShaderSource {
|
||||
public:
|
||||
/// \brief Returns shader source which can be used to evaluate
|
||||
/// position and first and second derivatives on piecewise parametric
|
||||
/// patches resulting from subdivision refinement.
|
||||
static std::string GetPatchBasisShaderSource();
|
||||
|
||||
/// \brief Returns shader source which can be used while drawing
|
||||
/// piecewise parametric patches resulting from subdivision refinement,
|
||||
/// e.g. while using GPU HW tessellation.
|
||||
static std::string GetPatchDrawingShaderSource();
|
||||
|
||||
/// \name Alternative methods
|
||||
/// \{
|
||||
/// These methods return shader source which can be used
|
||||
/// while drawing. Unlike the methods above, the source returned
|
||||
/// by these methods includes support for legacy patch types along
|
||||
/// with dependencies on specific resource bindings and interstage
|
||||
/// shader variable declarations.
|
||||
|
||||
static std::string GetCommonShaderSource();
|
||||
|
||||
static std::string GetVertexShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
static std::string GetHullShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
static std::string GetDomainShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_HLSL_PATCH_SHADER_SOURCE_H
|
||||
706
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mesh.h
vendored
Normal file
706
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mesh.h
vendored
Normal file
@@ -0,0 +1,706 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MESH_H
|
||||
#define OPENSUBDIV3_OSD_MESH_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "../far/topologyRefiner.h"
|
||||
#include "../far/patchTableFactory.h"
|
||||
#include "../far/stencilTable.h"
|
||||
#include "../far/stencilTableFactory.h"
|
||||
|
||||
#include "../osd/bufferDescriptor.h"
|
||||
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
enum MeshBits {
|
||||
MeshAdaptive = 0,
|
||||
MeshInterleaveVarying = 1,
|
||||
MeshFVarData = 2,
|
||||
MeshFVarAdaptive = 3,
|
||||
MeshUseSmoothCornerPatch = 4,
|
||||
MeshUseSingleCreasePatch = 5,
|
||||
MeshUseInfSharpPatch = 6,
|
||||
MeshEndCapBilinearBasis = 7, // exclusive
|
||||
MeshEndCapBSplineBasis = 8, // exclusive
|
||||
MeshEndCapGregoryBasis = 9, // exclusive
|
||||
MeshEndCapLegacyGregory = 10, // exclusive
|
||||
NUM_MESH_BITS = 11,
|
||||
};
|
||||
typedef std::bitset<NUM_MESH_BITS> MeshBitset;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <class PATCH_TABLE>
|
||||
class MeshInterface {
|
||||
public:
|
||||
typedef PATCH_TABLE PatchTable;
|
||||
typedef typename PatchTable::VertexBufferBinding VertexBufferBinding;
|
||||
|
||||
public:
|
||||
MeshInterface() { }
|
||||
|
||||
virtual ~MeshInterface() { }
|
||||
|
||||
virtual int GetNumVertices() const = 0;
|
||||
|
||||
virtual int GetMaxValence() const = 0;
|
||||
|
||||
virtual void UpdateVertexBuffer(float const *vertexData,
|
||||
int startVertex, int numVerts) = 0;
|
||||
|
||||
virtual void UpdateVaryingBuffer(float const *varyingData,
|
||||
int startVertex, int numVerts) = 0;
|
||||
|
||||
virtual void Refine() = 0;
|
||||
|
||||
virtual void Synchronize() = 0;
|
||||
|
||||
virtual PatchTable * GetPatchTable() const = 0;
|
||||
|
||||
virtual Far::PatchTable const *GetFarPatchTable() const = 0;
|
||||
|
||||
virtual VertexBufferBinding BindVertexBuffer() = 0;
|
||||
|
||||
virtual VertexBufferBinding BindVaryingBuffer() = 0;
|
||||
|
||||
protected:
|
||||
static inline void refineMesh(Far::TopologyRefiner & refiner,
|
||||
int level, bool adaptive,
|
||||
bool singleCreasePatch) {
|
||||
if (adaptive) {
|
||||
Far::TopologyRefiner::AdaptiveOptions options(level);
|
||||
options.useSingleCreasePatch = singleCreasePatch;
|
||||
refiner.RefineAdaptive(options);
|
||||
} else {
|
||||
// This dependency on FVar channels should not be necessary
|
||||
bool fullTopologyInLastLevel = refiner.GetNumFVarChannels()>0;
|
||||
|
||||
Far::TopologyRefiner::UniformOptions options(level);
|
||||
options.fullTopologyInLastLevel = fullTopologyInLastLevel;
|
||||
refiner.RefineUniform(options);
|
||||
}
|
||||
}
|
||||
static inline void refineMesh(Far::TopologyRefiner & refiner,
|
||||
int level, MeshBitset bits) {
|
||||
if (bits.test(MeshAdaptive)) {
|
||||
Far::TopologyRefiner::AdaptiveOptions options(level);
|
||||
options.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch);
|
||||
options.useInfSharpPatch = bits.test(MeshUseInfSharpPatch);
|
||||
options.considerFVarChannels = bits.test(MeshFVarAdaptive);
|
||||
refiner.RefineAdaptive(options);
|
||||
} else {
|
||||
// This dependency on FVar channels should not be necessary
|
||||
bool fullTopologyInLastLevel = refiner.GetNumFVarChannels()>0;
|
||||
|
||||
Far::TopologyRefiner::UniformOptions options(level);
|
||||
options.fullTopologyInLastLevel = fullTopologyInLastLevel;
|
||||
refiner.RefineUniform(options);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <typename STENCIL_TABLE, typename SRC_STENCIL_TABLE,
|
||||
typename DEVICE_CONTEXT>
|
||||
STENCIL_TABLE const *
|
||||
convertToCompatibleStencilTable(
|
||||
SRC_STENCIL_TABLE const *table, DEVICE_CONTEXT *context) {
|
||||
if (! table) return NULL;
|
||||
return STENCIL_TABLE::Create(table, context);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Far::StencilTable const *
|
||||
convertToCompatibleStencilTable<Far::StencilTable, Far::StencilTable, void>(
|
||||
Far::StencilTable const *table, void * /*context*/) {
|
||||
// no need for conversion
|
||||
// XXX: We don't want to even copy.
|
||||
if (! table) return NULL;
|
||||
return new Far::StencilTable(*table);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Far::LimitStencilTable const *
|
||||
convertToCompatibleStencilTable<Far::LimitStencilTable, Far::LimitStencilTable, void>(
|
||||
Far::LimitStencilTable const *table, void * /*context*/) {
|
||||
// no need for conversion
|
||||
// XXX: We don't want to even copy.
|
||||
if (! table) return NULL;
|
||||
return new Far::LimitStencilTable(*table);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline Far::StencilTable const *
|
||||
convertToCompatibleStencilTable<Far::StencilTable, Far::StencilTable, ID3D11DeviceContext>(
|
||||
Far::StencilTable const *table, ID3D11DeviceContext * /*context*/) {
|
||||
// no need for conversion
|
||||
// XXX: We don't want to even copy.
|
||||
if (! table) return NULL;
|
||||
return new Far::StencilTable(*table);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Osd evaluator cache: for the GPU backends require compiled instance
|
||||
// (GLXFB, GLCompute, CL)
|
||||
//
|
||||
// note: this is just an example usage and client applications are supposed
|
||||
// to implement their own structure for Evaluator instance.
|
||||
//
|
||||
template <typename EVALUATOR>
|
||||
class EvaluatorCacheT {
|
||||
public:
|
||||
~EvaluatorCacheT() {
|
||||
for(typename Evaluators::iterator it = _evaluators.begin();
|
||||
it != _evaluators.end(); ++it) {
|
||||
delete it->evaluator;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: FIXME, linear search
|
||||
struct Entry {
|
||||
Entry(BufferDescriptor const &srcDescArg,
|
||||
BufferDescriptor const &dstDescArg,
|
||||
BufferDescriptor const &duDescArg,
|
||||
BufferDescriptor const &dvDescArg,
|
||||
EVALUATOR *evalArg) : srcDesc(srcDescArg), dstDesc(dstDescArg),
|
||||
duDesc(duDescArg), dvDesc(dvDescArg),
|
||||
duuDesc(BufferDescriptor()),
|
||||
duvDesc(BufferDescriptor()),
|
||||
dvvDesc(BufferDescriptor()),
|
||||
evaluator(evalArg) {}
|
||||
Entry(BufferDescriptor const &srcDescArg,
|
||||
BufferDescriptor const &dstDescArg,
|
||||
BufferDescriptor const &duDescArg,
|
||||
BufferDescriptor const &dvDescArg,
|
||||
BufferDescriptor const &duuDescArg,
|
||||
BufferDescriptor const &duvDescArg,
|
||||
BufferDescriptor const &dvvDescArg,
|
||||
EVALUATOR *evalArg) : srcDesc(srcDescArg), dstDesc(dstDescArg),
|
||||
duDesc(duDescArg), dvDesc(dvDescArg),
|
||||
duuDesc(duuDescArg),
|
||||
duvDesc(duvDescArg),
|
||||
dvvDesc(dvvDescArg),
|
||||
evaluator(evalArg) {}
|
||||
BufferDescriptor srcDesc, dstDesc;
|
||||
BufferDescriptor duDesc, dvDesc;
|
||||
BufferDescriptor duuDesc, duvDesc, dvvDesc;
|
||||
EVALUATOR *evaluator;
|
||||
};
|
||||
typedef std::vector<Entry> Evaluators;
|
||||
|
||||
template <typename DEVICE_CONTEXT>
|
||||
EVALUATOR *GetEvaluator(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
DEVICE_CONTEXT *deviceContext) {
|
||||
return GetEvaluator(srcDesc, dstDesc,
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
deviceContext);
|
||||
}
|
||||
|
||||
template <typename DEVICE_CONTEXT>
|
||||
EVALUATOR *GetEvaluator(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
DEVICE_CONTEXT *deviceContext) {
|
||||
return GetEvaluator(srcDesc, dstDesc,
|
||||
duDesc, dvDesc,
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
deviceContext);
|
||||
}
|
||||
|
||||
template <typename DEVICE_CONTEXT>
|
||||
EVALUATOR *GetEvaluator(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
DEVICE_CONTEXT *deviceContext) {
|
||||
|
||||
for(typename Evaluators::iterator it = _evaluators.begin();
|
||||
it != _evaluators.end(); ++it) {
|
||||
if (isEqual(srcDesc, it->srcDesc) &&
|
||||
isEqual(dstDesc, it->dstDesc) &&
|
||||
isEqual(duDesc, it->duDesc) &&
|
||||
isEqual(dvDesc, it->dvDesc) &&
|
||||
isEqual(duuDesc, it->duuDesc) &&
|
||||
isEqual(duvDesc, it->duvDesc) &&
|
||||
isEqual(dvvDesc, it->dvvDesc)) {
|
||||
return it->evaluator;
|
||||
}
|
||||
}
|
||||
EVALUATOR *e = EVALUATOR::Create(srcDesc, dstDesc,
|
||||
duDesc, dvDesc,
|
||||
duuDesc, duvDesc, dvvDesc,
|
||||
deviceContext);
|
||||
_evaluators.push_back(Entry(srcDesc, dstDesc,
|
||||
duDesc, dvDesc,
|
||||
duuDesc, duvDesc, dvvDesc, e));
|
||||
return e;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool isEqual(BufferDescriptor const &a,
|
||||
BufferDescriptor const &b) {
|
||||
int offsetA = a.stride ? (a.offset % a.stride) : 0;
|
||||
int offsetB = b.stride ? (b.offset % b.stride) : 0;
|
||||
|
||||
// Note: XFB kernel needs to be configured with the local offset
|
||||
// of the dstDesc to skip preceding primvars.
|
||||
return (offsetA == offsetB &&
|
||||
a.length == b.length &&
|
||||
a.stride == b.stride);
|
||||
}
|
||||
|
||||
Evaluators _evaluators;
|
||||
};
|
||||
|
||||
/// @cond INTERNAL
|
||||
|
||||
// template helpers to see if the evaluator is instantiatable or not.
|
||||
template <typename EVALUATOR>
|
||||
struct instantiatable
|
||||
{
|
||||
typedef char yes[1];
|
||||
typedef char no[2];
|
||||
template <typename C> static yes &chk(typename C::Instantiatable *t=0);
|
||||
template <typename C> static no &chk(...);
|
||||
static bool const value = sizeof(chk<EVALUATOR>(0)) == sizeof(yes);
|
||||
};
|
||||
template <bool C, typename T=void>
|
||||
struct enable_if { typedef T type; };
|
||||
template <typename T>
|
||||
struct enable_if<false, T> { };
|
||||
|
||||
/// @endcond
|
||||
|
||||
// extract a kernel from cache if available
|
||||
template <typename EVALUATOR, typename DEVICE_CONTEXT>
|
||||
static EVALUATOR *GetEvaluator(
|
||||
EvaluatorCacheT<EVALUATOR> *cache,
|
||||
BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
DEVICE_CONTEXT deviceContext,
|
||||
typename enable_if<instantiatable<EVALUATOR>::value, void>::type*t=0) {
|
||||
(void)t;
|
||||
if (cache == NULL) return NULL;
|
||||
return cache->GetEvaluator(srcDesc, dstDesc,
|
||||
duDesc, dvDesc, duuDesc, duvDesc, dvvDesc,
|
||||
deviceContext);
|
||||
}
|
||||
|
||||
template <typename EVALUATOR, typename DEVICE_CONTEXT>
|
||||
static EVALUATOR *GetEvaluator(
|
||||
EvaluatorCacheT<EVALUATOR> *cache,
|
||||
BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
DEVICE_CONTEXT deviceContext,
|
||||
typename enable_if<instantiatable<EVALUATOR>::value, void>::type*t=0) {
|
||||
(void)t;
|
||||
if (cache == NULL) return NULL;
|
||||
return cache->GetEvaluator(srcDesc, dstDesc, duDesc, dvDesc, deviceContext);
|
||||
}
|
||||
|
||||
template <typename EVALUATOR, typename DEVICE_CONTEXT>
|
||||
static EVALUATOR *GetEvaluator(
|
||||
EvaluatorCacheT<EVALUATOR> *cache,
|
||||
BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
DEVICE_CONTEXT deviceContext,
|
||||
typename enable_if<instantiatable<EVALUATOR>::value, void>::type*t=0) {
|
||||
(void)t;
|
||||
if (cache == NULL) return NULL;
|
||||
return cache->GetEvaluator(srcDesc, dstDesc,
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
deviceContext);
|
||||
}
|
||||
|
||||
// fallback
|
||||
template <typename EVALUATOR, typename DEVICE_CONTEXT>
|
||||
static EVALUATOR *GetEvaluator(
|
||||
EvaluatorCacheT<EVALUATOR> *,
|
||||
BufferDescriptor const &,
|
||||
BufferDescriptor const &,
|
||||
BufferDescriptor const &,
|
||||
BufferDescriptor const &,
|
||||
BufferDescriptor const &,
|
||||
BufferDescriptor const &,
|
||||
BufferDescriptor const &,
|
||||
DEVICE_CONTEXT,
|
||||
typename enable_if<!instantiatable<EVALUATOR>::value, void>::type*t=0) {
|
||||
(void)t;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename EVALUATOR, typename DEVICE_CONTEXT>
|
||||
static EVALUATOR *GetEvaluator(
|
||||
EvaluatorCacheT<EVALUATOR> *,
|
||||
BufferDescriptor const &,
|
||||
BufferDescriptor const &,
|
||||
BufferDescriptor const &,
|
||||
BufferDescriptor const &,
|
||||
DEVICE_CONTEXT,
|
||||
typename enable_if<!instantiatable<EVALUATOR>::value, void>::type*t=0) {
|
||||
(void)t;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename EVALUATOR, typename DEVICE_CONTEXT>
|
||||
static EVALUATOR *GetEvaluator(
|
||||
EvaluatorCacheT<EVALUATOR> *,
|
||||
BufferDescriptor const &,
|
||||
BufferDescriptor const &,
|
||||
DEVICE_CONTEXT,
|
||||
typename enable_if<!instantiatable<EVALUATOR>::value, void>::type*t=0) {
|
||||
(void)t;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <typename VERTEX_BUFFER,
|
||||
typename STENCIL_TABLE,
|
||||
typename EVALUATOR,
|
||||
typename PATCH_TABLE,
|
||||
typename DEVICE_CONTEXT = void>
|
||||
class Mesh : public MeshInterface<PATCH_TABLE> {
|
||||
public:
|
||||
typedef VERTEX_BUFFER VertexBuffer;
|
||||
typedef EVALUATOR Evaluator;
|
||||
typedef STENCIL_TABLE StencilTable;
|
||||
typedef PATCH_TABLE PatchTable;
|
||||
typedef DEVICE_CONTEXT DeviceContext;
|
||||
typedef EvaluatorCacheT<Evaluator> EvaluatorCache;
|
||||
typedef typename PatchTable::VertexBufferBinding VertexBufferBinding;
|
||||
|
||||
Mesh(Far::TopologyRefiner * refiner,
|
||||
int numVertexElements,
|
||||
int numVaryingElements,
|
||||
int level,
|
||||
MeshBitset bits = MeshBitset(),
|
||||
EvaluatorCache * evaluatorCache = NULL,
|
||||
DeviceContext * deviceContext = NULL) :
|
||||
|
||||
_refiner(refiner),
|
||||
_farPatchTable(NULL),
|
||||
_numVertices(0),
|
||||
_maxValence(0),
|
||||
_vertexBuffer(NULL),
|
||||
_varyingBuffer(NULL),
|
||||
_vertexStencilTable(NULL),
|
||||
_varyingStencilTable(NULL),
|
||||
_evaluatorCache(evaluatorCache),
|
||||
_patchTable(NULL),
|
||||
_deviceContext(deviceContext) {
|
||||
|
||||
assert(_refiner);
|
||||
|
||||
MeshInterface<PATCH_TABLE>::refineMesh(
|
||||
*_refiner, level, bits);
|
||||
|
||||
int vertexBufferStride = numVertexElements +
|
||||
(bits.test(MeshInterleaveVarying) ? numVaryingElements : 0);
|
||||
int varyingBufferStride =
|
||||
(bits.test(MeshInterleaveVarying) ? 0 : numVaryingElements);
|
||||
|
||||
initializeContext(numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
|
||||
initializeVertexBuffers(_numVertices,
|
||||
vertexBufferStride,
|
||||
varyingBufferStride);
|
||||
|
||||
// configure vertex buffer descriptor
|
||||
_vertexDesc =
|
||||
BufferDescriptor(0, numVertexElements, vertexBufferStride);
|
||||
if (bits.test(MeshInterleaveVarying)) {
|
||||
_varyingDesc = BufferDescriptor(
|
||||
numVertexElements, numVaryingElements, vertexBufferStride);
|
||||
} else {
|
||||
_varyingDesc = BufferDescriptor(
|
||||
0, numVaryingElements, varyingBufferStride);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~Mesh() {
|
||||
delete _refiner;
|
||||
delete _farPatchTable;
|
||||
delete _vertexBuffer;
|
||||
delete _varyingBuffer;
|
||||
delete _vertexStencilTable;
|
||||
delete _varyingStencilTable;
|
||||
delete _patchTable;
|
||||
// deviceContext and evaluatorCache are not owned by this class.
|
||||
}
|
||||
|
||||
virtual void UpdateVertexBuffer(float const *vertexData,
|
||||
int startVertex, int numVerts) {
|
||||
_vertexBuffer->UpdateData(vertexData, startVertex, numVerts,
|
||||
_deviceContext);
|
||||
}
|
||||
|
||||
virtual void UpdateVaryingBuffer(float const *varyingData,
|
||||
int startVertex, int numVerts) {
|
||||
_varyingBuffer->UpdateData(varyingData, startVertex, numVerts,
|
||||
_deviceContext);
|
||||
}
|
||||
|
||||
virtual void Refine() {
|
||||
|
||||
int numControlVertices = _refiner->GetLevel(0).GetNumVertices();
|
||||
|
||||
BufferDescriptor srcDesc = _vertexDesc;
|
||||
BufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += numControlVertices * dstDesc.stride;
|
||||
|
||||
// note that the _evaluatorCache can be NULL and thus
|
||||
// the evaluatorInstance can be NULL
|
||||
// (for uninstantiatable kernels CPU,TBB etc)
|
||||
Evaluator const *instance = GetEvaluator<Evaluator>(
|
||||
_evaluatorCache, srcDesc, dstDesc,
|
||||
_deviceContext);
|
||||
|
||||
Evaluator::EvalStencils(_vertexBuffer, srcDesc,
|
||||
_vertexBuffer, dstDesc,
|
||||
_vertexStencilTable,
|
||||
instance, _deviceContext);
|
||||
|
||||
if (_varyingDesc.length > 0) {
|
||||
BufferDescriptor vSrcDesc = _varyingDesc;
|
||||
BufferDescriptor vDstDesc(vSrcDesc);
|
||||
vDstDesc.offset += numControlVertices * vDstDesc.stride;
|
||||
|
||||
instance = GetEvaluator<Evaluator>(
|
||||
_evaluatorCache, vSrcDesc, vDstDesc,
|
||||
_deviceContext);
|
||||
|
||||
if (_varyingBuffer) {
|
||||
// non-interleaved
|
||||
Evaluator::EvalStencils(_varyingBuffer, vSrcDesc,
|
||||
_varyingBuffer, vDstDesc,
|
||||
_varyingStencilTable,
|
||||
instance, _deviceContext);
|
||||
} else {
|
||||
// interleaved
|
||||
Evaluator::EvalStencils(_vertexBuffer, vSrcDesc,
|
||||
_vertexBuffer, vDstDesc,
|
||||
_varyingStencilTable,
|
||||
instance, _deviceContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Synchronize() {
|
||||
Evaluator::Synchronize(_deviceContext);
|
||||
}
|
||||
|
||||
virtual PatchTable * GetPatchTable() const {
|
||||
return _patchTable;
|
||||
}
|
||||
|
||||
virtual Far::PatchTable const *GetFarPatchTable() const {
|
||||
return _farPatchTable;
|
||||
}
|
||||
|
||||
virtual int GetNumVertices() const { return _numVertices; }
|
||||
|
||||
virtual int GetMaxValence() const { return _maxValence; }
|
||||
|
||||
virtual VertexBufferBinding BindVertexBuffer() {
|
||||
return _vertexBuffer->BindVBO(_deviceContext);
|
||||
}
|
||||
|
||||
virtual VertexBufferBinding BindVaryingBuffer() {
|
||||
return _varyingBuffer->BindVBO(_deviceContext);
|
||||
}
|
||||
|
||||
virtual VertexBuffer * GetVertexBuffer() {
|
||||
return _vertexBuffer;
|
||||
}
|
||||
|
||||
virtual VertexBuffer * GetVaryingBuffer() {
|
||||
return _varyingBuffer;
|
||||
}
|
||||
|
||||
virtual Far::TopologyRefiner const * GetTopologyRefiner() const {
|
||||
return _refiner;
|
||||
}
|
||||
|
||||
private:
|
||||
void initializeContext(int numVertexElements,
|
||||
int numVaryingElements,
|
||||
int level, MeshBitset bits) {
|
||||
assert(_refiner);
|
||||
|
||||
Far::StencilTableFactory::Options options;
|
||||
options.generateOffsets = true;
|
||||
options.generateIntermediateLevels =
|
||||
_refiner->IsUniform() ? false : true;
|
||||
|
||||
Far::StencilTable const * vertexStencils = NULL;
|
||||
Far::StencilTable const * varyingStencils = NULL;
|
||||
|
||||
if (numVertexElements>0) {
|
||||
|
||||
vertexStencils = Far::StencilTableFactory::Create(*_refiner,
|
||||
options);
|
||||
}
|
||||
|
||||
if (numVaryingElements>0) {
|
||||
|
||||
options.interpolationMode =
|
||||
Far::StencilTableFactory::INTERPOLATE_VARYING;
|
||||
|
||||
varyingStencils = Far::StencilTableFactory::Create(*_refiner,
|
||||
options);
|
||||
}
|
||||
|
||||
Far::PatchTableFactory::Options poptions(level);
|
||||
poptions.generateFVarTables = bits.test(MeshFVarData);
|
||||
poptions.generateFVarLegacyLinearPatches = !bits.test(MeshFVarAdaptive);
|
||||
poptions.generateLegacySharpCornerPatches = !bits.test(MeshUseSmoothCornerPatch);
|
||||
poptions.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch);
|
||||
poptions.useInfSharpPatch = bits.test(MeshUseInfSharpPatch);
|
||||
|
||||
// points on bilinear and gregory basis endcap boundaries can be
|
||||
// shared among adjacent patches to save some stencils.
|
||||
if (bits.test(MeshEndCapBilinearBasis)) {
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTableFactory::Options::ENDCAP_BILINEAR_BASIS);
|
||||
poptions.shareEndCapPatchPoints = true;
|
||||
} else if (bits.test(MeshEndCapBSplineBasis)) {
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
|
||||
} else if (bits.test(MeshEndCapGregoryBasis)) {
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
|
||||
poptions.shareEndCapPatchPoints = true;
|
||||
} else if (bits.test(MeshEndCapLegacyGregory)) {
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTableFactory::Options::ENDCAP_LEGACY_GREGORY);
|
||||
}
|
||||
|
||||
_farPatchTable = Far::PatchTableFactory::Create(*_refiner, poptions);
|
||||
|
||||
// if there's endcap stencils, merge it into regular stencils.
|
||||
if (_farPatchTable->GetLocalPointStencilTable()) {
|
||||
// append stencils
|
||||
if (Far::StencilTable const *vertexStencilsWithLocalPoints =
|
||||
Far::StencilTableFactory::AppendLocalPointStencilTable(
|
||||
*_refiner,
|
||||
vertexStencils,
|
||||
_farPatchTable->GetLocalPointStencilTable())) {
|
||||
delete vertexStencils;
|
||||
vertexStencils = vertexStencilsWithLocalPoints;
|
||||
}
|
||||
if (varyingStencils) {
|
||||
if (Far::StencilTable const *varyingStencilsWithLocalPoints =
|
||||
Far::StencilTableFactory::AppendLocalPointStencilTable(
|
||||
*_refiner,
|
||||
varyingStencils,
|
||||
_farPatchTable->GetLocalPointVaryingStencilTable())) {
|
||||
delete varyingStencils;
|
||||
varyingStencils = varyingStencilsWithLocalPoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_maxValence = _farPatchTable->GetMaxValence();
|
||||
_patchTable = PatchTable::Create(_farPatchTable, _deviceContext);
|
||||
|
||||
// numvertices = coarse verts + refined verts + gregory basis verts
|
||||
_numVertices = vertexStencils->GetNumControlVertices()
|
||||
+ vertexStencils->GetNumStencils();
|
||||
|
||||
// convert to device stenciltable if necessary.
|
||||
_vertexStencilTable =
|
||||
convertToCompatibleStencilTable<StencilTable>(
|
||||
vertexStencils, _deviceContext);
|
||||
_varyingStencilTable =
|
||||
convertToCompatibleStencilTable<StencilTable>(
|
||||
varyingStencils, _deviceContext);
|
||||
|
||||
// FIXME: we do extra copyings for Far::Stencils.
|
||||
delete vertexStencils;
|
||||
delete varyingStencils;
|
||||
}
|
||||
|
||||
void initializeVertexBuffers(int numVertices,
|
||||
int numVertexElements,
|
||||
int numVaryingElements) {
|
||||
|
||||
if (numVertexElements) {
|
||||
_vertexBuffer = VertexBuffer::Create(numVertexElements,
|
||||
numVertices, _deviceContext);
|
||||
}
|
||||
|
||||
if (numVaryingElements) {
|
||||
_varyingBuffer = VertexBuffer::Create(numVaryingElements,
|
||||
numVertices, _deviceContext);
|
||||
}
|
||||
}
|
||||
|
||||
Far::TopologyRefiner * _refiner;
|
||||
Far::PatchTable * _farPatchTable;
|
||||
|
||||
int _numVertices;
|
||||
int _maxValence;
|
||||
|
||||
VertexBuffer * _vertexBuffer;
|
||||
VertexBuffer * _varyingBuffer;
|
||||
|
||||
BufferDescriptor _vertexDesc;
|
||||
BufferDescriptor _varyingDesc;
|
||||
|
||||
StencilTable const * _vertexStencilTable;
|
||||
StencilTable const * _varyingStencilTable;
|
||||
EvaluatorCache * _evaluatorCache;
|
||||
|
||||
PatchTable *_patchTable;
|
||||
DeviceContext *_deviceContext;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_MESH_H
|
||||
36
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlCommon.h
vendored
Normal file
36
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlCommon.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MTL_COMMON_H
|
||||
#define OPENSUBDIV3_OSD_MTL_COMMON_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
@protocol MTLDevice;
|
||||
@protocol MTLCommandQueue;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class MTLContext {
|
||||
public:
|
||||
id<MTLDevice> device = nullptr;
|
||||
id<MTLCommandQueue> commandQueue = nullptr;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif //OPENSUBDIV3_OSD_MTL_COMMON_H
|
||||
2150
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlComputeEvaluator.h
vendored
Normal file
2150
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlComputeEvaluator.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
595
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlComputeEvaluator.mm
vendored
Normal file
595
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlComputeEvaluator.mm
vendored
Normal file
@@ -0,0 +1,595 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/mtlComputeEvaluator.h"
|
||||
#include "../osd/mtlPatchShaderSource.h"
|
||||
|
||||
#include <vector>
|
||||
#include <Metal/Metal.h>
|
||||
#include <simd/simd.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "../far/stencilTable.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#define PARAMETER_BUFFER_INDEX 0
|
||||
#define SIZES_BUFFER_INDEX 1
|
||||
#define OFFSETS_BUFFER_INDEX 2
|
||||
#define INDICES_BUFFER_INDEX 3
|
||||
#define WEIGHTS_BUFFER_INDEX 4
|
||||
#define DST_VERTEX_BUFFER_INDEX 5
|
||||
#define SRC_VERTEX_BUFFER_INDEX 6
|
||||
#define DU_WEIGHTS_BUFFER_INDEX 7
|
||||
#define DV_WEIGHTS_BUFFER_INDEX 8
|
||||
#define DU_DERIVATIVE_BUFFER_INDEX 9
|
||||
#define DV_DERIVATIVE_BUFFER_INDEX 10
|
||||
#define DUU_WEIGHTS_BUFFER_INDEX 11
|
||||
#define DUV_WEIGHTS_BUFFER_INDEX 12
|
||||
#define DVV_WEIGHTS_BUFFER_INDEX 13
|
||||
#define DUU_DERIVATIVE_BUFFER_INDEX 14
|
||||
#define DUV_DERIVATIVE_BUFFER_INDEX 15
|
||||
#define DVV_DERIVATIVE_BUFFER_INDEX 16
|
||||
#define PATCH_ARRAYS_BUFFER_INDEX 17
|
||||
#define PATCH_COORDS_BUFFER_INDEX 18
|
||||
#define PATCH_INDICES_BUFFER_INDEX 19
|
||||
#define PATCH_PARAMS_BUFFER_INDEX 20
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
namespace Osd {
|
||||
|
||||
namespace mtl
|
||||
{
|
||||
struct PatchCoord
|
||||
{
|
||||
int arrayIndex;
|
||||
int patchIndex;
|
||||
int vertIndex;
|
||||
float s;
|
||||
float t;
|
||||
};
|
||||
|
||||
struct PatchParam
|
||||
{
|
||||
uint field0;
|
||||
uint field1;
|
||||
float sharpness;
|
||||
};
|
||||
|
||||
struct KernelUniformArgs
|
||||
{
|
||||
int batchStart;
|
||||
int batchEnd;
|
||||
|
||||
int srcOffset;
|
||||
int dstOffset;
|
||||
|
||||
simd::int3 duDesc;
|
||||
simd::int3 dvDesc;
|
||||
|
||||
simd::int3 duuDesc;
|
||||
simd::int3 duvDesc;
|
||||
simd::int3 dvvDesc;
|
||||
};
|
||||
} //end namespace mtl
|
||||
|
||||
static const char *KernelSource =
|
||||
#include "mtlComputeKernel.gen.h"
|
||||
;
|
||||
|
||||
template <typename T>
|
||||
static id<MTLBuffer> createBuffer(const std::vector<T> &vec,
|
||||
MTLContext* context)
|
||||
{
|
||||
if (vec.empty()) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
const auto length = sizeof(T) * vec.size();
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
return [context->device newBufferWithBytes:vec.data() length:length options:MTLResourceCPUCacheModeDefaultCache];
|
||||
#elif TARGET_OS_OSX
|
||||
@autoreleasepool {
|
||||
auto cmdBuf = [context->commandQueue commandBuffer];
|
||||
auto blitEncoder = [cmdBuf blitCommandEncoder];
|
||||
|
||||
auto stageBuffer = [context->device newBufferWithBytes:vec.data() length:length options:MTLResourceCPUCacheModeDefaultCache];
|
||||
|
||||
auto finalBuffer = [context->device newBufferWithLength:length options:MTLResourceStorageModePrivate];
|
||||
|
||||
[blitEncoder copyFromBuffer:stageBuffer sourceOffset:0 toBuffer:finalBuffer destinationOffset:0 size:length];
|
||||
[blitEncoder endEncoding];
|
||||
[cmdBuf commit];
|
||||
[cmdBuf waitUntilCompleted];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
[stageBuffer release];
|
||||
#endif
|
||||
|
||||
return finalBuffer;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
using namespace OpenSubdiv::OPENSUBDIV_VERSION;
|
||||
using namespace Osd;
|
||||
|
||||
MTLStencilTable::MTLStencilTable(Far::StencilTable const *stencilTable,
|
||||
MTLContext* context)
|
||||
{
|
||||
assert(context != nil);
|
||||
assert(context->device != nil && context->commandQueue != nil);
|
||||
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0)
|
||||
{
|
||||
auto sizes = stencilTable->GetSizes();
|
||||
|
||||
_sizesBuffer = createBuffer(stencilTable->GetSizes(), context);
|
||||
_offsetsBuffer = createBuffer(stencilTable->GetOffsets(), context);
|
||||
_indicesBuffer = createBuffer(stencilTable->GetControlIndices(), context);
|
||||
_weightsBuffer = createBuffer(stencilTable->GetWeights(), context);
|
||||
|
||||
_sizesBuffer.label = @"StencilTable Sizes";
|
||||
_offsetsBuffer.label = @"StencilTable Offsets";
|
||||
_indicesBuffer.label = @"StencilTable Indices";
|
||||
_weightsBuffer.label = @"StencilTable Weights";
|
||||
}
|
||||
|
||||
_duWeightsBuffer = nil;
|
||||
_dvWeightsBuffer = nil;
|
||||
_duuWeightsBuffer = nil;
|
||||
_duvWeightsBuffer = nil;
|
||||
_dvvWeightsBuffer = nil;
|
||||
}
|
||||
|
||||
MTLStencilTable::MTLStencilTable(Far::LimitStencilTable const *stencilTable,
|
||||
MTLContext* context)
|
||||
{
|
||||
assert(context != nil);
|
||||
assert(context->device != nil && context->commandQueue != nil);
|
||||
|
||||
_numStencils = stencilTable->GetNumStencils();
|
||||
if (_numStencils > 0)
|
||||
{
|
||||
auto sizes = stencilTable->GetSizes();
|
||||
|
||||
_sizesBuffer = createBuffer(stencilTable->GetSizes(), context);
|
||||
_offsetsBuffer = createBuffer(stencilTable->GetOffsets(), context);
|
||||
_indicesBuffer = createBuffer(stencilTable->GetControlIndices(), context);
|
||||
_weightsBuffer = createBuffer(stencilTable->GetWeights(), context);
|
||||
_duWeightsBuffer = createBuffer(stencilTable->GetDuWeights(), context);
|
||||
_dvWeightsBuffer = createBuffer(stencilTable->GetDvWeights(), context);
|
||||
_duuWeightsBuffer = createBuffer(stencilTable->GetDuuWeights(), context);
|
||||
_duvWeightsBuffer = createBuffer(stencilTable->GetDuvWeights(), context);
|
||||
_dvvWeightsBuffer = createBuffer(stencilTable->GetDvvWeights(), context);
|
||||
|
||||
_sizesBuffer.label = @"StencilTable Sizes";
|
||||
_offsetsBuffer.label = @"StencilTable Offsets";
|
||||
_indicesBuffer.label = @"StencilTable Indices";
|
||||
_weightsBuffer.label = @"StencilTable Weights";
|
||||
if (_duWeightsBuffer) {
|
||||
_duWeightsBuffer.label = @"StencilTable duWeights";
|
||||
}
|
||||
if (_dvWeightsBuffer) {
|
||||
_dvWeightsBuffer.label = @"StencilTable dvWeights";
|
||||
}
|
||||
if (_duuWeightsBuffer) {
|
||||
_duuWeightsBuffer.label = @"StencilTable duuWeights";
|
||||
}
|
||||
if (_duvWeightsBuffer) {
|
||||
_duvWeightsBuffer.label = @"StencilTable duvWeights";
|
||||
}
|
||||
if (_dvvWeightsBuffer) {
|
||||
_dvvWeightsBuffer.label = @"StencilTable dvvWeights";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MTLStencilTable::~MTLStencilTable() {}
|
||||
|
||||
MTLComputeEvaluator *MTLComputeEvaluator::Create(
|
||||
BufferDescriptor const &srcDesc, BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc, BufferDescriptor const &dvDesc,
|
||||
MTLContext* context)
|
||||
{
|
||||
assert(context != nil);
|
||||
assert(context->device != nil && context->commandQueue != nil);
|
||||
|
||||
auto instance = new MTLComputeEvaluator();
|
||||
if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc,
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
BufferDescriptor(),
|
||||
context))
|
||||
return instance;
|
||||
|
||||
delete instance;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MTLComputeEvaluator *MTLComputeEvaluator::Create(
|
||||
BufferDescriptor const &srcDesc, BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc, BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc, BufferDescriptor const &duvDesc, BufferDescriptor const &dvvDesc,
|
||||
MTLContext* context)
|
||||
{
|
||||
assert(context != nil);
|
||||
assert(context->device != nil && context->commandQueue != nil);
|
||||
|
||||
auto instance = new MTLComputeEvaluator();
|
||||
if (instance->Compile(srcDesc, dstDesc, duDesc, dvDesc,
|
||||
duuDesc, duvDesc, dvvDesc, context)) {
|
||||
return instance;
|
||||
}
|
||||
|
||||
delete instance;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool MTLComputeEvaluator::Compile(BufferDescriptor const &srcDesc,
|
||||
BufferDescriptor const &dstDesc,
|
||||
BufferDescriptor const &duDesc,
|
||||
BufferDescriptor const &dvDesc,
|
||||
BufferDescriptor const &duuDesc,
|
||||
BufferDescriptor const &duvDesc,
|
||||
BufferDescriptor const &dvvDesc,
|
||||
MTLContext* context)
|
||||
{
|
||||
assert(context != nil);
|
||||
assert(context->device != nil && context->commandQueue != nil);
|
||||
|
||||
using namespace Osd;
|
||||
using namespace Far;
|
||||
|
||||
MTLCompileOptions *compileOptions = [[MTLCompileOptions alloc] init];
|
||||
compileOptions.preprocessorMacros = nil;
|
||||
|
||||
bool deriv1 = duDesc.length > 0 || dvDesc.length > 0;
|
||||
bool deriv2 = duuDesc.length > 0 || duvDesc.length > 0 || dvvDesc.length > 0;
|
||||
|
||||
#define DEFINE(x,y) @(#x) : @(y)
|
||||
auto preprocessor = @{
|
||||
DEFINE(LENGTH, srcDesc.length),
|
||||
DEFINE(SRC_STRIDE, srcDesc.stride),
|
||||
DEFINE(DST_STRIDE, dstDesc.stride),
|
||||
DEFINE(WORK_GROUP_SIZE, _workGroupSize),
|
||||
DEFINE(OPENSUBDIV_MTL_COMPUTE_USE_1ST_DERIVATIVES, deriv1),
|
||||
DEFINE(OPENSUBDIV_MTL_COMPUTE_USE_2ND_DERIVATIVES, deriv2),
|
||||
DEFINE(PARAMETER_BUFFER_INDEX,PARAMETER_BUFFER_INDEX),
|
||||
DEFINE(SIZES_BUFFER_INDEX,SIZES_BUFFER_INDEX),
|
||||
DEFINE(OFFSETS_BUFFER_INDEX,OFFSETS_BUFFER_INDEX),
|
||||
DEFINE(INDICES_BUFFER_INDEX,INDICES_BUFFER_INDEX),
|
||||
DEFINE(WEIGHTS_BUFFER_INDEX,WEIGHTS_BUFFER_INDEX),
|
||||
DEFINE(SRC_VERTEX_BUFFER_INDEX,SRC_VERTEX_BUFFER_INDEX),
|
||||
DEFINE(DST_VERTEX_BUFFER_INDEX,DST_VERTEX_BUFFER_INDEX),
|
||||
DEFINE(DU_WEIGHTS_BUFFER_INDEX,DU_WEIGHTS_BUFFER_INDEX),
|
||||
DEFINE(DV_WEIGHTS_BUFFER_INDEX,DV_WEIGHTS_BUFFER_INDEX),
|
||||
DEFINE(DU_DERIVATIVE_BUFFER_INDEX,DU_DERIVATIVE_BUFFER_INDEX),
|
||||
DEFINE(DV_DERIVATIVE_BUFFER_INDEX,DV_DERIVATIVE_BUFFER_INDEX),
|
||||
DEFINE(DUU_WEIGHTS_BUFFER_INDEX,DUU_WEIGHTS_BUFFER_INDEX),
|
||||
DEFINE(DUV_WEIGHTS_BUFFER_INDEX,DUV_WEIGHTS_BUFFER_INDEX),
|
||||
DEFINE(DVV_WEIGHTS_BUFFER_INDEX,DVV_WEIGHTS_BUFFER_INDEX),
|
||||
DEFINE(DUU_DERIVATIVE_BUFFER_INDEX,DUU_DERIVATIVE_BUFFER_INDEX),
|
||||
DEFINE(DUV_DERIVATIVE_BUFFER_INDEX,DUV_DERIVATIVE_BUFFER_INDEX),
|
||||
DEFINE(DVV_DERIVATIVE_BUFFER_INDEX,DVV_DERIVATIVE_BUFFER_INDEX),
|
||||
DEFINE(PATCH_ARRAYS_BUFFER_INDEX,PATCH_ARRAYS_BUFFER_INDEX),
|
||||
DEFINE(PATCH_COORDS_BUFFER_INDEX,PATCH_COORDS_BUFFER_INDEX),
|
||||
DEFINE(PATCH_INDICES_BUFFER_INDEX,PATCH_INDICES_BUFFER_INDEX),
|
||||
DEFINE(PATCH_PARAMS_BUFFER_INDEX,PATCH_PARAMS_BUFFER_INDEX),
|
||||
};
|
||||
#undef DEFINE
|
||||
|
||||
compileOptions.preprocessorMacros = preprocessor;
|
||||
|
||||
std::stringstream sourceString;
|
||||
sourceString << MTLPatchShaderSource::GetPatchBasisShaderSource();
|
||||
sourceString << KernelSource;
|
||||
|
||||
NSError *err = nil;
|
||||
|
||||
_computeLibrary =
|
||||
[context->device newLibraryWithSource:@(sourceString.str().c_str())
|
||||
options:compileOptions
|
||||
error:&err];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
[compileOptions release];
|
||||
#endif
|
||||
|
||||
if (!_computeLibrary)
|
||||
{
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Shader: %s\n",
|
||||
err ? err.localizedDescription.UTF8String : "");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto evalStencilsFunction = [_computeLibrary newFunctionWithName:@"eval_stencils"];
|
||||
_evalStencils =
|
||||
[context->device newComputePipelineStateWithFunction:evalStencilsFunction
|
||||
error:&err];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
[evalStencilsFunction release];
|
||||
#endif
|
||||
|
||||
if (!_evalStencils)
|
||||
{
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Pipeline eval_stencils: %s\n",
|
||||
err ? err.localizedDescription.UTF8String : "");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto evalPatchesFunction = [_computeLibrary newFunctionWithName:@"eval_patches"];
|
||||
_evalPatches =
|
||||
[context->device newComputePipelineStateWithFunction:evalPatchesFunction
|
||||
error:&err];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
[evalPatchesFunction release];
|
||||
#endif
|
||||
|
||||
if (!_evalPatches)
|
||||
{
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "Error compiling MTL Pipeline eval_patches: %s\n",
|
||||
err ? err.localizedDescription.UTF8String : "");
|
||||
return false;
|
||||
}
|
||||
|
||||
_parameterBuffer =
|
||||
[context->device newBufferWithLength:sizeof(mtl::KernelUniformArgs)
|
||||
options:MTLResourceCPUCacheModeDefaultCache];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MTLComputeEvaluator::MTLComputeEvaluator() : _workGroupSize(32) {}
|
||||
|
||||
MTLComputeEvaluator::~MTLComputeEvaluator()
|
||||
{
|
||||
#if !__has_feature(objc_arc)
|
||||
[_computeLibrary release];
|
||||
[_evalStencils release];
|
||||
[_evalPatches release];
|
||||
[_parameterBuffer release];
|
||||
#endif
|
||||
}
|
||||
|
||||
void MTLComputeEvaluator::Synchronize(MTLContext*) { }
|
||||
|
||||
bool MTLComputeEvaluator::EvalStencils(
|
||||
id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
|
||||
id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
|
||||
id<MTLBuffer> duBuffer, BufferDescriptor const &duDesc,
|
||||
id<MTLBuffer> dvBuffer, BufferDescriptor const &dvDesc,
|
||||
id<MTLBuffer> sizesBuffer,
|
||||
id<MTLBuffer> offsetsBuffer,
|
||||
id<MTLBuffer> indicesBuffer,
|
||||
id<MTLBuffer> weightsBuffer,
|
||||
id<MTLBuffer> duWeightsBuffer,
|
||||
id<MTLBuffer> dvWeightsBuffer,
|
||||
int start, int end,
|
||||
MTLContext* context) const
|
||||
{
|
||||
return EvalStencils(
|
||||
srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
duBuffer, duDesc,
|
||||
dvBuffer, dvDesc,
|
||||
nil, BufferDescriptor(),
|
||||
nil, BufferDescriptor(),
|
||||
nil, BufferDescriptor(),
|
||||
sizesBuffer,
|
||||
offsetsBuffer,
|
||||
indicesBuffer,
|
||||
weightsBuffer,
|
||||
duWeightsBuffer,
|
||||
dvWeightsBuffer,
|
||||
nil, nil, nil,
|
||||
start, end,
|
||||
context);
|
||||
}
|
||||
|
||||
bool MTLComputeEvaluator::EvalStencils(
|
||||
id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
|
||||
id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
|
||||
id<MTLBuffer> duBuffer, BufferDescriptor const &duDesc,
|
||||
id<MTLBuffer> dvBuffer, BufferDescriptor const &dvDesc,
|
||||
id<MTLBuffer> duuBuffer, BufferDescriptor const &duuDesc,
|
||||
id<MTLBuffer> duvBuffer, BufferDescriptor const &duvDesc,
|
||||
id<MTLBuffer> dvvBuffer, BufferDescriptor const &dvvDesc,
|
||||
id<MTLBuffer> sizesBuffer,
|
||||
id<MTLBuffer> offsetsBuffer,
|
||||
id<MTLBuffer> indicesBuffer,
|
||||
id<MTLBuffer> weightsBuffer,
|
||||
id<MTLBuffer> duWeightsBuffer,
|
||||
id<MTLBuffer> dvWeightsBuffer,
|
||||
id<MTLBuffer> duuWeightsBuffer,
|
||||
id<MTLBuffer> duvWeightsBuffer,
|
||||
id<MTLBuffer> dvvWeightsBuffer,
|
||||
int start, int end,
|
||||
MTLContext* context) const
|
||||
{
|
||||
if(_evalStencils == nil)
|
||||
return false;
|
||||
|
||||
auto count = end - start;
|
||||
if (count <= 0)
|
||||
return true;
|
||||
|
||||
assert(context != nullptr);
|
||||
|
||||
auto device = context->device;
|
||||
auto commandQueue = context->commandQueue;
|
||||
|
||||
assert(device != nil && commandQueue != nil);
|
||||
|
||||
mtl::KernelUniformArgs args;
|
||||
args.batchStart = start;
|
||||
args.batchEnd = end;
|
||||
args.srcOffset = srcDesc.offset;
|
||||
args.dstOffset = dstDesc.offset;
|
||||
args.duDesc = (simd::int3){duDesc.offset, duDesc.length, duDesc.stride};
|
||||
args.dvDesc = (simd::int3){dvDesc.offset, dvDesc.length, dvDesc.stride};
|
||||
args.duuDesc = (simd::int3){duuDesc.offset, duuDesc.length, duuDesc.stride};
|
||||
args.duvDesc = (simd::int3){duvDesc.offset, duvDesc.length, duvDesc.stride};
|
||||
args.dvvDesc = (simd::int3){dvvDesc.offset, dvvDesc.length, dvvDesc.stride};
|
||||
|
||||
memcpy(_parameterBuffer.contents, &args, sizeof(args));
|
||||
|
||||
auto commandBuffer = [commandQueue commandBuffer];
|
||||
|
||||
auto computeEncoder = [commandBuffer computeCommandEncoder];
|
||||
|
||||
[computeEncoder setBuffer:_parameterBuffer offset:0 atIndex:PARAMETER_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:sizesBuffer offset:0 atIndex:SIZES_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:weightsBuffer offset:0 atIndex:WEIGHTS_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:offsetsBuffer offset:0 atIndex:OFFSETS_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:indicesBuffer offset:0 atIndex:INDICES_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:srcBuffer offset:0 atIndex:SRC_VERTEX_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:dstBuffer offset:0 atIndex:DST_VERTEX_BUFFER_INDEX];
|
||||
if(duWeightsBuffer && dvWeightsBuffer)
|
||||
{
|
||||
[computeEncoder setBuffer:duWeightsBuffer offset:0 atIndex:DU_WEIGHTS_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:dvWeightsBuffer offset:0 atIndex:DV_WEIGHTS_BUFFER_INDEX];
|
||||
}
|
||||
[computeEncoder setBuffer:duBuffer offset:0 atIndex:DU_DERIVATIVE_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:dvBuffer offset:0 atIndex:DV_DERIVATIVE_BUFFER_INDEX];
|
||||
if(duuWeightsBuffer && duvWeightsBuffer && dvvWeightsBuffer)
|
||||
{
|
||||
[computeEncoder setBuffer:duuWeightsBuffer offset:0 atIndex:DUU_WEIGHTS_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:duvWeightsBuffer offset:0 atIndex:DUV_WEIGHTS_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:dvvWeightsBuffer offset:0 atIndex:DVV_WEIGHTS_BUFFER_INDEX];
|
||||
}
|
||||
if(duuBuffer && duvBuffer && dvvBuffer)
|
||||
{
|
||||
[computeEncoder setBuffer:duuBuffer offset:0 atIndex:DUU_DERIVATIVE_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:duvBuffer offset:0 atIndex:DUV_DERIVATIVE_BUFFER_INDEX];
|
||||
[computeEncoder setBuffer:dvvBuffer offset:0 atIndex:DVV_DERIVATIVE_BUFFER_INDEX];
|
||||
}
|
||||
[computeEncoder setComputePipelineState:_evalStencils];
|
||||
|
||||
auto threadgroups = MTLSizeMake((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
auto threadsPerGroup = MTLSizeMake(_workGroupSize, 1, 1);
|
||||
[computeEncoder dispatchThreadgroups:threadgroups
|
||||
threadsPerThreadgroup:threadsPerGroup];
|
||||
|
||||
[computeEncoder endEncoding];
|
||||
[commandBuffer commit];
|
||||
[commandBuffer waitUntilCompleted];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MTLComputeEvaluator::EvalPatches(
|
||||
id<MTLBuffer> srcBuffer, const BufferDescriptor &srcDesc,
|
||||
id<MTLBuffer> dstBuffer, const BufferDescriptor &dstDesc,
|
||||
id<MTLBuffer> duBuffer, const BufferDescriptor &duDesc,
|
||||
id<MTLBuffer> dvBuffer, const BufferDescriptor &dvDesc,
|
||||
int numPatchCoords,
|
||||
id<MTLBuffer> patchCoordsBuffer,
|
||||
const PatchArrayVector &patchArrays,
|
||||
id<MTLBuffer> patchIndexBuffer,
|
||||
id<MTLBuffer> patchParamsBuffer,
|
||||
MTLContext* context) const
|
||||
{
|
||||
return EvalPatches(
|
||||
srcBuffer, srcDesc,
|
||||
dstBuffer, dstDesc,
|
||||
duBuffer, duDesc,
|
||||
dvBuffer, dvDesc,
|
||||
nil, BufferDescriptor(),
|
||||
nil, BufferDescriptor(),
|
||||
nil, BufferDescriptor(),
|
||||
numPatchCoords,
|
||||
patchCoordsBuffer,
|
||||
patchArrays,
|
||||
patchIndexBuffer,
|
||||
patchParamsBuffer,
|
||||
context);
|
||||
}
|
||||
|
||||
bool
|
||||
MTLComputeEvaluator::EvalPatches(
|
||||
id<MTLBuffer> srcBuffer, const BufferDescriptor &srcDesc,
|
||||
id<MTLBuffer> dstBuffer, const BufferDescriptor &dstDesc,
|
||||
id<MTLBuffer> duBuffer, const BufferDescriptor &duDesc,
|
||||
id<MTLBuffer> dvBuffer, const BufferDescriptor &dvDesc,
|
||||
id<MTLBuffer> duuBuffer, const BufferDescriptor &duuDesc,
|
||||
id<MTLBuffer> duvBuffer, const BufferDescriptor &duvDesc,
|
||||
id<MTLBuffer> dvvBuffer, const BufferDescriptor &dvvDesc,
|
||||
int numPatchCoords,
|
||||
id<MTLBuffer> patchCoordsBuffer,
|
||||
const PatchArrayVector &patchArrays,
|
||||
id<MTLBuffer> patchIndexBuffer,
|
||||
id<MTLBuffer> patchParamsBuffer,
|
||||
MTLContext* context) const
|
||||
{
|
||||
if(_evalPatches == nil)
|
||||
return false;
|
||||
|
||||
assert(context != nullptr);
|
||||
|
||||
auto device = context->device;
|
||||
auto commandQueue = context->commandQueue;
|
||||
|
||||
assert(device != nil && commandQueue != nil);
|
||||
|
||||
auto commandBuffer = [commandQueue commandBuffer];
|
||||
auto computeCommandEncoder = [commandBuffer computeCommandEncoder];
|
||||
|
||||
mtl::KernelUniformArgs args;
|
||||
args.batchStart = 0;
|
||||
args.batchEnd = numPatchCoords;
|
||||
args.srcOffset = srcDesc.offset;
|
||||
args.dstOffset = dstDesc.offset;
|
||||
args.duDesc = (simd::int3){duDesc.offset, duDesc.length, duDesc.stride};
|
||||
args.dvDesc = (simd::int3){dvDesc.offset, dvDesc.length, dvDesc.stride};
|
||||
args.duuDesc = (simd::int3){duuDesc.offset, duuDesc.length, duuDesc.stride};
|
||||
args.duvDesc = (simd::int3){duvDesc.offset, duvDesc.length, duvDesc.stride};
|
||||
args.dvvDesc = (simd::int3){dvvDesc.offset, dvvDesc.length, dvvDesc.stride};
|
||||
|
||||
[computeCommandEncoder setBytes:&args length:sizeof(mtl::KernelUniformArgs) atIndex:PARAMETER_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:srcBuffer offset:0 atIndex:SRC_VERTEX_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:dstBuffer offset:0 atIndex:DST_VERTEX_BUFFER_INDEX];
|
||||
if (duBuffer && dvBuffer) {
|
||||
[computeCommandEncoder setBuffer:duBuffer offset:0 atIndex:DU_DERIVATIVE_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:dvBuffer offset:0 atIndex:DV_DERIVATIVE_BUFFER_INDEX];
|
||||
}
|
||||
if (duuBuffer && duvBuffer && dvvBuffer) {
|
||||
[computeCommandEncoder setBuffer:duuBuffer offset:0 atIndex:DUU_DERIVATIVE_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:duvBuffer offset:0 atIndex:DUV_DERIVATIVE_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:dvvBuffer offset:0 atIndex:DVV_DERIVATIVE_BUFFER_INDEX];
|
||||
}
|
||||
[computeCommandEncoder setBuffer:patchCoordsBuffer offset:0 atIndex:PATCH_COORDS_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:patchIndexBuffer offset:0 atIndex:PATCH_INDICES_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBuffer:patchParamsBuffer offset:0 atIndex:PATCH_PARAMS_BUFFER_INDEX];
|
||||
assert(!patchArrays.empty());
|
||||
[computeCommandEncoder setBytes:&patchArrays[0] length:sizeof(patchArrays[0]) * patchArrays.size() atIndex:PATCH_ARRAYS_BUFFER_INDEX];
|
||||
[computeCommandEncoder setComputePipelineState:_evalPatches];
|
||||
|
||||
auto threadgroups =
|
||||
MTLSizeMake((numPatchCoords + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
auto threadsPerGroup = MTLSizeMake(_workGroupSize, 1, 1);
|
||||
[computeCommandEncoder dispatchThreadgroups:threadgroups
|
||||
threadsPerThreadgroup:threadsPerGroup];
|
||||
|
||||
[computeCommandEncoder endEncoding];
|
||||
[commandBuffer commit];
|
||||
[commandBuffer waitUntilCompleted];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} //end namespace Osd
|
||||
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
} //end namespace OpenSubdiv
|
||||
301
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlComputeKernel.metal
vendored
Normal file
301
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlComputeKernel.metal
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
#line 0 "osd/mtlComputeKernel.metal"
|
||||
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include <metal_stdlib>
|
||||
|
||||
#ifndef OPENSUBDIV_MTL_COMPUTE_USE_1ST_DERIVATIVES
|
||||
#define OPENSUBDIV_MTL_COMPUTE_USE_1ST_DERIVATIVES 0
|
||||
#endif
|
||||
|
||||
#ifndef OPENSUBDIV_MTL_COMPUTE_USE_2ND_DERIVATIVES
|
||||
#define OPENSUBDIV_MTL_COMPUTE_USE_2ND_DERIVATIVES 0
|
||||
#endif
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct KernelUniformArgs
|
||||
{
|
||||
int batchStart;
|
||||
int batchEnd;
|
||||
|
||||
int srcOffset;
|
||||
int dstOffset;
|
||||
|
||||
int3 duDesc;
|
||||
int3 dvDesc;
|
||||
|
||||
int3 duuDesc;
|
||||
int3 duvDesc;
|
||||
int3 dvvDesc;
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
float vertexData[LENGTH];
|
||||
};
|
||||
|
||||
void clear(thread Vertex& v) {
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vertex readVertex(int index, device const float* vertexBuffer, KernelUniformArgs args) {
|
||||
Vertex v;
|
||||
int vertexIndex = args.srcOffset + index * SRC_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] = vertexBuffer[vertexIndex + i];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void writeVertex(int index, Vertex v, device float* vertexBuffer, KernelUniformArgs args) {
|
||||
int vertexIndex = args.dstOffset + index * DST_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
vertexBuffer[vertexIndex + i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeVertexSeparate(int index, Vertex v, device float* dstVertexBuffer, KernelUniformArgs args) {
|
||||
int vertexIndex = args.dstOffset + index * DST_STRIDE;
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
dstVertexBuffer[vertexIndex + i] = v.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void addWithWeight(thread Vertex& v, const Vertex src, float weight) {
|
||||
for (int i = 0; i < LENGTH; ++i) {
|
||||
v.vertexData[i] += weight * src.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_1ST_DERIVATIVES
|
||||
void writeDu(int index, Vertex du, device float* duDerivativeBuffer, KernelUniformArgs args)
|
||||
{
|
||||
int duIndex = args.duDesc.x + index * args.duDesc.z;
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
duDerivativeBuffer[duIndex + i] = du.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDv(int index, Vertex dv, device float* dvDerivativeBuffer, KernelUniformArgs args)
|
||||
{
|
||||
int dvIndex = args.dvDesc.x + index * args.dvDesc.z;
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
dvDerivativeBuffer[dvIndex + i] = dv.vertexData[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_2ND_DERIVATIVES
|
||||
void writeDuu(int index, Vertex duu, device float* duuDerivativeBuffer, KernelUniformArgs args)
|
||||
{
|
||||
int duuIndex = args.duuDesc.x + index * args.duuDesc.z;
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
duuDerivativeBuffer[duuIndex + i] = duu.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDuv(int index, Vertex duv, device float* duvDerivativeBuffer, KernelUniformArgs args)
|
||||
{
|
||||
int duvIndex = args.duvDesc.x + index * args.duvDesc.z;
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
duvDerivativeBuffer[duvIndex + i] = duv.vertexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
void writeDvv(int index, Vertex dvv, device float* dvvDerivativeBuffer, KernelUniformArgs args)
|
||||
{
|
||||
int dvvIndex = args.dvvDesc.x + index * args.dvvDesc.z;
|
||||
for(int i = 0; i < LENGTH; i++) {
|
||||
dvvDerivativeBuffer[dvvIndex + i] = dvv.vertexData[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
kernel void eval_stencils(
|
||||
uint thread_position_in_grid [[thread_position_in_grid]],
|
||||
const device int* sizes [[buffer(SIZES_BUFFER_INDEX)]],
|
||||
const device int* offsets [[buffer(OFFSETS_BUFFER_INDEX)]],
|
||||
const device int* indices [[buffer(INDICES_BUFFER_INDEX)]],
|
||||
const device float* weights [[buffer(WEIGHTS_BUFFER_INDEX)]],
|
||||
const device float* srcVertices [[buffer(SRC_VERTEX_BUFFER_INDEX)]],
|
||||
device float* dstVertexBuffer [[buffer(DST_VERTEX_BUFFER_INDEX)]],
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_1ST_DERIVATIVES
|
||||
const device float* duWeights [[buffer(DU_WEIGHTS_BUFFER_INDEX)]],
|
||||
const device float* dvWeights [[buffer(DV_WEIGHTS_BUFFER_INDEX)]],
|
||||
device float* duDerivativeBuffer [[buffer(DU_DERIVATIVE_BUFFER_INDEX)]],
|
||||
device float* dvDerivativeBuffer [[buffer(DV_DERIVATIVE_BUFFER_INDEX)]],
|
||||
#endif
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_2ND_DERIVATIVES
|
||||
const device float* duuWeights [[buffer(DUU_WEIGHTS_BUFFER_INDEX)]],
|
||||
const device float* duvWeights [[buffer(DUV_WEIGHTS_BUFFER_INDEX)]],
|
||||
const device float* dvvWeights [[buffer(DVV_WEIGHTS_BUFFER_INDEX)]],
|
||||
device float* duuDerivativeBuffer [[buffer(DUU_DERIVATIVE_BUFFER_INDEX)]],
|
||||
device float* duvDerivativeBuffer [[buffer(DUV_DERIVATIVE_BUFFER_INDEX)]],
|
||||
device float* dvvDerivativeBuffer [[buffer(DVV_DERIVATIVE_BUFFER_INDEX)]],
|
||||
#endif
|
||||
const constant KernelUniformArgs& args [[buffer(PARAMETER_BUFFER_INDEX)]]
|
||||
)
|
||||
{
|
||||
auto current = thread_position_in_grid + args.batchStart;
|
||||
if(current >= (unsigned int)args.batchEnd)
|
||||
return;
|
||||
|
||||
Vertex dst;
|
||||
clear(dst);
|
||||
|
||||
|
||||
auto offset = offsets[current];
|
||||
auto size = sizes[current];
|
||||
|
||||
for(auto stencil = 0; stencil < size; stencil++)
|
||||
{
|
||||
auto vindex = offset + stencil;
|
||||
addWithWeight(dst, readVertex(indices[vindex], srcVertices, args), weights[vindex]);
|
||||
}
|
||||
|
||||
writeVertex(current, dst, dstVertexBuffer, args);
|
||||
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_1ST_DERIVATIVES
|
||||
Vertex du, dv;
|
||||
clear(du);
|
||||
clear(dv);
|
||||
|
||||
|
||||
for(auto i = 0; i < size; i++)
|
||||
{
|
||||
auto src = readVertex(indices[offset + i], srcVertices, args);
|
||||
addWithWeight(du, src, duWeights[offset + i]);
|
||||
addWithWeight(dv, src, dvWeights[offset + i]);
|
||||
}
|
||||
|
||||
writeDu(current, du, duDerivativeBuffer, args);
|
||||
writeDv(current, dv, dvDerivativeBuffer, args);
|
||||
#endif
|
||||
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_2ND_DERIVATIVES
|
||||
Vertex duu, duv, dvv;
|
||||
clear(duu);
|
||||
clear(duv);
|
||||
clear(dvv);
|
||||
|
||||
|
||||
for(auto i = 0; i < size; i++)
|
||||
{
|
||||
auto src = readVertex(indices[offset + i], srcVertices, args);
|
||||
addWithWeight(duu, src, duuWeights[offset + i]);
|
||||
addWithWeight(duv, src, duvWeights[offset + i]);
|
||||
addWithWeight(dvv, src, dvvWeights[offset + i]);
|
||||
}
|
||||
|
||||
writeDuu(current, duu, duuDerivativeBuffer, args);
|
||||
writeDuv(current, duv, duvDerivativeBuffer, args);
|
||||
writeDvv(current, dvv, dvvDerivativeBuffer, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// PERFORMANCE: stride could be constant, but not as significant as length
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
kernel void eval_patches(
|
||||
uint thread_position_in_grid [[thread_position_in_grid]],
|
||||
const constant int* patchArrays [[buffer(PATCH_ARRAYS_BUFFER_INDEX)]],
|
||||
const device int* patchCoords [[buffer(PATCH_COORDS_BUFFER_INDEX)]],
|
||||
const device int* patchIndices [[buffer(PATCH_INDICES_BUFFER_INDEX)]],
|
||||
const device uint* patchParams [[buffer(PATCH_PARAMS_BUFFER_INDEX)]],
|
||||
const device float* srcVertexBuffer [[buffer(SRC_VERTEX_BUFFER_INDEX)]],
|
||||
device float* dstVertexBuffer [[buffer(DST_VERTEX_BUFFER_INDEX)]],
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_1ST_DERIVATIVES
|
||||
device float* duDerivativeBuffer [[buffer(DU_DERIVATIVE_BUFFER_INDEX)]],
|
||||
device float* dvDerivativeBuffer [[buffer(DV_DERIVATIVE_BUFFER_INDEX)]],
|
||||
#endif
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_2ND_DERIVATIVES
|
||||
device float* duuDerivativeBuffer [[buffer(DUU_DERIVATIVE_BUFFER_INDEX)]],
|
||||
device float* duvDerivativeBuffer [[buffer(DUV_DERIVATIVE_BUFFER_INDEX)]],
|
||||
device float* dvvDerivativeBuffer [[buffer(DVV_DERIVATIVE_BUFFER_INDEX)]],
|
||||
#endif
|
||||
const constant KernelUniformArgs& args [[buffer(PARAMETER_BUFFER_INDEX)]]
|
||||
)
|
||||
{
|
||||
auto current = thread_position_in_grid;
|
||||
|
||||
// unpack struct (5 ints unaligned)
|
||||
OsdPatchCoord patchCoord = OsdPatchCoordInit(patchCoords[current*5+0],
|
||||
patchCoords[current*5+1],
|
||||
patchCoords[current*5+2],
|
||||
as_type<float>(patchCoords[current*5+3]),
|
||||
as_type<float>(patchCoords[current*5+4]));
|
||||
|
||||
OsdPatchArray patchArray = OsdPatchArrayInit(patchArrays[patchCoord.arrayIndex*6+0],
|
||||
patchArrays[patchCoord.arrayIndex*6+1],
|
||||
patchArrays[patchCoord.arrayIndex*6+2],
|
||||
patchArrays[patchCoord.arrayIndex*6+3],
|
||||
patchArrays[patchCoord.arrayIndex*6+4],
|
||||
patchArrays[patchCoord.arrayIndex*6+5]);
|
||||
|
||||
OsdPatchParam patchParam = OsdPatchParamInit(patchParams[patchCoord.patchIndex*3+0],
|
||||
patchParams[patchCoord.patchIndex*3+1],
|
||||
as_type<float>(patchParams[patchCoord.patchIndex*3+2]));
|
||||
|
||||
int patchType = OsdPatchParamIsRegular(patchParam)
|
||||
? patchArray.regDesc : patchArray.desc;
|
||||
|
||||
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
|
||||
int nPoints = OsdEvaluatePatchBasis(patchType, patchParam,
|
||||
patchCoord.s, patchCoord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
|
||||
|
||||
Vertex dst, du, dv, duu, duv, dvv;
|
||||
clear(dst);
|
||||
clear(du);
|
||||
clear(dv);
|
||||
clear(duu);
|
||||
clear(duv);
|
||||
clear(dvv);
|
||||
|
||||
auto indexBase = patchArray.indexBase + patchArray.stride *
|
||||
(patchCoord.patchIndex - patchArray.primitiveIdBase);
|
||||
for(auto cv = 0; cv < nPoints; cv++)
|
||||
{
|
||||
auto index = patchIndices[indexBase + cv];
|
||||
auto src = readVertex(index, srcVertexBuffer, args);
|
||||
addWithWeight(dst, src, wP[cv]);
|
||||
addWithWeight(du, src, wDu[cv]);
|
||||
addWithWeight(dv, src, wDv[cv]);
|
||||
addWithWeight(duu, src, wDuu[cv]);
|
||||
addWithWeight(duv, src, wDuv[cv]);
|
||||
addWithWeight(dvv, src, wDvv[cv]);
|
||||
}
|
||||
|
||||
writeVertex(current, dst, dstVertexBuffer, args);
|
||||
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_1ST_DERIVATIVES
|
||||
if(args.duDesc.y > 0)
|
||||
writeDu(current, du, duDerivativeBuffer, args);
|
||||
|
||||
if(args.dvDesc.y > 0)
|
||||
writeDv(current, dv, dvDerivativeBuffer, args);
|
||||
#endif
|
||||
|
||||
#if OPENSUBDIV_MTL_COMPUTE_USE_2ND_DERIVATIVES
|
||||
if(args.duuDesc.y > 0)
|
||||
writeDuu(current, duu, duuDerivativeBuffer, args);
|
||||
|
||||
if(args.duvDesc.y > 0)
|
||||
writeDuv(current, duv, duvDerivativeBuffer, args);
|
||||
|
||||
if(args.dvvDesc.y > 0)
|
||||
writeDvv(current, dvv, dvvDerivativeBuffer, args);
|
||||
#endif
|
||||
}
|
||||
75
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlLegacyGregoryPatchTable.h
vendored
Normal file
75
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlLegacyGregoryPatchTable.h
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MTL_LEGACY_GREGORY_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_OSD_MTL_LEGACY_GREGORY_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../far/patchTable.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/mtlCommon.h"
|
||||
|
||||
@protocol MTLDevice;
|
||||
@protocol MTLBuffer;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class MTLLegacyGregoryPatchTable
|
||||
: private NonCopyable<MTLLegacyGregoryPatchTable>
|
||||
{
|
||||
public:
|
||||
~MTLLegacyGregoryPatchTable();
|
||||
|
||||
template<typename DEVICE_CONTEXT>
|
||||
static MTLLegacyGregoryPatchTable* Create(Far::PatchTable const* farPatchTable, DEVICE_CONTEXT context) {
|
||||
return Create(farPatchTable, context);
|
||||
}
|
||||
|
||||
static MTLLegacyGregoryPatchTable* Create(Far::PatchTable const* farPatchTable, MTLContext* context);
|
||||
|
||||
void UpdateVertexBuffer(id<MTLBuffer> vbo, int numVertices, int numVertexElements, MTLContext* context);
|
||||
|
||||
id<MTLBuffer> GetVertexBuffer() const
|
||||
{
|
||||
return _vertexBuffer;
|
||||
}
|
||||
|
||||
id<MTLBuffer> GetVertexValenceBuffer() const
|
||||
{
|
||||
return _vertexValenceBuffer;
|
||||
}
|
||||
|
||||
id<MTLBuffer> GetQuadOffsetsBuffer() const
|
||||
{
|
||||
return _quadOffsetsBuffer;
|
||||
}
|
||||
|
||||
int GetQuadOffsetsBase(Far::PatchDescriptor::Type type)
|
||||
{
|
||||
if(type == Far::PatchDescriptor::GREGORY_BOUNDARY)
|
||||
return _quadOffsetsBase[1];
|
||||
return _quadOffsetsBase[0];
|
||||
}
|
||||
|
||||
private:
|
||||
id<MTLBuffer> _vertexBuffer;
|
||||
id<MTLBuffer> _vertexValenceBuffer;
|
||||
id<MTLBuffer> _quadOffsetsBuffer;
|
||||
int _quadOffsetsBase[2];
|
||||
};
|
||||
|
||||
} //end namespace Osd
|
||||
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} //end namespace OpenSuddiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_MTL_LEGACY_GREGORY_PATCH_TABLE_H
|
||||
84
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlLegacyGregoryPatchTable.mm
vendored
Normal file
84
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlLegacyGregoryPatchTable.mm
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/mtlLegacyGregoryPatchTable.h"
|
||||
#include <Metal/Metal.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
namespace Osd {
|
||||
|
||||
static id<MTLBuffer> createBuffer(const void* data, const size_t length,
|
||||
MTLContext* context)
|
||||
{
|
||||
@autoreleasepool {
|
||||
auto cmdBuf = [context->commandQueue commandBuffer];
|
||||
auto blitEncoder = [cmdBuf blitCommandEncoder];
|
||||
|
||||
auto stageBuffer = [context->device newBufferWithBytes:data length:length options:MTLResourceCPUCacheModeDefaultCache];
|
||||
|
||||
auto finalBuffer = [context->device newBufferWithLength:length options:MTLResourceStorageModePrivate];
|
||||
|
||||
[blitEncoder copyFromBuffer:stageBuffer sourceOffset:0 toBuffer:finalBuffer destinationOffset:0 size:length];
|
||||
[blitEncoder endEncoding];
|
||||
[cmdBuf commit];
|
||||
[cmdBuf waitUntilCompleted];
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
[stageBuffer release];
|
||||
#endif
|
||||
|
||||
return finalBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
MTLLegacyGregoryPatchTable::~MTLLegacyGregoryPatchTable()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MTLLegacyGregoryPatchTable* MTLLegacyGregoryPatchTable::Create(const Far::PatchTable *farPatchTable,
|
||||
MTLContext* context)
|
||||
{
|
||||
auto pt = new MTLLegacyGregoryPatchTable();
|
||||
auto& vertexValenceTable = farPatchTable->GetVertexValenceTable();
|
||||
auto& quadOffsetsTable = farPatchTable->GetQuadOffsetsTable();
|
||||
|
||||
if(!vertexValenceTable.empty())
|
||||
{
|
||||
pt->_vertexValenceBuffer = createBuffer(vertexValenceTable.data(), vertexValenceTable.size() * sizeof(vertexValenceTable[0]), context);
|
||||
}
|
||||
|
||||
if(!quadOffsetsTable.empty())
|
||||
{
|
||||
pt->_quadOffsetsBuffer = createBuffer(quadOffsetsTable.data(), quadOffsetsTable.size() * sizeof(quadOffsetsTable[0]), context);
|
||||
}
|
||||
|
||||
pt->_quadOffsetsBase[0] = 0;
|
||||
pt->_quadOffsetsBase[1] = 0;
|
||||
|
||||
for(auto i = 0; i < farPatchTable->GetNumPatchArrays(); i++)
|
||||
{
|
||||
if(farPatchTable->GetPatchArrayDescriptor(i).GetType() == Far::PatchDescriptor::GREGORY)
|
||||
{
|
||||
pt->_quadOffsetsBase[1] = farPatchTable->GetNumPatches(i) * 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pt;
|
||||
}
|
||||
|
||||
void MTLLegacyGregoryPatchTable::UpdateVertexBuffer(id<MTLBuffer> vbo, int, int, MTLContext*)
|
||||
{
|
||||
_vertexBuffer = vbo;
|
||||
}
|
||||
|
||||
} //end namespace Osd
|
||||
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
} //end namespace OpenSubdiv
|
||||
30
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlMesh.h
vendored
Normal file
30
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlMesh.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MTL_MESH_H
|
||||
#define OPENSUBDIV3_OSD_MTL_MESH_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../osd/mesh.h"
|
||||
#include "../osd/mtlPatchTable.h"
|
||||
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
typedef MeshInterface<MTLPatchTable> MTLMeshInterface;
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_MTL_MESH_H
|
||||
8
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlMesh.mm
vendored
Normal file
8
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlMesh.mm
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#import "../osd/mtlMesh.h"
|
||||
217
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchBSpline.metal
vendored
Normal file
217
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchBSpline.metal
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
#line 0 "osd/mtlPatchBSpline.metal"
|
||||
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BSpline.Hull
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerVertex(
|
||||
float4 position,
|
||||
threadgroup HullVertex& hullVertex,
|
||||
int vertexId,
|
||||
float4x4 modelViewProjectionMatrix,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
hullVertex.position = position;
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
float4 clipPos = mul(modelViewProjectionMatrix, position);
|
||||
short3 clip0 = short3(clipPos.x < clipPos.w,
|
||||
clipPos.y < clipPos.w,
|
||||
clipPos.z < clipPos.w);
|
||||
short3 clip1 = short3(clipPos.x > -clipPos.w,
|
||||
clipPos.y > -clipPos.w,
|
||||
clipPos.z > -clipPos.w);
|
||||
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BSpline.Factors
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchBSplineFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
device OsdPerPatchVertexBezier* patch,
|
||||
#if !USE_PTVS_FACTORS
|
||||
device OsdPerPatchTessFactors& patchFactors,
|
||||
#endif
|
||||
device MTLQuadTessellationFactorsHalf& quadFactors
|
||||
)
|
||||
{
|
||||
float4 tessLevelOuter = float4(0);
|
||||
float2 tessLevelInner = float2(0);
|
||||
float4 tessOuterLo = float4(0);
|
||||
float4 tessOuterHi = float4(0);
|
||||
|
||||
#if OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
patch,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(
|
||||
tessLevel,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#endif
|
||||
|
||||
quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
|
||||
quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
|
||||
quadFactors.edgeTessellationFactor[2] = tessLevelOuter[2];
|
||||
quadFactors.edgeTessellationFactor[3] = tessLevelOuter[3];
|
||||
quadFactors.insideTessellationFactor[0] = tessLevelInner[0];
|
||||
quadFactors.insideTessellationFactor[1] = tessLevelInner[1];
|
||||
#if !USE_PTVS_FACTORS
|
||||
patchFactors.tessOuterLo = tessOuterLo;
|
||||
patchFactors.tessOuterHi = tessOuterHi;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OsdComputePerPatchFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
unsigned patchID,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
OsdPatchParamBufferSet osdBuffer,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
device MTLQuadTessellationFactorsHalf& quadFactors
|
||||
)
|
||||
{
|
||||
OsdComputePerPatchBSplineFactors(
|
||||
patchParam,
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
osdBuffer.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
#if !USE_PTVS_FACTORS
|
||||
osdBuffer.patchTessBuffer[patchID],
|
||||
#endif
|
||||
quadFactors
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BSpline.Vertex
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchVertex(
|
||||
int3 patchParam,
|
||||
unsigned ID,
|
||||
unsigned PrimitiveID,
|
||||
unsigned ControlID,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
OsdComputePerPatchVertexBSpline(patchParam, ID,
|
||||
patchVertices, osdBuffers.perPatchVertexBuffer[ControlID]);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BSpline.Domain
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<typename PerPatchVertexBezier>
|
||||
OsdPatchVertex ds_regular_patches(
|
||||
const float tessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
float4 tessOuterLo,
|
||||
float4 tessOuterHi,
|
||||
#endif
|
||||
PerPatchVertexBezier cv,
|
||||
int3 patchParam,
|
||||
float2 domainCoord
|
||||
)
|
||||
{
|
||||
#if USE_PTVS_FACTORS
|
||||
float4 tessOuterLo(0), tessOuterHi(0);
|
||||
OsdGetTessLevelsUniform(tessLevel, patchParam, tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
float2 UV = OsdGetTessParameterization(domainCoord,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
OsdPatchVertex output;
|
||||
|
||||
float3 P = float3(0), dPu = float3(0), dPv = float3(0);
|
||||
float3 N = float3(0), dNu = float3(0), dNv = float3(0);
|
||||
float2 vSegments = float2(0);
|
||||
|
||||
OsdEvalPatchBezier(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv, vSegments);
|
||||
|
||||
output.normal = N;
|
||||
output.tangent = dPu;
|
||||
output.bitangent = dPv;
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
output.vSegments = vSegments;
|
||||
#endif
|
||||
|
||||
output.tessCoord = UV;
|
||||
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
output.position = P;
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_STAGE_IN
|
||||
template<typename PerPatchVertexBezier>
|
||||
#endif
|
||||
OsdPatchVertex OsdComputePatch(
|
||||
float tessLevel,
|
||||
float2 domainCoord,
|
||||
unsigned patchID,
|
||||
#if USE_STAGE_IN
|
||||
PerPatchVertexBezier osdPatch
|
||||
#else
|
||||
OsdVertexBufferSet osdBuffers
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return ds_regular_patches(
|
||||
tessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.tessOuterLo,
|
||||
osdPatch.tessOuterHi,
|
||||
#else
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterLo,
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterHi,
|
||||
#endif
|
||||
#endif
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.cv,
|
||||
osdPatch.patchParam,
|
||||
#else
|
||||
osdBuffers.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers.patchParamBuffer[patchID],
|
||||
#endif
|
||||
domainCoord
|
||||
);
|
||||
}
|
||||
|
||||
219
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchBoxSplineTriangle.metal
vendored
Normal file
219
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchBoxSplineTriangle.metal
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
#line 0 "osd/mtlPatchBoxSplineTriangle.metal"
|
||||
|
||||
//
|
||||
// Copyright 2019 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BoxSplineTriangle.Hull
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerVertex(
|
||||
float4 position,
|
||||
threadgroup HullVertex& hullVertex,
|
||||
int vertexId,
|
||||
float4x4 modelViewProjectionMatrix,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
hullVertex.position = position;
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
float4 clipPos = mul(modelViewProjectionMatrix, position);
|
||||
short3 clip0 = short3(clipPos.x < clipPos.w,
|
||||
clipPos.y < clipPos.w,
|
||||
clipPos.z < clipPos.w);
|
||||
short3 clip1 = short3(clipPos.x > -clipPos.w,
|
||||
clipPos.y > -clipPos.w,
|
||||
clipPos.z > -clipPos.w);
|
||||
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BoxSplineTriangle.Factors
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchBezierTriangleFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
device OsdPerPatchVertexBezier* patch,
|
||||
#if !USE_PTVS_FACTORS
|
||||
device OsdPerPatchTessFactors& patchFactors,
|
||||
#endif
|
||||
device MTLTriangleTessellationFactorsHalf& triFactors
|
||||
)
|
||||
{
|
||||
float4 tessLevelOuter = float4(0);
|
||||
float2 tessLevelInner = float2(0);
|
||||
float4 tessOuterLo = float4(0);
|
||||
float4 tessOuterHi = float4(0);
|
||||
|
||||
#if OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
float3 bezcv[15];
|
||||
for (int i=0; i<15; ++i) {
|
||||
bezcv[i] = patch[i].P;
|
||||
}
|
||||
|
||||
OsdEvalPatchBezierTriangleTessLevels(
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
bezcv,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#else
|
||||
OsdGetTessLevelsUniformTriangle(
|
||||
tessLevel,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#endif
|
||||
|
||||
triFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
|
||||
triFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
|
||||
triFactors.edgeTessellationFactor[2] = tessLevelOuter[2];
|
||||
triFactors.insideTessellationFactor = tessLevelInner[0];
|
||||
#if !USE_PTVS_FACTORS
|
||||
patchFactors.tessOuterLo = tessOuterLo;
|
||||
patchFactors.tessOuterHi = tessOuterHi;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OsdComputePerPatchFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
unsigned patchID,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
OsdPatchParamBufferSet osdBuffer,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
device MTLTriangleTessellationFactorsHalf& triFactors
|
||||
)
|
||||
{
|
||||
OsdComputePerPatchBezierTriangleFactors(
|
||||
patchParam,
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
osdBuffer.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
#if !USE_PTVS_FACTORS
|
||||
osdBuffer.patchTessBuffer[patchID],
|
||||
#endif
|
||||
triFactors
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BoxSplineTriangle.Vertex
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchVertex(
|
||||
int3 patchParam,
|
||||
unsigned ID,
|
||||
unsigned PrimitiveID,
|
||||
unsigned ControlID,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
OsdComputePerPatchVertexBoxSplineTriangle(
|
||||
patchParam, ID, patchVertices,
|
||||
osdBuffers.perPatchVertexBuffer[ControlID]);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.BoxSplineTriangle.Domain
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<typename PerPatchVertexBezier>
|
||||
OsdPatchVertex ds_regular_patches(
|
||||
float tessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
float4 tessOuterLo,
|
||||
float4 tessOuterHi,
|
||||
#endif
|
||||
PerPatchVertexBezier cv,
|
||||
int3 patchParam,
|
||||
float3 domainCoord
|
||||
)
|
||||
{
|
||||
#if USE_PTVS_FACTORS
|
||||
float4 tessOuterLo(0), tessOuterHi(0);
|
||||
OsdGetTessLevelsUniformTriangle(
|
||||
tessLevel, patchParam, tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
float2 UV = OsdGetTessParameterizationTriangle(domainCoord,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
OsdPatchVertex output;
|
||||
|
||||
float3 P = float3(0), dPu = float3(0), dPv = float3(0);
|
||||
float3 N = float3(0), dNu = float3(0), dNv = float3(0);
|
||||
|
||||
OsdEvalPatchBezierTriangle(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
output.normal = N;
|
||||
output.tangent = dPu;
|
||||
output.bitangent = dPv;
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
|
||||
output.tessCoord = UV;
|
||||
output.patchCoord = OsdInterpolatePatchCoordTriangle(UV, patchParam);
|
||||
output.position = P;
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_STAGE_IN
|
||||
template<typename PerPatchVertexBezier>
|
||||
#endif
|
||||
OsdPatchVertex OsdComputePatch(
|
||||
float tessLevel,
|
||||
float3 domainCoord,
|
||||
unsigned patchID,
|
||||
#if USE_STAGE_IN
|
||||
PerPatchVertexBezier osdPatch
|
||||
#else
|
||||
OsdVertexBufferSet osdBuffers
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return ds_regular_patches(
|
||||
tessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.tessOuterLo,
|
||||
osdPatch.tessOuterHi,
|
||||
#else
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterLo,
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterHi,
|
||||
#endif
|
||||
#endif
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.cv,
|
||||
osdPatch.patchParam,
|
||||
#else
|
||||
osdBuffers.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers.patchParamBuffer[patchID],
|
||||
#endif
|
||||
domainCoord
|
||||
);
|
||||
}
|
||||
|
||||
1234
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchCommon.metal
vendored
Normal file
1234
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchCommon.metal
vendored
Normal file
File diff suppressed because it is too large
Load Diff
896
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchCommonTess.metal
vendored
Normal file
896
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchCommonTess.metal
vendored
Normal file
@@ -0,0 +1,896 @@
|
||||
#line 0 "osd/mtlPatchCommonTess.metal"
|
||||
|
||||
//
|
||||
// Copyright 2015-2019 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Tessellation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// For now, fractional spacing is supported only with screen space tessellation
|
||||
#ifndef OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
#undef OSD_FRACTIONAL_EVEN_SPACING
|
||||
#undef OSD_FRACTIONAL_ODD_SPACING
|
||||
#endif
|
||||
|
||||
//
|
||||
// Organization of B-spline and Bezier control points.
|
||||
//
|
||||
// Each patch is defined by 16 control points (labeled 0-15).
|
||||
//
|
||||
// The patch will be evaluated across the domain from (0,0) at
|
||||
// the lower-left to (1,1) at the upper-right. When computing
|
||||
// adaptive tessellation metrics, we consider refined vertex-vertex
|
||||
// and edge-vertex points along the transition edges of the patch
|
||||
// (labeled vv* and ev* respectively).
|
||||
//
|
||||
// The two segments of each transition edge are labeled Lo and Hi,
|
||||
// with the Lo segment occurring before the Hi segment along the
|
||||
// transition edge's domain parameterization. These Lo and Hi segment
|
||||
// tessellation levels determine how domain evaluation coordinates
|
||||
// are remapped along transition edges. The Hi segment value will
|
||||
// be zero for a non-transition edge.
|
||||
//
|
||||
// (0,1) (1,1)
|
||||
//
|
||||
// vv3 ev23 vv2
|
||||
// | Lo3 | Hi3 |
|
||||
// --O-----------O-----+-----O-----------O--
|
||||
// | 12 | 13 14 | 15 |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// Hi0 | | | | Hi2
|
||||
// | | | |
|
||||
// O-----------O-----------O-----------O
|
||||
// | 8 | 9 10 | 11 |
|
||||
// | | | |
|
||||
// ev03 --+ | | +-- ev12
|
||||
// | | | |
|
||||
// | 4 | 5 6 | 7 |
|
||||
// O-----------O-----------O-----------O
|
||||
// | | | |
|
||||
// Lo0 | | | | Lo2
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | 0 | 1 2 | 3 |
|
||||
// --O-----------O-----+-----O-----------O--
|
||||
// | Lo1 | Hi1 |
|
||||
// vv0 ev01 vv1
|
||||
//
|
||||
// (0,0) (1,0)
|
||||
//
|
||||
|
||||
#ifndef OSD_MAX_TESS_LEVEL
|
||||
#define OSD_MAX_TESS_LEVEL 64
|
||||
#endif
|
||||
|
||||
float OsdComputePostProjectionSphereExtent(
|
||||
const float4x4 OsdProjectionMatrix, float3 center, float diameter)
|
||||
{
|
||||
float4 p = OsdProjectionMatrix * float4(center, 1.0);
|
||||
return abs(diameter * OsdProjectionMatrix[1][1] / p.w);
|
||||
}
|
||||
|
||||
float OsdComputeTessLevel(
|
||||
const float OsdTessLevel,
|
||||
const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix,
|
||||
float3 p0, float3 p1)
|
||||
{
|
||||
// Adaptive factor can be any computation that depends only on arg values.
|
||||
// Project the diameter of the edge's bounding sphere instead of using the
|
||||
// length of the projected edge itself to avoid problems near silhouettes.
|
||||
p0 = (OsdModelViewMatrix * float4(p0, 1.0)).xyz;
|
||||
p1 = (OsdModelViewMatrix * float4(p1, 1.0)).xyz;
|
||||
float3 center = (p0 + p1) / 2.0;
|
||||
float diameter = distance(p0, p1);
|
||||
float projLength = OsdComputePostProjectionSphereExtent(OsdProjectionMatrix, center, diameter);
|
||||
float tessLevel = max(1.0, OsdTessLevel * projLength);
|
||||
|
||||
// We restrict adaptive tessellation levels to half of the device
|
||||
// supported maximum because transition edges are split into two
|
||||
// halves and the sum of the two corresponding levels must not exceed
|
||||
// the device maximum. We impose this limit even for non-transition
|
||||
// edges because a non-transition edge must be able to match up with
|
||||
// one half of the transition edge of an adjacent transition patch.
|
||||
return min(tessLevel, (float)(OSD_MAX_TESS_LEVEL / 2));
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniform(const float OsdTessLevel, int3 patchParam,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
// Uniform factors are simple powers of two for each level.
|
||||
// The maximum here can be increased if we know the maximum
|
||||
// refinement level of the mesh:
|
||||
// min(OSD_MAX_TESS_LEVEL, pow(2, MaximumRefinementLevel-1)
|
||||
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
|
||||
float tessLevel = min(OsdTessLevel, (float)OSD_MAX_TESS_LEVEL) /
|
||||
pow(2, refinementLevel - 1.0f);
|
||||
|
||||
// tessLevels of transition edge should be clamped to 2.
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
float4 tessLevelMin = float4(1) + float4(((transitionMask & 8) >> 3),
|
||||
((transitionMask & 1) >> 0),
|
||||
((transitionMask & 2) >> 1),
|
||||
((transitionMask & 4) >> 2));
|
||||
|
||||
tessOuterLo = max(float4(tessLevel), tessLevelMin);
|
||||
tessOuterHi = float4(0);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniformTriangle(const float OsdTessLevel, int3 patchParam,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
// Uniform factors are simple powers of two for each level.
|
||||
// The maximum here can be increased if we know the maximum
|
||||
// refinement level of the mesh:
|
||||
// min(OSD_MAX_TESS_LEVEL, pow(2, MaximumRefinementLevel-1)
|
||||
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
|
||||
float tessLevel = min(OsdTessLevel, (float)OSD_MAX_TESS_LEVEL) /
|
||||
pow(2, refinementLevel - 1.0f);
|
||||
|
||||
// tessLevels of transition edge should be clamped to 2.
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
float4 tessLevelMin = float4(1) + float4(((transitionMask & 4) >> 2),
|
||||
((transitionMask & 1) >> 0),
|
||||
((transitionMask & 2) >> 1),
|
||||
0);
|
||||
|
||||
tessOuterLo = max(float4(tessLevel), tessLevelMin);
|
||||
tessOuterHi = float4(0);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsRefinedPoints(
|
||||
const float OsdTessLevel,
|
||||
const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix,
|
||||
float3 cp[16], int3 patchParam,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. We compute the corresponding
|
||||
// vertex-vertex and edge-vertex refined points along the edges of the
|
||||
// patch using Catmull-Clark subdivision stencil weights.
|
||||
// For simplicity, we let the optimizer discard unused computation.
|
||||
|
||||
float3 vv0 = (cp[0] + cp[2] + cp[8] + cp[10]) * 0.015625 +
|
||||
(cp[1] + cp[4] + cp[6] + cp[9]) * 0.09375 + cp[5] * 0.5625;
|
||||
float3 ev01 = (cp[1] + cp[2] + cp[9] + cp[10]) * 0.0625 +
|
||||
(cp[5] + cp[6]) * 0.375;
|
||||
|
||||
float3 vv1 = (cp[1] + cp[3] + cp[9] + cp[11]) * 0.015625 +
|
||||
(cp[2] + cp[5] + cp[7] + cp[10]) * 0.09375 + cp[6] * 0.5625;
|
||||
float3 ev12 = (cp[5] + cp[7] + cp[9] + cp[11]) * 0.0625 +
|
||||
(cp[6] + cp[10]) * 0.375;
|
||||
|
||||
float3 vv2 = (cp[5] + cp[7] + cp[13] + cp[15]) * 0.015625 +
|
||||
(cp[6] + cp[9] + cp[11] + cp[14]) * 0.09375 + cp[10] * 0.5625;
|
||||
float3 ev23 = (cp[5] + cp[6] + cp[13] + cp[14]) * 0.0625 +
|
||||
(cp[9] + cp[10]) * 0.375;
|
||||
|
||||
float3 vv3 = (cp[4] + cp[6] + cp[12] + cp[14]) * 0.015625 +
|
||||
(cp[5] + cp[8] + cp[10] + cp[13]) * 0.09375 + cp[9] * 0.5625;
|
||||
float3 ev03 = (cp[4] + cp[6] + cp[8] + cp[10]) * 0.0625 +
|
||||
(cp[5] + cp[9]) * 0.375;
|
||||
|
||||
tessOuterLo = float4(0);
|
||||
tessOuterHi = float4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 8) != 0) {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, vv0, ev03);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, vv3, ev03);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, cp[5], cp[9]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, vv0, ev01);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, vv1, ev01);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, cp[5], cp[6]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, vv1, ev12);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, vv2, ev12);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, cp[6], cp[10]);
|
||||
}
|
||||
if ((transitionMask & 4) != 0) {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, vv3, ev23);
|
||||
tessOuterHi[3] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, vv2, ev23);
|
||||
} else {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, cp[9], cp[10]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Patch boundary corners are ordered counter-clockwise from the first
|
||||
// corner while patch boundary edges and their midpoints are similarly
|
||||
// ordered counter-clockwise beginning at the edge preceding corner[0].
|
||||
//
|
||||
void
|
||||
Osd_GetTessLevelsFromPatchBoundaries4(
|
||||
const float OsdTessLevel,
|
||||
const float4x4 OsdProjectionMatrix,
|
||||
const float4x4 OsdModelViewMatrix,
|
||||
float3 corners[3], float3 midpoints[3],
|
||||
int3 patchParam,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
tessOuterLo = float4(0);
|
||||
tessOuterHi = float4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 8) != 0) {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[0], midpoints[0]);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[3], midpoints[0]);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[0], corners[3]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[0], midpoints[1]);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[1], midpoints[1]);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[0], corners[1]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[1], midpoints[2]);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[2], midpoints[2]);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[1], corners[2]);
|
||||
}
|
||||
if ((transitionMask & 4) != 0) {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[3], midpoints[3]);
|
||||
tessOuterHi[3] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[2], midpoints[3]);
|
||||
} else {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[3], corners[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Osd_GetTessLevelsFromPatchBoundaries3(
|
||||
const float OsdTessLevel,
|
||||
const float4x4 OsdProjectionMatrix,
|
||||
const float4x4 OsdModelViewMatrix,
|
||||
float3 corners[3], float3 midpoints[3],
|
||||
int3 patchParam,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
tessOuterLo = float4(0);
|
||||
tessOuterHi = float4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 4) != 0) {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[0], midpoints[0]);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[2], midpoints[0]);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[0], corners[2]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[0], midpoints[1]);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[1], midpoints[1]);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[0], corners[1]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[2], midpoints[2]);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[1], midpoints[2]);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners[1], corners[2]);
|
||||
}
|
||||
}
|
||||
|
||||
float3
|
||||
Osd_EvalBezierCurveMidPoint(float3 p0, float3 p1, float3 p2, float3 p3)
|
||||
{
|
||||
// Coefficients for the midpoint are { 1/8, 3/8, 3/8, 1/8 }:
|
||||
return 0.125 * (p0 + p3) + 0.375 * (p1 + p2);
|
||||
}
|
||||
|
||||
float3
|
||||
Osd_EvalQuarticBezierCurveMidPoint(float3 p0, float3 p1, float3 p2, float3 p3, float3 p4)
|
||||
{
|
||||
// Coefficients for the midpoint are { 1/16, 1/4, 3/8, 1/4, 1/16 }:
|
||||
return 0.0625 * (p0 + p4) + 0.25 * (p1 + p3) + 0.375 * p2;
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
const float OsdTessLevel,
|
||||
const float4x4 OsdProjectionMatrix,
|
||||
const float4x4 OsdModelViewMatrix,
|
||||
device OsdPerPatchVertexBezier* cpBezier,
|
||||
int3 patchParam,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. When the patch control
|
||||
// points have been converted to the Bezier basis, the control points
|
||||
// at the four corners are on the limit surface (since a Bezier patch
|
||||
// interpolates its corner control points). We can compute an adaptive
|
||||
// tessellation level for transition edges on the limit surface by
|
||||
// evaluating a limit position at the mid point of each transition edge.
|
||||
|
||||
tessOuterLo = float4(0);
|
||||
tessOuterHi = float4(0);
|
||||
|
||||
float3 corners[4];
|
||||
float3 midpoints[4];
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
corners[0] = OsdEvalBezier(cpBezier, patchParam, float2(0.0, 0.0));
|
||||
corners[1] = OsdEvalBezier(cpBezier, patchParam, float2(1.0, 0.0));
|
||||
corners[2] = OsdEvalBezier(cpBezier, patchParam, float2(1.0, 1.0));
|
||||
corners[3] = OsdEvalBezier(cpBezier, patchParam, float2(0.0, 1.0));
|
||||
|
||||
midpoints[0] = ((transitionMask & 8) == 0) ? float3(0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, float2(0.0, 0.5));
|
||||
midpoints[1] = ((transitionMask & 1) == 0) ? float3(0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, float2(0.5, 0.0));
|
||||
midpoints[2] = ((transitionMask & 2) == 0) ? float3(0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, float2(1.0, 0.5));
|
||||
midpoints[3] = ((transitionMask & 4) == 0) ? float3(0) :
|
||||
OsdEvalBezier(cpBezier, patchParam, float2(0.5, 1.0));
|
||||
|
||||
#else // OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
corners[0] = cpBezier[ 0].P;
|
||||
corners[1] = cpBezier[ 3].P;
|
||||
corners[2] = cpBezier[15].P;
|
||||
corners[3] = cpBezier[12].P;
|
||||
|
||||
midpoints[0] = ((transitionMask & 8) == 0) ? float3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[0].P, cpBezier[4].P, cpBezier[8].P, cpBezier[12].P);
|
||||
midpoints[1] = ((transitionMask & 1) == 0) ? float3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[0].P, cpBezier[1].P, cpBezier[2].P, cpBezier[3].P);
|
||||
midpoints[2] = ((transitionMask & 2) == 0) ? float3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[3].P, cpBezier[7].P, cpBezier[11].P, cpBezier[15].P);
|
||||
midpoints[3] = ((transitionMask & 4) == 0) ? float3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[12].P, cpBezier[13].P, cpBezier[14].P, cpBezier[15].P);
|
||||
#endif
|
||||
|
||||
Osd_GetTessLevelsFromPatchBoundaries4(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners, midpoints, patchParam, tessOuterLo, tessOuterHi);
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
const float OsdTessLevel,
|
||||
const float4x4 OsdProjectionMatrix,
|
||||
const float4x4 OsdModelViewMatrix,
|
||||
float3 cv[16],
|
||||
int3 patchParam,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. When the patch control
|
||||
// points have been converted to the Bezier basis, the control points
|
||||
// at the four corners are on the limit surface (since a Bezier patch
|
||||
// interpolates its corner control points). We can compute an adaptive
|
||||
// tessellation level for transition edges on the limit surface by
|
||||
// evaluating a limit position at the mid point of each transition edge.
|
||||
|
||||
tessOuterLo = float4(0);
|
||||
tessOuterHi = float4(0);
|
||||
|
||||
float3 corners[4];
|
||||
float3 midpoints[4];
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
corners[0] = cv[ 0];
|
||||
corners[1] = cv[ 3];
|
||||
corners[2] = cv[15];
|
||||
corners[3] = cv[12];
|
||||
|
||||
midpoints[0] = ((transitionMask & 8) == 0) ? float3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(cv[0], cv[4], cv[8], cv[12]);
|
||||
midpoints[1] = ((transitionMask & 1) == 0) ? float3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(cv[0], cv[1], cv[2], cv[3]);
|
||||
midpoints[2] = ((transitionMask & 2) == 0) ? float3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(cv[3], cv[7], cv[11], cv[15]);
|
||||
midpoints[3] = ((transitionMask & 4) == 0) ? float3(0) :
|
||||
Osd_EvalBezierCurveMidPoint(cv[12], cv[13], cv[14], cv[15]);
|
||||
|
||||
Osd_GetTessLevelsFromPatchBoundaries4(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners, midpoints, patchParam, tessOuterLo, tessOuterHi);
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTriangleTessLevels(
|
||||
const float OsdTessLevel,
|
||||
const float4x4 OsdProjectionMatrix,
|
||||
const float4x4 OsdModelViewMatrix,
|
||||
float3 cv[15],
|
||||
int3 patchParam,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. When the patch control
|
||||
// points have been converted to the Bezier basis, the control points
|
||||
// at the corners are on the limit surface (since a Bezier patch
|
||||
// interpolates its corner control points). We can compute an adaptive
|
||||
// tessellation level for transition edges on the limit surface by
|
||||
// evaluating a limit position at the mid point of each transition edge.
|
||||
|
||||
tessOuterLo = float4(0);
|
||||
tessOuterHi = float4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
float3 corners[3];
|
||||
corners[0] = cv[0];
|
||||
corners[1] = cv[4];
|
||||
corners[2] = cv[14];
|
||||
|
||||
float3 midpoints[3];
|
||||
midpoints[0] = ((transitionMask & 4) == 0) ? float3(0) :
|
||||
Osd_EvalQuarticBezierCurveMidPoint(cv[0], cv[5], cv[9], cv[12], cv[14]);
|
||||
midpoints[1] = ((transitionMask & 1) == 0) ? float3(0) :
|
||||
Osd_EvalQuarticBezierCurveMidPoint(cv[0], cv[1], cv[2], cv[3], cv[4]);
|
||||
midpoints[2] = ((transitionMask & 2) == 0) ? float3(0) :
|
||||
Osd_EvalQuarticBezierCurveMidPoint(cv[4], cv[8], cv[11], cv[13], cv[14]);
|
||||
|
||||
Osd_GetTessLevelsFromPatchBoundaries3(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
corners, midpoints, patchParam, tessOuterLo, tessOuterHi);
|
||||
}
|
||||
|
||||
// Round up to the nearest even integer
|
||||
float OsdRoundUpEven(float x) {
|
||||
return 2*ceil(x/2);
|
||||
}
|
||||
|
||||
// Round up to the nearest odd integer
|
||||
float OsdRoundUpOdd(float x) {
|
||||
return 2*ceil((x+1)/2)-1;
|
||||
}
|
||||
|
||||
// Compute outer and inner tessellation levels taking into account the
|
||||
// current tessellation spacing mode.
|
||||
void
|
||||
OsdComputeTessLevels(thread float4& tessOuterLo, thread float4& tessOuterHi,
|
||||
thread float4& tessLevelOuter, thread float2& tessLevelInner)
|
||||
{
|
||||
// Outer levels are the sum of the Lo and Hi segments where the Hi
|
||||
// segments will have lengths of zero for non-transition edges.
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
// Combine fractional outer transition edge levels before rounding.
|
||||
float4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
|
||||
// Round the segments of transition edges separately. We will recover the
|
||||
// fractional parameterization of transition edges after tessellation.
|
||||
|
||||
tessLevelOuter = combinedOuter;
|
||||
if (tessOuterHi[0] > 0) {
|
||||
tessLevelOuter[0] =
|
||||
OsdRoundUpEven(tessOuterLo[0]) + OsdRoundUpEven(tessOuterHi[0]);
|
||||
}
|
||||
if (tessOuterHi[1] > 0) {
|
||||
tessLevelOuter[1] =
|
||||
OsdRoundUpEven(tessOuterLo[1]) + OsdRoundUpEven(tessOuterHi[1]);
|
||||
}
|
||||
if (tessOuterHi[2] > 0) {
|
||||
tessLevelOuter[2] =
|
||||
OsdRoundUpEven(tessOuterLo[2]) + OsdRoundUpEven(tessOuterHi[2]);
|
||||
}
|
||||
if (tessOuterHi[3] > 0) {
|
||||
tessLevelOuter[3] =
|
||||
OsdRoundUpEven(tessOuterLo[3]) + OsdRoundUpEven(tessOuterHi[3]);
|
||||
}
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
// Combine fractional outer transition edge levels before rounding.
|
||||
float4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
|
||||
// Round the segments of transition edges separately. We will recover the
|
||||
// fractional parameterization of transition edges after tessellation.
|
||||
//
|
||||
// The sum of the two outer odd segment lengths will be an even number
|
||||
// which the tessellator will increase by +1 so that there will be a
|
||||
// total odd number of segments. We clamp the combinedOuter tess levels
|
||||
// (used to compute the inner tess levels) so that the outer transition
|
||||
// edges will be sampled without degenerate triangles.
|
||||
|
||||
tessLevelOuter = combinedOuter;
|
||||
if (tessOuterHi[0] > 0) {
|
||||
tessLevelOuter[0] =
|
||||
OsdRoundUpOdd(tessOuterLo[0]) + OsdRoundUpOdd(tessOuterHi[0]);
|
||||
combinedOuter = max(float4(3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[1] > 0) {
|
||||
tessLevelOuter[1] =
|
||||
OsdRoundUpOdd(tessOuterLo[1]) + OsdRoundUpOdd(tessOuterHi[1]);
|
||||
combinedOuter = max(float4(3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[2] > 0) {
|
||||
tessLevelOuter[2] =
|
||||
OsdRoundUpOdd(tessOuterLo[2]) + OsdRoundUpOdd(tessOuterHi[2]);
|
||||
combinedOuter = max(float4(3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[3] > 0) {
|
||||
tessLevelOuter[3] =
|
||||
OsdRoundUpOdd(tessOuterLo[3]) + OsdRoundUpOdd(tessOuterHi[3]);
|
||||
combinedOuter = max(float4(3), combinedOuter);
|
||||
}
|
||||
#else
|
||||
// Round equally spaced transition edge levels before combining.
|
||||
tessOuterLo = round(tessOuterLo);
|
||||
tessOuterHi = round(tessOuterHi);
|
||||
|
||||
float4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
tessLevelOuter = combinedOuter;
|
||||
#endif
|
||||
|
||||
// Inner levels are the averages the corresponding outer levels.
|
||||
tessLevelInner[0] = (combinedOuter[1] + combinedOuter[3]) * 0.5;
|
||||
tessLevelInner[1] = (combinedOuter[0] + combinedOuter[2]) * 0.5;
|
||||
}
|
||||
|
||||
void
|
||||
OsdComputeTessLevelsTriangle(
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi,
|
||||
thread float4& tessLevelOuter, thread float2& tessLevelInner)
|
||||
{
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
|
||||
// Inner level is the max of the three outer levels.
|
||||
tessLevelInner[0] = max(max(tessLevelOuter[0],
|
||||
tessLevelOuter[1]),
|
||||
tessLevelOuter[2]);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniform(
|
||||
const float OsdTessLevel, int3 patchParam,
|
||||
thread float4& tessLevelOuter, thread float2& tessLevelInner,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsUniform(OsdTessLevel, patchParam, tessOuterLo, tessOuterHi);
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi, tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniformTriangle(
|
||||
const float OsdTessLevel, int3 patchParam,
|
||||
thread float4& tessLevelOuter, thread float2& tessLevelInner,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsUniformTriangle(OsdTessLevel, patchParam, tessOuterLo, tessOuterHi);
|
||||
OsdComputeTessLevelsTriangle(tessOuterLo, tessOuterHi, tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
const float OsdTessLevels,
|
||||
const float4x4 OsdProjectionMatrix,
|
||||
const float4x4 OsdModelViewMatrix,
|
||||
device OsdPerPatchVertexBezier* cpBezier,
|
||||
int3 patchParam,
|
||||
thread float4& tessLevelOuter, thread float2& tessLevelInner,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
OsdTessLevels,
|
||||
OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
cpBezier, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
const float OsdTessLevels,
|
||||
const float4x4 OsdProjectionMatrix,
|
||||
const float4x4 OsdModelViewMatrix,
|
||||
float3 cv[16],
|
||||
int3 patchParam,
|
||||
thread float4& tessLevelOuter, thread float2& tessLevelInner,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
OsdTessLevels,
|
||||
OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
cv, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdEvalPatchBezierTriangleTessLevels(
|
||||
const float OsdTessLevels,
|
||||
const float4x4 OsdProjectionMatrix,
|
||||
const float4x4 OsdModelViewMatrix,
|
||||
float3 cv[15],
|
||||
int3 patchParam,
|
||||
thread float4& tessLevelOuter, thread float2& tessLevelInner,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
OsdEvalPatchBezierTriangleTessLevels(
|
||||
OsdTessLevels,
|
||||
OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
cv, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevelsTriangle(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsAdaptiveRefinedPoints(
|
||||
const float OsdTessLevel,
|
||||
const float4x4 OsdProjectionMatrix,
|
||||
const float4x4 OsdModelViewMatrix,
|
||||
float3 cpRefined[16], int3 patchParam,
|
||||
thread float4& tessLevelOuter, thread float2& tessLevelInner,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsRefinedPoints(OsdTessLevel,
|
||||
OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
cpRefined, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
// Deprecated -- prefer use of newer Bezier patch equivalent:
|
||||
void
|
||||
OsdGetTessLevelsLimitPoints(
|
||||
const float OsdTessLevel,
|
||||
const float4x4 OsdProjectionMatrix,
|
||||
const float4x4 OsdModelViewMatrix,
|
||||
device OsdPerPatchVertexBezier* cpBezier,
|
||||
int3 patchParam,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
cpBezier, patchParam, tessOuterLo, tessOuterHi);
|
||||
}
|
||||
|
||||
// Deprecated -- prefer use of newer Bezier patch equivalent:
|
||||
void
|
||||
OsdGetTessLevelsAdaptiveLimitPoints(
|
||||
const float OsdTessLevel,
|
||||
const float4x4 OsdProjectionMatrix,
|
||||
const float4x4 OsdModelViewMatrix,
|
||||
device OsdPerPatchVertexBezier* cpBezier,
|
||||
int3 patchParam,
|
||||
thread float4& tessLevelOuter, thread float2& tessLevelInner,
|
||||
thread float4& tessOuterLo, thread float4& tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsLimitPoints(OsdTessLevel,
|
||||
OsdProjectionMatrix, OsdModelViewMatrix,
|
||||
cpBezier, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
// Deprecated -- prefer use of newer Bezier patch equivalent:
|
||||
void
|
||||
OsdGetTessLevels(
|
||||
const float OsdTessLevel,
|
||||
const float4x4 OsdProjectionMatrix, const float4x4 OsdModelViewMatrix,
|
||||
float3 cp0, float3 cp1, float3 cp2, float3 cp3, int3 patchParam,
|
||||
thread float4& tessLevelOuter, thread float2& tessLevelInner)
|
||||
{
|
||||
float4 tessOuterLo = float4(0);
|
||||
float4 tessOuterHi = float4(0);
|
||||
|
||||
#if OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
tessOuterLo[0] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, cp0, cp1);
|
||||
tessOuterLo[1] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, cp0, cp3);
|
||||
tessOuterLo[2] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, cp2, cp3);
|
||||
tessOuterLo[3] = OsdComputeTessLevel(
|
||||
OsdTessLevel, OsdProjectionMatrix, OsdModelViewMatrix, cp1, cp2);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(OsdTessLevel, patchParam, tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING || defined OSD_FRACTIONAL_ODD_SPACING
|
||||
float
|
||||
OsdGetTessFractionalSplit(float t, float level, float levelUp)
|
||||
{
|
||||
// Fractional tessellation of an edge will produce n segments where n
|
||||
// is the tessellation level of the edge (level) rounded up to the
|
||||
// nearest even or odd integer (levelUp). There will be n-2 segments of
|
||||
// equal length (dx1) and two additional segments of equal length (dx0)
|
||||
// that are typically shorter than the other segments. The two additional
|
||||
// segments should be placed symmetrically on opposite sides of the
|
||||
// edge (offset).
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
if (level <= 2) return t;
|
||||
|
||||
float base = pow(2.0,floor(log2(levelUp)));
|
||||
float offset = 1.0/(int(2*base-levelUp)/2 & int(base/2-1));
|
||||
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
if (level <= 1) return t;
|
||||
|
||||
float base = pow(2.0,floor(log2(levelUp)));
|
||||
float offset = 1.0/(((int(2*base-levelUp)/2+1) & int(base/2-1))+1);
|
||||
#endif
|
||||
|
||||
float dx0 = (1.0 - (levelUp-level)/2) / levelUp;
|
||||
float dx1 = (1.0 - 2.0*dx0) / (levelUp - 2.0*ceil(dx0));
|
||||
|
||||
if (t < 0.5) {
|
||||
float x = levelUp/2 - round(t*levelUp);
|
||||
return 0.5 - (x*dx1 + int(x*offset > 1) * (dx0 - dx1));
|
||||
} else if (t > 0.5) {
|
||||
float x = round(t*levelUp) - levelUp/2;
|
||||
return 0.5 + (x*dx1 + int(x*offset > 1) * (dx0 - dx1));
|
||||
} else {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
float
|
||||
OsdGetTessTransitionSplit(float t, float lo, float hi)
|
||||
{
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
float loRoundUp = OsdRoundUpEven(lo);
|
||||
float hiRoundUp = OsdRoundUpEven(hi);
|
||||
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
float ti = round(t * (loRoundUp + hiRoundUp));
|
||||
|
||||
if (ti <= loRoundUp) {
|
||||
float t0 = ti / loRoundUp;
|
||||
return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5;
|
||||
} else {
|
||||
float t1 = (ti - loRoundUp) / hiRoundUp;
|
||||
return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5;
|
||||
}
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
float loRoundUp = OsdRoundUpOdd(lo);
|
||||
float hiRoundUp = OsdRoundUpOdd(hi);
|
||||
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
// The +1 below is to account for the extra segment produced by the
|
||||
// tessellator since the sum of two odd tess levels will be rounded
|
||||
// up by one to the next odd integer tess level.
|
||||
float ti = round(t * (loRoundUp + hiRoundUp + 1));
|
||||
|
||||
if (ti <= loRoundUp) {
|
||||
float t0 = ti / loRoundUp;
|
||||
return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5;
|
||||
} else if (ti > (loRoundUp+1)) {
|
||||
float t1 = (ti - (loRoundUp+1)) / hiRoundUp;
|
||||
return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5;
|
||||
} else {
|
||||
return 0.5;
|
||||
}
|
||||
#else
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
float ti = round(t * (lo + hi));
|
||||
|
||||
if (ti <= lo) {
|
||||
return (ti / lo) * 0.5;
|
||||
} else {
|
||||
return ((ti - lo) / hi) * 0.5 + 0.5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float2
|
||||
OsdGetTessParameterization(float2 p, float4 tessOuterLo, float4 tessOuterHi)
|
||||
{
|
||||
float2 UV = p;
|
||||
if (p.x == 0 && tessOuterHi[0] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[0], tessOuterHi[0]);
|
||||
} else
|
||||
if (p.y == 0 && tessOuterHi[1] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[1], tessOuterHi[1]);
|
||||
} else
|
||||
if (p.x == 1 && tessOuterHi[2] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[2], tessOuterHi[2]);
|
||||
} else
|
||||
if (p.y == 1 && tessOuterHi[3] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[3], tessOuterHi[3]);
|
||||
}
|
||||
return UV;
|
||||
}
|
||||
|
||||
float2
|
||||
OsdGetTessParameterizationTriangle(float3 p, float4 tessOuterLo, float4 tessOuterHi)
|
||||
{
|
||||
float2 UV = p.xy;
|
||||
if (p.x == 0 && tessOuterHi[0] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[0], tessOuterHi[0]);
|
||||
} else
|
||||
if (p.y == 0 && tessOuterHi[1] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[1], tessOuterHi[1]);
|
||||
} else
|
||||
if (p.z == 0 && tessOuterHi[2] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[2], tessOuterHi[2]);
|
||||
UV.y = 1.0 - UV.x;
|
||||
}
|
||||
return UV;
|
||||
}
|
||||
260
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchGregory.metal
vendored
Normal file
260
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchGregory.metal
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
#line 0 "osd/mtlPatchGregory.metal"
|
||||
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Gregory.Hull
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerVertex(
|
||||
float4 position,
|
||||
threadgroup OsdPerVertexGregory& hullVertex,
|
||||
int vertexId,
|
||||
float4x4 modelViewProjectionMatrix,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
OsdComputePerVertexGregory(vertexId, position.xyz, hullVertex, osdBuffers);
|
||||
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
float4 clipPos = mul(modelViewProjectionMatrix, position);
|
||||
short3 clip0 = short3(clipPos.x < clipPos.w,
|
||||
clipPos.y < clipPos.w,
|
||||
clipPos.z < clipPos.w);
|
||||
short3 clip1 = short3(clipPos.x > -clipPos.w,
|
||||
clipPos.y > -clipPos.w,
|
||||
clipPos.z > -clipPos.w);
|
||||
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Gregory.Factors
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchGregoryFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
device OsdPerPatchVertexGregory* patchVertices,
|
||||
#if !USE_PTVS_FACTORS
|
||||
device OsdPerPatchTessFactors& patchFactors,
|
||||
#endif
|
||||
device MTLQuadTessellationFactorsHalf& quadFactors
|
||||
)
|
||||
{
|
||||
float4 tessLevelOuter = float4(0);
|
||||
float2 tessLevelInner = float2(0);
|
||||
float4 tessOuterLo = float4(0);
|
||||
float4 tessOuterHi = float4(0);
|
||||
|
||||
#if OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
float3 bezcv[16];
|
||||
bezcv[ 0] = patchVertices[0].P;
|
||||
bezcv[ 1] = patchVertices[0].Ep;
|
||||
bezcv[ 2] = patchVertices[1].Em;
|
||||
bezcv[ 3] = patchVertices[1].P;
|
||||
bezcv[ 4] = patchVertices[0].Em;
|
||||
bezcv[ 5] = patchVertices[0].Fp;
|
||||
bezcv[ 6] = patchVertices[1].Fm;
|
||||
bezcv[ 7] = patchVertices[1].Ep;
|
||||
bezcv[ 8] = patchVertices[3].Ep;
|
||||
bezcv[ 9] = patchVertices[3].Fm;
|
||||
bezcv[10] = patchVertices[2].Fp;
|
||||
bezcv[11] = patchVertices[2].Em;
|
||||
bezcv[12] = patchVertices[3].P;
|
||||
bezcv[13] = patchVertices[3].Em;
|
||||
bezcv[14] = patchVertices[2].Ep;
|
||||
bezcv[15] = patchVertices[2].P;
|
||||
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
bezcv,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(
|
||||
tessLevel,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#endif
|
||||
|
||||
quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
|
||||
quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
|
||||
quadFactors.edgeTessellationFactor[2] = tessLevelOuter[2];
|
||||
quadFactors.edgeTessellationFactor[3] = tessLevelOuter[3];
|
||||
quadFactors.insideTessellationFactor[0] = tessLevelInner[0];
|
||||
quadFactors.insideTessellationFactor[1] = tessLevelInner[1];
|
||||
#if !USE_PTVS_FACTORS
|
||||
patchFactors.tessOuterLo = tessOuterLo;
|
||||
patchFactors.tessOuterHi = tessOuterHi;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OsdComputePerPatchFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
unsigned patchID,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
OsdPatchParamBufferSet osdBuffer,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
device MTLQuadTessellationFactorsHalf& quadFactors
|
||||
)
|
||||
{
|
||||
OsdComputePerPatchGregoryFactors(
|
||||
patchParam,
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
osdBuffer.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
#if !USE_PTVS_FACTORS
|
||||
osdBuffer.patchTessBuffer[patchID],
|
||||
#endif
|
||||
quadFactors
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Gregory.Vertex
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchVertex(
|
||||
int3 patchParam,
|
||||
unsigned ID,
|
||||
unsigned PrimitiveID,
|
||||
unsigned ControlID,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
OsdComputePerPatchVertexGregory(
|
||||
patchParam,
|
||||
ID,
|
||||
PrimitiveID,
|
||||
patchVertices,
|
||||
osdBuffers.perPatchVertexBuffer[ControlID],
|
||||
osdBuffers);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Gregory.Domain
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<typename PerPatchVertexGregory>
|
||||
OsdPatchVertex ds_gregory_patches(
|
||||
const float tessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
float4 tessOuterLo,
|
||||
float4 tessOuterHi,
|
||||
#endif
|
||||
PerPatchVertexGregory patch,
|
||||
int3 patchParam,
|
||||
float2 domainCoord
|
||||
)
|
||||
{
|
||||
float3 cv[20];
|
||||
cv[0] = patch[0].P;
|
||||
cv[1] = patch[0].Ep;
|
||||
cv[2] = patch[0].Em;
|
||||
cv[3] = patch[0].Fp;
|
||||
cv[4] = patch[0].Fm;
|
||||
cv[5] = patch[1].P;
|
||||
cv[6] = patch[1].Ep;
|
||||
cv[7] = patch[1].Em;
|
||||
cv[8] = patch[1].Fp;
|
||||
cv[9] = patch[1].Fm;
|
||||
cv[10] = patch[2].P;
|
||||
cv[11] = patch[2].Ep;
|
||||
cv[12] = patch[2].Em;
|
||||
cv[13] = patch[2].Fp;
|
||||
cv[14] = patch[2].Fm;
|
||||
cv[15] = patch[3].P;
|
||||
cv[16] = patch[3].Ep;
|
||||
cv[17] = patch[3].Em;
|
||||
cv[18] = patch[3].Fp;
|
||||
cv[19] = patch[3].Fm;
|
||||
|
||||
#if USE_PTVS_FACTORS
|
||||
float4 tessOuterLo(0), tessOuterHi(0);
|
||||
OsdGetTessLevelsUniform(tessLevel, patchParam, tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
float2 UV = OsdGetTessParameterization(domainCoord,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
OsdPatchVertex output;
|
||||
|
||||
float3 P = float3(0), dPu = float3(0), dPv = float3(0);
|
||||
float3 N = float3(0), dNu = float3(0), dNv = float3(0);
|
||||
|
||||
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
output.position = P;
|
||||
output.normal = N;
|
||||
output.tangent = dPu;
|
||||
output.bitangent = dPv;
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
|
||||
output.tessCoord = UV;
|
||||
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_STAGE_IN
|
||||
template<typename PerPatchVertexGregoryBasis>
|
||||
#endif
|
||||
OsdPatchVertex OsdComputePatch(
|
||||
float tessLevel,
|
||||
float2 domainCoord,
|
||||
unsigned patchID,
|
||||
#if USE_STAGE_IN
|
||||
PerPatchVertexGregoryBasis osdPatch
|
||||
#else
|
||||
OsdVertexBufferSet osdBuffers
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return ds_gregory_patches(
|
||||
tessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.tessOuterLo,
|
||||
osdPatch.tessOuterHi,
|
||||
#else
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterLo,
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterHi,
|
||||
#endif
|
||||
#endif
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.cv,
|
||||
osdPatch.patchParam,
|
||||
#else
|
||||
osdBuffers.perPatchVertexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers.patchParamBuffer[patchID],
|
||||
#endif
|
||||
domainCoord);
|
||||
}
|
||||
266
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchGregoryBasis.metal
vendored
Normal file
266
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchGregoryBasis.metal
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
#line 0 "osd/mtlPatchGregoryBasis.metal"
|
||||
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryBasis.Hull
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerVertex(
|
||||
float4 position,
|
||||
threadgroup HullVertex& hullVertex,
|
||||
int vertexId,
|
||||
float4x4 modelViewProjectionMatrix,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
hullVertex.position = position;
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
float4 clipPos = mul(modelViewProjectionMatrix, position);
|
||||
short3 clip0 = short3(clipPos.x < clipPos.w,
|
||||
clipPos.y < clipPos.w,
|
||||
clipPos.z < clipPos.w);
|
||||
short3 clip1 = short3(clipPos.x > -clipPos.w,
|
||||
clipPos.y > -clipPos.w,
|
||||
clipPos.z > -clipPos.w);
|
||||
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryBasis.Factors
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchGregoryFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
#if !USE_PTVS_FACTORS
|
||||
device OsdPerPatchTessFactors& patchFactors,
|
||||
#endif
|
||||
device MTLQuadTessellationFactorsHalf& quadFactors
|
||||
)
|
||||
{
|
||||
float4 tessLevelOuter = float4(0);
|
||||
float2 tessLevelInner = float2(0);
|
||||
float4 tessOuterLo = float4(0);
|
||||
float4 tessOuterHi = float4(0);
|
||||
|
||||
#if OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
float3 bezcv[16];
|
||||
bezcv[ 0] = patchVertices[ 0].position.xyz;
|
||||
bezcv[ 1] = patchVertices[ 1].position.xyz;
|
||||
bezcv[ 2] = patchVertices[ 7].position.xyz;
|
||||
bezcv[ 3] = patchVertices[ 5].position.xyz;
|
||||
bezcv[ 4] = patchVertices[ 2].position.xyz;
|
||||
bezcv[ 5] = patchVertices[ 3].position.xyz;
|
||||
bezcv[ 6] = patchVertices[ 8].position.xyz;
|
||||
bezcv[ 7] = patchVertices[ 6].position.xyz;
|
||||
bezcv[ 8] = patchVertices[16].position.xyz;
|
||||
bezcv[ 9] = patchVertices[18].position.xyz;
|
||||
bezcv[10] = patchVertices[13].position.xyz;
|
||||
bezcv[11] = patchVertices[12].position.xyz;
|
||||
bezcv[12] = patchVertices[15].position.xyz;
|
||||
bezcv[13] = patchVertices[17].position.xyz;
|
||||
bezcv[14] = patchVertices[11].position.xyz;
|
||||
bezcv[15] = patchVertices[10].position.xyz;
|
||||
|
||||
OsdEvalPatchBezierTessLevels(
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
bezcv,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(
|
||||
tessLevel,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#endif
|
||||
|
||||
quadFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
|
||||
quadFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
|
||||
quadFactors.edgeTessellationFactor[2] = tessLevelOuter[2];
|
||||
quadFactors.edgeTessellationFactor[3] = tessLevelOuter[3];
|
||||
quadFactors.insideTessellationFactor[0] = tessLevelInner[0];
|
||||
quadFactors.insideTessellationFactor[1] = tessLevelInner[1];
|
||||
#if !USE_PTVS_FACTORS
|
||||
patchFactors.tessOuterLo = tessOuterLo;
|
||||
patchFactors.tessOuterHi = tessOuterHi;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OsdComputePerPatchFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
unsigned patchID,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
OsdPatchParamBufferSet osdBuffer,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
device MTLQuadTessellationFactorsHalf& quadFactors
|
||||
)
|
||||
{
|
||||
OsdComputePerPatchGregoryFactors(
|
||||
patchParam,
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
patchVertices,
|
||||
#if !USE_PTVS_FACTORS
|
||||
osdBuffer.patchTessBuffer[patchID],
|
||||
#endif
|
||||
quadFactors
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryBasis.Vertex
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchVertex(
|
||||
int3 patchParam,
|
||||
unsigned ID,
|
||||
unsigned PrimitiveID,
|
||||
unsigned ControlID,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
//Does nothing, all transforms are in the PTVS
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryBasis.Domain
|
||||
//----------------------------------------------------------
|
||||
|
||||
#define USE_128BIT_GREGORY_BASIS_INDICES_READ 1
|
||||
|
||||
|
||||
#if USE_STAGE_IN
|
||||
template<typename PerPatchVertexGregoryBasis>
|
||||
#endif
|
||||
OsdPatchVertex ds_gregory_basis_patches(
|
||||
const float tessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
float4 tessOuterLo,
|
||||
float4 tessOuterHi,
|
||||
#endif
|
||||
#if USE_STAGE_IN
|
||||
PerPatchVertexGregoryBasis patch,
|
||||
#else
|
||||
const device OsdInputVertexType* patch,
|
||||
const device unsigned* patchIndices,
|
||||
#endif
|
||||
int3 patchParam,
|
||||
float2 domainCoord
|
||||
)
|
||||
{
|
||||
#if USE_STAGE_IN
|
||||
float3 cv[20];
|
||||
for(int i = 0; i < 20; i++)
|
||||
cv[i] = patch[i].position;
|
||||
#else
|
||||
#if USE_128BIT_GREGORY_BASIS_INDICES_READ
|
||||
float3 cv[20];
|
||||
for(int i = 0; i < 5; i++) {
|
||||
int4 indices = ((device int4*)patchIndices)[i];
|
||||
|
||||
int n = i * 4;
|
||||
cv[n + 0] = (patch + indices[0])->position;
|
||||
cv[n + 1] = (patch + indices[1])->position;
|
||||
cv[n + 2] = (patch + indices[2])->position;
|
||||
cv[n + 3] = (patch + indices[3])->position;
|
||||
}
|
||||
#else
|
||||
float3 cv[20];
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
cv[i] = patch[patchIndices[i]].position;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if USE_PTVS_FACTORS
|
||||
float4 tessOuterLo(0), tessOuterHi(0);
|
||||
OsdGetTessLevelsUniform(tessLevel, patchParam, tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
float2 UV = OsdGetTessParameterization(domainCoord,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
OsdPatchVertex output;
|
||||
|
||||
float3 P = float3(0), dPu = float3(0), dPv = float3(0);
|
||||
float3 N = float3(0), dNu = float3(0), dNv = float3(0);
|
||||
|
||||
OsdEvalPatchGregory(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
output.position = P;
|
||||
output.normal = N;
|
||||
output.tangent = dPu;
|
||||
output.bitangent = dPv;
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
|
||||
output.tessCoord = UV;
|
||||
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_STAGE_IN
|
||||
template<typename PerPatchVertexGregoryBasis>
|
||||
#endif
|
||||
OsdPatchVertex OsdComputePatch(
|
||||
float tessLevel,
|
||||
float2 domainCoord,
|
||||
unsigned patchID,
|
||||
#if USE_STAGE_IN
|
||||
PerPatchVertexGregoryBasis osdPatch
|
||||
#else
|
||||
OsdVertexBufferSet osdBuffers
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return ds_gregory_basis_patches(
|
||||
tessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.tessOuterLo,
|
||||
osdPatch.tessOuterHi,
|
||||
#else
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterLo,
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterHi,
|
||||
#endif
|
||||
#endif
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.cv,
|
||||
osdPatch.patchParam,
|
||||
#else
|
||||
osdBuffers.vertexBuffer,
|
||||
osdBuffers.indexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers.patchParamBuffer[patchID],
|
||||
#endif
|
||||
domainCoord
|
||||
);
|
||||
}
|
||||
248
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchGregoryTriangle.metal
vendored
Normal file
248
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchGregoryTriangle.metal
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
#line 0 "osd/mtlPatchGregoryTriangle.metal"
|
||||
|
||||
//
|
||||
// Copyright 2019 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryTriangle.Hull
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerVertex(
|
||||
float4 position,
|
||||
threadgroup HullVertex& hullVertex,
|
||||
int vertexId,
|
||||
float4x4 modelViewProjectionMatrix,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
hullVertex.position = position;
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
float4 clipPos = mul(modelViewProjectionMatrix, position);
|
||||
short3 clip0 = short3(clipPos.x < clipPos.w,
|
||||
clipPos.y < clipPos.w,
|
||||
clipPos.z < clipPos.w);
|
||||
short3 clip1 = short3(clipPos.x > -clipPos.w,
|
||||
clipPos.y > -clipPos.w,
|
||||
clipPos.z > -clipPos.w);
|
||||
hullVertex.clipFlag = short3(clip0) + 2*short3(clip1);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryTriangle.Factors
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchGregoryTriangleFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
#if !USE_PTVS_FACTORS
|
||||
device OsdPerPatchTessFactors& patchFactors,
|
||||
#endif
|
||||
device MTLTriangleTessellationFactorsHalf& triFactors
|
||||
)
|
||||
{
|
||||
float4 tessLevelOuter = float(0);
|
||||
float2 tessLevelInner = float(0);
|
||||
float4 tessOuterLo = float(0);
|
||||
float4 tessOuterHi = float(0);
|
||||
|
||||
#if OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
float3 cv[15];
|
||||
cv[ 0] = patchVertices[ 0].position.xyz;
|
||||
cv[ 1] = patchVertices[ 1].position.xyz;
|
||||
cv[ 2] = patchVertices[15].position.xyz;
|
||||
cv[ 3] = patchVertices[ 7].position.xyz;
|
||||
cv[ 4] = patchVertices[ 5].position.xyz;
|
||||
cv[ 5] = patchVertices[ 2].position.xyz;
|
||||
cv[ 6] = patchVertices[ 3].position.xyz;
|
||||
cv[ 7] = patchVertices[ 8].position.xyz;
|
||||
cv[ 8] = patchVertices[ 6].position.xyz;
|
||||
cv[ 9] = patchVertices[17].position.xyz;
|
||||
cv[10] = patchVertices[13].position.xyz;
|
||||
cv[11] = patchVertices[16].position.xyz;
|
||||
cv[12] = patchVertices[11].position.xyz;
|
||||
cv[13] = patchVertices[12].position.xyz;
|
||||
cv[14] = patchVertices[10].position.xyz;
|
||||
|
||||
OsdEvalPatchBezierTriangleTessLevels(
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
cv,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#else
|
||||
OsdGetTessLevelsUniformTriangle(
|
||||
tessLevel,
|
||||
patchParam,
|
||||
tessLevelOuter,
|
||||
tessLevelInner,
|
||||
tessOuterLo,
|
||||
tessOuterHi
|
||||
);
|
||||
#endif
|
||||
|
||||
triFactors.edgeTessellationFactor[0] = tessLevelOuter[0];
|
||||
triFactors.edgeTessellationFactor[1] = tessLevelOuter[1];
|
||||
triFactors.edgeTessellationFactor[2] = tessLevelOuter[2];
|
||||
triFactors.insideTessellationFactor = tessLevelInner[0];
|
||||
#if !USE_PTVS_FACTORS
|
||||
patchFactors.tessOuterLo = tessOuterLo;
|
||||
patchFactors.tessOuterHi = tessOuterHi;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OsdComputePerPatchFactors(
|
||||
int3 patchParam,
|
||||
float tessLevel,
|
||||
unsigned patchID,
|
||||
float4x4 projectionMatrix,
|
||||
float4x4 modelViewMatrix,
|
||||
OsdPatchParamBufferSet osdBuffer,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
device MTLTriangleTessellationFactorsHalf& triFactors
|
||||
)
|
||||
{
|
||||
OsdComputePerPatchGregoryTriangleFactors(
|
||||
patchParam,
|
||||
tessLevel,
|
||||
projectionMatrix,
|
||||
modelViewMatrix,
|
||||
patchVertices,
|
||||
#if !USE_PTVS_FACTORS
|
||||
osdBuffer.patchTessBuffer[patchID],
|
||||
#endif
|
||||
triFactors
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryTriangle.Vertex
|
||||
//----------------------------------------------------------
|
||||
|
||||
void OsdComputePerPatchVertex(
|
||||
int3 patchParam,
|
||||
unsigned ID,
|
||||
unsigned PrimitiveID,
|
||||
unsigned ControlID,
|
||||
threadgroup PatchVertexType* patchVertices,
|
||||
OsdPatchParamBufferSet osdBuffers
|
||||
)
|
||||
{
|
||||
//Does nothing, all transforms are in the PTVS
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.GregoryTriangle.Domain
|
||||
//----------------------------------------------------------
|
||||
|
||||
#if USE_STAGE_IN
|
||||
template<typename PerPatchVertexGregoryBasis>
|
||||
#endif
|
||||
OsdPatchVertex ds_gregory_triangle_patches(
|
||||
const float tessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
float4 tessOuterLo,
|
||||
float4 tessOuterHi,
|
||||
#endif
|
||||
#if USE_STAGE_IN
|
||||
PerPatchVertexGregoryBasis patch,
|
||||
#else
|
||||
const device OsdInputVertexType* patch,
|
||||
const device unsigned* patchIndices,
|
||||
#endif
|
||||
int3 patchParam,
|
||||
float3 domainCoord
|
||||
)
|
||||
{
|
||||
#if USE_STAGE_IN
|
||||
float3 cv[18];
|
||||
for(int i = 0; i < 18; i++)
|
||||
cv[i] = patch[i].position;
|
||||
#else
|
||||
float3 cv[18];
|
||||
for (int i = 0; i < 18; ++i) {
|
||||
cv[i] = patch[patchIndices[i]].position;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_PTVS_FACTORS
|
||||
float4 tessOuterLo(0), tessOuterHi(0);
|
||||
OsdGetTessLevelsUniform(tessLevel, patchParam, tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
float2 UV = OsdGetTessParameterizationTriangle(domainCoord,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
OsdPatchVertex output;
|
||||
|
||||
float3 P = float3(0), dPu = float3(0), dPv = float3(0);
|
||||
float3 N = float3(0), dNu = float3(0), dNv = float3(0);
|
||||
|
||||
OsdEvalPatchGregoryTriangle(
|
||||
patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
output.position = P;
|
||||
output.normal = N;
|
||||
output.tangent = dPu;
|
||||
output.bitangent = dPv;
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
output.Nu = dNu;
|
||||
output.Nv = dNv;
|
||||
#endif
|
||||
|
||||
output.tessCoord = UV;
|
||||
output.patchCoord = OsdInterpolatePatchCoord(UV, patchParam);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#if USE_STAGE_IN
|
||||
template<typename PerPatchVertexGregoryBasis>
|
||||
#endif
|
||||
OsdPatchVertex OsdComputePatch(
|
||||
float tessLevel,
|
||||
float3 domainCoord,
|
||||
unsigned patchID,
|
||||
#if USE_STAGE_IN
|
||||
PerPatchVertexGregoryBasis osdPatch
|
||||
#else
|
||||
OsdVertexBufferSet osdBuffers
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return ds_gregory_triangle_patches(
|
||||
tessLevel,
|
||||
#if !USE_PTVS_FACTORS
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.tessOuterLo,
|
||||
osdPatch.tessOuterHi,
|
||||
#else
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterLo,
|
||||
osdBuffers.patchTessBuffer[patchID].tessOuterHi,
|
||||
#endif
|
||||
#endif
|
||||
#if USE_STAGE_IN
|
||||
osdPatch.cv,
|
||||
osdPatch.patchParam,
|
||||
#else
|
||||
osdBuffers.vertexBuffer,
|
||||
osdBuffers.indexBuffer + patchID * VERTEX_CONTROL_POINTS_PER_PATCH,
|
||||
osdBuffers.patchParamBuffer[patchID],
|
||||
#endif
|
||||
domainCoord
|
||||
);
|
||||
}
|
||||
550
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchLegacy.metal
vendored
Normal file
550
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchLegacy.metal
vendored
Normal file
@@ -0,0 +1,550 @@
|
||||
#line 0 "osd/mtlPatchBoxSplineTriangle.metal"
|
||||
|
||||
//
|
||||
// Copyright 2015-2019 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Common
|
||||
//----------------------------------------------------------
|
||||
|
||||
#define offsetof_(X, Y) &(((device X*)nullptr)->Y)
|
||||
|
||||
#define OSD_IS_ADAPTIVE (OSD_PATCH_REGULAR || OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_TRIANGLE || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY)
|
||||
|
||||
#ifndef OSD_NUM_ELEMENTS
|
||||
#define OSD_NUM_ELEMENTS 3
|
||||
#endif
|
||||
|
||||
struct OsdPerVertexGregory {
|
||||
float3 P;
|
||||
short3 clipFlag;
|
||||
int valence;
|
||||
float3 e0;
|
||||
float3 e1;
|
||||
#if OSD_PATCH_GREGORY_BOUNDARY
|
||||
int zerothNeighbor;
|
||||
float3 org;
|
||||
#endif
|
||||
float3 r[OSD_MAX_VALENCE];
|
||||
};
|
||||
|
||||
struct OsdPerPatchVertexGregory {
|
||||
packed_float3 P;
|
||||
packed_float3 Ep;
|
||||
packed_float3 Em;
|
||||
packed_float3 Fp;
|
||||
packed_float3 Fm;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
// HLSL->Metal Compatibility
|
||||
//----------------------------------------------------------
|
||||
|
||||
float4 mul(float4x4 a, float4 b)
|
||||
{
|
||||
return a * b;
|
||||
}
|
||||
|
||||
float3 mul(float4x4 a, float3 b)
|
||||
{
|
||||
float3x3 m(a[0].xyz, a[1].xyz, a[2].xyz);
|
||||
return m * b;
|
||||
|
||||
}
|
||||
|
||||
struct HullVertex {
|
||||
float4 position;
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
short3 clipFlag;
|
||||
#endif
|
||||
|
||||
float3 GetPosition() threadgroup
|
||||
{
|
||||
return position.xyz;
|
||||
}
|
||||
|
||||
void SetPosition(float3 v) threadgroup
|
||||
{
|
||||
position.xyz = v;
|
||||
}
|
||||
};
|
||||
|
||||
// XXXdyu all downstream data can be handled by client code
|
||||
struct OsdPatchVertex {
|
||||
float3 position;
|
||||
float3 normal;
|
||||
float3 tangent;
|
||||
float3 bitangent;
|
||||
float4 patchCoord; //u, v, faceLevel, faceId
|
||||
float2 tessCoord; // tesscoord.st
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
float3 Nu;
|
||||
float3 Nv;
|
||||
#endif
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
float2 vSegments;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct OsdPerPatchTessFactors {
|
||||
float4 tessOuterLo;
|
||||
float4 tessOuterHi;
|
||||
};
|
||||
|
||||
using OsdPatchParamBufferType = packed_int3;
|
||||
|
||||
#if OSD_PATCH_REGULAR || OSD_PATCH_BOX_SPLINE_TRIANGLE
|
||||
using PatchVertexType = HullVertex;
|
||||
using PerPatchVertexType = OsdPerPatchVertexBezier;
|
||||
#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
using PatchVertexType = OsdPerVertexGregory;
|
||||
using PerPatchVertexType = OsdPerPatchVertexGregory;
|
||||
#elif OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_TRIANGLE
|
||||
using PatchVertexType = HullVertex;
|
||||
using PerPatchVertexType = OsdPerPatchVertexGregoryBasis;
|
||||
#else
|
||||
using PatchVertexType = OsdInputVertexType;
|
||||
using PerPatchVertexType = OsdInputVertexType;
|
||||
#endif
|
||||
|
||||
//Shared buffers used by OSD that are common to all kernels
|
||||
struct OsdPatchParamBufferSet
|
||||
{
|
||||
const device OsdInputVertexType* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]];
|
||||
const device unsigned* indexBuffer [[buffer(CONTROL_INDICES_BUFFER_INDEX)]];
|
||||
|
||||
const device OsdPatchParamBufferType* patchParamBuffer [[buffer(OSD_PATCHPARAM_BUFFER_INDEX)]];
|
||||
|
||||
device PerPatchVertexType* perPatchVertexBuffer [[buffer(OSD_PERPATCHVERTEX_BUFFER_INDEX)]];
|
||||
|
||||
#if !USE_PTVS_FACTORS
|
||||
device OsdPerPatchTessFactors* patchTessBuffer [[buffer(OSD_PERPATCHTESSFACTORS_BUFFER_INDEX)]];
|
||||
#endif
|
||||
|
||||
#if OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
const device int* quadOffsetBuffer [[buffer(OSD_QUADOFFSET_BUFFER_INDEX)]];
|
||||
const device int* valenceBuffer [[buffer(OSD_VALENCE_BUFFER_INDEX)]];
|
||||
#endif
|
||||
|
||||
const constant unsigned& kernelExecutionLimit [[buffer(OSD_KERNELLIMIT_BUFFER_INDEX)]];
|
||||
};
|
||||
|
||||
//Shared buffers used by OSD that are common to all PTVS implementations
|
||||
struct OsdVertexBufferSet
|
||||
{
|
||||
const device OsdInputVertexType* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]];
|
||||
const device unsigned* indexBuffer [[buffer(CONTROL_INDICES_BUFFER_INDEX)]];
|
||||
|
||||
const device OsdPatchParamBufferType* patchParamBuffer [[buffer(OSD_PATCHPARAM_BUFFER_INDEX)]];
|
||||
|
||||
device PerPatchVertexType* perPatchVertexBuffer [[buffer(OSD_PERPATCHVERTEX_BUFFER_INDEX)]];
|
||||
|
||||
#if !USE_PTVS_FACTORS
|
||||
device OsdPerPatchTessFactors* patchTessBuffer [[buffer(OSD_PERPATCHTESSFACTORS_BUFFER_INDEX)]];
|
||||
#endif
|
||||
};
|
||||
|
||||
// These are stored in OsdPatchParamBuffer indexed by the value returned
|
||||
// from OsdGetPatchIndex() which is a function of the current PrimitiveID
|
||||
// along with an optional client provided offset.
|
||||
|
||||
int3 OsdGetPatchParam(int patchIndex, const device OsdPatchParamBufferType* osdPatchParamBuffer)
|
||||
{
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
return int3(osdPatchParamBuffer[patchIndex]);
|
||||
#else
|
||||
auto p = osdPatchParamBuffer[patchIndex];
|
||||
return int3(p[0], p[1], 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int OsdGetPatchIndex(int primitiveId)
|
||||
{
|
||||
return primitiveId;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// patch culling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool OsdCullPerPatchVertex(
|
||||
threadgroup PatchVertexType* patch,
|
||||
float4x4 ModelViewMatrix
|
||||
)
|
||||
{
|
||||
#if OSD_ENABLE_BACKPATCH_CULL && OSD_PATCH_REGULAR
|
||||
auto v0 = float3(ModelViewMatrix * patch[5].position);
|
||||
auto v3 = float3(ModelViewMatrix * patch[6].position);
|
||||
auto v12 = float3(ModelViewMatrix * patch[9].position);
|
||||
|
||||
auto n = normalize(cross(v3 - v0, v12 - v0));
|
||||
v0 = normalize(v0 + v3 + v12);
|
||||
|
||||
if(dot(v0, n) > 0.6f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
short3 clipFlag = short3(0,0,0);
|
||||
for(int i = 0; i < CONTROL_POINTS_PER_PATCH; ++i) {
|
||||
clipFlag |= patch[i].clipFlag;
|
||||
}
|
||||
if (any(clipFlag != short3(3,3,3))) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Legacy Gregory
|
||||
// ----------------------------------------------------------------------------
|
||||
#if defined(OSD_PATCH_GREGORY) || defined(OSD_PATCH_GREGORY_BOUNDARY)
|
||||
|
||||
// precomputed catmark coefficient table up to valence 29
|
||||
constant float OsdCatmarkCoefficient[30] = {
|
||||
0, 0, 0, 0.812816, 0.500000, 0.363644, 0.287514,
|
||||
0.238688, 0.204544, 0.179229, 0.159657,
|
||||
0.144042, 0.131276, 0.120632, 0.111614,
|
||||
0.103872, 0.09715, 0.0912559, 0.0860444,
|
||||
0.0814022, 0.0772401, 0.0734867, 0.0700842,
|
||||
0.0669851, 0.0641504, 0.0615475, 0.0591488,
|
||||
0.0569311, 0.0548745, 0.0529621
|
||||
};
|
||||
|
||||
float
|
||||
OsdComputeCatmarkCoefficient(int valence)
|
||||
{
|
||||
#if OSD_MAX_VALENCE < 30
|
||||
return OsdCatmarkCoefficient[valence];
|
||||
#else
|
||||
if (valence < 30) {
|
||||
return OsdCatmarkCoefficient[valence];
|
||||
} else {
|
||||
float t = 2.0f / float(valence);
|
||||
return 1.0f / (valence * (cospi(t) + 5.0f +
|
||||
sqrt((cospi(t) + 9) * (cospi(t) + 1)))/16.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float cosfn(int n, int j) {
|
||||
return cospi((2.0f * j)/float(n));
|
||||
}
|
||||
|
||||
float sinfn(int n, int j) {
|
||||
return sinpi((2.0f * j)/float(n));
|
||||
}
|
||||
|
||||
#ifndef OSD_MAX_VALENCE
|
||||
#define OSD_MAX_VALENCE 4
|
||||
#endif
|
||||
|
||||
template<typename OsdVertexBuffer>
|
||||
float3 OsdReadVertex(int vertexIndex, OsdVertexBuffer osdVertexBuffer)
|
||||
{
|
||||
int index = (vertexIndex /*+ OsdBaseVertex()*/);
|
||||
return osdVertexBuffer[index].position;
|
||||
}
|
||||
|
||||
template<typename OsdValenceBuffer>
|
||||
int OsdReadVertexValence(int vertexID, OsdValenceBuffer osdValenceBuffer)
|
||||
{
|
||||
int index = int(vertexID * (2 * OSD_MAX_VALENCE + 1));
|
||||
return osdValenceBuffer[index];
|
||||
}
|
||||
|
||||
template<typename OsdValenceBuffer>
|
||||
int OsdReadVertexIndex(int vertexID, int valenceVertex, OsdValenceBuffer osdValenceBuffer)
|
||||
{
|
||||
int index = int(vertexID * (2 * OSD_MAX_VALENCE + 1) + 1 + valenceVertex);
|
||||
return osdValenceBuffer[index];
|
||||
}
|
||||
|
||||
template<typename OsdQuadOffsetBuffer>
|
||||
int OsdReadQuadOffset(int primitiveID, int offsetVertex, OsdQuadOffsetBuffer osdQuadOffsetBuffer)
|
||||
{
|
||||
int index = int(4*primitiveID + offsetVertex);
|
||||
return osdQuadOffsetBuffer[index];
|
||||
}
|
||||
|
||||
|
||||
void OsdComputePerVertexGregory(unsigned vID, float3 P, threadgroup OsdPerVertexGregory& v, OsdPatchParamBufferSet osdBuffers)
|
||||
{
|
||||
v.clipFlag = short3(0,0,0);
|
||||
|
||||
int ivalence = OsdReadVertexValence(vID, osdBuffers.valenceBuffer);
|
||||
v.valence = ivalence;
|
||||
int valence = abs(ivalence);
|
||||
|
||||
float3 f[OSD_MAX_VALENCE];
|
||||
float3 pos = P;
|
||||
float3 opos = float3(0,0,0);
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
v.org = pos;
|
||||
int boundaryEdgeNeighbors[2];
|
||||
int currNeighbor = 0;
|
||||
int ibefore = 0;
|
||||
int zerothNeighbor = 0;
|
||||
#endif
|
||||
|
||||
for (int i=0; i<valence; ++i) {
|
||||
int im = (i+valence-1)%valence;
|
||||
int ip = (i+1)%valence;
|
||||
|
||||
int idx_neighbor = OsdReadVertexIndex(vID, 2*i, osdBuffers.valenceBuffer);
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
bool isBoundaryNeighbor = false;
|
||||
int valenceNeighbor = OsdReadVertexValence(idx_neighbor, osdBuffers.valenceBuffer);
|
||||
|
||||
if (valenceNeighbor < 0) {
|
||||
isBoundaryNeighbor = true;
|
||||
if (currNeighbor<2) {
|
||||
boundaryEdgeNeighbors[currNeighbor] = idx_neighbor;
|
||||
}
|
||||
currNeighbor++;
|
||||
if (currNeighbor == 1) {
|
||||
ibefore = i;
|
||||
zerothNeighbor = i;
|
||||
} else {
|
||||
if (i-ibefore == 1) {
|
||||
int tmp = boundaryEdgeNeighbors[0];
|
||||
boundaryEdgeNeighbors[0] = boundaryEdgeNeighbors[1];
|
||||
boundaryEdgeNeighbors[1] = tmp;
|
||||
zerothNeighbor = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
float3 neighbor = OsdReadVertex(idx_neighbor, osdBuffers.vertexBuffer);
|
||||
|
||||
int idx_diagonal = OsdReadVertexIndex(vID, 2*i + 1, osdBuffers.valenceBuffer);
|
||||
float3 diagonal = OsdReadVertex(idx_diagonal, osdBuffers.vertexBuffer);
|
||||
|
||||
int idx_neighbor_p = OsdReadVertexIndex(vID, 2*ip, osdBuffers.valenceBuffer);
|
||||
float3 neighbor_p = OsdReadVertex(idx_neighbor_p, osdBuffers.vertexBuffer);
|
||||
|
||||
int idx_neighbor_m = OsdReadVertexIndex(vID, 2*im, osdBuffers.valenceBuffer);
|
||||
float3 neighbor_m = OsdReadVertex(idx_neighbor_m, osdBuffers.vertexBuffer);
|
||||
|
||||
int idx_diagonal_m = OsdReadVertexIndex(vID, 2*im + 1, osdBuffers.valenceBuffer);
|
||||
float3 diagonal_m = OsdReadVertex(idx_diagonal_m, osdBuffers.vertexBuffer);
|
||||
|
||||
f[i] = (pos * float(valence) + (neighbor_p + neighbor)*2.0f + diagonal) / (float(valence)+5.0f);
|
||||
|
||||
opos += f[i];
|
||||
v.r[i] = (neighbor_p-neighbor_m)/3.0f + (diagonal - diagonal_m)/6.0f;
|
||||
}
|
||||
|
||||
opos /= valence;
|
||||
v.P = float4(opos, 1.0f).xyz;
|
||||
|
||||
float3 e;
|
||||
v.e0 = float3(0,0,0);
|
||||
v.e1 = float3(0,0,0);
|
||||
|
||||
for(int i=0; i<valence; ++i) {
|
||||
int im = (i + valence -1) % valence;
|
||||
e = 0.5f * (f[i] + f[im]);
|
||||
v.e0 += cosfn(valence, i)*e;
|
||||
v.e1 += sinfn(valence, i)*e;
|
||||
}
|
||||
float ef = OsdComputeCatmarkCoefficient(valence);
|
||||
v.e0 *= ef;
|
||||
v.e1 *= ef;
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
v.zerothNeighbor = zerothNeighbor;
|
||||
if (currNeighbor == 1) {
|
||||
boundaryEdgeNeighbors[1] = boundaryEdgeNeighbors[0];
|
||||
}
|
||||
|
||||
if (ivalence < 0) {
|
||||
if (valence > 2) {
|
||||
v.P = (OsdReadVertex(boundaryEdgeNeighbors[0], osdBuffers.vertexBuffer) +
|
||||
OsdReadVertex(boundaryEdgeNeighbors[1], osdBuffers.vertexBuffer) +
|
||||
4.0f * pos)/6.0f;
|
||||
} else {
|
||||
v.P = pos;
|
||||
}
|
||||
|
||||
v.e0 = (OsdReadVertex(boundaryEdgeNeighbors[0], osdBuffers.vertexBuffer) -
|
||||
OsdReadVertex(boundaryEdgeNeighbors[1], osdBuffers.vertexBuffer))/6.0;
|
||||
|
||||
float k = float(float(valence) - 1.0f); //k is the number of faces
|
||||
float c = cospi(1.0/k);
|
||||
float s = sinpi(1.0/k);
|
||||
float gamma = -(4.0f*s)/(3.0f*k+c);
|
||||
float alpha_0k = -((1.0f+2.0f*c)*sqrt(1.0f+c))/((3.0f*k+c)*sqrt(1.0f-c));
|
||||
float beta_0 = s/(3.0f*k + c);
|
||||
|
||||
int idx_diagonal = OsdReadVertexIndex(vID, 2*zerothNeighbor + 1, osdBuffers.valenceBuffer);
|
||||
float3 diagonal = OsdReadVertex(idx_diagonal, osdBuffers.vertexBuffer);
|
||||
|
||||
v.e1 = gamma * pos +
|
||||
alpha_0k * OsdReadVertex(boundaryEdgeNeighbors[0], osdBuffers.vertexBuffer) +
|
||||
alpha_0k * OsdReadVertex(boundaryEdgeNeighbors[1], osdBuffers.vertexBuffer) +
|
||||
beta_0 * diagonal;
|
||||
|
||||
for (int x=1; x<valence - 1; ++x) {
|
||||
int curri = ((x + zerothNeighbor)%valence);
|
||||
float alpha = (4.0f*sinpi((float(x))/k))/(3.0f*k+c);
|
||||
float beta = (sinpi((float(x))/k) + sinpi((float(x+1))/k))/(3.0f*k+c);
|
||||
|
||||
int idx_neighbor = OsdReadVertexIndex(vID, 2*curri, osdBuffers.valenceBuffer);
|
||||
float3 neighbor = OsdReadVertex(idx_neighbor, osdBuffers.vertexBuffer);
|
||||
|
||||
idx_diagonal = OsdReadVertexIndex(vID, 2*curri + 1, osdBuffers.valenceBuffer);
|
||||
diagonal = OsdReadVertex(idx_diagonal, osdBuffers.vertexBuffer);
|
||||
|
||||
v.e1 += alpha * neighbor + beta * diagonal;
|
||||
}
|
||||
|
||||
v.e1 /= 3.0f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
OsdComputePerPatchVertexGregory(int3 patchParam, unsigned ID, unsigned primitiveID,
|
||||
threadgroup OsdPerVertexGregory* v,
|
||||
device OsdPerPatchVertexGregory& result,
|
||||
OsdPatchParamBufferSet osdBuffers)
|
||||
{
|
||||
result.P = v[ID].P;
|
||||
|
||||
int i = ID;
|
||||
int ip = (i+1)%4;
|
||||
int im = (i+3)%4;
|
||||
int valence = abs(v[i].valence);
|
||||
int n = valence;
|
||||
|
||||
int start = OsdReadQuadOffset(primitiveID, i, osdBuffers.quadOffsetBuffer) & 0xff;
|
||||
int prev = (OsdReadQuadOffset(primitiveID, i, osdBuffers.quadOffsetBuffer) >> 8) & 0xff;
|
||||
|
||||
int start_m = OsdReadQuadOffset(primitiveID, im, osdBuffers.quadOffsetBuffer) & 0xff;
|
||||
int prev_p = (OsdReadQuadOffset(primitiveID, ip, osdBuffers.quadOffsetBuffer) >> 8) & 0xff;
|
||||
|
||||
int np = abs(v[ip].valence);
|
||||
int nm = abs(v[im].valence);
|
||||
|
||||
// Control Vertices based on :
|
||||
// "Approximating Subdivision Surfaces with Gregory Patches
|
||||
// for Hardware Tessellation"
|
||||
// Loop, Schaefer, Ni, Castano (ACM ToG Siggraph Asia 2009)
|
||||
//
|
||||
// P3 e3- e2+ P2
|
||||
// O--------O--------O--------O
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | f3- | f2+ |
|
||||
// | O O |
|
||||
// e3+ O------O O------O e2-
|
||||
// | f3+ f2- |
|
||||
// | |
|
||||
// | |
|
||||
// | f0- f1+ |
|
||||
// e0- O------O O------O e1+
|
||||
// | O O |
|
||||
// | | f0+ | f1- |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// O--------O--------O--------O
|
||||
// P0 e0+ e1- P1
|
||||
//
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
float3 Em_ip;
|
||||
if (v[ip].valence < -2) {
|
||||
int j = (np + prev_p - v[ip].zerothNeighbor) % np;
|
||||
Em_ip = v[ip].P + cospi(j/float(np-1))*v[ip].e0 + sinpi(j/float(np-1))*v[ip].e1;
|
||||
} else {
|
||||
Em_ip = v[ip].P + v[ip].e0*cosfn(np, prev_p) + v[ip].e1*sinfn(np, prev_p);
|
||||
}
|
||||
|
||||
float3 Ep_im;
|
||||
if (v[im].valence < -2) {
|
||||
int j = (nm + start_m - v[im].zerothNeighbor) % nm;
|
||||
Ep_im = v[im].P + cospi(j/float(nm-1))*v[im].e0 + sinpi(j/float(nm-1))*v[im].e1;
|
||||
} else {
|
||||
Ep_im = v[im].P + v[im].e0*cosfn(nm, start_m) + v[im].e1*sinfn(nm, start_m);
|
||||
}
|
||||
|
||||
if (v[i].valence < 0) {
|
||||
n = (n-1)*2;
|
||||
}
|
||||
if (v[im].valence < 0) {
|
||||
nm = (nm-1)*2;
|
||||
}
|
||||
if (v[ip].valence < 0) {
|
||||
np = (np-1)*2;
|
||||
}
|
||||
|
||||
if (v[i].valence > 2) {
|
||||
result.Ep = v[i].P + (v[i].e0*cosfn(n, start) + v[i].e1*sinfn(n, start));
|
||||
result.Em = v[i].P + (v[i].e0*cosfn(n, prev) + v[i].e1*sinfn(n, prev));
|
||||
|
||||
float s1=3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2=2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cospi(2.0f/float(n))-cospi(2.0f/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
|
||||
} else if (v[i].valence < -2) {
|
||||
int j = (valence + start - v[i].zerothNeighbor) % valence;
|
||||
|
||||
result.Ep = v[i].P + cospi(j/float(valence-1))*v[i].e0 + sinpi(j/float(valence-1))*v[i].e1;
|
||||
j = (valence + prev - v[i].zerothNeighbor) % valence;
|
||||
result.Em = v[i].P + cospi(j/float(valence-1))*v[i].e0 + sinpi(j/float(valence-1))*v[i].e1;
|
||||
|
||||
float3 Rp = ((-2.0f * v[i].org - 1.0f * v[im].org) + (2.0f * v[ip].org + 1.0f * v[(i+2)%4].org))/3.0f;
|
||||
float3 Rm = ((-2.0f * v[i].org - 1.0f * v[ip].org) + (2.0f * v[im].org + 1.0f * v[(i+2)%4].org))/3.0f;
|
||||
|
||||
float s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2 = 2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cospi(2.0f/float(n))-cospi(2.0f/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
|
||||
if (v[im].valence < 0) {
|
||||
s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
result.Fp = result.Fm = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
} else if (v[ip].valence < 0) {
|
||||
s1 = 3.0f-2.0f*cospi(2.0f/n)-cospi(2.0f/nm);
|
||||
result.Fm = result.Fp = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
}
|
||||
|
||||
} else if (v[i].valence == -2) {
|
||||
result.Ep = (2.0f * v[i].org + v[ip].org)/3.0f;
|
||||
result.Em = (2.0f * v[i].org + v[im].org)/3.0f;
|
||||
result.Fp = result.Fm = (4.0f * v[i].org + v[(i+2)%n].org + 2.0f * v[ip].org + 2.0f * v[im].org)/9.0f;
|
||||
}
|
||||
|
||||
#else // not OSD_PATCH_GREGORY_BOUNDARY
|
||||
|
||||
result.Ep = v[i].P + v[i].e0 * cosfn(n, start) + v[i].e1*sinfn(n, start);
|
||||
result.Em = v[i].P + v[i].e0 * cosfn(n, prev ) + v[i].e1*sinfn(n, prev );
|
||||
|
||||
float3 Em_ip = v[ip].P + v[ip].e0*cosfn(np, prev_p) + v[ip].e1*sinfn(np, prev_p);
|
||||
float3 Ep_im = v[im].P + v[im].e0*cosfn(nm, start_m) + v[im].e1*sinfn(nm, start_m);
|
||||
|
||||
float s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2 = 2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cospi(2.0f/float(n))-cospi(2.0f/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em +s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
76
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchShaderSource.h
vendored
Normal file
76
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchShaderSource.h
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MTL_PATCH_SHADER_SOURCE_H
|
||||
#define OPENSUBDIV3_OSD_MTL_PATCH_SHADER_SOURCE_H
|
||||
|
||||
#import "../version.h"
|
||||
|
||||
#import "../far/patchDescriptor.h"
|
||||
|
||||
#import <string>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Provides shader source which can be used by client code.
|
||||
class MTLPatchShaderSource {
|
||||
public:
|
||||
/// \brief Returns shader source which can be used to evaluate
|
||||
/// position and first and second derivatives on piecewise parametric
|
||||
/// patches resulting from subdivision refinement.
|
||||
static std::string GetPatchBasisShaderSource();
|
||||
|
||||
/// \brief Returns shader source which can be used while drawing
|
||||
/// piecewise parametric patches resulting from subdivision refinement,
|
||||
/// e.g. while using GPU HW tessellation.
|
||||
static std::string GetPatchDrawingShaderSource();
|
||||
|
||||
/// \name Alternative methods
|
||||
/// \{
|
||||
/// These methods return shader source which can be used
|
||||
/// while drawing. Unlike the methods above, the source returned
|
||||
/// by these methods includes support for legacy patch types along
|
||||
/// with dependencies on specific resource bindings and interstage
|
||||
/// shader variable declarations.
|
||||
|
||||
static std::string GetCommonShaderSource();
|
||||
|
||||
static std::string GetVertexShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
static std::string GetHullShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
static std::string GetDomainShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
/// These methods are deprecated. Clients should determine the
|
||||
/// patch type of a face-varying patch by inspecting the
|
||||
/// face-varying patch array descriptors.
|
||||
/// \brief Deprecated
|
||||
static std::string GetVertexShaderSource(
|
||||
Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType);
|
||||
static std::string GetHullShaderSource(
|
||||
Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType);
|
||||
static std::string GetDomainShaderSource(
|
||||
Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType);
|
||||
|
||||
/// @}
|
||||
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OPENSUBDIV3_OSD_MTL_PATCH_SHADER_SOURCE
|
||||
228
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchShaderSource.mm
vendored
Normal file
228
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchShaderSource.mm
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#include "../osd/mtlPatchShaderSource.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static std::string commonShaderSource(
|
||||
#include "mtlPatchCommon.gen.h"
|
||||
);
|
||||
static std::string commonTessShaderSource(
|
||||
#include "mtlPatchCommonTess.gen.h"
|
||||
);
|
||||
static std::string patchLegacyShaderSource(
|
||||
#include "mtlPatchLegacy.gen.h"
|
||||
);
|
||||
static std::string patchBasisTypesShaderSource(
|
||||
#include "patchBasisTypes.gen.h"
|
||||
);
|
||||
static std::string patchBasisShaderSource(
|
||||
#include "patchBasis.gen.h"
|
||||
);
|
||||
static std::string bsplineShaderSource(
|
||||
#include "mtlPatchBSpline.gen.h"
|
||||
);
|
||||
static std::string boxSplineTriangleShaderSource(
|
||||
#include "mtlPatchBoxSplineTriangle.gen.h"
|
||||
);
|
||||
static std::string gregoryShaderSource(
|
||||
#include "mtlPatchGregory.gen.h"
|
||||
);
|
||||
static std::string gregoryBasisShaderSource(
|
||||
#include "mtlPatchGregoryBasis.gen.h"
|
||||
);
|
||||
static std::string gregoryTriangleShaderSource(
|
||||
#include "mtlPatchGregoryTriangle.gen.h"
|
||||
);
|
||||
|
||||
static std::string
|
||||
GetPatchTypeDefine(Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType =
|
||||
Far::PatchDescriptor::NON_PATCH) {
|
||||
|
||||
std::stringstream ss;
|
||||
switch(type) {
|
||||
case Far::PatchDescriptor::LINES:
|
||||
ss << "#define OSD_PATCH_LINES 1\n";
|
||||
break;
|
||||
case Far::PatchDescriptor::TRIANGLES:
|
||||
ss << "#define OSD_PATCH_TRIANGLES 1\n";
|
||||
break;
|
||||
case Far::PatchDescriptor::QUADS:
|
||||
ss << "#define OSD_PATCH_QUADS 1\n";
|
||||
break;
|
||||
case Far::PatchDescriptor::REGULAR:
|
||||
ss << "#define OSD_PATCH_BSPLINE 1\n"
|
||||
"#define OSD_PATCH_REGULAR 1\n";
|
||||
break;
|
||||
case Far::PatchDescriptor::LOOP:
|
||||
ss << "#define OSD_PATCH_BOX_SPLINE_TRIANGLE 1\n";
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
ss << "#define OSD_PATCH_GREGORY 1\n";
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY:
|
||||
ss << "#define OSD_PATCH_GREGORY_BOUNDARY 1\n";
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||
ss << "#define OSD_PATCH_GREGORY_BASIS 1\n";
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_TRIANGLE:
|
||||
ss << "#define OSD_PATCH_GREGORY_TRIANGLE 1\n";
|
||||
break;
|
||||
default:
|
||||
assert("Unknown Far::PatchDescriptor::Type" && 0);
|
||||
return "";
|
||||
}
|
||||
switch(fvarType) {
|
||||
case Far::PatchDescriptor::REGULAR:
|
||||
ss << "#define OSD_FACEVARYING_PATCH_REGULAR 1\n";
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||
ss << "#define OSD_FACEVARYING_PATCH_GREGORY_BASIS 1\n";
|
||||
break;
|
||||
default:
|
||||
return ss.str();
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string
|
||||
GetPatchTypeSource(Far::PatchDescriptor::Type type) {
|
||||
|
||||
switch(type) {
|
||||
case Far::PatchDescriptor::QUADS:
|
||||
case Far::PatchDescriptor::TRIANGLES:
|
||||
return "";
|
||||
case Far::PatchDescriptor::REGULAR:
|
||||
return bsplineShaderSource;
|
||||
case Far::PatchDescriptor::LOOP:
|
||||
return boxSplineTriangleShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
return gregoryShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY:
|
||||
return gregoryShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||
return gregoryBasisShaderSource;
|
||||
case Far::PatchDescriptor::GREGORY_TRIANGLE:
|
||||
return gregoryTriangleShaderSource;
|
||||
default:
|
||||
assert("Unknown Far::PatchDescriptor::Type" && 0);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetPatchDrawingShaderSource() {
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
return std::string("#define OSD_METAL_IOS 1\n")
|
||||
.append(commonShaderSource)
|
||||
.append(commonTessShaderSource);
|
||||
#elif TARGET_OS_OSX
|
||||
return std::string("#define OSD_METAL_OSX 1\n")
|
||||
.append(commonShaderSource)
|
||||
.append(commonTessShaderSource);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetCommonShaderSource() {
|
||||
return GetPatchDrawingShaderSource()
|
||||
.append(patchLegacyShaderSource);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetPatchBasisShaderSource() {
|
||||
std::stringstream ss;
|
||||
ss << "#define OSD_PATCH_BASIS_METAL 1\n";
|
||||
#if defined(OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES)
|
||||
ss << "#define OPENSUBDIV_GREGORY_EVAL_TRUE_DERIVATIVES 1\n";
|
||||
#endif
|
||||
ss << patchBasisTypesShaderSource;
|
||||
ss << patchBasisShaderSource;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type, fvarType);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetHullShaderSource(Far::PatchDescriptor::Type type) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetHullShaderSource(Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type, fvarType);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetDomainShaderSource(Far::PatchDescriptor::Type type) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetDomainShaderSource(Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type, fvarType);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
80
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchTable.h
vendored
Normal file
80
blender-5.2.0/extern/opensubdiv-source/opensubdiv/osd/mtlPatchTable.h
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV3_OSD_MTL_PATCH_TABLE_H
|
||||
#define OPENSUBDIV3_OSD_MTL_PATCH_TABLE_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../far/patchDescriptor.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/types.h"
|
||||
#include "../osd/mtlCommon.h"
|
||||
|
||||
@protocol MTLDevice;
|
||||
@protocol MTLBuffer;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class PatchTable;
|
||||
};
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class MTLPatchTable : private NonCopyable<MTLPatchTable> {
|
||||
public:
|
||||
using VertexBufferBinding = id<MTLBuffer>; // buffer binding type
|
||||
|
||||
MTLPatchTable();
|
||||
~MTLPatchTable();
|
||||
|
||||
template<typename DEVICE_CONTEXT>
|
||||
static MTLPatchTable *Create(Far::PatchTable const *farPatchTable, DEVICE_CONTEXT context)
|
||||
{
|
||||
return Create(farPatchTable, context);
|
||||
}
|
||||
|
||||
static MTLPatchTable *Create(Far::PatchTable const *farPatchTable, MTLContext* context);
|
||||
|
||||
PatchArrayVector const &GetPatchArrays() const { return _patchArrays; }
|
||||
id<MTLBuffer> GetPatchIndexBuffer() const { return _indexBuffer; }
|
||||
id<MTLBuffer> GetPatchParamBuffer() const { return _patchParamBuffer; }
|
||||
|
||||
PatchArrayVector const &GetVaryingPatchArrays() const { return _varyingPatchArrays; }
|
||||
id<MTLBuffer> GetVaryingPatchIndexBuffer() const { return _varyingPatchIndexBuffer; }
|
||||
|
||||
int GetNumFVarChannels() const { return (int)_fvarPatchArrays.size(); }
|
||||
PatchArrayVector const &GetFVarPatchArrays(int fvarChannel = 0) const { return _fvarPatchArrays[fvarChannel]; }
|
||||
id<MTLBuffer> GetFVarPatchIndexBuffer(int fvarChannel = 0) const { return _fvarIndexBuffers[fvarChannel]; }
|
||||
id<MTLBuffer> GetFVarPatchParamBuffer(int fvarChannel = 0) const { return _fvarParamBuffers[fvarChannel]; }
|
||||
|
||||
protected:
|
||||
bool allocate(Far::PatchTable const *farPatchTable, MTLContext* context);
|
||||
|
||||
PatchArrayVector _patchArrays;
|
||||
|
||||
id<MTLBuffer> _indexBuffer;
|
||||
id<MTLBuffer> _patchParamBuffer;
|
||||
|
||||
PatchArrayVector _varyingPatchArrays;
|
||||
|
||||
id<MTLBuffer> _varyingPatchIndexBuffer;
|
||||
|
||||
std::vector<PatchArrayVector> _fvarPatchArrays;
|
||||
std::vector<id<MTLBuffer>> _fvarIndexBuffers;
|
||||
std::vector<id<MTLBuffer>> _fvarParamBuffers;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} //end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} //end namespace OpenSubdiv
|
||||
|
||||
#endif //end OPENSUBDIV3_OSD_MTL_PATCH_TABLE_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user