mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-25 13:00:07 +00:00
Merge pull request #466 from takahito-tejima/refactor
Refurbish osd layer API.
This commit is contained in:
commit
41df98c9cc
@ -30,41 +30,28 @@
|
||||
#include <far/error.h>
|
||||
|
||||
#include <osd/cpuD3D11VertexBuffer.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
OpenSubdiv::Osd::CpuComputeController * g_cpuComputeController = NULL;
|
||||
#include <osd/cpuEvaluator.h>
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <osd/ompComputeController.h>
|
||||
OpenSubdiv::Osd::OmpComputeController * g_ompComputeController = NULL;
|
||||
#include <osd/ompEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clD3D11VertexBuffer.h>
|
||||
#include <osd/clComputeContext.h>
|
||||
#include <osd/clComputeController.h>
|
||||
|
||||
#include <osd/clEvaluator.h>
|
||||
#include "../common/clDeviceContext.h"
|
||||
|
||||
CLD3D11DeviceContext g_clDeviceContext;
|
||||
OpenSubdiv::Osd::CLComputeController * g_clComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaD3D11VertexBuffer.h>
|
||||
#include <osd/cudaComputeContext.h>
|
||||
#include <osd/cudaComputeController.h>
|
||||
|
||||
#include <osd/cudaEvaluator.h>
|
||||
#include "../common/cudaDeviceContext.h"
|
||||
|
||||
CudaDeviceContext g_cudaDeviceContext;
|
||||
OpenSubdiv::Osd::CudaComputeController * g_cudaComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#include <osd/d3d11VertexBuffer.h>
|
||||
#include <osd/d3d11ComputeContext.h>
|
||||
#include <osd/d3d11ComputeController.h>
|
||||
OpenSubdiv::Osd::D3D11ComputeController * g_d3d11ComputeController = NULL;
|
||||
#include <osd/d3d11ComputeEvaluator.h>
|
||||
|
||||
#include <osd/d3d11Mesh.h>
|
||||
OpenSubdiv::Osd::D3D11MeshInterface *g_mesh;
|
||||
@ -635,6 +622,8 @@ createPtex(const char *filename) {
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
createOsdMesh(int level, int kernel) {
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
Ptex::String ptexError;
|
||||
PtexTexture *ptexColor = PtexTexture::open(g_ptexColorFilename, ptexError, true);
|
||||
if (ptexColor == NULL) {
|
||||
@ -691,79 +680,81 @@ createOsdMesh(int level, int kernel) {
|
||||
int numVertexElements = 6; //g_adaptive ? 3 : 6;
|
||||
int numVaryingElements = 0;
|
||||
|
||||
if (kernel == kCPU) {
|
||||
if (not g_cpuComputeController) {
|
||||
g_cpuComputeController = new OpenSubdiv::Osd::CpuComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuD3D11VertexBuffer,
|
||||
OpenSubdiv::Osd::CpuComputeController,
|
||||
OpenSubdiv::Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
g_cpuComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, g_pd3dDeviceContext);
|
||||
if (g_kernel == kCPU) {
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Osd::CpuEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, NULL, g_pd3dDeviceContext);
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (kernel == kOPENMP) {
|
||||
if (not g_ompComputeController) {
|
||||
g_ompComputeController = new OpenSubdiv::Osd::OmpComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuD3D11VertexBuffer,
|
||||
OpenSubdiv::Osd::OmpComputeController,
|
||||
OpenSubdiv::Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
g_ompComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, g_pd3dDeviceContext);
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Osd::OmpEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, NULL, g_pd3dDeviceContext);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (kernel == kTBB) {
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Osd::TbbEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, NULL, g_pd3dDeviceContext);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if (kernel == kCL) {
|
||||
if (not g_clComputeController) {
|
||||
g_clComputeController = new OpenSubdiv::Osd::CLComputeController(
|
||||
g_clDeviceContext.GetContext(),
|
||||
g_clDeviceContext.GetCommandQueue());
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CLD3D11VertexBuffer,
|
||||
OpenSubdiv::Osd::CLComputeController,
|
||||
OpenSubdiv::Osd::D3D11DrawContext,
|
||||
CLD3D11DeviceContext>(
|
||||
g_clComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, &g_clDeviceContext);
|
||||
} else if(kernel == kCL) {
|
||||
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::CLD3D11VertexBuffer,
|
||||
Osd::CLStencilTables,
|
||||
Osd::CLEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
CLD3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits,
|
||||
&clEvaluatorCache,
|
||||
&g_clDeviceContext);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (kernel == kCUDA) {
|
||||
if (not g_cudaComputeController) {
|
||||
g_cudaComputeController = new OpenSubdiv::Osd::CudaComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CudaD3D11VertexBuffer,
|
||||
OpenSubdiv::Osd::CudaComputeController,
|
||||
OpenSubdiv::Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
g_cudaComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, g_pd3dDeviceContext);
|
||||
} else if (g_kernel == kCUDA) {
|
||||
g_mesh = new Osd::Mesh<Osd::CudaD3D11VertexBuffer,
|
||||
Osd::CudaStencilTables,
|
||||
Osd::CudaEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, NULL, g_pd3dDeviceContext);
|
||||
#endif
|
||||
} else if (g_kernel == kDirectCompute) {
|
||||
if (not g_d3d11ComputeController) {
|
||||
g_d3d11ComputeController = new OpenSubdiv::Osd::D3D11ComputeController(g_pd3dDeviceContext);
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::D3D11VertexBuffer,
|
||||
OpenSubdiv::Osd::D3D11ComputeController,
|
||||
OpenSubdiv::Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
g_d3d11ComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, g_pd3dDeviceContext);
|
||||
static Osd::EvaluatorCacheT<Osd::D3D11ComputeEvaluator> d3d11ComputeEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::D3D11VertexBuffer,
|
||||
Osd::D3D11StencilTables,
|
||||
Osd::D3D11ComputeEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits,
|
||||
&d3d11ComputeEvaluatorCache,
|
||||
g_pd3dDeviceContext);
|
||||
} else {
|
||||
printf("Unsupported kernel %s\n", getKernelName(kernel));
|
||||
}
|
||||
@ -1122,22 +1113,6 @@ quit() {
|
||||
SAFE_RELEASE(g_pd3dDeviceContext);
|
||||
SAFE_RELEASE(g_pd3dDevice);
|
||||
|
||||
delete g_cpuComputeController;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
delete g_ompComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
delete g_clComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
delete g_cudaComputeController;
|
||||
#endif
|
||||
|
||||
delete g_d3d11ComputeController;
|
||||
|
||||
PostQuitMessage(0);
|
||||
exit(0);
|
||||
}
|
||||
|
@ -30,46 +30,32 @@
|
||||
#include <far/error.h>
|
||||
|
||||
#include <osd/cpuD3D11VertexBuffer.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
OpenSubdiv::Osd::CpuComputeController * g_cpuComputeController = NULL;
|
||||
#include <osd/cpuEvaluator.h>
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <osd/ompComputeController.h>
|
||||
OpenSubdiv::Osd::OmpComputeController * g_ompComputeController = NULL;
|
||||
#include <osd/ompEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
#include <osd/tbbComputeController.h>
|
||||
OpenSubdiv::Osd::TbbComputeController *g_tbbComputeController = NULL;
|
||||
#include <osd/tbbEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clD3D11VertexBuffer.h>
|
||||
#include <osd/clComputeContext.h>
|
||||
#include <osd/clComputeController.h>
|
||||
|
||||
#include <osd/clEvaluator.h>
|
||||
#include "../common/clDeviceContext.h"
|
||||
|
||||
CLD3D11DeviceContext g_clDeviceContext;
|
||||
OpenSubdiv::Osd::CLComputeController * g_clComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaD3D11VertexBuffer.h>
|
||||
#include <osd/cudaComputeContext.h>
|
||||
#include <osd/cudaComputeController.h>
|
||||
|
||||
#include <osd/cudaEvaluator.h>
|
||||
#include "../common/cudaDeviceContext.h"
|
||||
|
||||
CudaDeviceContext g_cudaDeviceContext;
|
||||
OpenSubdiv::Osd::CudaComputeController * g_cudaComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#include <osd/d3d11VertexBuffer.h>
|
||||
#include <osd/d3d11ComputeContext.h>
|
||||
#include <osd/d3d11ComputeController.h>
|
||||
OpenSubdiv::Osd::D3D11ComputeController * g_d3d11ComputeController = NULL;
|
||||
#include <osd/d3d11ComputeEvaluator.h>
|
||||
|
||||
#include <osd/d3d11Mesh.h>
|
||||
OpenSubdiv::Osd::D3D11MeshInterface *g_mesh;
|
||||
@ -272,17 +258,18 @@ getKernelName(int kernel) {
|
||||
static void
|
||||
createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=kCatmark) {
|
||||
|
||||
typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
|
||||
using namespace OpenSubdiv;
|
||||
typedef Far::ConstIndexArray IndexArray;
|
||||
|
||||
Shape * shape = Shape::parseObj(shapeDesc.data.c_str(), shapeDesc.scheme);
|
||||
|
||||
// create Vtr mesh (topology)
|
||||
OpenSubdiv::Sdc::SchemeType sdctype = GetSdcType(*shape);
|
||||
OpenSubdiv::Sdc::Options sdcoptions = GetSdcOptions(*shape);
|
||||
Sdc::SchemeType sdctype = GetSdcType(*shape);
|
||||
Sdc::Options sdcoptions = GetSdcOptions(*shape);
|
||||
|
||||
OpenSubdiv::Far::TopologyRefiner * refiner =
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Create(*shape,
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
||||
Far::TopologyRefiner * refiner =
|
||||
Far::TopologyRefinerFactory<Shape>::Create(*shape,
|
||||
Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
int nedges = refiner->GetNumEdges(0),
|
||||
@ -316,104 +303,90 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
bool doAdaptive = (g_adaptive!=0 and g_scheme==kCatmark),
|
||||
doSingleCreasePatch = (g_singleCreasePatch!=0 and g_scheme==kCatmark);
|
||||
|
||||
OpenSubdiv::Osd::MeshBitset bits;
|
||||
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
|
||||
bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, doSingleCreasePatch);
|
||||
Osd::MeshBitset bits;
|
||||
bits.set(Osd::MeshAdaptive, doAdaptive);
|
||||
bits.set(Osd::MeshUseSingleCreasePatch, doSingleCreasePatch);
|
||||
// gregory basis hasn't supported yet in D3D11Mesh
|
||||
bits.set(OpenSubdiv::Osd::MeshEndCapLegacyGregory, true);
|
||||
bits.set(Osd::MeshEndCapLegacyGregory, true);
|
||||
|
||||
int numVertexElements = 6;
|
||||
int numVaryingElements = 0;
|
||||
|
||||
if (g_kernel == kCPU) {
|
||||
if (not g_cpuComputeController) {
|
||||
g_cpuComputeController = new OpenSubdiv::Osd::CpuComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuD3D11VertexBuffer,
|
||||
OpenSubdiv::Osd::CpuComputeController,
|
||||
OpenSubdiv::Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
g_cpuComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, g_pd3dDeviceContext);
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Osd::CpuEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, NULL, g_pd3dDeviceContext);
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (kernel == kOPENMP) {
|
||||
if (not g_ompComputeController) {
|
||||
g_ompComputeController = new OpenSubdiv::Osd::OmpComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuD3D11VertexBuffer,
|
||||
OpenSubdiv::Osd::OmpComputeController,
|
||||
OpenSubdiv::Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
g_ompComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, g_pd3dDeviceContext);
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Osd::OmpEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, NULL, g_pd3dDeviceContext);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (kernel == kTBB) {
|
||||
if (not g_tbbComputeController) {
|
||||
g_tbbComputeController = new OpenSubdiv::Osd::TbbComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuD3D11VertexBuffer,
|
||||
OpenSubdiv::Osd::TbbComputeController,
|
||||
OpenSubdiv::Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
g_tbbComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, g_pd3dDeviceContext);
|
||||
g_mesh = new Osd::Mesh<Osd::CpuD3D11VertexBuffer,
|
||||
Far::StencilTables,
|
||||
Osd::TbbEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, NULL, g_pd3dDeviceContext);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if(kernel == kCL) {
|
||||
if (not g_clComputeController) {
|
||||
g_clComputeController = new OpenSubdiv::Osd::CLComputeController(
|
||||
g_clDeviceContext.GetContext(),
|
||||
g_clDeviceContext.GetCommandQueue());
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CLD3D11VertexBuffer,
|
||||
OpenSubdiv::Osd::CLComputeController,
|
||||
OpenSubdiv::Osd::D3D11DrawContext,
|
||||
CLD3D11DeviceContext>(
|
||||
g_clComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits,
|
||||
&g_clDeviceContext);
|
||||
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::CLD3D11VertexBuffer,
|
||||
Osd::CLStencilTables,
|
||||
Osd::CLEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
CLD3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits,
|
||||
&clEvaluatorCache,
|
||||
&g_clDeviceContext);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (g_kernel == kCUDA) {
|
||||
if (not g_cudaComputeController) {
|
||||
g_cudaComputeController = new OpenSubdiv::Osd::CudaComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CudaD3D11VertexBuffer,
|
||||
OpenSubdiv::Osd::CudaComputeController,
|
||||
OpenSubdiv::Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
g_cudaComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, g_pd3dDeviceContext);
|
||||
g_mesh = new Osd::Mesh<Osd::CudaD3D11VertexBuffer,
|
||||
Osd::CudaStencilTables,
|
||||
Osd::CudaEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, NULL, g_pd3dDeviceContext);
|
||||
#endif
|
||||
} else if (g_kernel == kDirectCompute) {
|
||||
if (not g_d3d11ComputeController) {
|
||||
g_d3d11ComputeController = new OpenSubdiv::Osd::D3D11ComputeController(g_pd3dDeviceContext);
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::D3D11VertexBuffer,
|
||||
OpenSubdiv::Osd::D3D11ComputeController,
|
||||
OpenSubdiv::Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
g_d3d11ComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, g_pd3dDeviceContext);
|
||||
static Osd::EvaluatorCacheT<Osd::D3D11ComputeEvaluator> d3d11ComputeEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::D3D11VertexBuffer,
|
||||
Osd::D3D11StencilTables,
|
||||
Osd::D3D11ComputeEvaluator,
|
||||
Osd::D3D11DrawContext,
|
||||
ID3D11DeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits,
|
||||
&d3d11ComputeEvaluatorCache,
|
||||
g_pd3dDeviceContext);
|
||||
} else {
|
||||
printf("Unsupported kernel %s\n", getKernelName(kernel));
|
||||
}
|
||||
@ -995,26 +968,6 @@ quit() {
|
||||
SAFE_RELEASE(g_pd3dDeviceContext);
|
||||
SAFE_RELEASE(g_pd3dDevice);
|
||||
|
||||
delete g_cpuComputeController;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
delete g_ompComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
delete g_tbbComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
delete g_clComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
delete g_cudaComputeController;
|
||||
#endif
|
||||
|
||||
delete g_d3d11ComputeController;
|
||||
|
||||
PostQuitMessage(0);
|
||||
exit(0);
|
||||
}
|
||||
|
@ -42,19 +42,18 @@
|
||||
GLFWwindow* g_window=0;
|
||||
GLFWmonitor* g_primary=0;
|
||||
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
#include <osd/cpuEvalLimitContext.h>
|
||||
#include <osd/cpuEvalLimitController.h>
|
||||
#include <osd/cpuEvaluator.h>
|
||||
#include <osd/cpuVertexBuffer.h>
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/drawContext.h>
|
||||
#include <osd/mesh.h>
|
||||
|
||||
#include <far/gregoryBasis.h>
|
||||
#include <far/endCapGregoryBasisPatchFactory.h>
|
||||
#include <far/topologyRefiner.h>
|
||||
#include <far/stencilTablesFactory.h>
|
||||
#include <far/patchTablesFactory.h>
|
||||
#include <far/patchMap.h>
|
||||
|
||||
#include <far/error.h>
|
||||
|
||||
@ -198,13 +197,12 @@ Far::TopologyRefiner * g_topologyRefiner = 0;
|
||||
Osd::CpuVertexBuffer * g_vertexData = 0,
|
||||
* g_varyingData = 0;
|
||||
|
||||
Osd::CpuComputeContext * g_computeCtx = 0;
|
||||
Far::StencilTables const * g_vertexStencils = NULL;
|
||||
Far::StencilTables const * g_varyingStencils = NULL;
|
||||
|
||||
Osd::CpuComputeController g_computeCtrl;
|
||||
|
||||
Osd::CpuEvalLimitContext * g_evalCtx = 0;
|
||||
|
||||
Osd::CpuEvalLimitController g_evalCtrl;
|
||||
Far::PatchTables const * g_patchTables = NULL;
|
||||
Far::PatchMap const * g_patchMap = NULL;
|
||||
Osd::PatchCoordArray g_patchCoords;
|
||||
|
||||
Osd::VertexBufferDescriptor g_idesc( /*offset*/ 0, /*legnth*/ 3, /*stride*/ 3 ),
|
||||
g_odesc( /*offset*/ 0, /*legnth*/ 3, /*stride*/ 6 ),
|
||||
@ -245,7 +243,25 @@ updateGeom() {
|
||||
|
||||
g_vertexData->UpdateData( &g_positions[0], 0, nverts);
|
||||
|
||||
g_computeCtrl.Compute(g_computeCtx, g_vertexData, g_varyingData);
|
||||
if (! g_topologyRefiner) return;
|
||||
|
||||
// note that for patch eval we need coarse+refined combined buffer.
|
||||
int nCoarseVertices = g_topologyRefiner->GetNumVertices(0);
|
||||
Osd::CpuEvaluator::EvalStencils(g_vertexData,
|
||||
Osd::VertexBufferDescriptor(0, 3, 3),
|
||||
g_vertexData,
|
||||
Osd::VertexBufferDescriptor(
|
||||
nCoarseVertices*3, 3, 3),
|
||||
g_vertexStencils);
|
||||
|
||||
if (g_varyingData) {
|
||||
Osd::CpuEvaluator::EvalStencils(g_varyingData,
|
||||
Osd::VertexBufferDescriptor(0, 3, 3),
|
||||
g_varyingData,
|
||||
Osd::VertexBufferDescriptor(
|
||||
nCoarseVertices*3, 3, 3),
|
||||
g_varyingStencils);
|
||||
}
|
||||
|
||||
s.Stop();
|
||||
g_computeTime = float(s.GetElapsed() * 1000.0f);
|
||||
@ -255,66 +271,37 @@ updateGeom() {
|
||||
|
||||
s.Start();
|
||||
|
||||
// The varying data ends-up interleaved in the same g_Q output buffer because
|
||||
// g_Q has a stride of 6 and g_vdesc sets the offset to 3, while g_odesc sets
|
||||
// the offset to 0
|
||||
switch (g_drawMode) {
|
||||
case kVARYING : g_evalCtrl.BindVaryingBuffers( g_idesc, g_varyingData, g_vdesc, g_Q ); break;
|
||||
|
||||
case kFACEVARYING : //g_evalCtrl.BindFacevaryingBuffers( g_fvidesc, g_fvodesc, g_Q ); break;
|
||||
case kRANDOM :
|
||||
case kUV :
|
||||
default : g_evalCtrl.Unbind(); break;
|
||||
}
|
||||
|
||||
// Bind/Unbind of the vertex buffers to the context needs to happen
|
||||
// outside of the parallel loop
|
||||
g_evalCtrl.BindVertexBuffers( g_idesc, g_vertexData, g_odesc, g_Q, g_dQs, g_dQt );
|
||||
|
||||
|
||||
// Apply 'dynamics' update
|
||||
assert(g_particles);
|
||||
g_particles->Update(g_evalTime); // XXXX g_evalTime is not really elapsed time...
|
||||
|
||||
|
||||
// Evaluate the positions of the samples on the limit surface
|
||||
g_nsamplesFound=0;
|
||||
#define USE_OPENMP
|
||||
#if defined(OPENSUBDIV_HAS_OPENMP) and defined(USE_OPENMP)
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int i=0; i<g_nparticles; ++i) {
|
||||
|
||||
Osd::LimitLocation & coord = g_particles->GetPositions()[i];
|
||||
|
||||
int n = g_evalCtrl.EvalLimitSample( coord, g_evalCtx, i );
|
||||
|
||||
if (n) {
|
||||
// point colors
|
||||
switch (g_drawMode) {
|
||||
case kUV : { float * color = g_Q->BindCpuBuffer() + i*g_Q->GetNumElements() + 3;
|
||||
color[0] = coord.s;
|
||||
color[1] = 0.0f;
|
||||
color[2] = coord.t; } break;
|
||||
|
||||
case kRANDOM : // no update needed
|
||||
case kVARYING :
|
||||
case kFACEVARYING : break;
|
||||
|
||||
default : break;
|
||||
}
|
||||
#if defined(OPENSUBDIV_HAS_OPENMP) and defined(USE_OPENMP)
|
||||
#pragma omp atomic
|
||||
#endif
|
||||
g_nsamplesFound += n;
|
||||
} else {
|
||||
// "hide" unfound samples (hole tags...) as a black dot at the origin
|
||||
float * sample = g_Q->BindCpuBuffer() + i*g_Q->GetNumElements();
|
||||
memset(sample, 0, g_Q->GetNumElements() * sizeof(float));
|
||||
// resolve particle positions into patch handles
|
||||
// XXX: this process should be handled by OsdKernel in parallel
|
||||
g_patchCoords.clear();
|
||||
for (int i = 0; i < g_particles->GetNumParticles(); ++i) {
|
||||
STParticles::Position const &position = g_particles->GetPositions()[i];
|
||||
Far::PatchTables::PatchHandle const *handle =
|
||||
g_patchMap->FindPatch(position.ptexIndex, position.s, position.t);
|
||||
if (handle) {
|
||||
g_patchCoords.push_back(Osd::PatchCoord(
|
||||
*handle, position.s, position.t));
|
||||
}
|
||||
}
|
||||
|
||||
g_evalCtrl.Unbind();
|
||||
// Evaluate the positions of the samples on the limit surface
|
||||
g_nsamplesFound = Osd::CpuEvaluator::EvalPatches(g_vertexData, g_idesc,
|
||||
g_Q, g_odesc,
|
||||
g_patchCoords,
|
||||
g_patchTables, NULL);
|
||||
|
||||
// varying
|
||||
if (g_drawMode == kVARYING) {
|
||||
Osd::CpuEvaluator::EvalPatches(g_varyingData, g_idesc,
|
||||
g_Q, g_vdesc,
|
||||
g_patchCoords,
|
||||
g_patchTables, NULL);
|
||||
}
|
||||
|
||||
g_Q->BindVBO();
|
||||
|
||||
@ -335,7 +322,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
OpenSubdiv::Sdc::Options sdcoptions = GetSdcOptions(*shape);
|
||||
|
||||
delete g_topologyRefiner;
|
||||
OpenSubdiv::Far::TopologyRefiner * g_topologyRefiner =
|
||||
g_topologyRefiner =
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Create(*shape,
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
||||
|
||||
@ -409,18 +396,17 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
nverts = vertexStencils->GetNumControlVertices() +
|
||||
vertexStencils->GetNumStencils();
|
||||
|
||||
// Create an Osd Compute context, used to "pose" the vertices with
|
||||
// the stencils tables
|
||||
delete g_computeCtx;
|
||||
g_computeCtx = Osd::CpuComputeContext::Create(vertexStencils,
|
||||
varyingStencils);
|
||||
if (g_vertexStencils) delete g_vertexStencils;
|
||||
g_vertexStencils = vertexStencils;
|
||||
if (g_varyingStencils) delete g_varyingStencils;
|
||||
g_varyingStencils = varyingStencils;
|
||||
|
||||
// Create a limit Eval context with the patch tables
|
||||
delete g_evalCtx;
|
||||
g_evalCtx = Osd::CpuEvalLimitContext::Create(*patchTables);
|
||||
if (g_patchTables) delete g_patchTables;
|
||||
g_patchTables = patchTables;
|
||||
|
||||
delete vertexStencils;
|
||||
delete varyingStencils;
|
||||
// Create a far patch map
|
||||
if (g_patchMap) delete g_patchMap;
|
||||
g_patchMap = new Far::PatchMap(*g_patchTables);
|
||||
}
|
||||
|
||||
{ // Create vertex primvar buffer for the CVs
|
||||
|
@ -25,7 +25,6 @@
|
||||
#ifndef ST_PARTICLES_H
|
||||
#define ST_PARTICLES_H
|
||||
|
||||
#include <osd/evalLimitContext.h>
|
||||
#include <far/topologyRefiner.h>
|
||||
|
||||
#include <iostream>
|
||||
@ -54,8 +53,25 @@
|
||||
class STParticles {
|
||||
|
||||
public:
|
||||
/// \brief Coordinates set on a limit surface
|
||||
///
|
||||
struct Position {
|
||||
Position() { }
|
||||
|
||||
/// \brief Constructor
|
||||
///
|
||||
/// @param f Ptex face id
|
||||
///
|
||||
/// @param x parametric location on face
|
||||
///
|
||||
/// @param y parametric location on face
|
||||
///
|
||||
Position(int f, float x, float y) : ptexIndex(f), s(x), t(y) { }
|
||||
|
||||
int ptexIndex; ///< ptex face index
|
||||
float s, t; ///< parametric location on face
|
||||
};
|
||||
|
||||
typedef OpenSubdiv::Osd::LimitLocation Position;
|
||||
typedef OpenSubdiv::Far::TopologyRefiner Refiner;
|
||||
|
||||
STParticles(Refiner const & refiner, int nparticles, bool centered=false);
|
||||
|
@ -46,10 +46,8 @@ GLFWmonitor* g_primary = 0;
|
||||
#include <osd/glDrawRegistry.h>
|
||||
#include <far/error.h>
|
||||
|
||||
#include <osd/cpuEvaluator.h>
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
OpenSubdiv::Osd::CpuComputeController *g_cpuComputeController = NULL;
|
||||
|
||||
#include <osd/glMesh.h>
|
||||
OpenSubdiv::Osd::GLMeshInterface *g_mesh = NULL;
|
||||
@ -358,20 +356,15 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark)
|
||||
int numVertexElements = 3;
|
||||
int numVaryingElements = 0;
|
||||
|
||||
if (not g_cpuComputeController) {
|
||||
g_cpuComputeController = new OpenSubdiv::Osd::CpuComputeController();
|
||||
}
|
||||
|
||||
delete g_mesh;
|
||||
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Osd::CpuComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_cpuComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
OpenSubdiv::Far::StencilTables,
|
||||
OpenSubdiv::Osd::CpuEvaluator,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
|
||||
std::vector<float> fvarData;
|
||||
|
||||
@ -1008,8 +1001,6 @@ uninitGL() {
|
||||
|
||||
if (g_mesh)
|
||||
delete g_mesh;
|
||||
|
||||
delete g_cpuComputeController;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -46,55 +46,40 @@
|
||||
#include <limits>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <osd/cpuEvaluator.h>
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
OpenSubdiv::Osd::CpuComputeController *g_cpuComputeController = NULL;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <osd/ompComputeController.h>
|
||||
OpenSubdiv::Osd::OmpComputeController *g_ompComputeController = NULL;
|
||||
#include <osd/ompEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
#include <osd/tbbComputeController.h>
|
||||
OpenSubdiv::Osd::TbbComputeController *g_tbbComputeController = NULL;
|
||||
#include <osd/tbbEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clEvaluator.h>
|
||||
#include <osd/clGLVertexBuffer.h>
|
||||
#include <osd/clComputeContext.h>
|
||||
#include <osd/clComputeController.h>
|
||||
|
||||
#include "../common/clDeviceContext.h"
|
||||
|
||||
CLDeviceContext g_clDeviceContext;
|
||||
OpenSubdiv::Osd::CLComputeController *g_clComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaEvaluator.h>
|
||||
#include <osd/cudaGLVertexBuffer.h>
|
||||
#include <osd/cudaComputeContext.h>
|
||||
#include <osd/cudaComputeController.h>
|
||||
|
||||
#include "../common/cudaDeviceContext.h"
|
||||
|
||||
CudaDeviceContext g_cudaDeviceContext;
|
||||
OpenSubdiv::Osd::CudaComputeController *g_cudaComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
#include <osd/glslTransformFeedbackComputeContext.h>
|
||||
#include <osd/glslTransformFeedbackComputeController.h>
|
||||
#include <osd/glXFBEvaluator.h>
|
||||
#include <osd/glVertexBuffer.h>
|
||||
OpenSubdiv::Osd::GLSLTransformFeedbackComputeController *g_glslTransformFeedbackComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
#include <osd/glslComputeContext.h>
|
||||
#include <osd/glslComputeController.h>
|
||||
#include <osd/glComputeEvaluator.h>
|
||||
#include <osd/glVertexBuffer.h>
|
||||
OpenSubdiv::Osd::GLSLComputeController *g_glslComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#include <osd/glDrawContext.h>
|
||||
@ -244,103 +229,82 @@ createOsdMesh(std::string const &kernel,
|
||||
Osd::MeshBitset bits)
|
||||
{
|
||||
if (kernel == "CPU") {
|
||||
if (not g_cpuComputeController) {
|
||||
g_cpuComputeController = new Osd::CpuComputeController();
|
||||
}
|
||||
return new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Osd::CpuComputeController,
|
||||
Osd::GLDrawContext>(
|
||||
g_cpuComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
Far::StencilTables,
|
||||
Osd::CpuEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (kernel == "OPENMP") {
|
||||
if (not g_ompComputeController) {
|
||||
g_ompComputeController = new Osd::OmpComputeController();
|
||||
}
|
||||
return new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Osd::OmpComputeController,
|
||||
Osd::GLDrawContext>(
|
||||
g_ompComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
Far::StencilTables,
|
||||
Osd::OmpEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (kernel == "TBB") {
|
||||
if (not g_tbbComputeController) {
|
||||
g_tbbComputeController = new Osd::TbbComputeController();
|
||||
}
|
||||
return new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Osd::TbbComputeController,
|
||||
Osd::GLDrawContext>(
|
||||
g_tbbComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
Far::StencilTables,
|
||||
Osd::TbbEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if(kernel == "CL") {
|
||||
if (not g_clComputeController) {
|
||||
g_clComputeController = new Osd::CLComputeController(
|
||||
g_clDeviceContext.GetContext(),
|
||||
g_clDeviceContext.GetCommandQueue());
|
||||
}
|
||||
return new Osd::Mesh<Osd::CLGLVertexBuffer,
|
||||
Osd::CLComputeController,
|
||||
Osd::GLDrawContext,
|
||||
CLDeviceContext>(
|
||||
g_clComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, &g_clDeviceContext);
|
||||
Osd::CLStencilTables,
|
||||
Osd::CLEvaluator,
|
||||
Osd::GLDrawContext,
|
||||
CLDeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits,
|
||||
NULL,
|
||||
&g_clDeviceContext);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if(kernel == "CUDA") {
|
||||
if (not g_cudaComputeController) {
|
||||
g_cudaComputeController = new Osd::CudaComputeController();
|
||||
}
|
||||
return new Osd::Mesh<Osd::CudaGLVertexBuffer,
|
||||
Osd::CudaComputeController,
|
||||
Osd::GLDrawContext>(
|
||||
g_cudaComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
Osd::CudaStencilTables,
|
||||
Osd::CudaEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
} else if(kernel == "XFB") {
|
||||
if (not g_glslTransformFeedbackComputeController) {
|
||||
g_glslTransformFeedbackComputeController = new Osd::GLSLTransformFeedbackComputeController();
|
||||
}
|
||||
return new Osd::Mesh<Osd::GLVertexBuffer,
|
||||
Osd::GLSLTransformFeedbackComputeController,
|
||||
Osd::GLDrawContext>(
|
||||
g_glslTransformFeedbackComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
Osd::GLStencilTablesTBO,
|
||||
Osd::GLXFBEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
} else if(kernel == "GLSL") {
|
||||
if (not g_glslComputeController) {
|
||||
g_glslComputeController = new Osd::GLSLComputeController();
|
||||
}
|
||||
return new Osd::Mesh<Osd::GLVertexBuffer,
|
||||
Osd::GLSLComputeController,
|
||||
Osd::GLDrawContext>(
|
||||
g_glslComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
Osd::GLStencilTablesSSBO,
|
||||
Osd::GLComputeEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -47,10 +47,8 @@ GLFWmonitor* g_primary=0;
|
||||
#include <far/error.h>
|
||||
#include <far/ptexIndices.h>
|
||||
|
||||
#include <osd/cpuEvaluator.h>
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
OpenSubdiv::Osd::CpuComputeController *g_cpuComputeController = NULL;
|
||||
|
||||
#include <osd/glMesh.h>
|
||||
OpenSubdiv::Osd::GLMeshInterface *g_mesh;
|
||||
@ -240,14 +238,11 @@ createOsdMesh() {
|
||||
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
|
||||
bits.set(OpenSubdiv::Osd::MeshPtexData, true);
|
||||
|
||||
if (not g_cpuComputeController) {
|
||||
g_cpuComputeController = new OpenSubdiv::Osd::CpuComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Osd::CpuComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_cpuComputeController,
|
||||
refiner, 3, 0, g_level, bits);
|
||||
OpenSubdiv::Far::StencilTables,
|
||||
OpenSubdiv::Osd::CpuEvaluator,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
refiner, 3, 0, g_level, bits);
|
||||
|
||||
// compute model bounding
|
||||
float min[3] = { FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
@ -1095,8 +1090,6 @@ uninitGL() {
|
||||
|
||||
if (g_mesh)
|
||||
delete g_mesh;
|
||||
|
||||
delete g_cpuComputeController;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -54,56 +54,39 @@ GLFWmonitor* g_primary = 0;
|
||||
#include <osd/glDrawRegistry.h>
|
||||
#include <far/error.h>
|
||||
|
||||
#include <osd/cpuEvaluator.h>
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
OpenSubdiv::Osd::CpuComputeController * g_cpuComputeController = NULL;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <osd/ompComputeController.h>
|
||||
OpenSubdiv::Osd::OmpComputeController * g_ompComputeController = NULL;
|
||||
#include <osd/ompEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
#include <osd/tbbComputeController.h>
|
||||
OpenSubdiv::Osd::TbbComputeController *g_tbbComputeController = NULL;
|
||||
#include <osd/tbbEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clEvaluator.h>
|
||||
#include <osd/clGLVertexBuffer.h>
|
||||
#include <osd/clComputeContext.h>
|
||||
#include <osd/clComputeController.h>
|
||||
|
||||
#include "../common/clDeviceContext.h"
|
||||
|
||||
CLDeviceContext g_clDeviceContext;
|
||||
OpenSubdiv::Osd::CLComputeController * g_clComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaEvaluator.h>
|
||||
#include <osd/cudaGLVertexBuffer.h>
|
||||
#include <osd/cudaComputeContext.h>
|
||||
#include <osd/cudaComputeController.h>
|
||||
|
||||
#include "../common/cudaDeviceContext.h"
|
||||
|
||||
CudaDeviceContext g_cudaDeviceContext;
|
||||
OpenSubdiv::Osd::CudaComputeController * g_cudaComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
#include <osd/glslTransformFeedbackComputeContext.h>
|
||||
#include <osd/glslTransformFeedbackComputeController.h>
|
||||
#include <osd/glXFBEvaluator.h>
|
||||
#include <osd/glVertexBuffer.h>
|
||||
OpenSubdiv::Osd::GLSLTransformFeedbackComputeController
|
||||
*g_glslTransformFeedbackComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
#include <osd/glslComputeContext.h>
|
||||
#include <osd/glslComputeController.h>
|
||||
#include <osd/glComputeEvaluator.h>
|
||||
#include <osd/glVertexBuffer.h>
|
||||
OpenSubdiv::Osd::GLSLComputeController * g_glslComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#include <osd/glMesh.h>
|
||||
@ -1029,26 +1012,20 @@ createOsdMesh(int level, int kernel) {
|
||||
int numVaryingElements = 0;
|
||||
|
||||
if (kernel == kCPU) {
|
||||
if (not g_cpuComputeController) {
|
||||
g_cpuComputeController = new OpenSubdiv::Osd::CpuComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Osd::CpuComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_cpuComputeController,
|
||||
OpenSubdiv::Far::StencilTables,
|
||||
OpenSubdiv::Osd::CpuEvaluator,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (kernel == kOPENMP) {
|
||||
if (not g_ompComputeController) {
|
||||
g_ompComputeController = new OpenSubdiv::Osd::OmpComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Osd::OmpComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_ompComputeController,
|
||||
OpenSubdiv::Far::StencilTables,
|
||||
OpenSubdiv::Osd::OmpEvaluator,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
@ -1056,13 +1033,10 @@ createOsdMesh(int level, int kernel) {
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (kernel == kTBB) {
|
||||
if (not g_tbbComputeController) {
|
||||
g_tbbComputeController = new OpenSubdiv::Osd::TbbComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Osd::TbbComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_tbbComputeController,
|
||||
OpenSubdiv::Far::StencilTables,
|
||||
OpenSubdiv::Osd::TbbEvaluator,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
@ -1070,30 +1044,25 @@ createOsdMesh(int level, int kernel) {
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if (kernel == kCL) {
|
||||
if (not g_clComputeController) {
|
||||
g_clComputeController = new OpenSubdiv::Osd::CLComputeController(
|
||||
g_clDeviceContext.GetContext(),
|
||||
g_clDeviceContext.GetCommandQueue());
|
||||
}
|
||||
static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::CLEvaluator> clEvaluatorCache;
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CLGLVertexBuffer,
|
||||
OpenSubdiv::Osd::CLComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext,
|
||||
CLDeviceContext>(
|
||||
g_clComputeController,
|
||||
OpenSubdiv::Osd::CLStencilTables,
|
||||
OpenSubdiv::Osd::CLEvaluator,
|
||||
OpenSubdiv::Osd::GLDrawContext,
|
||||
CLDeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, &g_clDeviceContext);
|
||||
level, bits,
|
||||
&clEvaluatorCache,
|
||||
&g_clDeviceContext);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (kernel == kCUDA) {
|
||||
if (not g_cudaComputeController) {
|
||||
g_cudaComputeController = new OpenSubdiv::Osd::CudaComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CudaGLVertexBuffer,
|
||||
OpenSubdiv::Osd::CudaComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_cudaComputeController,
|
||||
OpenSubdiv::Osd::CudaStencilTables,
|
||||
OpenSubdiv::Osd::CudaEvaluator,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
@ -1101,32 +1070,29 @@ createOsdMesh(int level, int kernel) {
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
} else if (kernel == kGLSL) {
|
||||
if (not g_glslTransformFeedbackComputeController) {
|
||||
g_glslTransformFeedbackComputeController =
|
||||
new OpenSubdiv::Osd::GLSLTransformFeedbackComputeController();
|
||||
}
|
||||
static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::GLXFBEvaluator> glXFBEvaluatorCache;
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::GLVertexBuffer,
|
||||
OpenSubdiv::Osd::GLSLTransformFeedbackComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_glslTransformFeedbackComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
OpenSubdiv::Osd::GLStencilTablesTBO,
|
||||
OpenSubdiv::Osd::GLXFBEvaluator,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits,
|
||||
&glXFBEvaluatorCache);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
} else if (kernel == kGLSLCompute) {
|
||||
if (not g_glslComputeController) {
|
||||
g_glslComputeController = new OpenSubdiv::Osd::GLSLComputeController();
|
||||
}
|
||||
static OpenSubdiv::Osd::EvaluatorCacheT<OpenSubdiv::Osd::GLComputeEvaluator> glComputeEvaluatorCache;
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::GLVertexBuffer,
|
||||
OpenSubdiv::Osd::GLSLComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_glslComputeController,
|
||||
OpenSubdiv::Osd::GLStencilTablesSSBO,
|
||||
OpenSubdiv::Osd::GLComputeEvaluator,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
level, bits,
|
||||
&glComputeEvaluatorCache);
|
||||
#endif
|
||||
} else {
|
||||
printf("Unsupported kernel %s\n", getKernelName(kernel));
|
||||
@ -1977,32 +1943,6 @@ void uninitGL() {
|
||||
if (g_mesh)
|
||||
delete g_mesh;
|
||||
|
||||
delete g_cpuComputeController;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
delete g_ompComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
delete g_tbbComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
delete g_clComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
delete g_cudaComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
delete g_glslTransformFeedbackComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
delete g_glslComputeController;
|
||||
#endif
|
||||
|
||||
if (g_diffuseEnvironmentMap)
|
||||
glDeleteTextures(1, &g_diffuseEnvironmentMap);
|
||||
if (g_specularEnvironmentMap)
|
||||
|
@ -46,55 +46,42 @@ GLFWmonitor* g_primary=0;
|
||||
#include <osd/glDrawRegistry.h>
|
||||
#include <osd/glMesh.h>
|
||||
#include <far/error.h>
|
||||
#include <far/stencilTables.h>
|
||||
#include <far/ptexIndices.h>
|
||||
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/glVertexBuffer.h>
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
OpenSubdiv::Osd::CpuComputeController *g_cpuComputeController = NULL;
|
||||
#include <osd/cpuEvaluator.h>
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <osd/ompComputeController.h>
|
||||
OpenSubdiv::Osd::OmpComputeController *g_ompComputeController = NULL;
|
||||
#include <osd/ompEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
#include <osd/tbbComputeController.h>
|
||||
OpenSubdiv::Osd::TbbComputeController *g_tbbComputeController = NULL;
|
||||
#include <osd/tbbEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clGLVertexBuffer.h>
|
||||
#include <osd/clComputeContext.h>
|
||||
#include <osd/clComputeController.h>
|
||||
OpenSubdiv::Osd::CLComputeController *g_clComputeController = NULL;
|
||||
|
||||
#include <osd/clEvaluator.h>
|
||||
#include "../common/clDeviceContext.h"
|
||||
CLDeviceContext g_clDeviceContext;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaGLVertexBuffer.h>
|
||||
#include <osd/cudaComputeContext.h>
|
||||
#include <osd/cudaComputeController.h>
|
||||
OpenSubdiv::Osd::CudaComputeController *g_cudaComputeController = NULL;
|
||||
|
||||
#include <osd/cudaEvaluator.h>
|
||||
#include "../common/cudaDeviceContext.h"
|
||||
CudaDeviceContext g_cudaDeviceContext;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
#include <osd/glslTransformFeedbackComputeContext.h>
|
||||
#include <osd/glslTransformFeedbackComputeController.h>
|
||||
#include <osd/glVertexBuffer.h>
|
||||
OpenSubdiv::Osd::GLSLTransformFeedbackComputeController *g_glslXFBComputeController = NULL;
|
||||
#include <osd/glXFBEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
#include <osd/glslComputeContext.h>
|
||||
#include <osd/glslComputeController.h>
|
||||
#include <osd/glVertexBuffer.h>
|
||||
OpenSubdiv::Osd::GLSLComputeController *g_glslComputeController = NULL;
|
||||
#include <osd/glComputeEvaluator.h>
|
||||
#endif
|
||||
|
||||
|
||||
@ -171,7 +158,6 @@ public:
|
||||
|
||||
if (interleaved) {
|
||||
assert(vertexDesc.stride == varyingDesc.stride);
|
||||
|
||||
_vertexBuffer = createVertexBuffer(
|
||||
vertexDesc.stride, numInstances * numVertices);
|
||||
} else {
|
||||
@ -259,9 +245,12 @@ public:
|
||||
return _restPosition;
|
||||
}
|
||||
|
||||
int GetNumVertices() const {
|
||||
int GetNumVertices() const { // total (control + refined)
|
||||
return _numVertices;
|
||||
}
|
||||
int GetNumControlVertices() const {
|
||||
return _numControlVertices;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@ -281,40 +270,47 @@ protected:
|
||||
}
|
||||
|
||||
int _numVertices;
|
||||
int _numControlVertices;
|
||||
|
||||
private:
|
||||
Osd::GLDrawContext *_drawContext;
|
||||
std::vector<float> _restPosition;
|
||||
};
|
||||
|
||||
template <class COMPUTE_CONTROLLER, class VERTEX_BUFFER,
|
||||
template <class EVALUATOR,
|
||||
class VERTEX_BUFFER,
|
||||
class STENCIL_TABLES,
|
||||
class DEVICE_CONTEXT=void>
|
||||
class Topology : public TopologyBase {
|
||||
|
||||
public:
|
||||
|
||||
typedef COMPUTE_CONTROLLER ComputeController;
|
||||
typedef typename COMPUTE_CONTROLLER::ComputeContext ComputeContext;
|
||||
typedef EVALUATOR Evaluator;
|
||||
typedef STENCIL_TABLES StencilTables;
|
||||
typedef DEVICE_CONTEXT DeviceContext;
|
||||
typedef Osd::EvaluatorCacheT<Evaluator> EvaluatorCache;
|
||||
|
||||
Topology(ComputeController * computeController,
|
||||
Far::PatchTables const * patchTables,
|
||||
Far::StencilTables const * vertexStencils,
|
||||
Topology(Far::PatchTables const * patchTables,
|
||||
Far::StencilTables const * vertexStencils, //XXX: takes ownership
|
||||
Far::StencilTables const * varyingStencils,
|
||||
int numControlVertices,
|
||||
EvaluatorCache * evaluatorCache = NULL,
|
||||
DeviceContext * deviceContext = NULL)
|
||||
: TopologyBase(patchTables),
|
||||
_computeController(computeController),
|
||||
_evaluatorCache(evaluatorCache),
|
||||
_deviceContext(deviceContext) {
|
||||
|
||||
_computeContext = ComputeContext::Create(
|
||||
vertexStencils, varyingStencils, deviceContext);
|
||||
_numControlVertices = numControlVertices;
|
||||
_numVertices = numControlVertices + vertexStencils->GetNumStencils();
|
||||
|
||||
_vertexStencils = Osd::convertToCompatibleStencilTables<StencilTables>(
|
||||
vertexStencils, deviceContext);
|
||||
_varyingStencils = Osd::convertToCompatibleStencilTables<StencilTables>(
|
||||
varyingStencils, deviceContext);
|
||||
|
||||
_numVertices = vertexStencils->GetNumStencils() +
|
||||
vertexStencils->GetNumControlVertices();
|
||||
}
|
||||
|
||||
~Topology() {
|
||||
delete _computeContext;
|
||||
delete _vertexStencils;
|
||||
delete _varyingStencils;
|
||||
}
|
||||
|
||||
void Refine(InstancesBase *instance, int numInstances) {
|
||||
@ -329,21 +325,59 @@ public:
|
||||
|
||||
for (int i = 0; i < numInstances; ++i) {
|
||||
|
||||
Osd::VertexBufferDescriptor vertexDesc(
|
||||
globalVertexDesc.offset + _numVertices*globalVertexDesc.stride*i,
|
||||
Osd::VertexBufferDescriptor vertexSrcDesc(
|
||||
globalVertexDesc.offset + _numVertices*i*globalVertexDesc.stride,
|
||||
globalVertexDesc.length,
|
||||
globalVertexDesc.stride);
|
||||
|
||||
Osd::VertexBufferDescriptor varyingDesc(
|
||||
globalVaryingDesc.offset + _numVertices*globalVaryingDesc.stride*i,
|
||||
globalVaryingDesc.length,
|
||||
globalVaryingDesc.stride);
|
||||
Osd::VertexBufferDescriptor vertexDstDesc(
|
||||
globalVertexDesc.offset + (_numVertices*i + _numControlVertices)*globalVertexDesc.stride,
|
||||
globalVertexDesc.length,
|
||||
globalVertexDesc.stride);
|
||||
|
||||
_computeController->Compute(_computeContext,
|
||||
typedInstance->GetVertexBuffer(),
|
||||
typedInstance->GetVaryingBuffer(),
|
||||
&vertexDesc,
|
||||
&varyingDesc);
|
||||
// vertex
|
||||
Evaluator const *evalInstance = Osd::GetEvaluator<Evaluator>(
|
||||
_evaluatorCache, vertexSrcDesc, vertexDstDesc, _deviceContext);
|
||||
|
||||
Evaluator::EvalStencils(typedInstance->GetVertexBuffer(), vertexSrcDesc,
|
||||
typedInstance->GetVertexBuffer(), vertexDstDesc,
|
||||
_vertexStencils,
|
||||
evalInstance,
|
||||
_deviceContext);
|
||||
|
||||
// varying
|
||||
if (_varyingStencils) {
|
||||
Osd::VertexBufferDescriptor varyingSrcDesc(
|
||||
globalVaryingDesc.offset + _numVertices*i*globalVaryingDesc.stride,
|
||||
globalVaryingDesc.length,
|
||||
globalVaryingDesc.stride);
|
||||
|
||||
Osd::VertexBufferDescriptor varyingDstDesc(
|
||||
globalVaryingDesc.offset + (_numVertices*i + _numControlVertices)*globalVaryingDesc.stride,
|
||||
globalVaryingDesc.length,
|
||||
globalVaryingDesc.stride);
|
||||
|
||||
evalInstance = Osd::GetEvaluator<Evaluator>(
|
||||
_evaluatorCache, varyingSrcDesc, varyingDstDesc, _deviceContext);
|
||||
|
||||
if (typedInstance->GetVaryingBuffer()) {
|
||||
// non interleaved
|
||||
Evaluator::EvalStencils(
|
||||
typedInstance->GetVaryingBuffer(), varyingSrcDesc,
|
||||
typedInstance->GetVaryingBuffer(), varyingDstDesc,
|
||||
_varyingStencils,
|
||||
evalInstance,
|
||||
_deviceContext);
|
||||
} else {
|
||||
// interleaved
|
||||
Evaluator::EvalStencils(
|
||||
typedInstance->GetVertexBuffer(), varyingSrcDesc,
|
||||
typedInstance->GetVertexBuffer(), varyingDstDesc,
|
||||
_varyingStencils,
|
||||
evalInstance,
|
||||
_deviceContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -359,7 +393,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void Synchronize() {
|
||||
_computeController->Synchronize();
|
||||
Evaluator::Synchronize(_deviceContext);
|
||||
}
|
||||
|
||||
virtual void UpdateVertexTexture(InstancesBase *instances) {
|
||||
@ -371,8 +405,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
ComputeController *_computeController;
|
||||
ComputeContext *_computeContext;
|
||||
StencilTables const *_vertexStencils;
|
||||
StencilTables const *_varyingStencils;
|
||||
EvaluatorCache * _evaluatorCache;
|
||||
DeviceContext *_deviceContext;
|
||||
};
|
||||
|
||||
@ -644,81 +679,85 @@ createOsdMesh( const std::string &shapeStr, int level, Scheme scheme=kCatmark )
|
||||
}
|
||||
}
|
||||
|
||||
int numControlVertices = refiner->GetNumVertices(0);
|
||||
|
||||
// create partitioned patcharray
|
||||
TopologyBase *topology = NULL;
|
||||
|
||||
if (g_kernel == kCPU) {
|
||||
if (not g_cpuComputeController)
|
||||
g_cpuComputeController = new Osd::CpuComputeController();
|
||||
topology = new Topology<Osd::CpuComputeController,
|
||||
Osd::CpuGLVertexBuffer>(g_cpuComputeController,
|
||||
topology = new Topology<Osd::CpuEvaluator,
|
||||
Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables>(
|
||||
patchTables,
|
||||
vertexStencils, varyingStencils);
|
||||
vertexStencils, varyingStencils,
|
||||
numControlVertices);
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (g_kernel == kOPENMP) {
|
||||
if (not g_ompComputeController)
|
||||
g_ompComputeController = new Osd::OmpComputeController();
|
||||
topology = new Topology<Osd::OmpComputeController,
|
||||
Osd::CpuGLVertexBuffer>(g_ompComputeController,
|
||||
topology = new Topology<Osd::OmpEvaluator,
|
||||
Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables>(
|
||||
patchTables,
|
||||
vertexStencils, varyingStencils);
|
||||
vertexStencils, varyingStencils,
|
||||
numControlVertices);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (g_kernel == kTBB) {
|
||||
if (not g_tbbComputeController)
|
||||
g_tbbComputeController = new Osd::TbbComputeController();
|
||||
topology = new Topology<Osd::TbbComputeController,
|
||||
Osd::CpuGLVertexBuffer>(g_tbbComputeController,
|
||||
topology = new Topology<Osd::TbbEvaluator,
|
||||
Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables>(
|
||||
patchTables,
|
||||
vertexStencils, varyingStencils);
|
||||
vertexStencils, varyingStencils,
|
||||
numControlVertices);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (g_kernel == kCUDA) {
|
||||
if (not g_cudaComputeController)
|
||||
g_cudaComputeController = new Osd::CudaComputeController();
|
||||
topology = new Topology<Osd::CudaComputeController,
|
||||
Osd::CudaGLVertexBuffer>(g_cudaComputeController,
|
||||
topology = new Topology<Osd::CudaEvaluator,
|
||||
Osd::CudaGLVertexBuffer,
|
||||
Osd::CudaStencilTables>(
|
||||
patchTables,
|
||||
vertexStencils, varyingStencils);
|
||||
vertexStencils, varyingStencils,
|
||||
numControlVertices);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if (g_kernel == kCL) {
|
||||
if (not g_clComputeController)
|
||||
g_clComputeController = new Osd::CLComputeController(
|
||||
g_clDeviceContext.GetContext(),
|
||||
g_clDeviceContext.GetCommandQueue());
|
||||
topology = new Topology<Osd::CLComputeController,
|
||||
Osd::CLGLVertexBuffer,
|
||||
CLDeviceContext>(g_clComputeController,
|
||||
patchTables,
|
||||
vertexStencils, varyingStencils,
|
||||
&g_clDeviceContext);
|
||||
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
|
||||
topology = new Topology<Osd::CLEvaluator,
|
||||
Osd::CLGLVertexBuffer,
|
||||
Osd::CLStencilTables,
|
||||
CLDeviceContext>(
|
||||
patchTables,
|
||||
vertexStencils, varyingStencils,
|
||||
numControlVertices,
|
||||
&clEvaluatorCache,
|
||||
&g_clDeviceContext);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
} else if (g_kernel == kGLSL) {
|
||||
if (not g_glslXFBComputeController)
|
||||
g_glslXFBComputeController = new Osd::GLSLTransformFeedbackComputeController();
|
||||
topology = new Topology<Osd::GLSLTransformFeedbackComputeController,
|
||||
Osd::GLVertexBuffer>(g_glslXFBComputeController,
|
||||
patchTables,
|
||||
vertexStencils, varyingStencils);
|
||||
static Osd::EvaluatorCacheT<Osd::GLXFBEvaluator> glXFBEvaluatorCache;
|
||||
topology = new Topology<Osd::GLXFBEvaluator,
|
||||
Osd::GLVertexBuffer,
|
||||
Osd::GLStencilTablesTBO>(
|
||||
patchTables,
|
||||
vertexStencils, varyingStencils,
|
||||
numControlVertices);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
} else if (g_kernel == kGLSLCompute) {
|
||||
if (not g_glslComputeController)
|
||||
g_glslComputeController = new Osd::GLSLComputeController();
|
||||
topology = new Topology<Osd::GLSLComputeController,
|
||||
Osd::GLVertexBuffer>(g_glslComputeController,
|
||||
patchTables,
|
||||
vertexStencils, varyingStencils);
|
||||
static Osd::EvaluatorCacheT<Osd::GLComputeEvaluator> glComputeEvaluatorCache;
|
||||
topology = new Topology<Osd::GLComputeEvaluator,
|
||||
Osd::GLVertexBuffer,
|
||||
Osd::GLStencilTablesSSBO>(
|
||||
patchTables,
|
||||
vertexStencils, varyingStencils,
|
||||
numControlVertices);
|
||||
#endif
|
||||
} else {
|
||||
}
|
||||
|
||||
delete refiner;
|
||||
delete vertexStencils;
|
||||
delete varyingStencils;
|
||||
// XXX: Weired API. think again..
|
||||
/// delete vertexStencils;
|
||||
/// delete varyingStencils;
|
||||
delete patchTables;
|
||||
|
||||
// centering rest position
|
||||
@ -1291,28 +1330,6 @@ uninitGL() {
|
||||
delete g_instances;
|
||||
if (g_topology)
|
||||
delete g_topology;
|
||||
|
||||
delete g_cpuComputeController;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
delete g_ompComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
delete g_tbbComputeController;
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
delete g_clComputeController;
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
delete g_cudaComputeController;
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
delete g_glslXFBComputeController;
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
delete g_glslComputeController;
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -1453,7 +1470,7 @@ static void
|
||||
callbackDisplayStyle(int b) {
|
||||
|
||||
g_displayStyle = b;
|
||||
rebuildInstances();
|
||||
rebuildOsdMesh();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -54,8 +54,7 @@ GLFWmonitor* g_primary=0;
|
||||
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/cpuVertexBuffer.h>
|
||||
#include <osd/cpuEvalStencilsContext.h>
|
||||
#include <osd/cpuEvalStencilsController.h>
|
||||
#include <osd/cpuEvaluator.h>
|
||||
|
||||
#include <cfloat>
|
||||
#include <list>
|
||||
@ -154,18 +153,12 @@ Osd::VertexBufferDescriptor g_controlDesc( /*offset*/ 0, /*legnth*/ 3, /*stride*
|
||||
g_outputDuDesc( /*offset*/ 3, /*legnth*/ 3, /*stride*/ 18 ),
|
||||
g_outputDvDesc( /*offset*/ 9, /*legnth*/ 3, /*stride*/ 18 );
|
||||
|
||||
Osd::CpuEvalStencilsContext * g_evalCtx=0;
|
||||
|
||||
Osd::CpuEvalStencilsController g_evalCpuCtrl;
|
||||
|
||||
#if defined(OPENSUBDIV_HAS_OPENMP)
|
||||
#include <osd/ompEvalStencilsController.h>
|
||||
Osd::OmpEvalStencilsController g_evalOmpCtrl;
|
||||
#include <osd/ompEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
#include <osd/tbbEvalStencilsController.h>
|
||||
Osd::TbbEvalStencilsController g_evalTbbCtrl;
|
||||
#include <osd/tbbEvaluator.h>
|
||||
#endif
|
||||
|
||||
|
||||
@ -200,48 +193,41 @@ updateGeom() {
|
||||
float * ptr = g_stencilValues->BindCpuBuffer();
|
||||
memset(ptr, 0, g_controlStencils->GetNumStencils() * 18 * sizeof(float));
|
||||
|
||||
// Uppdate random points by applying point & tangent stencils
|
||||
// Update random points by applying point & tangent stencils
|
||||
switch (g_kernel) {
|
||||
case kCPU: {
|
||||
g_evalCpuCtrl.UpdateValues<Osd::CpuVertexBuffer,Osd::CpuGLVertexBuffer>(
|
||||
g_evalCtx,
|
||||
g_controlDesc, g_controlValues,
|
||||
g_outputDataDesc, g_stencilValues );
|
||||
|
||||
g_evalCpuCtrl.UpdateDerivs<Osd::CpuVertexBuffer,Osd::CpuGLVertexBuffer>(
|
||||
g_evalCtx,
|
||||
g_controlDesc, g_controlValues,
|
||||
g_outputDuDesc, g_stencilValues,
|
||||
g_outputDvDesc, g_stencilValues );
|
||||
Osd::CpuEvaluator::EvalStencils(
|
||||
g_controlValues, g_controlDesc, // input
|
||||
g_stencilValues, g_outputDataDesc, // position
|
||||
g_stencilValues, g_outputDuDesc, // Du
|
||||
g_stencilValues, g_outputDvDesc, // Dv
|
||||
// Normals will be filled afterwards
|
||||
g_controlStencils);
|
||||
} break;
|
||||
|
||||
#if defined(OPENSUBDIV_HAS_OPENMP)
|
||||
case kOPENMP: {
|
||||
g_evalOmpCtrl.UpdateValues<Osd::CpuVertexBuffer,Osd::CpuGLVertexBuffer>(
|
||||
g_evalCtx,
|
||||
g_controlDesc, g_controlValues,
|
||||
g_outputDataDesc, g_stencilValues );
|
||||
|
||||
g_evalOmpCtrl.UpdateDerivs<Osd::CpuVertexBuffer,Osd::CpuGLVertexBuffer>(
|
||||
g_evalCtx,
|
||||
g_controlDesc, g_controlValues,
|
||||
g_outputDuDesc, g_stencilValues,
|
||||
g_outputDvDesc, g_stencilValues );
|
||||
// FIXME: implements OmpEvaluator
|
||||
Osd::CpuEvaluator::EvalStencils(
|
||||
g_controlValues, g_controlDesc, // input
|
||||
g_stencilValues, g_outputDataDesc, // position
|
||||
g_stencilValues, g_outputDuDesc, // Du
|
||||
g_stencilValues, g_outputDvDesc, // Dv
|
||||
// Normals will be filled afterwards
|
||||
g_controlStencils);
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#if defined(OPENSUBDIV_HAS_TBB)
|
||||
// FIXME: implements TbbEvaluator
|
||||
case kTBB: {
|
||||
g_evalTbbCtrl.UpdateValues<Osd::CpuVertexBuffer,Osd::CpuGLVertexBuffer>(
|
||||
g_evalCtx,
|
||||
g_controlDesc, g_controlValues,
|
||||
g_outputDataDesc, g_stencilValues );
|
||||
|
||||
g_evalTbbCtrl.UpdateDerivs<Osd::CpuVertexBuffer,Osd::CpuGLVertexBuffer>(
|
||||
g_evalCtx,
|
||||
g_controlDesc, g_controlValues,
|
||||
g_outputDuDesc, g_stencilValues,
|
||||
g_outputDvDesc, g_stencilValues );
|
||||
Osd::CpuEvaluator::EvalStencils(
|
||||
g_controlValues, g_controlDesc, // input
|
||||
g_stencilValues, g_outputDataDesc, // position
|
||||
g_stencilValues, g_outputDuDesc, // Du
|
||||
g_stencilValues, g_outputDvDesc, // Dv
|
||||
// Normals will be filled afterwards
|
||||
g_controlStencils);
|
||||
} break;
|
||||
#endif
|
||||
default:
|
||||
@ -364,9 +350,6 @@ createMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
g_controlValues = Osd::CpuVertexBuffer::Create(3, nverts);
|
||||
|
||||
// Create eval context & data buffers
|
||||
delete g_evalCtx;
|
||||
g_evalCtx = Osd::CpuEvalStencilsContext::Create(g_controlStencils);
|
||||
|
||||
delete g_stencilValues;
|
||||
g_stencilValues = Osd::CpuGLVertexBuffer::Create(3, g_controlStencils->GetNumStencils() * 6 );
|
||||
|
||||
@ -674,6 +657,7 @@ drawStencils() {
|
||||
|
||||
g_samplesProgram.EnableVertexAttributes();
|
||||
|
||||
glDrawArrays(GL_POINTS, 0, numEdges*2);
|
||||
glDrawArrays(GL_LINES, 0, numEdges*2);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
@ -46,55 +46,41 @@ GLFWmonitor* g_primary=0;
|
||||
#include <osd/glDrawContext.h>
|
||||
#include <osd/glDrawRegistry.h>
|
||||
|
||||
#include <osd/cpuEvaluator.h>
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
OpenSubdiv::Osd::CpuComputeController *g_cpuComputeController = NULL;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <osd/ompComputeController.h>
|
||||
OpenSubdiv::Osd::OmpComputeController *g_ompComputeController = NULL;
|
||||
#include <osd/ompEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
#include <osd/tbbComputeController.h>
|
||||
OpenSubdiv::Osd::TbbComputeController *g_tbbComputeController = NULL;
|
||||
#include <osd/tbbEvaluator.h>
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
#include <osd/clGLVertexBuffer.h>
|
||||
#include <osd/clComputeContext.h>
|
||||
#include <osd/clComputeController.h>
|
||||
|
||||
#include <osd/clEvaluator.h>
|
||||
#include "../common/clDeviceContext.h"
|
||||
|
||||
CLDeviceContext g_clDeviceContext;
|
||||
OpenSubdiv::Osd::CLComputeController *g_clComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
#include <osd/cudaGLVertexBuffer.h>
|
||||
#include <osd/cudaComputeContext.h>
|
||||
#include <osd/cudaComputeController.h>
|
||||
|
||||
#include <osd/cudaEvaluator.h>
|
||||
#include "../common/cudaDeviceContext.h"
|
||||
|
||||
CudaDeviceContext g_cudaDeviceContext;
|
||||
OpenSubdiv::Osd::CudaComputeController *g_cudaComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
#include <osd/glslTransformFeedbackComputeContext.h>
|
||||
#include <osd/glslTransformFeedbackComputeController.h>
|
||||
#include <osd/glXFBEvaluator.h>
|
||||
#include <osd/glVertexBuffer.h>
|
||||
OpenSubdiv::Osd::GLSLTransformFeedbackComputeController *g_glslTransformFeedbackComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
#include <osd/glslComputeContext.h>
|
||||
#include <osd/glslComputeController.h>
|
||||
#include <osd/glComputeEvaluator.h>
|
||||
#include <osd/glVertexBuffer.h>
|
||||
OpenSubdiv::Osd::GLSLComputeController *g_glslComputeController = NULL;
|
||||
#endif
|
||||
|
||||
#include <osd/glMesh.h>
|
||||
@ -438,13 +424,7 @@ updateGeom() {
|
||||
Stopwatch s;
|
||||
s.Start();
|
||||
|
||||
if (g_displayStyle == kInterleavedVaryingColor) {
|
||||
OpenSubdiv::Osd::VertexBufferDescriptor vertexDesc(0, 3, 7);
|
||||
OpenSubdiv::Osd::VertexBufferDescriptor varyingDesc(3, 4, 7);
|
||||
g_mesh->Refine(&vertexDesc, &varyingDesc, true);
|
||||
} else {
|
||||
g_mesh->Refine();
|
||||
}
|
||||
g_mesh->Refine();
|
||||
|
||||
s.Stop();
|
||||
g_cpuTime = float(s.GetElapsed() * 1000.0f);
|
||||
@ -481,7 +461,8 @@ getKernelName(int kernel) {
|
||||
static void
|
||||
createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=kCatmark) {
|
||||
|
||||
typedef OpenSubdiv::Far::ConstIndexArray IndexArray;
|
||||
using namespace OpenSubdiv;
|
||||
typedef Far::ConstIndexArray IndexArray;
|
||||
|
||||
bool doAnim = g_objAnim and g_currentShape==0;
|
||||
|
||||
@ -493,12 +474,12 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
}
|
||||
|
||||
// create Vtr mesh (topology)
|
||||
OpenSubdiv::Sdc::SchemeType sdctype = GetSdcType(*shape);
|
||||
OpenSubdiv::Sdc::Options sdcoptions = GetSdcOptions(*shape);
|
||||
Sdc::SchemeType sdctype = GetSdcType(*shape);
|
||||
Sdc::Options sdcoptions = GetSdcOptions(*shape);
|
||||
|
||||
OpenSubdiv::Far::TopologyRefiner * refiner =
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Create(*shape,
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
||||
Far::TopologyRefiner * refiner =
|
||||
Far::TopologyRefinerFactory<Shape>::Create(*shape,
|
||||
Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
int nedges = refiner->GetNumEdges(0),
|
||||
@ -533,117 +514,104 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
|
||||
interleaveVarying = g_displayStyle == kInterleavedVaryingColor,
|
||||
doSingleCreasePatch = (g_singleCreasePatch!=0 and g_scheme==kCatmark);
|
||||
|
||||
OpenSubdiv::Osd::MeshBitset bits;
|
||||
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
|
||||
bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, doSingleCreasePatch);
|
||||
bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, interleaveVarying);
|
||||
bits.set(OpenSubdiv::Osd::MeshFVarData, g_displayStyle == kFaceVaryingColor);
|
||||
bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, g_endCap == kEndCapBSplineBasis);
|
||||
bits.set(OpenSubdiv::Osd::MeshEndCapGregoryBasis, g_endCap == kEndCapGregoryBasis);
|
||||
bits.set(OpenSubdiv::Osd::MeshEndCapLegacyGregory, g_endCap == kEndCapLegacyGregory);
|
||||
Osd::MeshBitset bits;
|
||||
bits.set(Osd::MeshAdaptive, doAdaptive);
|
||||
bits.set(Osd::MeshUseSingleCreasePatch, doSingleCreasePatch);
|
||||
bits.set(Osd::MeshInterleaveVarying, interleaveVarying);
|
||||
bits.set(Osd::MeshFVarData, g_displayStyle == kFaceVaryingColor);
|
||||
bits.set(Osd::MeshEndCapBSplineBasis, g_endCap == kEndCapBSplineBasis);
|
||||
bits.set(Osd::MeshEndCapGregoryBasis, g_endCap == kEndCapGregoryBasis);
|
||||
bits.set(Osd::MeshEndCapLegacyGregory, g_endCap == kEndCapLegacyGregory);
|
||||
|
||||
int numVertexElements = 3;
|
||||
int numVaryingElements =
|
||||
(g_displayStyle == kVaryingColor or interleaveVarying) ? 4 : 0;
|
||||
|
||||
if (kernel == kCPU) {
|
||||
if (not g_cpuComputeController) {
|
||||
g_cpuComputeController = new OpenSubdiv::Osd::CpuComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Osd::CpuComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_cpuComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables,
|
||||
Osd::CpuEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (kernel == kOPENMP) {
|
||||
if (not g_ompComputeController) {
|
||||
g_ompComputeController = new OpenSubdiv::Osd::OmpComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Osd::OmpComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_ompComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables,
|
||||
Osd::OmpEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (kernel == kTBB) {
|
||||
if (not g_tbbComputeController) {
|
||||
g_tbbComputeController = new OpenSubdiv::Osd::TbbComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CpuGLVertexBuffer,
|
||||
OpenSubdiv::Osd::TbbComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_tbbComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
||||
Far::StencilTables,
|
||||
Osd::TbbEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if(kernel == kCL) {
|
||||
if (not g_clComputeController) {
|
||||
g_clComputeController = new OpenSubdiv::Osd::CLComputeController(
|
||||
g_clDeviceContext.GetContext(),
|
||||
g_clDeviceContext.GetCommandQueue());
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CLGLVertexBuffer,
|
||||
OpenSubdiv::Osd::CLComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext,
|
||||
CLDeviceContext>(
|
||||
g_clComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits, &g_clDeviceContext);
|
||||
// CLKernel
|
||||
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::CLGLVertexBuffer,
|
||||
Osd::CLStencilTables,
|
||||
Osd::CLEvaluator,
|
||||
Osd::GLDrawContext,
|
||||
CLDeviceContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits,
|
||||
&clEvaluatorCache,
|
||||
&g_clDeviceContext);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if(kernel == kCUDA) {
|
||||
if (not g_cudaComputeController) {
|
||||
g_cudaComputeController = new OpenSubdiv::Osd::CudaComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::CudaGLVertexBuffer,
|
||||
OpenSubdiv::Osd::CudaComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_cudaComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
g_mesh = new Osd::Mesh<Osd::CudaGLVertexBuffer,
|
||||
Osd::CudaStencilTables,
|
||||
Osd::CudaEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
} else if(kernel == kGLSL) {
|
||||
if (not g_glslTransformFeedbackComputeController) {
|
||||
g_glslTransformFeedbackComputeController = new OpenSubdiv::Osd::GLSLTransformFeedbackComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::GLVertexBuffer,
|
||||
OpenSubdiv::Osd::GLSLTransformFeedbackComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_glslTransformFeedbackComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
static Osd::EvaluatorCacheT<Osd::GLXFBEvaluator> glXFBEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::GLVertexBuffer,
|
||||
Osd::GLStencilTablesTBO,
|
||||
Osd::GLXFBEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits,
|
||||
&glXFBEvaluatorCache);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
} else if(kernel == kGLSLCompute) {
|
||||
if (not g_glslComputeController) {
|
||||
g_glslComputeController = new OpenSubdiv::Osd::GLSLComputeController();
|
||||
}
|
||||
g_mesh = new OpenSubdiv::Osd::Mesh<OpenSubdiv::Osd::GLVertexBuffer,
|
||||
OpenSubdiv::Osd::GLSLComputeController,
|
||||
OpenSubdiv::Osd::GLDrawContext>(
|
||||
g_glslComputeController,
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits);
|
||||
static Osd::EvaluatorCacheT<Osd::GLComputeEvaluator> glComputeEvaluatorCache;
|
||||
g_mesh = new Osd::Mesh<Osd::GLVertexBuffer,
|
||||
Osd::GLStencilTablesSSBO,
|
||||
Osd::GLComputeEvaluator,
|
||||
Osd::GLDrawContext>(
|
||||
refiner,
|
||||
numVertexElements,
|
||||
numVaryingElements,
|
||||
level, bits,
|
||||
&glComputeEvaluatorCache);
|
||||
|
||||
|
||||
#endif
|
||||
} else {
|
||||
printf("Unsupported kernel %s\n", getKernelName(kernel));
|
||||
@ -1384,28 +1352,6 @@ uninitGL() {
|
||||
|
||||
if (g_mesh)
|
||||
delete g_mesh;
|
||||
|
||||
delete g_cpuComputeController;
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
delete g_ompComputeController;
|
||||
#endif
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
delete g_tbbComputeController;
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
delete g_clComputeController;
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
delete g_cudaComputeController;
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
delete g_glslTransformFeedbackComputeController;
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
delete g_glslComputeController;
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -64,8 +64,6 @@
|
||||
#include <far/stencilTablesFactory.h>
|
||||
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
#include <osd/cpuVertexBuffer.h>
|
||||
|
||||
|
||||
|
@ -27,20 +27,11 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# source & headers
|
||||
set(CPU_SOURCE_FILES
|
||||
cpuEvaluator.cpp
|
||||
cpuKernel.cpp
|
||||
cpuComputeController.cpp
|
||||
cpuComputeContext.cpp
|
||||
cpuEvalLimitContext.cpp
|
||||
cpuEvalLimitController.cpp
|
||||
cpuEvalLimitKernel.cpp
|
||||
cpuEvalStencilsContext.cpp
|
||||
cpuEvalStencilsController.cpp
|
||||
cpuSmoothNormalContext.cpp
|
||||
cpuSmoothNormalController.cpp
|
||||
cpuVertexBuffer.cpp
|
||||
drawContext.cpp
|
||||
drawRegistry.cpp
|
||||
evalLimitContext.cpp
|
||||
)
|
||||
|
||||
set(GPU_SOURCE_FILES )
|
||||
@ -50,21 +41,11 @@ set(INC_FILES )
|
||||
set(PRIVATE_HEADER_FILES
|
||||
debug.h
|
||||
cpuKernel.h
|
||||
cpuEvalLimitKernel.h
|
||||
)
|
||||
|
||||
set(PUBLIC_HEADER_FILES
|
||||
computeController.h
|
||||
cpuComputeContext.h
|
||||
cpuComputeController.h
|
||||
cpuEvalLimitContext.h
|
||||
cpuEvalLimitController.h
|
||||
cpuEvalStencilsContext.h
|
||||
cpuEvalStencilsController.h
|
||||
cpuSmoothNormalContext.h
|
||||
cpuSmoothNormalController.h
|
||||
cpuEvaluator.h
|
||||
cpuVertexBuffer.h
|
||||
evalLimitContext.h
|
||||
mesh.h
|
||||
nonCopyable.h
|
||||
opengl.h
|
||||
@ -75,21 +56,16 @@ set(PUBLIC_HEADER_FILES
|
||||
|
||||
set(DOXY_HEADER_FILES ${PUBLIC_HEADER_FILES})
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
set(OPENMP_PUBLIC_HEADERS
|
||||
ompEvaluator.h
|
||||
ompKernel.h
|
||||
ompComputeController.h
|
||||
ompEvalStencilsController.h
|
||||
ompSmoothNormalController.h
|
||||
)
|
||||
|
||||
if(OPENMP_FOUND )
|
||||
list(APPEND CPU_SOURCE_FILES
|
||||
ompEvaluator.cpp
|
||||
ompKernel.cpp
|
||||
ompComputeController.cpp
|
||||
ompEvalStencilsController.cpp
|
||||
ompSmoothNormalController.cpp
|
||||
)
|
||||
|
||||
list(APPEND PUBLIC_HEADER_FILES ${OPENMP_PUBLIC_HEADERS})
|
||||
@ -103,20 +79,16 @@ list(APPEND DOXY_HEADER_FILES ${OPENMP_PUBLIC_HEADERS})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
set(TBB_PUBLIC_HEADERS
|
||||
tbbEvaluator.h
|
||||
tbbKernel.h
|
||||
tbbComputeController.h
|
||||
tbbEvalStencilsController.h
|
||||
tbbSmoothNormalController.h
|
||||
)
|
||||
|
||||
if( TBB_FOUND )
|
||||
include_directories("${TBB_INCLUDE_DIR}")
|
||||
|
||||
list(APPEND CPU_SOURCE_FILES
|
||||
tbbEvaluator.cpp
|
||||
tbbKernel.cpp
|
||||
tbbComputeController.cpp
|
||||
tbbEvalStencilsController.cpp
|
||||
tbbSmoothNormalController.cpp
|
||||
)
|
||||
|
||||
list(APPEND PUBLIC_HEADER_FILES ${TBB_PUBLIC_HEADERS})
|
||||
@ -166,18 +138,16 @@ 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
|
||||
glslTransformFeedbackComputeContext.h
|
||||
glslTransformFeedbackComputeController.h
|
||||
glXFBEvaluator.h
|
||||
)
|
||||
|
||||
if( OPENGL_4_2_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
glslTransformFeedbackComputeContext.cpp
|
||||
glslTransformFeedbackComputeController.cpp
|
||||
glXFBEvaluator.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES ${GL_4_2_PUBLIC_HEADERS})
|
||||
list(APPEND KERNEL_FILES
|
||||
glslTransformFeedbackKernel.glsl
|
||||
glslXFBKernel.glsl
|
||||
)
|
||||
list(APPEND PLATFORM_GPU_LIBRARIES
|
||||
${GLEW_LIBRARY}
|
||||
@ -191,14 +161,12 @@ 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
|
||||
glslComputeContext.h
|
||||
glslComputeController.h
|
||||
glComputeEvaluator.h
|
||||
)
|
||||
|
||||
if( OPENGL_4_3_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
glslComputeContext.cpp
|
||||
glslComputeController.cpp
|
||||
glComputeEvaluator.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES ${GL_4_3_PUBLIC_HEADERS})
|
||||
list(APPEND KERNEL_FILES
|
||||
@ -215,8 +183,7 @@ list(APPEND DOXY_HEADER_FILES ${GL_4_3_PUBLIC_HEADERS})
|
||||
# DX11 code & dependencies
|
||||
set(DXSDK_PUBLIC_HEADERS
|
||||
cpuD3D11VertexBuffer.h
|
||||
d3d11ComputeContext.h
|
||||
d3d11ComputeController.h
|
||||
d3d11ComputeEvaluator.h
|
||||
d3d11DrawContext.h
|
||||
d3d11DrawRegistry.h
|
||||
d3d11VertexBuffer.h
|
||||
@ -225,8 +192,7 @@ set(DXSDK_PUBLIC_HEADERS
|
||||
if( DXSDK_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
cpuD3D11VertexBuffer.cpp
|
||||
d3d11ComputeContext.cpp
|
||||
d3d11ComputeController.cpp
|
||||
d3d11ComputeEvaluator.cpp
|
||||
d3d11DrawContext.cpp
|
||||
d3d11DrawRegistry.cpp
|
||||
d3d11VertexBuffer.cpp
|
||||
@ -248,16 +214,14 @@ list(APPEND DOXY_HEADER_FILES ${DXSDK_PUBLIC_HEADERS})
|
||||
#-------------------------------------------------------------------------------
|
||||
# OpenCL code & dependencies
|
||||
set(OPENCL_PUBLIC_HEADERS
|
||||
clComputeContext.h
|
||||
clComputeController.h
|
||||
clEvaluator.h
|
||||
clVertexBuffer.h
|
||||
opencl.h
|
||||
)
|
||||
|
||||
if ( OPENCL_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
clComputeContext.cpp
|
||||
clComputeController.cpp
|
||||
clEvaluator.cpp
|
||||
clVertexBuffer.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES ${OPENCL_PUBLIC_HEADERS})
|
||||
@ -288,15 +252,13 @@ list(APPEND DOXY_HEADER_FILES ${OPENCL_PUBLIC_HEADERS})
|
||||
#-------------------------------------------------------------------------------
|
||||
# CUDA code & dependencies
|
||||
set(CUDA_PUBLIC_HEADERS
|
||||
cudaComputeContext.h
|
||||
cudaComputeController.h
|
||||
cudaEvaluator.h
|
||||
cudaVertexBuffer.h
|
||||
)
|
||||
|
||||
if( CUDA_FOUND )
|
||||
list(APPEND GPU_SOURCE_FILES
|
||||
cudaComputeController.cpp
|
||||
cudaComputeContext.cpp
|
||||
cudaEvaluator.cpp
|
||||
cudaVertexBuffer.cpp
|
||||
)
|
||||
list(APPEND PUBLIC_HEADER_FILES ${CUDA_PUBLIC_HEADERS})
|
||||
|
@ -1,233 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/clComputeContext.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template <class T> cl_mem
|
||||
createCLBuffer(std::vector<T> const & src, cl_context clContext) {
|
||||
|
||||
cl_mem devicePtr = 0;
|
||||
cl_int errNum = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class CLComputeContext::CLStencilTables {
|
||||
|
||||
public:
|
||||
CLStencilTables(Far::StencilTables const & stencilTables,
|
||||
cl_context clContext) {
|
||||
_numStencils = stencilTables.GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCLBuffer(stencilTables.GetSizes(), clContext);
|
||||
_offsets = createCLBuffer(stencilTables.GetOffsets(), clContext);
|
||||
_indices = createCLBuffer(stencilTables.GetControlIndices(),
|
||||
clContext);
|
||||
_weights = createCLBuffer(stencilTables.GetWeights(), clContext);
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
~CLStencilTables() {
|
||||
if (_sizes) clReleaseMemObject(_sizes);
|
||||
if (_offsets) clReleaseMemObject(_offsets);
|
||||
if (_indices) clReleaseMemObject(_indices);
|
||||
if (_weights) clReleaseMemObject(_weights);
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return _sizes and _offsets and _indices and _weights;
|
||||
}
|
||||
|
||||
cl_mem GetSizes() const {
|
||||
return _sizes;
|
||||
}
|
||||
|
||||
cl_mem GetOffsets() const {
|
||||
return _offsets;
|
||||
}
|
||||
|
||||
cl_mem GetIndices() const {
|
||||
return _indices;
|
||||
}
|
||||
|
||||
cl_mem GetWeights() const {
|
||||
return _weights;
|
||||
}
|
||||
|
||||
int GetNumStencils() const {
|
||||
return _numStencils;
|
||||
}
|
||||
|
||||
private:
|
||||
cl_mem _sizes,
|
||||
_offsets,
|
||||
_indices,
|
||||
_weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
CLComputeContext::CLComputeContext(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
cl_context clContext) :
|
||||
_vertexStencilTables(0), _varyingStencilTables(0),
|
||||
_numControlVertices(0) {
|
||||
|
||||
if (vertexStencilTables) {
|
||||
_vertexStencilTables = new CLStencilTables(*vertexStencilTables,
|
||||
clContext);
|
||||
_numControlVertices = vertexStencilTables->GetNumControlVertices();
|
||||
}
|
||||
|
||||
if (varyingStencilTables) {
|
||||
_varyingStencilTables = new CLStencilTables(*varyingStencilTables,
|
||||
clContext);
|
||||
|
||||
if (_numControlVertices) {
|
||||
assert(_numControlVertices
|
||||
== varyingStencilTables->GetNumControlVertices());
|
||||
} else {
|
||||
_numControlVertices = varyingStencilTables->GetNumControlVertices();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CLComputeContext::~CLComputeContext() {
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
CLComputeContext::HasVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
CLComputeContext::HasVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
int
|
||||
CLComputeContext::GetNumStencilsInVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
int
|
||||
CLComputeContext::GetNumStencilsInVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVertexStencilTablesSizes() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetSizes() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVertexStencilTablesOffsets() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetOffsets() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVertexStencilTablesIndices() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetIndices() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVertexStencilTablesWeights() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetWeights() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVaryingStencilTablesSizes() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetSizes() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVaryingStencilTablesOffsets() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetOffsets() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVaryingStencilTablesIndices() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetIndices() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVaryingStencilTablesWeights() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetWeights() : 0;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
CLComputeContext *
|
||||
CLComputeContext::Create(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
cl_context clContext) {
|
||||
|
||||
CLComputeContext *result =
|
||||
new CLComputeContext(
|
||||
vertexStencilTables, varyingStencilTables, clContext);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,155 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CL_COMPUTE_CONTEXT_H
|
||||
#define OSD_CL_COMPUTE_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/opencl.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far { class StencilTables; }
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief OpenCL Refine Context
|
||||
///
|
||||
/// The OpenCL-Compute implementation of the Refine module contextual functionality.
|
||||
///
|
||||
/// Contexts interface the serialized topological data pertaining to the
|
||||
/// geometric primitives with the capabilities of the selected discrete
|
||||
/// compute device.
|
||||
///
|
||||
class CLComputeContext : public NonCopyable<CLComputeContext> {
|
||||
|
||||
public:
|
||||
/// Creates an CLComputeContext instance
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
/// @param clContext An active OpenCL compute context
|
||||
///
|
||||
static CLComputeContext * Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
cl_context clContext);
|
||||
|
||||
/// Creates an CLComputeContext instance (template version)
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
/// @param context A user defined class to provide cl_context.
|
||||
/// must implement GetContext()
|
||||
///
|
||||
template<typename DEVICE_CONTEXT>
|
||||
static CLComputeContext * Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
DEVICE_CONTEXT context) {
|
||||
return Create(vertexStencilTables, varyingStencilTables,
|
||||
context->GetContext());
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~CLComputeContext();
|
||||
|
||||
|
||||
/// Returns true if the Context has a 'vertex' interpolation stencil table
|
||||
bool HasVertexStencilTables() const;
|
||||
|
||||
/// Returns true if the Context has a 'varying' interpolation stencil table
|
||||
bool HasVaryingStencilTables() const;
|
||||
|
||||
/// Returns the number of control vertices
|
||||
int GetNumControlVertices() const {
|
||||
return _numControlVertices;
|
||||
}
|
||||
|
||||
/// Returns the number of stencils in vertex stencil table
|
||||
int GetNumStencilsInVertexStencilTables() const;
|
||||
|
||||
/// Returns the number of stencils in varying stencil table
|
||||
int GetNumStencilsInVaryingStencilTables() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil sizes
|
||||
cl_mem GetVertexStencilTablesSizes() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil offsets
|
||||
cl_mem GetVertexStencilTablesOffsets() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil indices
|
||||
cl_mem GetVertexStencilTablesIndices() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil weights
|
||||
cl_mem GetVertexStencilTablesWeights() const;
|
||||
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil sizes
|
||||
cl_mem GetVaryingStencilTablesSizes() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil offsets
|
||||
cl_mem GetVaryingStencilTablesOffsets() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil indices
|
||||
cl_mem GetVaryingStencilTablesIndices() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil weights
|
||||
cl_mem GetVaryingStencilTablesWeights() const;
|
||||
|
||||
|
||||
protected:
|
||||
explicit CLComputeContext(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
cl_context clContext);
|
||||
|
||||
private:
|
||||
class CLStencilTables;
|
||||
|
||||
CLStencilTables * _vertexStencilTables,
|
||||
* _varyingStencilTables;
|
||||
|
||||
int _numControlVertices;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_CL_COMPUTE_CONTEXT_H
|
@ -1,285 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/clComputeController.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static const char *clSource =
|
||||
#include "clKernel.gen.h"
|
||||
;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static cl_kernel buildKernel(cl_program prog, const char * name) {
|
||||
|
||||
cl_int errNum;
|
||||
cl_kernel k = clCreateKernel(prog, name, &errNum);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "buildKernel '%s' (%d)\n", name, errNum);
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class CLComputeController::KernelBundle :
|
||||
NonCopyable<CLComputeController::KernelBundle> {
|
||||
|
||||
public:
|
||||
|
||||
bool Compile(cl_context clContext,
|
||||
VertexBufferDescriptor const & srcDesc,
|
||||
VertexBufferDescriptor const & dstDesc) {
|
||||
|
||||
cl_int errNum;
|
||||
|
||||
// XXX: only store srcDesc.
|
||||
// this is ok since currently this kernel doesn't get called with
|
||||
// different strides for src and dst. This function will be
|
||||
// refactored soon.
|
||||
_desc = VertexBufferDescriptor(0, srcDesc.length, srcDesc.stride);
|
||||
|
||||
std::ostringstream defines;
|
||||
defines << "#define LENGTH " << srcDesc.length << "\n"
|
||||
<< "#define SRC_STRIDE " << srcDesc.stride << "\n"
|
||||
<< "#define DST_STRIDE " << dstDesc.stride << "\n";
|
||||
std::string defineStr = defines.str();
|
||||
|
||||
const char *sources[] = { defineStr.c_str(), clSource };
|
||||
_program = clCreateProgramWithSource(clContext, 2, 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;
|
||||
}
|
||||
|
||||
// compile all cl compute kernels
|
||||
_stencilsKernel = buildKernel(_program, "computeStencils");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
cl_kernel GetStencilsKernel() const {
|
||||
return _stencilsKernel;
|
||||
}
|
||||
|
||||
struct Match {
|
||||
|
||||
Match(VertexBufferDescriptor const & d) : desc(d) { }
|
||||
|
||||
bool operator() (KernelBundle const * kernel) {
|
||||
return (desc.length==kernel->_desc.length and
|
||||
desc.stride==kernel->_desc.stride);
|
||||
}
|
||||
|
||||
VertexBufferDescriptor desc;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
cl_program _program;
|
||||
|
||||
cl_kernel _stencilsKernel;
|
||||
|
||||
VertexBufferDescriptor _desc;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
CLComputeController::ApplyStencilTableKernel(ComputeContext const *context) {
|
||||
|
||||
assert(context);
|
||||
|
||||
cl_int errNum;
|
||||
|
||||
size_t globalWorkSize = 0;
|
||||
|
||||
if (context->HasVertexStencilTables()) {
|
||||
int start = 0;
|
||||
int end = context->GetNumStencilsInVertexStencilTables();
|
||||
globalWorkSize = (size_t)(end - start);
|
||||
|
||||
KernelBundle const * bundle = getKernel(_currentBindState.vertexDesc);
|
||||
|
||||
cl_kernel kernel = bundle->GetStencilsKernel();
|
||||
|
||||
cl_mem sizes = context->GetVertexStencilTablesSizes(),
|
||||
offsets = context->GetVertexStencilTablesOffsets(),
|
||||
indices = context->GetVertexStencilTablesIndices(),
|
||||
weights = context->GetVertexStencilTablesWeights();
|
||||
|
||||
cl_mem src = _currentBindState.vertexBuffer;
|
||||
cl_mem dst = _currentBindState.vertexBuffer;
|
||||
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.vertexDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += context->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
clSetKernelArg(kernel, 0, sizeof(cl_mem), &src);
|
||||
clSetKernelArg(kernel, 1, sizeof(int), &srcDesc.offset);
|
||||
clSetKernelArg(kernel, 2, sizeof(cl_mem), &dst);
|
||||
clSetKernelArg(kernel, 3, sizeof(int), &dstDesc.offset);
|
||||
clSetKernelArg(kernel, 4, sizeof(cl_mem), &sizes);
|
||||
clSetKernelArg(kernel, 5, sizeof(cl_mem), &offsets);
|
||||
clSetKernelArg(kernel, 6, sizeof(cl_mem), &indices);
|
||||
clSetKernelArg(kernel, 7, sizeof(cl_mem), &weights);
|
||||
clSetKernelArg(kernel, 8, sizeof(int), &start);
|
||||
clSetKernelArg(kernel, 9, sizeof(int), &end);
|
||||
|
||||
errNum = clEnqueueNDRangeKernel(
|
||||
_clQueue, kernel, 1, NULL, &globalWorkSize, NULL, 0, NULL, NULL);
|
||||
if (errNum!=CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"ApplyStencilTableKernel (%d) ", errNum);
|
||||
}
|
||||
}
|
||||
|
||||
if (context->HasVaryingStencilTables()) {
|
||||
int start = 0;
|
||||
int end = context->GetNumStencilsInVaryingStencilTables();
|
||||
globalWorkSize = (size_t)(end - start);
|
||||
|
||||
KernelBundle const * bundle = getKernel(_currentBindState.varyingDesc);
|
||||
|
||||
cl_kernel kernel = bundle->GetStencilsKernel();
|
||||
|
||||
cl_mem sizes = context->GetVaryingStencilTablesSizes(),
|
||||
offsets = context->GetVaryingStencilTablesOffsets(),
|
||||
indices = context->GetVaryingStencilTablesIndices(),
|
||||
weights = context->GetVaryingStencilTablesWeights();
|
||||
|
||||
cl_mem src = _currentBindState.varyingBuffer;
|
||||
cl_mem dst = _currentBindState.varyingBuffer;
|
||||
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.varyingDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += context->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
clSetKernelArg(kernel, 0, sizeof(cl_mem), &src);
|
||||
clSetKernelArg(kernel, 1, sizeof(int), &srcDesc.offset);
|
||||
clSetKernelArg(kernel, 2, sizeof(cl_mem), &dst);
|
||||
clSetKernelArg(kernel, 3, sizeof(int), &dstDesc.offset);
|
||||
clSetKernelArg(kernel, 4, sizeof(cl_mem), &sizes);
|
||||
clSetKernelArg(kernel, 5, sizeof(cl_mem), &offsets);
|
||||
clSetKernelArg(kernel, 6, sizeof(cl_mem), &indices);
|
||||
clSetKernelArg(kernel, 7, sizeof(cl_mem), &weights);
|
||||
clSetKernelArg(kernel, 8, sizeof(int), &start);
|
||||
clSetKernelArg(kernel, 9, sizeof(int), &end);
|
||||
|
||||
errNum = clEnqueueNDRangeKernel(
|
||||
_clQueue, kernel, 1, NULL, &globalWorkSize, NULL, 0, NULL, NULL);
|
||||
if (errNum!=CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"ApplyStencilTableKernel (%d)", errNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CLComputeController::KernelBundle const *
|
||||
CLComputeController::getKernel(VertexBufferDescriptor const &desc) {
|
||||
|
||||
KernelRegistry::iterator it =
|
||||
std::find_if(_kernelRegistry.begin(), _kernelRegistry.end(),
|
||||
KernelBundle::Match(desc));
|
||||
|
||||
if (it != _kernelRegistry.end()) {
|
||||
return *it;
|
||||
} else {
|
||||
KernelBundle * kernelBundle = new KernelBundle();
|
||||
kernelBundle->Compile(_clContext, desc, desc);
|
||||
_kernelRegistry.push_back(kernelBundle);
|
||||
return kernelBundle;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CLComputeController::CLComputeController(
|
||||
cl_context clContext, cl_command_queue queue) :
|
||||
_clContext(clContext), _clQueue(queue) {
|
||||
}
|
||||
|
||||
CLComputeController::~CLComputeController() {
|
||||
for (KernelRegistry::iterator it = _kernelRegistry.begin();
|
||||
it != _kernelRegistry.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
CLComputeController::Synchronize() {
|
||||
|
||||
clFinish(_clQueue);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,204 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CL_COMPUTE_CONTROLLER_H
|
||||
#define OSD_CL_COMPUTE_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/clComputeContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
#include "../osd/opencl.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class CLKernelBundle;
|
||||
|
||||
/// \brief Compute controller for launching OpenCL Compute subdivision kernels.
|
||||
///
|
||||
/// CLComputeController is a compute controller class to launch
|
||||
/// OpenCL subdivision kernels. It requires CLVertexBufferInterface
|
||||
/// as arguments of Refine function.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class CLComputeController {
|
||||
public:
|
||||
typedef CLComputeContext ComputeContext;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param clContext a valid instanciated OpenCL context
|
||||
///
|
||||
/// @param queue a valid non-zero OpenCL command queue
|
||||
///
|
||||
CLComputeController(cl_context clContext, cl_command_queue queue);
|
||||
|
||||
/// Destructor.
|
||||
~CLComputeController();
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CLContext to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param vertexDesc The descriptor of vertex elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
/// @param varyingBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param varyingDesc The descriptor of varying elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void Compute( CLComputeContext const * context,
|
||||
VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc=NULL,
|
||||
VertexBufferDescriptor const * varyingDesc=NULL ){
|
||||
|
||||
bind(vertexBuffer, varyingBuffer, vertexDesc, varyingDesc);
|
||||
|
||||
ApplyStencilTableKernel(context);
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CLContext to apply refinement operations to
|
||||
///
|
||||
/// @param batches Vector of batches of vertices organized by operative
|
||||
/// kernel
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
template<class VERTEX_BUFFER>
|
||||
void Compute(CLComputeContext const * context,
|
||||
VERTEX_BUFFER *vertexBuffer) {
|
||||
|
||||
Compute<VERTEX_BUFFER>(context, vertexBuffer, (VERTEX_BUFFER*)0);
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
/// Returns CL context
|
||||
cl_context GetContext() const { return _clContext; }
|
||||
|
||||
/// Returns CL command queue
|
||||
cl_command_queue GetCommandQueue() const { return _clQueue; }
|
||||
|
||||
protected:
|
||||
|
||||
void ApplyStencilTableKernel(ComputeContext const *context);
|
||||
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void bind( VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc,
|
||||
VertexBufferDescriptor const * varyingDesc ) {
|
||||
|
||||
// if the vertex buffer descriptor is specified, use it.
|
||||
// otherwise, assumes the data is tightly packed in the vertex buffer.
|
||||
if (vertexDesc) {
|
||||
_currentBindState.vertexDesc = *vertexDesc;
|
||||
} else {
|
||||
int numElements = vertexBuffer ? vertexBuffer->GetNumElements() : 0;
|
||||
_currentBindState.vertexDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
if (varyingDesc) {
|
||||
_currentBindState.varyingDesc = *varyingDesc;
|
||||
} else {
|
||||
int numElements = varyingBuffer ? varyingBuffer->GetNumElements() : 0;
|
||||
_currentBindState.varyingDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
_currentBindState.vertexBuffer = vertexBuffer ?
|
||||
vertexBuffer->BindCLBuffer(_clQueue) : 0;
|
||||
_currentBindState.varyingBuffer = varyingBuffer ?
|
||||
varyingBuffer->BindCLBuffer(_clQueue) : 0;
|
||||
}
|
||||
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
class KernelBundle;
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of the vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : vertexBuffer(0), varyingBuffer(0) { }
|
||||
|
||||
void Reset() {
|
||||
vertexBuffer = varyingBuffer = NULL;
|
||||
vertexDesc.Reset();
|
||||
varyingDesc.Reset();
|
||||
}
|
||||
|
||||
cl_mem vertexBuffer,
|
||||
varyingBuffer;
|
||||
|
||||
VertexBufferDescriptor vertexDesc,
|
||||
varyingDesc;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
|
||||
KernelBundle const * getKernel(VertexBufferDescriptor const &desc);
|
||||
|
||||
typedef std::vector<KernelBundle *> KernelRegistry;
|
||||
|
||||
KernelRegistry _kernelRegistry;
|
||||
|
||||
cl_context _clContext;
|
||||
cl_command_queue _clQueue;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_COMPUTE_CONTROLLER_H
|
0
opensubdiv/osd/clD3D11VertexBuffer.cpp
Executable file → Normal file
0
opensubdiv/osd/clD3D11VertexBuffer.cpp
Executable file → Normal file
@ -51,7 +51,7 @@ namespace Osd {
|
||||
/// D3D11VertexBuffer implements CLVertexBufferInterface and
|
||||
/// D3D11VertexBufferInterface.
|
||||
///
|
||||
/// An instance of this buffer class can be passed to D3D11ComputeController.
|
||||
/// An instance of this buffer class can be passed to D3D11ComputeEvaluator.
|
||||
///
|
||||
class CLD3D11VertexBuffer {
|
||||
public:
|
||||
|
206
opensubdiv/osd/clEvaluator.cpp
Normal file
206
opensubdiv/osd/clEvaluator.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/clEvaluator.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../osd/opencl.h"
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static const char *clSource =
|
||||
#include "clKernel.gen.h"
|
||||
;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
template <class T> cl_mem
|
||||
createCLBuffer(std::vector<T> const & src, cl_context clContext) {
|
||||
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;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CLStencilTables::CLStencilTables(Far::StencilTables const *stencilTables,
|
||||
cl_context clContext) {
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCLBuffer(stencilTables->GetSizes(), clContext);
|
||||
_offsets = createCLBuffer(stencilTables->GetOffsets(), clContext);
|
||||
_indices = createCLBuffer(stencilTables->GetControlIndices(),
|
||||
clContext);
|
||||
_weights = createCLBuffer(stencilTables->GetWeights(), clContext);
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CLStencilTables::~CLStencilTables() {
|
||||
if (_sizes) clReleaseMemObject(_sizes);
|
||||
if (_offsets) clReleaseMemObject(_offsets);
|
||||
if (_indices) clReleaseMemObject(_indices);
|
||||
if (_weights) clReleaseMemObject(_weights);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
CLEvaluator::CLEvaluator(cl_context context, cl_command_queue queue)
|
||||
: _clContext(context), _clCommandQueue(queue),
|
||||
_program(NULL), _stencilsKernel(NULL) {
|
||||
}
|
||||
|
||||
CLEvaluator::~CLEvaluator() {
|
||||
if (_stencilsKernel) clReleaseKernel(_stencilsKernel);
|
||||
if (_program) clReleaseProgram(_program);
|
||||
}
|
||||
|
||||
bool
|
||||
CLEvaluator::Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc) {
|
||||
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";
|
||||
std::string defineStr = defines.str();
|
||||
|
||||
const char *sources[] = { defineStr.c_str(), clSource };
|
||||
_program = clCreateProgramWithSource(_clContext, 2, 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;
|
||||
}
|
||||
|
||||
_stencilsKernel = clCreateKernel(_program, "computeStencils", &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,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
cl_mem dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
cl_mem sizes,
|
||||
cl_mem offsets,
|
||||
cl_mem indices,
|
||||
cl_mem weights,
|
||||
int start,
|
||||
int end) const {
|
||||
if (end <= start) return true;
|
||||
|
||||
size_t globalWorkSize = (size_t)(end - start);
|
||||
|
||||
clSetKernelArg(_stencilsKernel, 0, sizeof(cl_mem), &src);
|
||||
clSetKernelArg(_stencilsKernel, 1, sizeof(int), &srcDesc.offset);
|
||||
clSetKernelArg(_stencilsKernel, 2, sizeof(cl_mem), &dst);
|
||||
clSetKernelArg(_stencilsKernel, 3, sizeof(int), &dstDesc.offset);
|
||||
clSetKernelArg(_stencilsKernel, 4, sizeof(cl_mem), &sizes);
|
||||
clSetKernelArg(_stencilsKernel, 5, sizeof(cl_mem), &offsets);
|
||||
clSetKernelArg(_stencilsKernel, 6, sizeof(cl_mem), &indices);
|
||||
clSetKernelArg(_stencilsKernel, 7, sizeof(cl_mem), &weights);
|
||||
clSetKernelArg(_stencilsKernel, 8, sizeof(int), &start);
|
||||
clSetKernelArg(_stencilsKernel, 9, sizeof(int), &end);
|
||||
|
||||
cl_int errNum = clEnqueueNDRangeKernel(
|
||||
_clCommandQueue, _stencilsKernel, 1, NULL,
|
||||
&globalWorkSize, NULL, 0, NULL, NULL);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"ApplyStencilTableKernel (%d) ", errNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
clFinish(_clCommandQueue);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
CLEvaluator::Synchronize(cl_command_queue clCommandQueue) {
|
||||
clFinish(clCommandQueue);
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
230
opensubdiv/osd/clEvaluator.h
Normal file
230
opensubdiv/osd/clEvaluator.h
Normal file
@ -0,0 +1,230 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_CL_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_CL_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/opencl.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief OpenCL stencil tables
|
||||
///
|
||||
/// This class is an OpenCL buffer representation of Far::StencilTables.
|
||||
///
|
||||
/// CLCompute consumes this table to apply stencils
|
||||
///
|
||||
///
|
||||
class CLStencilTables {
|
||||
public:
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static CLStencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
DEVICE_CONTEXT context) {
|
||||
return new CLStencilTables(stencilTables, context->GetContext());
|
||||
}
|
||||
|
||||
CLStencilTables(Far::StencilTables const *stencilTables,
|
||||
cl_context clContext);
|
||||
~CLStencilTables();
|
||||
|
||||
// interfaces needed for CLComputeKernel
|
||||
cl_mem GetSizesBuffer() const { return _sizes; }
|
||||
cl_mem GetOffsetsBuffer() const { return _offsets; }
|
||||
cl_mem GetIndicesBuffer() const { return _indices; }
|
||||
cl_mem GetWeightsBuffer() const { return _weights; }
|
||||
int GetNumStencils() const { return _numStencils; }
|
||||
|
||||
private:
|
||||
cl_mem _sizes;
|
||||
cl_mem _offsets;
|
||||
cl_mem _indices;
|
||||
cl_mem _weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// \brief OpenCL stencil kernel
|
||||
///
|
||||
///
|
||||
class CLEvaluator {
|
||||
public:
|
||||
typedef bool Instantiatable;
|
||||
/// Constructor.
|
||||
CLEvaluator(cl_context context, cl_command_queue queue);
|
||||
|
||||
/// Desctructor.
|
||||
~CLEvaluator();
|
||||
|
||||
/// Generic creator template.
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static CLEvaluator *Create(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
DEVICE_CONTEXT deviceContext) {
|
||||
return Create(srcDesc, dstDesc,
|
||||
deviceContext->GetContext(),
|
||||
deviceContext->GetCommandQueue());
|
||||
}
|
||||
|
||||
static CLEvaluator * Create(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
cl_context clContext,
|
||||
cl_command_queue clCommandQueue) {
|
||||
CLEvaluator *kernel = new CLEvaluator(clContext, clCommandQueue);
|
||||
if (kernel->Compile(srcDesc, dstDesc)) return kernel;
|
||||
delete kernel;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// \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 BindCLBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCLBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTables stencil table to be applied. The table must have
|
||||
/// OpenCL memory 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 client providing context class which supports
|
||||
/// cL_context GetContext()
|
||||
/// cl_command_queue GetCommandQueue()
|
||||
/// methods.
|
||||
///
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE,
|
||||
typename DEVICE_CONTEXT>
|
||||
static bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
CLEvaluator const *instance,
|
||||
DEVICE_CONTEXT deviceContext) {
|
||||
if (instance) {
|
||||
return instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable);
|
||||
} else {
|
||||
// Create an instance on demand (slow)
|
||||
instance = Create(srcDesc, dstDesc, deviceContext);
|
||||
if (instance) {
|
||||
bool r = instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic compute function.
|
||||
/// Dispatch the CL compute kernel asynchronously.
|
||||
/// Returns false if the kernel hasn't been compiled yet.
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable) const {
|
||||
return EvalStencils(srcVertexBuffer->BindCLBuffer(_clCommandQueue),
|
||||
srcDesc,
|
||||
dstVertexBuffer->BindCLBuffer(_clCommandQueue),
|
||||
dstDesc,
|
||||
stencilTable->GetSizesBuffer(),
|
||||
stencilTable->GetOffsetsBuffer(),
|
||||
stencilTable->GetIndicesBuffer(),
|
||||
stencilTable->GetWeightsBuffer(),
|
||||
0,
|
||||
stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
/// Dispatch the CL compute kernel asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
bool EvalStencils(cl_mem src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
cl_mem dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
cl_mem sizes,
|
||||
cl_mem offsets,
|
||||
cl_mem indices,
|
||||
cl_mem weights,
|
||||
int start,
|
||||
int end) const;
|
||||
|
||||
/// Configure OpenCL kernel.
|
||||
/// Returns false if it fails to compile the kernel.
|
||||
bool Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc);
|
||||
|
||||
/// Wait the OpenCL kernels finish.
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static void Synchronize(DEVICE_CONTEXT deviceContext) {
|
||||
Synchronize(deviceContext->GetCommandQueue());
|
||||
}
|
||||
|
||||
static void Synchronize(cl_command_queue queue);
|
||||
|
||||
private:
|
||||
cl_context _clContext;
|
||||
cl_command_queue _clCommandQueue;
|
||||
cl_program _program;
|
||||
cl_kernel _stencilsKernel;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_CL_EVALUATOR_H
|
@ -37,7 +37,7 @@ namespace Osd {
|
||||
/// \brief Concrete vertex buffer class for OpenCL subvision.
|
||||
///
|
||||
/// CLVertexBuffer implements CLVertexBufferInterface. An instance of this
|
||||
/// buffer class can be passed to CLComputeController
|
||||
/// buffer class can be passed to CLEvaluator
|
||||
///
|
||||
class CLVertexBuffer {
|
||||
|
||||
|
@ -1,77 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
#include "../osd/cpuComputeContext.h"
|
||||
#include "../osd/cpuKernel.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CpuComputeContext::CpuComputeContext(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables) :
|
||||
_vertexStencilTables(0), _varyingStencilTables(0) {
|
||||
|
||||
// XXXX manuelk we do not own the tables, so use copy-constructor for now
|
||||
// smart pointers eventually
|
||||
if (vertexStencilTables) {
|
||||
_vertexStencilTables = new Far::StencilTables(*vertexStencilTables);
|
||||
}
|
||||
|
||||
if (varyingStencilTables) {
|
||||
_varyingStencilTables = new Far::StencilTables(*varyingStencilTables);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CpuComputeContext::~CpuComputeContext() {
|
||||
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CpuComputeContext *
|
||||
CpuComputeContext::Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
return new CpuComputeContext(vertexStencilTables, varyingStencilTables);
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,102 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CPU_COMPUTE_CONTEXT_H
|
||||
#define OSD_CPU_COMPUTE_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far { class StencilTables; }
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief CPU Compute Context
|
||||
///
|
||||
/// The CPU implementation of the Compute module contextual functionality.
|
||||
///
|
||||
/// The Osd Compute module provides functionality to interpolate primitive
|
||||
/// variable data according to a subdivision scheme.
|
||||
///
|
||||
/// Contexts provide an interface between the serialized topological data
|
||||
/// of a geometric primitive and the computation resources of a compute device.
|
||||
///
|
||||
class CpuComputeContext : private NonCopyable<CpuComputeContext> {
|
||||
public:
|
||||
/// Creates an CpuComputeContext instance
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
/// @param deviceContext (not used)
|
||||
///
|
||||
static CpuComputeContext * Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Destructor
|
||||
virtual ~CpuComputeContext();
|
||||
|
||||
/// Returns the stencils data applied by this context for vertex
|
||||
/// interpolation
|
||||
Far::StencilTables const * GetVertexStencilTables() const {
|
||||
return _vertexStencilTables;
|
||||
}
|
||||
|
||||
/// Returns the stencils data applied by this context for varying
|
||||
/// interpolation
|
||||
Far::StencilTables const * GetVaryingStencilTables() const {
|
||||
return _varyingStencilTables;
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit CpuComputeContext(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables);
|
||||
|
||||
private:
|
||||
Far::StencilTables const * _vertexStencilTables,
|
||||
* _varyingStencilTables;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_CPU_COMPUTE_CONTEXT_H
|
||||
|
||||
|
@ -1,106 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../osd/cpuComputeContext.h"
|
||||
#include "../osd/cpuComputeController.h"
|
||||
#include "../osd/cpuKernel.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuComputeController::CpuComputeController() {
|
||||
}
|
||||
|
||||
CpuComputeController::~CpuComputeController() {
|
||||
}
|
||||
|
||||
void
|
||||
CpuComputeController::Synchronize() {
|
||||
}
|
||||
|
||||
void
|
||||
CpuComputeController::ApplyStencilTableKernel(
|
||||
ComputeContext const *context) const {
|
||||
|
||||
assert(context);
|
||||
|
||||
Far::StencilTables const * vertexStencils = context->GetVertexStencilTables();
|
||||
|
||||
if (vertexStencils and _currentBindState.vertexBuffer) {
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.vertexDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += vertexStencils->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
int start = 0;
|
||||
int end = vertexStencils->GetNumStencils();
|
||||
|
||||
if (end > start) {
|
||||
CpuComputeStencils(_currentBindState.vertexBuffer,
|
||||
srcDesc,
|
||||
_currentBindState.vertexBuffer,
|
||||
dstDesc,
|
||||
&vertexStencils->GetSizes().at(0),
|
||||
&vertexStencils->GetOffsets().at(0),
|
||||
&vertexStencils->GetControlIndices().at(0),
|
||||
&vertexStencils->GetWeights().at(0),
|
||||
start,
|
||||
end);
|
||||
}
|
||||
}
|
||||
|
||||
Far::StencilTables const * varyingStencils = context->GetVaryingStencilTables();
|
||||
|
||||
if (varyingStencils and _currentBindState.varyingBuffer) {
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.varyingDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += varyingStencils->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
int start = 0;
|
||||
int end = varyingStencils->GetNumStencils();
|
||||
|
||||
if (end > start) {
|
||||
CpuComputeStencils(_currentBindState.varyingBuffer,
|
||||
srcDesc,
|
||||
_currentBindState.varyingBuffer,
|
||||
dstDesc,
|
||||
&varyingStencils->GetSizes().at(0),
|
||||
&varyingStencils->GetOffsets().at(0),
|
||||
&varyingStencils->GetControlIndices().at(0),
|
||||
&varyingStencils->GetWeights().at(0),
|
||||
start,
|
||||
end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,179 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CPU_COMPUTE_CONTROLLER_H
|
||||
#define OSD_CPU_COMPUTE_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/cpuComputeContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Compute controller for launching CPU subdivision kernels.
|
||||
///
|
||||
/// CpuComputeController is a compute controller class to launch
|
||||
/// single threaded CPU subdivision kernels. It requires
|
||||
/// CpuVertexBufferInterface as arguments of the Refine() function.
|
||||
///
|
||||
/// The Osd Compute module provides functionality to interpolate primitive
|
||||
/// variable data according to a subdivision scheme.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class CpuComputeController {
|
||||
public:
|
||||
typedef CpuComputeContext ComputeContext;
|
||||
|
||||
/// Constructor.
|
||||
CpuComputeController();
|
||||
|
||||
/// Destructor.
|
||||
~CpuComputeController();
|
||||
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CpuContext to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param vertexDesc The descriptor of vertex elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
/// @param varyingBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param varyingDesc The descriptor of varying elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void Compute( CpuComputeContext const * context,
|
||||
VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc=NULL,
|
||||
VertexBufferDescriptor const * varyingDesc=NULL ){
|
||||
|
||||
bind(vertexBuffer, varyingBuffer, vertexDesc, varyingDesc);
|
||||
|
||||
ApplyStencilTableKernel(context);
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CpuContext to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
template<class VERTEX_BUFFER>
|
||||
void Compute(CpuComputeContext const * context,
|
||||
VERTEX_BUFFER *vertexBuffer) {
|
||||
|
||||
Compute<VERTEX_BUFFER>(context, vertexBuffer, (VERTEX_BUFFER*)0);
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void ApplyStencilTableKernel(ComputeContext const *context) const;
|
||||
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void bind( VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc,
|
||||
VertexBufferDescriptor const * varyingDesc ) {
|
||||
|
||||
// if the vertex buffer descriptor is specified, use it.
|
||||
// otherwise, assumes the data is tightly packed in the vertex buffer.
|
||||
if (vertexDesc) {
|
||||
_currentBindState.vertexDesc = *vertexDesc;
|
||||
} else {
|
||||
int numElements = vertexBuffer ? vertexBuffer->GetNumElements() : 0;
|
||||
_currentBindState.vertexDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
if (varyingDesc) {
|
||||
_currentBindState.varyingDesc = *varyingDesc;
|
||||
} else {
|
||||
int numElements = varyingBuffer ? varyingBuffer->GetNumElements() : 0;
|
||||
_currentBindState.varyingDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
_currentBindState.vertexBuffer = vertexBuffer ?
|
||||
vertexBuffer->BindCpuBuffer() : 0;
|
||||
|
||||
_currentBindState.varyingBuffer = varyingBuffer ?
|
||||
varyingBuffer->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of the vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : vertexBuffer(0), varyingBuffer(0) { }
|
||||
|
||||
void Reset() {
|
||||
vertexBuffer = varyingBuffer = 0;
|
||||
vertexDesc.Reset();
|
||||
varyingDesc.Reset();
|
||||
}
|
||||
|
||||
float * vertexBuffer,
|
||||
* varyingBuffer;
|
||||
|
||||
VertexBufferDescriptor vertexDesc,
|
||||
varyingDesc;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_CPU_COMPUTE_CONTROLLER_H
|
@ -43,7 +43,7 @@ namespace Osd {
|
||||
/// CpuD3D11VertexBuffer implements CpuVertexBufferInterface and
|
||||
/// D3D11VertexBufferInterface.
|
||||
///
|
||||
/// An instance of this buffer class can be passed to CpuComputeController.
|
||||
/// An instance of this buffer class can be passed to CpuEvaluator.
|
||||
///
|
||||
class CpuD3D11VertexBuffer {
|
||||
public:
|
||||
|
@ -1,57 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cpuEvalLimitContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuEvalLimitContext *
|
||||
CpuEvalLimitContext::Create(Far::PatchTables const & patchTables) {
|
||||
|
||||
// there is no limit with uniform subdivision
|
||||
if (not patchTables.IsFeatureAdaptive())
|
||||
return NULL;
|
||||
|
||||
return new CpuEvalLimitContext(patchTables);
|
||||
}
|
||||
|
||||
CpuEvalLimitContext::CpuEvalLimitContext(Far::PatchTables const & patchTables) :
|
||||
EvalLimitContext(patchTables),
|
||||
_patchTables(patchTables),
|
||||
_patchMap(patchTables) {
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,80 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CPU_EVAL_LIMIT_CONTEXT_H
|
||||
#define OSD_CPU_EVAL_LIMIT_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/evalLimitContext.h"
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/patchMap.h"
|
||||
|
||||
#include <map>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class CpuEvalLimitContext : public EvalLimitContext {
|
||||
public:
|
||||
|
||||
/// \brief Factory
|
||||
/// Returns an EvalLimitContext from the given far patch tables.
|
||||
/// Note : the patchtables is expected to be feature-adaptive and have ptex
|
||||
/// coordinates tables.
|
||||
///
|
||||
/// @param patchTables a pointer to an initialized Far::PatchTables
|
||||
///
|
||||
static CpuEvalLimitContext * Create(Far::PatchTables const &patchTables);
|
||||
|
||||
Far::PatchTables const & GetPatchTables() const {
|
||||
return _patchTables;
|
||||
}
|
||||
|
||||
Far::PatchMap const & GetPatchMap() const {
|
||||
return _patchMap;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
explicit CpuEvalLimitContext(Far::PatchTables const & patchTables);
|
||||
|
||||
private:
|
||||
|
||||
Far::PatchTables const _patchTables; // Patch topology data
|
||||
Far::PatchMap const _patchMap; // Patch search accelerator
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* OSD_CPU_EVAL_LIMIT_CONTEXT_H */
|
@ -1,288 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cpuEvalLimitController.h"
|
||||
#include "../osd/cpuEvalLimitContext.h"
|
||||
#include "../osd/cpuEvalLimitKernel.h"
|
||||
#include "../far/patchTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuEvalLimitController::CpuEvalLimitController() {
|
||||
}
|
||||
|
||||
CpuEvalLimitController::~CpuEvalLimitController() {
|
||||
}
|
||||
|
||||
// Vertex interpolation of a sample at the limit
|
||||
int
|
||||
CpuEvalLimitController::EvalLimitSample( LimitLocation const & coord,
|
||||
CpuEvalLimitContext * context,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV ) const {
|
||||
typedef Far::PatchDescriptor Desc;
|
||||
|
||||
float s=coord.s,
|
||||
t=coord.t;
|
||||
|
||||
Far::PatchMap::Handle const * handle = context->GetPatchMap().FindPatch( coord.ptexIndex, s, t );
|
||||
if (not handle) {
|
||||
return 0; // no handle if there is a hole or 'coord' is incorrect
|
||||
}
|
||||
|
||||
VertexData const & vertexData = _currentBindState.vertexData;
|
||||
|
||||
if (vertexData.in) {
|
||||
|
||||
Far::PatchTables const & ptables = context->GetPatchTables();
|
||||
|
||||
Far::PatchParam pparam = ptables.GetPatchParam(*handle);
|
||||
|
||||
Far::ConstIndexArray cvs = ptables.GetPatchVertices(*handle);
|
||||
|
||||
Far::PatchDescriptor desc = ptables.GetPatchDescriptor(*handle);
|
||||
switch (desc.GetType()) {
|
||||
case Desc::REGULAR : evalBSpline( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
case Desc::BOUNDARY : evalBoundary( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
case Desc::CORNER : evalCorner( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
case Desc::GREGORY : evalGregory( pparam.bitField, t, s, cvs.begin(),
|
||||
&ptables.GetVertexValenceTable()[0],
|
||||
ptables.GetPatchQuadOffsets(*handle).begin(),
|
||||
ptables.GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
case Desc::GREGORY_BOUNDARY : evalGregoryBoundary( pparam.bitField, t, s, cvs.begin(),
|
||||
&ptables.GetVertexValenceTable()[0],
|
||||
ptables.GetPatchQuadOffsets(*handle).begin(),
|
||||
ptables.GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
case Desc::GREGORY_BASIS : {
|
||||
evalGregoryBasis( pparam.bitField, s, t,
|
||||
cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
} break;
|
||||
case Desc::QUADS : evalBilinear( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Vertex interpolation of samples at the limit
|
||||
int
|
||||
CpuEvalLimitController::_EvalLimitSample( LimitLocation const & coords,
|
||||
CpuEvalLimitContext * context,
|
||||
unsigned int index ) const {
|
||||
typedef Far::PatchDescriptor Desc;
|
||||
|
||||
float s=coords.s,
|
||||
t=coords.t;
|
||||
|
||||
Far::PatchMap::Handle const * handle = context->GetPatchMap().FindPatch( coords.ptexIndex, s, t );
|
||||
if (not handle) {
|
||||
return 0; // no handle if there is a hole or 'coord' is incorrect
|
||||
}
|
||||
|
||||
VertexData const & vertexData = _currentBindState.vertexData;
|
||||
|
||||
Far::PatchTables const & ptables = context->GetPatchTables();
|
||||
|
||||
Far::PatchParam pparam = ptables.GetPatchParam(*handle);
|
||||
|
||||
Far::PatchDescriptor desc = ptables.GetPatchDescriptor(*handle);
|
||||
|
||||
Far::ConstIndexArray cvs = ptables.GetPatchVertices(*handle);
|
||||
|
||||
if (vertexData.in) {
|
||||
|
||||
int offset = vertexData.outDesc.stride * index,
|
||||
doffset = vertexData.outDesc.length * index;
|
||||
|
||||
if (vertexData.out) {
|
||||
|
||||
// note : don't apply outDesc.offset here, it's done inside patch
|
||||
// evaluation
|
||||
float * out = vertexData.out+offset,
|
||||
* outDu = vertexData.outDu ? vertexData.outDu+doffset : 0,
|
||||
* outDv = vertexData.outDv ? vertexData.outDv+doffset : 0;
|
||||
|
||||
switch (desc.GetType()) {
|
||||
case Desc::REGULAR : evalBSpline( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
case Desc::BOUNDARY : evalBoundary( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
case Desc::CORNER : evalCorner( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
case Desc::GREGORY : evalGregory( pparam.bitField, t, s, cvs.begin(),
|
||||
&ptables.GetVertexValenceTable()[0],
|
||||
ptables.GetPatchQuadOffsets(*handle).begin(),
|
||||
ptables.GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
case Desc::GREGORY_BOUNDARY : evalGregoryBoundary( pparam.bitField, t, s, cvs.begin(),
|
||||
&ptables.GetVertexValenceTable()[0],
|
||||
ptables.GetPatchQuadOffsets(*handle).begin(),
|
||||
ptables.GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
case Desc::GREGORY_BASIS : {
|
||||
evalGregoryBasis( pparam.bitField, s, t,
|
||||
cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
} break;
|
||||
case Desc::QUADS : evalBilinear( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VaryingData const & varyingData = _currentBindState.varyingData;
|
||||
|
||||
if (varyingData.in and varyingData.out) {
|
||||
|
||||
static int const zeroRings[6][4] = { {5, 6,10, 9}, // regular
|
||||
{1, 2, 6, 5}, // boundary / single-crease
|
||||
{1, 2, 5, 4}, // corner
|
||||
{0, 1, 2, 3}, // no permutation
|
||||
{0, 5, 10, 15} }; // gregory basis
|
||||
|
||||
int const * permute = 0;
|
||||
switch (desc.GetType()) {
|
||||
case Desc::REGULAR : permute = zeroRings[0]; break;
|
||||
case Desc::BOUNDARY : permute = zeroRings[1]; break;
|
||||
case Desc::CORNER : permute = zeroRings[2]; break;
|
||||
case Desc::GREGORY :
|
||||
case Desc::GREGORY_BOUNDARY : permute = zeroRings[3]; break;
|
||||
case Desc::GREGORY_BASIS : permute = zeroRings[4]; break;
|
||||
default:
|
||||
assert(0);
|
||||
};
|
||||
|
||||
int offset = varyingData.outDesc.stride * index;
|
||||
|
||||
Far::Index zeroRing[4] = { cvs[permute[0]],
|
||||
cvs[permute[1]],
|
||||
cvs[permute[2]],
|
||||
cvs[permute[3]] };
|
||||
|
||||
evalBilinear( pparam.bitField, s, t, zeroRing,
|
||||
varyingData.inDesc,
|
||||
varyingData.in,
|
||||
varyingData.outDesc,
|
||||
varyingData.out+offset, 0, 0);
|
||||
|
||||
}
|
||||
|
||||
// Note : currently we only support bilinear boundary interpolation rules
|
||||
// for limit face-varying data.
|
||||
|
||||
FacevaryingData const & facevaryingData = _currentBindState.facevaryingData;
|
||||
|
||||
if (facevaryingData.in and facevaryingData.out) {
|
||||
|
||||
int offset = facevaryingData.outDesc.stride * index;
|
||||
|
||||
static int const zeroRing[4] = {0,1,2,3};
|
||||
|
||||
// XXXX manuelk this assumes FVar data is ordered with 4 CVs / patch :
|
||||
// bi-cubic FVar interpolation will require proper topology
|
||||
// accessors in Far::PatchTables and this code will change
|
||||
evalBilinear( pparam.bitField, s, t, zeroRing,
|
||||
facevaryingData.inDesc,
|
||||
&facevaryingData.in[handle->patchIndex*4*facevaryingData.outDesc.stride],
|
||||
facevaryingData.outDesc,
|
||||
facevaryingData.out+offset, 0, 0);
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,298 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CPU_EVAL_LIMIT_CONTROLLER_H
|
||||
#define OSD_CPU_EVAL_LIMIT_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
struct LimitLocation;
|
||||
class CpuEvalLimitContext;
|
||||
|
||||
/// \brief CPU controler for limit surface evaluation.
|
||||
///
|
||||
/// A CPU-driven controller that can be called to evaluate samples on the limit
|
||||
/// surface for a given EvalContext.
|
||||
///
|
||||
/// Warning : this eval controller is re-entrant but it breaks the Osd API pattern
|
||||
/// by requiring client code to bind and unbind the data buffers to the
|
||||
/// Controller before calling evaluation methods.
|
||||
///
|
||||
/// Ex :
|
||||
/// \code
|
||||
/// evalCtroller->BindVertexBuffers( ... );
|
||||
/// evalCtroller->BindVaryingBuffers( ... );
|
||||
/// evalCtroller->BindFacevaryingBuffers( ... );
|
||||
///
|
||||
/// parallel_for( int index=0; i<nsamples; ++index ) {
|
||||
/// evalCtroller->EvalLimitSample( coord, evalCtxt, index );
|
||||
/// }
|
||||
///
|
||||
/// evalCtroller->Unbind();
|
||||
/// \endcode
|
||||
///
|
||||
class CpuEvalLimitController {
|
||||
|
||||
public:
|
||||
/// Constructor.
|
||||
CpuEvalLimitController();
|
||||
|
||||
/// Destructor.
|
||||
~CpuEvalLimitController();
|
||||
|
||||
/// \brief Binds control vertex data buffer
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input vertex data
|
||||
///
|
||||
/// @param oDesc data descriptor for the outQ data buffer
|
||||
/// -- derivative buffers do not have a descriptor and
|
||||
/// cannot be offset or padded with a stride (yet ?)
|
||||
///
|
||||
/// @param outQ output vertex data
|
||||
///
|
||||
/// @param outdQu output derivative along "u" of the vertex data (optional)
|
||||
///
|
||||
/// @param outdQv output derivative along "v" of the vertex data (optional)
|
||||
///
|
||||
template<class INPUT_BUFFER, class OUTPUT_BUFFER>
|
||||
void BindVertexBuffers( VertexBufferDescriptor const & iDesc, INPUT_BUFFER *inQ,
|
||||
VertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ,
|
||||
OUTPUT_BUFFER *outdQu=0,
|
||||
OUTPUT_BUFFER *outdQv=0 ) {
|
||||
_currentBindState.vertexData.inDesc = iDesc;
|
||||
_currentBindState.vertexData.in = inQ ? inQ->BindCpuBuffer() : 0;
|
||||
|
||||
_currentBindState.vertexData.outDesc = oDesc;
|
||||
_currentBindState.vertexData.out = outQ ? outQ->BindCpuBuffer() : 0;
|
||||
_currentBindState.vertexData.outDu = outdQu ? outdQu->BindCpuBuffer() : 0;
|
||||
_currentBindState.vertexData.outDv = outdQv ? outdQv->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
/// \brief Binds the varying-interpolated data streams
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input varying data
|
||||
///
|
||||
/// @param oDesc data descriptor for the outQ data buffer
|
||||
///
|
||||
/// @param outQ output varying data
|
||||
///
|
||||
template<class INPUT_BUFFER, class OUTPUT_BUFFER>
|
||||
void BindVaryingBuffers( VertexBufferDescriptor const & iDesc, INPUT_BUFFER *inQ,
|
||||
VertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ ) {
|
||||
_currentBindState.varyingData.inDesc = iDesc;
|
||||
_currentBindState.varyingData.in = inQ ? inQ->BindCpuBuffer() : 0;
|
||||
|
||||
_currentBindState.varyingData.outDesc = oDesc;
|
||||
_currentBindState.varyingData.out = outQ ? outQ->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
/// \brief Binds the face-varying-interpolated data streams
|
||||
///
|
||||
/// Note : currently we only support bilinear boundary interpolation rules
|
||||
/// for face-varying data. Although Hbr supports 3 addition smooth rule sets,
|
||||
/// the feature-adaptive patch interpolation code currently does not support
|
||||
/// them, and neither does this EvalContext
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input face-varying data
|
||||
///
|
||||
/// @param oDesc data descriptor for the outQ data buffer
|
||||
///
|
||||
/// @param outQ output face-varying data
|
||||
///
|
||||
template<class INPUT_BUFFER, class OUTPUT_BUFFER>
|
||||
void BindFacevaryingBuffers( VertexBufferDescriptor const & iDesc, INPUT_BUFFER *inQ,
|
||||
VertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ ) {
|
||||
_currentBindState.facevaryingData.inDesc = iDesc;
|
||||
_currentBindState.facevaryingData.in = inQ ? inQ->BindCpuBuffer() : 0;
|
||||
|
||||
_currentBindState.facevaryingData.outDesc = oDesc;
|
||||
_currentBindState.facevaryingData.out = outQ ? outQ->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
/// \brief Vertex interpolation of a single sample at the limit
|
||||
///
|
||||
/// Evaluates "vertex" interpolation of a single sample on the surface limit.
|
||||
///
|
||||
/// This function is re-entrant but does not require binding the
|
||||
/// output vertex buffers. Pointers to memory where the data is
|
||||
/// output are explicitly passed to the function.
|
||||
///
|
||||
/// @param coord location on the limit surface to be evaluated
|
||||
///
|
||||
/// @param context the EvalLimitContext that the controller will evaluate
|
||||
///
|
||||
/// @param outDesc data descriptor for the outQ data buffer
|
||||
/// -- derivative buffers do not have a descriptor and
|
||||
/// cannot be offset or padded with a stride (yet ?)
|
||||
///
|
||||
/// @param outQ output vertex data
|
||||
///
|
||||
/// @param outDQU output derivative along "u" of the vertex data (optional)
|
||||
///
|
||||
/// @param outDQV output derivative along "v" of the vertex data (optional)
|
||||
///
|
||||
/// @return 1 if the sample was found
|
||||
///
|
||||
int EvalLimitSample( LimitLocation const & coord,
|
||||
CpuEvalLimitContext * context,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV ) const;
|
||||
|
||||
/// \brief Vertex interpolation of samples at the limit
|
||||
///
|
||||
/// Evaluates "vertex" interpolation of a sample on the surface limit.
|
||||
///
|
||||
/// @param coords location on the limit surface to be evaluated
|
||||
///
|
||||
/// @param context the EvalLimitContext that the controller will evaluate
|
||||
///
|
||||
/// @param index the index of the vertex in the output buffers bound to the
|
||||
/// context
|
||||
///
|
||||
/// @return the number of samples found (0 if the location was tagged as a hole
|
||||
/// or the coordinate was invalid)
|
||||
///
|
||||
int EvalLimitSample( LimitLocation const & coords,
|
||||
CpuEvalLimitContext * context,
|
||||
unsigned int index ) const {
|
||||
if (not context)
|
||||
return 0;
|
||||
|
||||
int n = _EvalLimitSample( coords, context, index );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void Unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
// Vertex interpolated streams
|
||||
struct VertexData {
|
||||
|
||||
VertexData() : in(0), out(0), outDu(0), outDv(0) { }
|
||||
|
||||
|
||||
void Reset() {
|
||||
in = out = outDu = outDv = NULL;
|
||||
inDesc.Reset();
|
||||
outDesc.Reset();
|
||||
}
|
||||
|
||||
VertexBufferDescriptor inDesc,
|
||||
outDesc;
|
||||
float * in,
|
||||
* out,
|
||||
* outDu,
|
||||
* outDv;
|
||||
};
|
||||
|
||||
// Varying interpolated streams
|
||||
struct VaryingData {
|
||||
|
||||
VaryingData() : in(0), out(0) { }
|
||||
|
||||
|
||||
void Reset() {
|
||||
in = out = NULL;
|
||||
inDesc.Reset();
|
||||
outDesc.Reset();
|
||||
}
|
||||
|
||||
VertexBufferDescriptor inDesc,
|
||||
outDesc;
|
||||
float * in,
|
||||
* out;
|
||||
};
|
||||
|
||||
// Facevarying interpolated streams
|
||||
struct FacevaryingData {
|
||||
|
||||
FacevaryingData() : in(0), out(0) { }
|
||||
|
||||
void Reset() {
|
||||
in = out = NULL;
|
||||
inDesc.Reset();
|
||||
outDesc.Reset();
|
||||
}
|
||||
|
||||
VertexBufferDescriptor inDesc,
|
||||
outDesc;
|
||||
float * in,
|
||||
* out;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int _EvalLimitSample( LimitLocation const & coords,
|
||||
CpuEvalLimitContext * context,
|
||||
unsigned int index ) const;
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() { }
|
||||
|
||||
void Reset() {
|
||||
vertexData.Reset();
|
||||
varyingData.Reset();
|
||||
facevaryingData.Reset();
|
||||
}
|
||||
|
||||
VertexData vertexData; // vertex interpolated data descriptor
|
||||
VaryingData varyingData; // varying interpolated data descriptor
|
||||
FacevaryingData facevaryingData; // face-varying interpolated data descriptor
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* OSD_CPU_EVAL_LIMIT_CONTROLLER_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,132 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CPU_EVAL_LIMIT_KERNEL_H
|
||||
#define OSD_CPU_EVAL_LIMIT_KERNEL_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
#include "../far/patchParam.h"
|
||||
|
||||
#include "../far/types.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
void
|
||||
evalBilinear(Far::PatchParam::BitField bits,
|
||||
float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV);
|
||||
|
||||
void
|
||||
evalBSpline(Far::PatchParam::BitField bits,
|
||||
float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
void
|
||||
evalBoundary(Far::PatchParam::BitField bits,
|
||||
float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
void
|
||||
evalCorner(Far::PatchParam::BitField bits,
|
||||
float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
void
|
||||
evalGregoryBasis(Far::PatchParam::BitField bits,
|
||||
float u, float v,
|
||||
Far::Index const *vertsIndices,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
void
|
||||
evalGregory(Far::PatchParam::BitField bits, float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
Far::Index const * vertexValenceBuffer,
|
||||
unsigned int const * quadOffsetBuffer,
|
||||
int maxValence,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
void
|
||||
evalGregoryBoundary(Far::PatchParam::BitField bits, float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
Far::Index const * vertexValenceBuffer,
|
||||
unsigned int const * quadOffsetBuffer,
|
||||
int maxValence,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* OSD_CPU_EVAL_LIMIT_KERNEL_H */
|
@ -1,74 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef FAR_CPU_EVALSTENCILS_CONTEXT_H
|
||||
#define FAR_CPU_EVALSTENCILS_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief CPU stencils evaluation context
|
||||
///
|
||||
///
|
||||
class CpuEvalStencilsContext : private NonCopyable<CpuEvalStencilsContext> {
|
||||
|
||||
public:
|
||||
/// \brief Creates an CpuEvalStencilsContext instance
|
||||
///
|
||||
/// @param stencils a pointer to the Far::StencilTables
|
||||
///
|
||||
static CpuEvalStencilsContext * Create(Far::LimitStencilTables const *stencils);
|
||||
|
||||
/// \brief Returns the Far::StencilTables applied
|
||||
Far::LimitStencilTables const * GetStencilTables() const {
|
||||
return _stencils;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
CpuEvalStencilsContext(Far::LimitStencilTables const *stencils);
|
||||
|
||||
private:
|
||||
|
||||
Far::LimitStencilTables const * _stencils;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // FAR_CPU_EVALSTENCILS_CONTEXT_H
|
@ -1,149 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cpuEvalStencilsController.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuEvalStencilsController::CpuEvalStencilsController() {
|
||||
}
|
||||
|
||||
CpuEvalStencilsController::~CpuEvalStencilsController() {
|
||||
}
|
||||
|
||||
int
|
||||
CpuEvalStencilsController::_UpdateValues( CpuEvalStencilsContext * context ) {
|
||||
|
||||
int result=0;
|
||||
|
||||
Far::LimitStencilTables const * stencils = context->GetStencilTables();
|
||||
|
||||
int nstencils = stencils->GetNumStencils();
|
||||
if (not nstencils)
|
||||
return result;
|
||||
|
||||
VertexBufferDescriptor ctrlDesc = _currentBindState.controlDataDesc,
|
||||
outDesc = _currentBindState.outputDataDesc;
|
||||
|
||||
// make sure that we have control data to work with
|
||||
if (not ctrlDesc.CanEval(outDesc))
|
||||
return 0;
|
||||
|
||||
float const * ctrl = _currentBindState.controlData + ctrlDesc.offset;
|
||||
|
||||
float * out = _currentBindState.outputData + outDesc.offset;
|
||||
|
||||
if ((not ctrl) or (not out))
|
||||
return result;
|
||||
|
||||
unsigned char const * sizes = &stencils->GetSizes().at(0);
|
||||
Far::Index const * index = &stencils->GetControlIndices().at(0);
|
||||
|
||||
float const * weight = &stencils->GetWeights().at(0);
|
||||
|
||||
for (int i=0; i<nstencils; ++i) {
|
||||
|
||||
memset(out, 0, outDesc.length*sizeof(float));
|
||||
|
||||
for (int j=0; j<sizes[i]; ++j, ++index, ++weight) {
|
||||
|
||||
float const * cv = ctrl + (*index)*ctrlDesc.stride;
|
||||
|
||||
for (int k=0; k<outDesc.length; ++k) {
|
||||
out[k] += cv[k] * (*weight);
|
||||
}
|
||||
}
|
||||
out += outDesc.stride;
|
||||
}
|
||||
|
||||
return nstencils;
|
||||
}
|
||||
|
||||
int
|
||||
CpuEvalStencilsController::_UpdateDerivs( CpuEvalStencilsContext * context ) {
|
||||
|
||||
int result=0;
|
||||
|
||||
Far::LimitStencilTables const * stencils = context->GetStencilTables();
|
||||
|
||||
int nstencils = stencils->GetNumStencils();
|
||||
if (not nstencils)
|
||||
return result;
|
||||
|
||||
VertexBufferDescriptor ctrlDesc = _currentBindState.controlDataDesc,
|
||||
duDesc = _currentBindState.outputDuDesc,
|
||||
dvDesc = _currentBindState.outputDvDesc;
|
||||
|
||||
// make sure that we have control data to work with
|
||||
if (not (ctrlDesc.CanEval(duDesc) and ctrlDesc.CanEval(dvDesc)))
|
||||
return 0;
|
||||
|
||||
float const * ctrl = _currentBindState.controlData + ctrlDesc.offset;
|
||||
|
||||
float * du = _currentBindState.outputUDeriv + duDesc.offset,
|
||||
* dv = _currentBindState.outputVDeriv + dvDesc.offset;
|
||||
|
||||
if ((not ctrl) or (not du) or (not dv))
|
||||
return result;
|
||||
|
||||
unsigned char const * sizes = &stencils->GetSizes().at(0);
|
||||
Far::Index const * index = &stencils->GetControlIndices().at(0);
|
||||
|
||||
float const * duweight = &stencils->GetDuWeights().at(0),
|
||||
* dvweight = &stencils->GetDvWeights().at(0);
|
||||
|
||||
for (int i=0; i<nstencils; ++i) {
|
||||
|
||||
memset(du, 0, duDesc.length*sizeof(float));
|
||||
memset(dv, 0, dvDesc.length*sizeof(float));
|
||||
|
||||
for (int j=0; j<sizes[i]; ++j, ++index, ++duweight, ++dvweight) {
|
||||
|
||||
float const * cv = ctrl + (*index)*ctrlDesc.stride;
|
||||
|
||||
for (int k=0; k<duDesc.length; ++k) {
|
||||
du[k] += cv[k] * (*duweight);
|
||||
dv[k] += cv[k] * (*dvweight);
|
||||
}
|
||||
}
|
||||
du += duDesc.stride;
|
||||
dv += dvDesc.stride;
|
||||
}
|
||||
|
||||
return nstencils;
|
||||
}
|
||||
|
||||
void
|
||||
CpuEvalStencilsController::Synchronize() {
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,209 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef FAR_CPU_EVALSTENCILS_CONTROLLER_H
|
||||
#define FAR_CPU_EVALSTENCILS_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/cpuEvalStencilsContext.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief CPU stencils evaluation controller
|
||||
///
|
||||
/// CpuStencilsController is a compute controller class to launch
|
||||
/// single threaded CPU stencil evalution kernels.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class CpuEvalStencilsController {
|
||||
public:
|
||||
|
||||
/// Constructor.
|
||||
CpuEvalStencilsController();
|
||||
|
||||
/// Destructor.
|
||||
~CpuEvalStencilsController();
|
||||
|
||||
|
||||
/// \brief Applies stencil weights to the control vertex data
|
||||
///
|
||||
/// Applies the stencil weights to the control vertex data to evaluate the
|
||||
/// interpolated limit positions at the parametric locations of the stencils
|
||||
///
|
||||
/// @param context the CpuEvalStencilsContext with the stencil weights
|
||||
///
|
||||
/// @param controlDataDesc vertex buffer descriptor for the control vertex data
|
||||
///
|
||||
/// @param controlVertices vertex buffer with the control vertices data
|
||||
///
|
||||
/// @param outputDataDesc vertex buffer descriptor for the output vertex data
|
||||
///
|
||||
/// @param outputData vertex buffer where the vertex data will be output
|
||||
///
|
||||
template<class CONTROL_BUFFER, class OUTPUT_BUFFER>
|
||||
int UpdateValues( CpuEvalStencilsContext * context,
|
||||
VertexBufferDescriptor const & controlDataDesc, CONTROL_BUFFER *controlVertices,
|
||||
VertexBufferDescriptor const & outputDataDesc, OUTPUT_BUFFER *outputData ) {
|
||||
|
||||
if (not context->GetStencilTables()->GetNumStencils())
|
||||
return 0;
|
||||
|
||||
bindControlData( controlDataDesc, controlVertices );
|
||||
|
||||
bindOutputData( outputDataDesc, outputData );
|
||||
|
||||
int n = _UpdateValues( context );
|
||||
|
||||
unbind();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/// \brief Applies derivative stencil weights to the control vertex data
|
||||
///
|
||||
/// Computes the U and V derivative stencils to the control vertex data at
|
||||
/// the parametric locations contained in each stencil
|
||||
///
|
||||
/// @param context the CpuEvalStencilsContext with the stencil weights
|
||||
///
|
||||
/// @param controlDataDesc vertex buffer descriptor for the control vertex data
|
||||
///
|
||||
/// @param controlVertices vertex buffer with the control vertices data
|
||||
///
|
||||
/// @param outputDuDesc vertex buffer descriptor for the U derivative output data
|
||||
///
|
||||
/// @param outputDuData output vertex buffer for the U derivative data
|
||||
///
|
||||
/// @param outputDvDesc vertex buffer descriptor for the V deriv output data
|
||||
///
|
||||
/// @param outputDvData output vertex buffer for the V derivative data
|
||||
///
|
||||
template<class CONTROL_BUFFER, class OUTPUT_BUFFER>
|
||||
int UpdateDerivs( CpuEvalStencilsContext * context,
|
||||
VertexBufferDescriptor const & controlDataDesc, CONTROL_BUFFER *controlVertices,
|
||||
VertexBufferDescriptor const & outputDuDesc, OUTPUT_BUFFER *outputDuData,
|
||||
VertexBufferDescriptor const & outputDvDesc, OUTPUT_BUFFER *outputDvData ) {
|
||||
|
||||
if (not context->GetStencilTables()->GetNumStencils())
|
||||
return 0;
|
||||
|
||||
bindControlData( controlDataDesc, controlVertices );
|
||||
|
||||
bindOutputDerivData( outputDuDesc, outputDuData, outputDvDesc, outputDvData );
|
||||
|
||||
int n = _UpdateDerivs( context );
|
||||
|
||||
unbind();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
protected:
|
||||
|
||||
/// \brief Binds control vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindControlData(VertexBufferDescriptor const & controlDataDesc, VERTEX_BUFFER *controlData ) {
|
||||
|
||||
_currentBindState.controlData = controlData ? controlData->BindCpuBuffer() : 0;
|
||||
_currentBindState.controlDataDesc = controlDataDesc;
|
||||
|
||||
}
|
||||
|
||||
/// \brief Binds output vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindOutputData( VertexBufferDescriptor const & outputDataDesc, VERTEX_BUFFER *outputData ) {
|
||||
|
||||
_currentBindState.outputData = outputData ? outputData->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputDataDesc = outputDataDesc;
|
||||
}
|
||||
|
||||
/// \brief Binds output derivative vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindOutputDerivData( VertexBufferDescriptor const & outputDuDesc, VERTEX_BUFFER *outputDu,
|
||||
VertexBufferDescriptor const & outputDvDesc, VERTEX_BUFFER *outputDv ) {
|
||||
|
||||
_currentBindState.outputUDeriv = outputDu ? outputDu ->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputVDeriv = outputDv ? outputDv->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputDuDesc = outputDuDesc;
|
||||
_currentBindState.outputDvDesc = outputDvDesc;
|
||||
}
|
||||
|
||||
/// \brief Unbinds any previously bound vertex and varying data buffers.
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int _UpdateValues( CpuEvalStencilsContext * context );
|
||||
int _UpdateDerivs( CpuEvalStencilsContext * context );
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : controlData(0), outputData(0), outputUDeriv(0), outputVDeriv(0) { }
|
||||
|
||||
void Reset() {
|
||||
controlData = outputData = outputUDeriv = outputVDeriv = NULL;
|
||||
controlDataDesc.Reset();
|
||||
outputDataDesc.Reset();
|
||||
outputDuDesc.Reset();
|
||||
outputDvDesc.Reset();
|
||||
}
|
||||
|
||||
// transient mesh data
|
||||
VertexBufferDescriptor controlDataDesc,
|
||||
outputDataDesc,
|
||||
outputDuDesc,
|
||||
outputDvDesc;
|
||||
|
||||
float * controlData,
|
||||
* outputData,
|
||||
* outputUDeriv,
|
||||
* outputVDeriv;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // FAR_CPU_EVALSTENCILS_CONTROLLER_H
|
148
opensubdiv/osd/cpuEvaluator.cpp
Normal file
148
opensubdiv/osd/cpuEvaluator.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cpuEvaluator.h"
|
||||
#include "../osd/cpuKernel.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CpuEvaluator::EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char * 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,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
float *dstDu,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
float *dstDv,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
const unsigned char * 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 != dstDuDesc.length) return false;
|
||||
if (srcDesc.length != dstDvDesc.length) return false;
|
||||
|
||||
CpuEvalStencils(src, srcDesc,
|
||||
dst, dstDesc,
|
||||
dstDu, dstDuDesc,
|
||||
dstDv, dstDvDesc,
|
||||
sizes, offsets, indices,
|
||||
weights, duWeights, dvWeights,
|
||||
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, float wu, float wv) {
|
||||
(void)wu;
|
||||
(void)wv;
|
||||
// TODO: derivatives.
|
||||
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 ++() {
|
||||
_p += _stride;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T *_p;
|
||||
int _length;
|
||||
int _stride;
|
||||
};
|
||||
|
||||
/* static */
|
||||
int
|
||||
CpuEvaluator::EvalPatches(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
PatchCoordArray const &patchCoords,
|
||||
Far::PatchTables const *patchTable) {
|
||||
src += srcDesc.offset;
|
||||
dst += dstDesc.offset;
|
||||
int count = 0;
|
||||
|
||||
// XXX: this implementaion is temporary.
|
||||
BufferAdapter<const float> srcT(src, srcDesc.length, srcDesc.stride);
|
||||
BufferAdapter<float> dstT(dst, dstDesc.length, dstDesc.stride);
|
||||
|
||||
for (size_t i = 0; i < patchCoords.size(); ++i) {
|
||||
PatchCoord const &coords = patchCoords[i];
|
||||
|
||||
patchTable->Evaluate(coords.handle, coords.s, coords.t,
|
||||
srcT, dstT);
|
||||
++count;
|
||||
++dstT;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
242
opensubdiv/osd/cpuEvaluator.h
Normal file
242
opensubdiv/osd/cpuEvaluator.h
Normal file
@ -0,0 +1,242 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_CPU_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_CPU_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
#include "../far/patchTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Coordinates set on a patch table
|
||||
/// XXX: this is a temporary structure, exists during Osd refactoring work.
|
||||
///
|
||||
struct PatchCoord {
|
||||
/// \brief Constructor
|
||||
///
|
||||
/// @param p patch handle
|
||||
///
|
||||
/// @param s parametric location on the patch
|
||||
///
|
||||
/// @param t parametric location on the patch
|
||||
///
|
||||
PatchCoord(Far::PatchTables::PatchHandle handle, float s, float t) :
|
||||
handle(handle), s(s), t(t) { }
|
||||
|
||||
Far::PatchTables::PatchHandle handle; ///< patch handle
|
||||
float s, t; ///< parametric location on patch
|
||||
};
|
||||
|
||||
typedef std::vector<PatchCoord> PatchCoordArray;
|
||||
|
||||
|
||||
class CpuEvaluator {
|
||||
public:
|
||||
/// \brief Generic static eval stencils 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 BindCpuBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTable stencil table to be applied.
|
||||
///
|
||||
/// @param instance not used in the cpu kernel
|
||||
/// (declared as a typed pointer to prevent
|
||||
/// undesirable template resolution)
|
||||
///
|
||||
/// @param deviceContext not used in the cpu kernel
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(SRC_BUFFER *srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
const CpuEvaluator *instance = NULL,
|
||||
void * deviceContext = NULL) {
|
||||
(void)instance; // unused
|
||||
(void)deviceContext; // unused
|
||||
|
||||
return EvalStencils(srcBuffer->BindCpuBuffer(),
|
||||
srcDesc,
|
||||
dstBuffer->BindCpuBuffer(),
|
||||
dstDesc,
|
||||
&stencilTable->GetSizes()[0],
|
||||
&stencilTable->GetOffsets()[0],
|
||||
&stencilTable->GetControlIndices()[0],
|
||||
&stencilTable->GetWeights()[0],
|
||||
/*start = */ 0,
|
||||
/*end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
/// stencil evaluate function.
|
||||
static bool EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end);
|
||||
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(SRC_BUFFER *srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
DST_BUFFER *dstDuBuffer,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
DST_BUFFER *dstDvBuffer,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
const CpuEvaluator *evaluator = NULL,
|
||||
void * deviceContext = NULL) {
|
||||
(void)evaluator; // unused
|
||||
(void)deviceContext; // unused
|
||||
|
||||
return EvalStencils(srcBuffer->BindCpuBuffer(),
|
||||
srcDesc,
|
||||
dstBuffer->BindCpuBuffer(),
|
||||
dstDesc,
|
||||
dstDuBuffer->BindCpuBuffer(),
|
||||
dstDuDesc,
|
||||
dstDvBuffer->BindCpuBuffer(),
|
||||
dstDvDesc,
|
||||
&stencilTable->GetSizes()[0],
|
||||
&stencilTable->GetOffsets()[0],
|
||||
&stencilTable->GetControlIndices()[0],
|
||||
&stencilTable->GetWeights()[0],
|
||||
&stencilTable->GetDuWeights()[0],
|
||||
&stencilTable->GetDvWeights()[0],
|
||||
/*start = */ 0,
|
||||
/*end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
static bool EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
float *dstDu,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
float *dstDv,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
const float * duWeights,
|
||||
const float * dvWeights,
|
||||
int start,
|
||||
int end);
|
||||
|
||||
/// \brief Generic limit eval function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently.
|
||||
///
|
||||
/// XXX: This interface is still work in progress. XXX
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param patchCoord array of locations to be evaluated.
|
||||
///
|
||||
/// @param patchTable Far::PatchTable
|
||||
///
|
||||
/// @param instanced not used in the cpu evaluator
|
||||
///
|
||||
/// @param deviceContext not used in the cpu evaluator
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER>
|
||||
static int EvalPatches(SRC_BUFFER *srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
PatchCoordArray const &patchCoords,
|
||||
Far::PatchTables const *patchTable,
|
||||
CpuEvaluator const *instance,
|
||||
void * deviceContext = NULL) {
|
||||
(void)instance; // unused
|
||||
(void)deviceContext; // unused
|
||||
|
||||
return EvalPatches(srcBuffer->BindCpuBuffer(),
|
||||
srcDesc,
|
||||
dstBuffer->BindCpuBuffer(),
|
||||
dstDesc,
|
||||
patchCoords,
|
||||
patchTable);
|
||||
}
|
||||
|
||||
/// \brief limit eval function.
|
||||
static int EvalPatches(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
PatchCoordArray const &patchCoords,
|
||||
Far::PatchTables const *patchTable);
|
||||
|
||||
/// \brief synchronize all asynchronous computation invoked on this device.
|
||||
static void Synchronize(void * /*deviceContext = NULL*/) {
|
||||
// nothing.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_CPU_EVALUATOR_H
|
@ -70,15 +70,15 @@ copy(float *dst, int dstIndex, const float *src,
|
||||
}
|
||||
|
||||
void
|
||||
CpuComputeStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end) {
|
||||
CpuEvalStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end) {
|
||||
|
||||
assert(start>=0 and start<end);
|
||||
|
||||
@ -125,21 +125,21 @@ CpuComputeStencils(float const * src,
|
||||
}
|
||||
|
||||
void
|
||||
CpuComputeStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
float * dstDu,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
float * dstDv,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
float const * duWeights,
|
||||
float const * dvWeights,
|
||||
int start, int end) {
|
||||
CpuEvalStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
float * dstDu,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
float * dstDv,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
unsigned char 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];
|
||||
|
@ -22,8 +22,8 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CPU_KERNEL_H
|
||||
#define OSD_CPU_KERNEL_H
|
||||
#ifndef OPENSUBDIV_OSD_CPU_KERNEL_H
|
||||
#define OPENSUBDIV_OSD_CPU_KERNEL_H
|
||||
|
||||
#include "../version.h"
|
||||
#include <cstring>
|
||||
@ -36,32 +36,32 @@ namespace Osd {
|
||||
struct VertexBufferDescriptor;
|
||||
|
||||
void
|
||||
CpuComputeStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end);
|
||||
CpuEvalStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end);
|
||||
|
||||
void
|
||||
CpuComputeStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
float * dstDu,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
float * dstDv,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
float const * duWeights,
|
||||
float const * dvWeights,
|
||||
int start, int end);
|
||||
CpuEvalStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
float * dstDu,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
float * dstDv,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
float const * duWeights,
|
||||
float const * dvWeights,
|
||||
int start, int end);
|
||||
|
||||
//
|
||||
// SIMD ICC optimization of the stencil kernel
|
||||
|
@ -37,7 +37,7 @@ namespace Osd {
|
||||
/// \brief Concrete vertex buffer class for cpu subvision.
|
||||
///
|
||||
/// CpuVertexBuffer implements the VertexBufferInterface. An instance
|
||||
/// of this buffer class can be passed to CpuComputeController
|
||||
/// of this buffer class can be passed to CpuEvaluator
|
||||
///
|
||||
class CpuVertexBuffer {
|
||||
public:
|
||||
|
@ -1,227 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
#include "../osd/cudaComputeContext.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
template <class T> void *
|
||||
createCudaBuffer(std::vector<T> const & src) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class CudaComputeContext::CudaStencilTables {
|
||||
|
||||
public:
|
||||
explicit CudaStencilTables(Far::StencilTables const & stencilTables) {
|
||||
_numStencils = stencilTables.GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCudaBuffer(stencilTables.GetSizes());
|
||||
_offsets = createCudaBuffer(stencilTables.GetOffsets());
|
||||
_indices = createCudaBuffer(stencilTables.GetControlIndices());
|
||||
_weights = createCudaBuffer(stencilTables.GetWeights());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
~CudaStencilTables() {
|
||||
if (_sizes) { cudaFree(_sizes); }
|
||||
if (_offsets) { cudaFree(_offsets); }
|
||||
if (_indices) { cudaFree(_indices); }
|
||||
if (_weights) { cudaFree(_weights); }
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return _sizes and _offsets and _indices and _weights;
|
||||
}
|
||||
|
||||
void * GetSizes() const {
|
||||
return _sizes;
|
||||
}
|
||||
|
||||
void * GetOffsets() const {
|
||||
return _offsets;
|
||||
}
|
||||
|
||||
void * GetIndices() const {
|
||||
return _indices;
|
||||
}
|
||||
|
||||
void * GetWeights() const {
|
||||
return _weights;
|
||||
}
|
||||
|
||||
int GetNumStencils() const {
|
||||
return _numStencils;
|
||||
}
|
||||
|
||||
private:
|
||||
void * _sizes,
|
||||
* _offsets,
|
||||
* _indices,
|
||||
* _weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CudaComputeContext::CudaComputeContext(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables) :
|
||||
_vertexStencilTables(0), _varyingStencilTables(0),
|
||||
_numControlVertices(0) {
|
||||
|
||||
if (vertexStencilTables) {
|
||||
_vertexStencilTables = new CudaStencilTables(*vertexStencilTables);
|
||||
_numControlVertices = vertexStencilTables->GetNumControlVertices();
|
||||
}
|
||||
|
||||
if (varyingStencilTables) {
|
||||
_varyingStencilTables = new CudaStencilTables(*varyingStencilTables);
|
||||
|
||||
if (_numControlVertices) {
|
||||
assert(_numControlVertices ==
|
||||
varyingStencilTables->GetNumControlVertices());
|
||||
} else {
|
||||
_numControlVertices = varyingStencilTables->GetNumControlVertices();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CudaComputeContext::~CudaComputeContext() {
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
CudaComputeContext::HasVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
CudaComputeContext::HasVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
int
|
||||
CudaComputeContext::GetNumStencilsInVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
int
|
||||
CudaComputeContext::GetNumStencilsInVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVertexStencilTablesSizes() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetSizes() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVertexStencilTablesOffsets() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetOffsets() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVertexStencilTablesIndices() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetIndices() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVertexStencilTablesWeights() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetWeights() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVaryingStencilTablesSizes() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetSizes() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVaryingStencilTablesOffsets() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetOffsets() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVaryingStencilTablesIndices() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetIndices() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVaryingStencilTablesWeights() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetWeights() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CudaComputeContext *
|
||||
CudaComputeContext::Create(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
CudaComputeContext *result =
|
||||
new CudaComputeContext(vertexStencilTables, varyingStencilTables);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,134 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CUDA_COMPUTE_CONTEXT_H
|
||||
#define OSD_CUDA_COMPUTE_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far { class StencilTables; }
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief CUDA Refine Context
|
||||
///
|
||||
/// The CUDA implementation of the Refine module contextual functionality.
|
||||
///
|
||||
/// Contexts interface the serialized topological data pertaining to the
|
||||
/// geometric primitives with the capabilities of the selected discrete
|
||||
/// compute device.
|
||||
///
|
||||
class CudaComputeContext : public NonCopyable<CudaComputeContext> {
|
||||
|
||||
public:
|
||||
/// Creates an CudaComputeContext instance
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
/// @param deviceContext (not used)
|
||||
///
|
||||
static CudaComputeContext * Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Destructor
|
||||
virtual ~CudaComputeContext();
|
||||
|
||||
/// Returns true if the Context has a 'vertex' interpolation stencil table
|
||||
bool HasVertexStencilTables() const;
|
||||
|
||||
/// Returns true if the Context has a 'varying' interpolation stencil table
|
||||
bool HasVaryingStencilTables() const;
|
||||
|
||||
/// Returns the number of control vertices
|
||||
int GetNumControlVertices() const {
|
||||
return _numControlVertices;
|
||||
}
|
||||
|
||||
/// Returns the number of stencils in vertex stencil tables
|
||||
int GetNumStencilsInVertexStencilTables() const;
|
||||
|
||||
/// Returns the number of stencils in varying stencil tables
|
||||
int GetNumStencilsInVaryingStencilTables() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil sizes
|
||||
void * GetVertexStencilTablesSizes() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil offsets
|
||||
void * GetVertexStencilTablesOffsets() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil indices
|
||||
void * GetVertexStencilTablesIndices() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil weights
|
||||
void * GetVertexStencilTablesWeights() const;
|
||||
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil sizes
|
||||
void * GetVaryingStencilTablesSizes() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil offsets
|
||||
void * GetVaryingStencilTablesOffsets() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil indices
|
||||
void * GetVaryingStencilTablesIndices() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil weights
|
||||
void * GetVaryingStencilTablesWeights() const;
|
||||
|
||||
|
||||
protected:
|
||||
explicit CudaComputeContext(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables);
|
||||
|
||||
private:
|
||||
class CudaStencilTables;
|
||||
|
||||
CudaStencilTables * _vertexStencilTables,
|
||||
* _varyingStencilTables;
|
||||
|
||||
int _numControlVertices;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_CUDA_COMPUTE_CONTEXT_H
|
@ -1,124 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cudaComputeController.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
|
||||
extern "C" {
|
||||
void CudaComputeStencils(const float *src,
|
||||
float *dst,
|
||||
int length,
|
||||
int srcStride,
|
||||
int dstStride,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end);
|
||||
}
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
void
|
||||
CudaComputeController::ApplyStencilTableKernel(
|
||||
ComputeContext const *context) const {
|
||||
|
||||
assert(context);
|
||||
|
||||
if (context->HasVertexStencilTables() and _currentBindState.vertexBuffer) {
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.vertexDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += context->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
int start = 0;
|
||||
int end = context->GetNumStencilsInVertexStencilTables();
|
||||
|
||||
float const * src = _currentBindState.vertexBuffer;
|
||||
float * dst = _currentBindState.vertexBuffer;
|
||||
|
||||
if (end > start) {
|
||||
CudaComputeStencils(src + srcDesc.offset,
|
||||
dst + dstDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
dstDesc.stride,
|
||||
(unsigned char const *)context->GetVertexStencilTablesSizes(),
|
||||
(int const *)context->GetVertexStencilTablesOffsets(),
|
||||
(int const *)context->GetVertexStencilTablesIndices(),
|
||||
(float const *)context->GetVertexStencilTablesWeights(),
|
||||
start,
|
||||
end);
|
||||
}
|
||||
}
|
||||
|
||||
if (context->HasVaryingStencilTables() and _currentBindState.varyingBuffer) {
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.varyingDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += context->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
int start = 0;
|
||||
int end = context->GetNumStencilsInVaryingStencilTables();
|
||||
|
||||
float const * src = _currentBindState.varyingBuffer;
|
||||
float * dst = _currentBindState.varyingBuffer;
|
||||
|
||||
if (end > start) {
|
||||
CudaComputeStencils(src + srcDesc.offset,
|
||||
dst + dstDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
dstDesc.stride,
|
||||
(unsigned char const *)context->GetVaryingStencilTablesSizes(),
|
||||
(int const *)context->GetVaryingStencilTablesOffsets(),
|
||||
(int const *)context->GetVaryingStencilTablesIndices(),
|
||||
(float const *)context->GetVaryingStencilTablesWeights(),
|
||||
start,
|
||||
end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CudaComputeController::CudaComputeController() {
|
||||
}
|
||||
|
||||
CudaComputeController::~CudaComputeController() {
|
||||
}
|
||||
|
||||
void
|
||||
CudaComputeController::Synchronize() {
|
||||
|
||||
cudaThreadSynchronize();
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,180 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CUDA_COMPUTE_CONTROLLER_H
|
||||
#define OSD_CUDA_COMPUTE_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/cudaComputeContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Compute controller for launching CUDA subdivision kernels.
|
||||
///
|
||||
/// CudaComputeController is a compute controller class to launch
|
||||
/// Cuda subdivision kernels. It requires CudaVertexBufferInterface
|
||||
/// as arguments of Refine function.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class CudaComputeController {
|
||||
public:
|
||||
typedef CudaComputeContext ComputeContext;
|
||||
|
||||
/// Constructor.
|
||||
CudaComputeController();
|
||||
|
||||
/// Destructor.
|
||||
~CudaComputeController();
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CudaContext to apply refinement operations to
|
||||
///
|
||||
/// @param batches Vector of batches of vertices organized by operative
|
||||
/// kernel
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param vertexDesc The descriptor of vertex elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
/// @param varyingBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param varyingDesc The descriptor of varying elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void Compute( CudaComputeContext const * context,
|
||||
VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc=NULL,
|
||||
VertexBufferDescriptor const * varyingDesc=NULL ){
|
||||
|
||||
bind(vertexBuffer, varyingBuffer, vertexDesc, varyingDesc);
|
||||
|
||||
ApplyStencilTableKernel(context);
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CudaContext to apply refinement operations to
|
||||
///
|
||||
/// @param batches Vector of batches of vertices organized by operative
|
||||
/// kernel
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
template<class VERTEX_BUFFER>
|
||||
void Compute(CudaComputeContext const * context,
|
||||
VERTEX_BUFFER *vertexBuffer) {
|
||||
|
||||
Compute<VERTEX_BUFFER>(context, vertexBuffer, (VERTEX_BUFFER*)0);
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
protected:
|
||||
|
||||
void ApplyStencilTableKernel(ComputeContext const *context) const;
|
||||
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void bind( VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc,
|
||||
VertexBufferDescriptor const * varyingDesc ) {
|
||||
|
||||
// if the vertex buffer descriptor is specified, use it.
|
||||
// otherwise, assumes the data is tightly packed in the vertex buffer.
|
||||
if (vertexDesc) {
|
||||
_currentBindState.vertexDesc = *vertexDesc;
|
||||
} else {
|
||||
int numElements = vertexBuffer ? vertexBuffer->GetNumElements() : 0;
|
||||
_currentBindState.vertexDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
if (varyingDesc) {
|
||||
_currentBindState.varyingDesc = *varyingDesc;
|
||||
} else {
|
||||
int numElements = varyingBuffer ? varyingBuffer->GetNumElements() : 0;
|
||||
_currentBindState.varyingDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
_currentBindState.vertexBuffer = vertexBuffer ?
|
||||
static_cast<float*>(vertexBuffer->BindCudaBuffer()) : 0;
|
||||
_currentBindState.varyingBuffer = varyingBuffer ?
|
||||
static_cast<float*>(varyingBuffer->BindCudaBuffer()) : 0;
|
||||
}
|
||||
|
||||
/// Unbinds any previously bound vertex and varying data buffers.
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of the vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : vertexBuffer(NULL), varyingBuffer(NULL) {}
|
||||
|
||||
void Reset() {
|
||||
vertexBuffer = varyingBuffer = NULL;
|
||||
vertexDesc.Reset();
|
||||
varyingDesc.Reset();
|
||||
}
|
||||
|
||||
float * vertexBuffer, // cuda buffers
|
||||
* varyingBuffer;
|
||||
|
||||
VertexBufferDescriptor vertexDesc,
|
||||
varyingDesc;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_CUDA_COMPUTE_CONTROLLER_H
|
124
opensubdiv/osd/cudaEvaluator.cpp
Normal file
124
opensubdiv/osd/cudaEvaluator.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cudaEvaluator.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <vector>
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
extern "C" {
|
||||
void CudaEvalStencils(const float *src,
|
||||
float *dst,
|
||||
int length,
|
||||
int srcStride,
|
||||
int dstStride,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end);
|
||||
}
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
template <class T> void *
|
||||
createCudaBuffer(std::vector<T> const & src) {
|
||||
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;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CudaStencilTables::CudaStencilTables(Far::StencilTables const *stencilTables) {
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCudaBuffer(stencilTables->GetSizes());
|
||||
_offsets = createCudaBuffer(stencilTables->GetOffsets());
|
||||
_indices = createCudaBuffer(stencilTables->GetControlIndices());
|
||||
_weights = createCudaBuffer(stencilTables->GetWeights());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CudaStencilTables::~CudaStencilTables() {
|
||||
if (_sizes) cudaFree(_sizes);
|
||||
if (_offsets) cudaFree(_offsets);
|
||||
if (_indices) cudaFree(_indices);
|
||||
if (_weights) cudaFree(_weights);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CudaEvaluator::EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end) {
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
dst + dstDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
dstDesc.stride,
|
||||
sizes, offsets, indices, weights,
|
||||
start, end);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
CudaEvaluator::Synchronize(void * /*deviceContext*/) {
|
||||
cudaThreadSynchronize();
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
148
opensubdiv/osd/cudaEvaluator.h
Normal file
148
opensubdiv/osd/cudaEvaluator.h
Normal file
@ -0,0 +1,148 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_CUDA_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_CUDA_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <vector>
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief CUDA stencil tables
|
||||
///
|
||||
/// This class is a cuda buffer representation of Far::StencilTables.
|
||||
///
|
||||
/// CudaComputeKernel consumes this table to apply stencils
|
||||
///
|
||||
///
|
||||
class CudaStencilTables {
|
||||
public:
|
||||
static CudaStencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
void *deviceContext = NULL) {
|
||||
(void)deviceContext; // unused
|
||||
return new CudaStencilTables(stencilTables);
|
||||
}
|
||||
|
||||
explicit CudaStencilTables(Far::StencilTables const *stencilTables);
|
||||
~CudaStencilTables();
|
||||
|
||||
// interfaces needed for CudaCompute
|
||||
void *GetSizesBuffer() const { return _sizes; }
|
||||
void *GetOffsetsBuffer() const { return _offsets; }
|
||||
void *GetIndicesBuffer() const { return _indices; }
|
||||
void *GetWeightsBuffer() const { return _weights; }
|
||||
int GetNumStencils() const { return _numStencils; }
|
||||
|
||||
private:
|
||||
void * _sizes,
|
||||
* _offsets,
|
||||
* _indices,
|
||||
* _weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class CudaEvaluator {
|
||||
public:
|
||||
/// \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 BindCudaBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCudaBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTables stencil table to be applied. The table must have
|
||||
/// Cuda memory interfaces.
|
||||
///
|
||||
/// @param instance not used in the CudaEvaluator
|
||||
///
|
||||
/// @param deviceContext not used in the CudaEvaluator
|
||||
///
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
const void *instance = NULL,
|
||||
void * deviceContext = NULL) {
|
||||
|
||||
(void)instance; // unused
|
||||
(void)deviceContext; // unused
|
||||
return EvalStencils(srcVertexBuffer->BindCudaBuffer(),
|
||||
srcDesc,
|
||||
dstVertexBuffer->BindCudaBuffer(),
|
||||
dstDesc,
|
||||
(unsigned char const *)stencilTable->GetSizesBuffer(),
|
||||
(int const *)stencilTable->GetOffsetsBuffer(),
|
||||
(int const *)stencilTable->GetIndicesBuffer(),
|
||||
(float const *)stencilTable->GetWeightsBuffer(),
|
||||
/*start = */ 0,
|
||||
/*end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
static bool EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end);
|
||||
|
||||
static void Synchronize(void *deviceContext = NULL);
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_CUDA_EVALUATOR_H
|
@ -257,17 +257,17 @@ __global__ void computeStencilsNv_v4(float const *__restrict cvs,
|
||||
|
||||
extern "C" {
|
||||
|
||||
void CudaComputeStencils(const float *src,
|
||||
float *dst,
|
||||
int length,
|
||||
int srcStride,
|
||||
int dstStride,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end)
|
||||
void CudaEvalStencils(const float *src,
|
||||
float *dst,
|
||||
int length,
|
||||
int srcStride,
|
||||
int dstStride,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end)
|
||||
{
|
||||
// assert(cvs and dst and sizes and offsets and indices and weights and (end>=start));
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace Osd {
|
||||
/// \brief Concrete vertex buffer class for Cuda subvision.
|
||||
///
|
||||
/// CudaVertexBuffer implements CudaVertexBufferInterface.
|
||||
/// An instance of this buffer class can be passed to CudaComputeController
|
||||
/// An instance of this buffer class can be passed to CudaEvaluator
|
||||
///
|
||||
class CudaVertexBuffer {
|
||||
|
||||
|
@ -1,284 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
#include "../osd/d3d11ComputeContext.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <D3D11.h>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct D3D11Table {
|
||||
|
||||
D3D11Table() : buffer(0), srv(0) { }
|
||||
|
||||
~D3D11Table() {
|
||||
SAFE_RELEASE(buffer);
|
||||
SAFE_RELEASE(srv);
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return (buffer and srv);
|
||||
}
|
||||
|
||||
template <class T> void initialize(std::vector<T> const & src,
|
||||
DXGI_FORMAT format, ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
size_t size = src.size()*sizeof(T);
|
||||
|
||||
if (size==0) {
|
||||
buffer = 0;
|
||||
srv = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ID3D11Device *device = 0;
|
||||
deviceContext->GetDevice(&device);
|
||||
assert(device);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)src.size();
|
||||
|
||||
hr = device->CreateShaderResourceView(buffer, &srvd, &srv);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Error creating compute table shader resource view\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11Buffer * buffer;
|
||||
ID3D11ShaderResourceView * srv;
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class D3D11ComputeContext::D3D11StencilTables {
|
||||
|
||||
public:
|
||||
|
||||
D3D11StencilTables(Far::StencilTables const & stencilTables,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
_numStencils = stencilTables.GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
// convert unsigned char sizes buffer to ints
|
||||
// (HLSL does not have uint8 type)
|
||||
std::vector<int> const sizes(stencilTables.GetSizes().begin(),
|
||||
stencilTables.GetSizes().end());
|
||||
|
||||
_sizes.initialize(sizes,
|
||||
DXGI_FORMAT_R32_SINT,
|
||||
deviceContext);
|
||||
_offsets.initialize(stencilTables.GetOffsets(),
|
||||
DXGI_FORMAT_R32_SINT,
|
||||
deviceContext);
|
||||
_indices.initialize(stencilTables.GetControlIndices(),
|
||||
DXGI_FORMAT_R32_SINT,
|
||||
deviceContext);
|
||||
_weights.initialize(stencilTables.GetWeights(),
|
||||
DXGI_FORMAT_R32_FLOAT,
|
||||
deviceContext);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return _sizes.IsValid() and _offsets.IsValid() and
|
||||
_indices.IsValid() and _weights.IsValid();
|
||||
}
|
||||
|
||||
D3D11Table const & GetSizes() const {
|
||||
return _sizes;
|
||||
}
|
||||
|
||||
D3D11Table const & GetOffsets() const {
|
||||
return _offsets;
|
||||
}
|
||||
|
||||
D3D11Table const & GetIndices() const {
|
||||
return _indices;
|
||||
}
|
||||
|
||||
D3D11Table const & GetWeights() const {
|
||||
return _weights;
|
||||
}
|
||||
|
||||
int GetNumStencils() const {
|
||||
return _numStencils;
|
||||
}
|
||||
|
||||
void Bind(ID3D11DeviceContext * deviceContext) const {
|
||||
ID3D11ShaderResourceView *SRViews[] = {
|
||||
_sizes.srv,
|
||||
_offsets.srv,
|
||||
_indices.srv,
|
||||
_weights.srv
|
||||
};
|
||||
deviceContext->CSSetShaderResources(1, 4, SRViews); // t1-t4
|
||||
}
|
||||
|
||||
static void Unbind(ID3D11DeviceContext * deviceContext) {
|
||||
ID3D11ShaderResourceView *SRViews[] = { 0, 0, 0, 0 };
|
||||
deviceContext->CSSetShaderResources(1, 4, SRViews);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
D3D11Table _sizes,
|
||||
_offsets,
|
||||
_indices,
|
||||
_weights;
|
||||
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
D3D11ComputeContext::D3D11ComputeContext(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
ID3D11DeviceContext *deviceContext) :
|
||||
_vertexStencilTables(0), _varyingStencilTables(0),
|
||||
_numControlVertices(0) {
|
||||
|
||||
if (vertexStencilTables) {
|
||||
_vertexStencilTables =
|
||||
new D3D11StencilTables(*vertexStencilTables, deviceContext);
|
||||
_numControlVertices = vertexStencilTables->GetNumControlVertices();
|
||||
}
|
||||
|
||||
if (varyingStencilTables) {
|
||||
_varyingStencilTables =
|
||||
new D3D11StencilTables(*varyingStencilTables, deviceContext);
|
||||
|
||||
if (_numControlVertices) {
|
||||
assert(_numControlVertices==varyingStencilTables->GetNumControlVertices());
|
||||
} else {
|
||||
_numControlVertices = varyingStencilTables->GetNumControlVertices();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3D11ComputeContext::~D3D11ComputeContext() {
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
D3D11ComputeContext::HasVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
D3D11ComputeContext::HasVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
int
|
||||
D3D11ComputeContext::GetNumStencilsInVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
int
|
||||
D3D11ComputeContext::GetNumStencilsInVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
D3D11ComputeContext::BindVertexStencilTables(ID3D11DeviceContext *deviceContext) const {
|
||||
if (_vertexStencilTables) {
|
||||
_vertexStencilTables->Bind(deviceContext);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
D3D11ComputeContext::BindVaryingStencilTables(ID3D11DeviceContext *deviceContext) const {
|
||||
if (_varyingStencilTables) {
|
||||
_varyingStencilTables->Bind(deviceContext);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
D3D11ComputeContext::UnbindStencilTables(ID3D11DeviceContext *deviceContext) const {
|
||||
D3D11StencilTables::Unbind(deviceContext);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
D3D11ComputeContext *
|
||||
D3D11ComputeContext::Create(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
D3D11ComputeContext *result =
|
||||
new D3D11ComputeContext(vertexStencilTables, varyingStencilTables,
|
||||
deviceContext);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,128 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_D3D11_COMPUTE_CONTEXT_H
|
||||
#define OSD_D3D11_COMPUTE_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far{ class StencilTables; }
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief D3D Refine Context
|
||||
///
|
||||
/// The D3D implementation of the Refine module contextual functionality.
|
||||
///
|
||||
/// Contexts interface the serialized topological data pertaining to the
|
||||
/// geometric primitives with the capabilities of the selected discrete
|
||||
/// compute device.
|
||||
///
|
||||
class D3D11ComputeContext : public NonCopyable<D3D11ComputeContext> {
|
||||
public:
|
||||
|
||||
/// Creates an D3D11ComputeContext instance
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
/// @param deviceContext The D3D device
|
||||
///
|
||||
static D3D11ComputeContext * Create(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Destructor
|
||||
virtual ~D3D11ComputeContext();
|
||||
|
||||
/// Returns true if the Context has a 'vertex' interpolation stencil table
|
||||
bool HasVertexStencilTables() const;
|
||||
|
||||
/// Returns true if the Context has a 'varying' interpolation stencil table
|
||||
bool HasVaryingStencilTables() const;
|
||||
|
||||
/// Returns the number of control vertices
|
||||
int GetNumControlVertices() const {
|
||||
return _numControlVertices;
|
||||
}
|
||||
|
||||
/// Returns the number of stencils in vertex stencil table
|
||||
int GetNumStencilsInVertexStencilTables() const;
|
||||
|
||||
/// Returns the number of stencils in varying stencil table
|
||||
int GetNumStencilsInVaryingStencilTables() const;
|
||||
|
||||
/// Binds D3D11 buffers containing stencils for 'vertex' interpolation
|
||||
///
|
||||
/// @param deviceContext The D3D device
|
||||
///
|
||||
void BindVertexStencilTables(ID3D11DeviceContext *deviceContext) const;
|
||||
|
||||
/// Binds D3D11 buffers containing stencils for 'varying' interpolation
|
||||
///
|
||||
/// @param deviceContext The D3D device
|
||||
///
|
||||
void BindVaryingStencilTables(ID3D11DeviceContext *deviceContext) const;
|
||||
|
||||
/// Unbinds D3D11 stencil buffers
|
||||
///
|
||||
/// @param deviceContext The D3D device
|
||||
///
|
||||
void UnbindStencilTables(ID3D11DeviceContext *deviceContext) const;
|
||||
|
||||
protected:
|
||||
|
||||
explicit D3D11ComputeContext(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
private:
|
||||
|
||||
class D3D11StencilTables;
|
||||
|
||||
D3D11StencilTables * _vertexStencilTables,
|
||||
* _varyingStencilTables;
|
||||
|
||||
int _numControlVertices;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_D3D11_COMPUTE_CONTEXT_H
|
@ -1,340 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/d3d11ComputeController.h"
|
||||
#include "../far/error.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
#define INITGUID // for IID_ID3D11ShaderReflection
|
||||
#include <D3D11.h>
|
||||
#include <D3D11shader.h>
|
||||
#include <D3Dcompiler.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class D3D11ComputeController::KernelBundle :
|
||||
NonCopyable<D3D11ComputeController::KernelBundle> {
|
||||
|
||||
public:
|
||||
|
||||
KernelBundle() :
|
||||
_computeShader(0),
|
||||
_classLinkage(0),
|
||||
_singleBufferKernel(0),
|
||||
_separateBufferKernel(0),
|
||||
_uniformArgs(0),
|
||||
_workGroupSize(64) { }
|
||||
|
||||
~KernelBundle() {
|
||||
SAFE_RELEASE(_computeShader);
|
||||
SAFE_RELEASE(_classLinkage);
|
||||
SAFE_RELEASE(_singleBufferKernel);
|
||||
SAFE_RELEASE(_separateBufferKernel);
|
||||
SAFE_RELEASE(_uniformArgs);
|
||||
}
|
||||
|
||||
|
||||
bool Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
// XXX: only store srcDesc.
|
||||
// this is ok since currently this kernel doesn't get called with
|
||||
// different strides for src and dst. This function will be
|
||||
// refactored soon.
|
||||
_desc = VertexBufferDescriptor(0, srcDesc.length, srcDesc.stride);
|
||||
|
||||
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
|
||||
#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);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ApplyStencilTableKernel(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
int start,
|
||||
int end,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
int count = end - start;
|
||||
if (count <= 0) return;
|
||||
|
||||
KernelUniformArgs args;
|
||||
args.start = start;
|
||||
args.end = end;
|
||||
args.srcOffset = srcDesc.offset;
|
||||
args.dstOffset = dstDesc.offset;
|
||||
|
||||
if (not _uniformArgs) {
|
||||
ID3D11Device *device = NULL;
|
||||
deviceContext->GetDevice(&device);
|
||||
assert(device);
|
||||
|
||||
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);
|
||||
}
|
||||
assert(_uniformArgs);
|
||||
|
||||
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
|
||||
|
||||
deviceContext->CSSetShader(_computeShader, &_singleBufferKernel, 1);
|
||||
deviceContext->Dispatch((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
}
|
||||
|
||||
struct Match {
|
||||
|
||||
Match(VertexBufferDescriptor const & d) : desc(d) { }
|
||||
|
||||
bool operator() (KernelBundle const * kernel) {
|
||||
return (desc.length==kernel->_desc.length and
|
||||
desc.stride==kernel->_desc.stride);
|
||||
}
|
||||
|
||||
VertexBufferDescriptor desc;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
ID3D11ComputeShader * _computeShader;
|
||||
|
||||
ID3D11ClassLinkage * _classLinkage;
|
||||
|
||||
ID3D11ClassInstance * _singleBufferKernel;
|
||||
ID3D11ClassInstance * _separateBufferKernel;
|
||||
|
||||
ID3D11Buffer * _uniformArgs; // uniform paramaeters for kernels
|
||||
|
||||
VertexBufferDescriptor _desc; // primvar buffer descriptor
|
||||
|
||||
int _workGroupSize;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void
|
||||
D3D11ComputeController::Synchronize() {
|
||||
|
||||
if (not _query) {
|
||||
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));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
D3D11ComputeController::KernelBundle const *
|
||||
D3D11ComputeController::getKernel(VertexBufferDescriptor const &desc) {
|
||||
|
||||
KernelRegistry::iterator it =
|
||||
std::find_if(_kernelRegistry.begin(), _kernelRegistry.end(),
|
||||
KernelBundle::Match(desc));
|
||||
|
||||
if (it != _kernelRegistry.end()) {
|
||||
return *it;
|
||||
} else {
|
||||
assert(_deviceContext);
|
||||
KernelBundle * kernelBundle = new KernelBundle();
|
||||
kernelBundle->Compile(desc, desc, _deviceContext);
|
||||
_kernelRegistry.push_back(kernelBundle);
|
||||
return kernelBundle;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
D3D11ComputeController::bindBuffer() {
|
||||
|
||||
// Unbind the vertexBuffer from the input assembler
|
||||
ID3D11Buffer *NULLBuffer = 0;
|
||||
UINT voffset = 0, vstride = 0;
|
||||
_deviceContext->IASetVertexBuffers(0, 1, &NULLBuffer, &voffset, &vstride);
|
||||
|
||||
// Unbind the vertexBuffer from the vertex shader
|
||||
ID3D11ShaderResourceView *NULLSRV = 0;
|
||||
_deviceContext->VSSetShaderResources(0, 1, &NULLSRV);
|
||||
|
||||
if (_currentBindState.buffer)
|
||||
_deviceContext->CSSetUnorderedAccessViews(0, 1, &_currentBindState.buffer, 0); // u0
|
||||
}
|
||||
|
||||
void
|
||||
D3D11ComputeController::unbindBuffer() {
|
||||
assert(_deviceContext);
|
||||
ID3D11UnorderedAccessView *UAViews[] = { 0 };
|
||||
_deviceContext->CSSetUnorderedAccessViews(0, 1, UAViews, 0); // u0
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
D3D11ComputeController::ApplyStencilTableKernel(
|
||||
D3D11ComputeContext const *context, int numStencils) const {
|
||||
|
||||
assert(context);
|
||||
|
||||
// XXXX manuelk messy const drop forced by D3D API - could use better solution
|
||||
D3D11ComputeController::KernelBundle * bundle =
|
||||
const_cast<D3D11ComputeController::KernelBundle *>(_currentBindState.kernelBundle);
|
||||
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.desc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += context->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
bundle->ApplyStencilTableKernel(srcDesc,
|
||||
dstDesc,
|
||||
0,
|
||||
numStencils,
|
||||
_deviceContext);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
D3D11ComputeController::D3D11ComputeController(
|
||||
ID3D11DeviceContext *deviceContext)
|
||||
: _deviceContext(deviceContext), _query(0) {
|
||||
}
|
||||
|
||||
D3D11ComputeController::~D3D11ComputeController() {
|
||||
|
||||
for (KernelRegistry::iterator it = _kernelRegistry.begin();
|
||||
it != _kernelRegistry.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
SAFE_RELEASE(_query);
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,213 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_D3D11_COMPUTE_CONTROLLER_H
|
||||
#define OSD_D3D11_COMPUTE_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/d3d11ComputeContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct ID3D11DeviceContext;
|
||||
struct ID3D11Query;
|
||||
struct ID3D11UnorderedAccessView;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Compute controller for launching D3D11 Compute subdivision kernels.
|
||||
///
|
||||
/// D3D11ComputeController is a compute controller class to launch
|
||||
/// D3D11Compute transfrom feedback subdivision kernels. It requires
|
||||
/// GLVertexBufferInterface as arguments of Refine function.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class D3D11ComputeController {
|
||||
public:
|
||||
typedef D3D11ComputeContext ComputeContext;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param deviceContext a valid instanciated D3D11 device context
|
||||
///
|
||||
D3D11ComputeController(ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Destructor.
|
||||
~D3D11ComputeController();
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The D3D11Context to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param vertexDesc The descriptor of vertex elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
/// @param varyingBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param varyingDesc The descriptor of varying elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void Compute( D3D11ComputeContext const * context,
|
||||
VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc=NULL,
|
||||
VertexBufferDescriptor const * varyingDesc=NULL ){
|
||||
|
||||
if (vertexBuffer) {
|
||||
bind(vertexBuffer, vertexDesc);
|
||||
|
||||
context->BindVertexStencilTables(_deviceContext);
|
||||
|
||||
ApplyStencilTableKernel(
|
||||
context, context->GetNumStencilsInVertexStencilTables());
|
||||
}
|
||||
|
||||
if (varyingBuffer) {
|
||||
bind(varyingBuffer, varyingDesc);
|
||||
|
||||
context->BindVaryingStencilTables(_deviceContext);
|
||||
|
||||
ApplyStencilTableKernel(
|
||||
context, context->GetNumStencilsInVaryingStencilTables());
|
||||
}
|
||||
|
||||
context->UnbindStencilTables(_deviceContext);
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The D3D11Context to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
template<class VERTEX_BUFFER>
|
||||
void Compute(D3D11ComputeContext const * context,
|
||||
VERTEX_BUFFER *vertexBuffer) {
|
||||
|
||||
Compute<VERTEX_BUFFER>(context, vertexBuffer, (VERTEX_BUFFER*)0);
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
protected:
|
||||
|
||||
void ApplyStencilTableKernel(ComputeContext const *context,
|
||||
int numStencils) const;
|
||||
|
||||
template<class BUFFER>
|
||||
void bind( BUFFER * buffer,
|
||||
VertexBufferDescriptor const * desc ) {
|
||||
|
||||
assert(buffer);
|
||||
|
||||
// if the vertex buffer descriptor is specified, use it
|
||||
// otherwise, assumes the data is tightly packed in the vertex buffer.
|
||||
if (desc) {
|
||||
_currentBindState.desc = *desc;
|
||||
} else {
|
||||
int numElements = buffer ? buffer->GetNumElements() : 0;
|
||||
_currentBindState.desc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
_currentBindState.buffer = buffer->BindD3D11UAV(_deviceContext);
|
||||
|
||||
_currentBindState.kernelBundle = getKernel(_currentBindState.desc);
|
||||
|
||||
bindBuffer();
|
||||
}
|
||||
|
||||
|
||||
// Unbinds any previously bound vertex and varying data buffers.
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
unbindBuffer();
|
||||
}
|
||||
|
||||
// binds the primvar data buffer
|
||||
void bindBuffer();
|
||||
|
||||
// unbinds the primvar data buffer
|
||||
void unbindBuffer();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
ID3D11DeviceContext *_deviceContext;
|
||||
ID3D11Query *_query;
|
||||
|
||||
class KernelBundle;
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of the vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : buffer(0), kernelBundle(0) { }
|
||||
|
||||
void Reset() {
|
||||
buffer = 0;
|
||||
desc.Reset();
|
||||
kernelBundle = 0;
|
||||
}
|
||||
|
||||
ID3D11UnorderedAccessView * buffer;
|
||||
|
||||
VertexBufferDescriptor desc;
|
||||
|
||||
KernelBundle const * kernelBundle;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
|
||||
typedef std::vector<KernelBundle *> KernelRegistry;
|
||||
|
||||
KernelBundle const * getKernel(VertexBufferDescriptor const &desc);
|
||||
|
||||
KernelRegistry _kernelRegistry;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_D3D11_COMPUTE_CONTROLLER_H
|
375
opensubdiv/osd/d3d11ComputeEvaluator.cpp
Normal file
375
opensubdiv/osd/d3d11ComputeEvaluator.cpp
Normal file
@ -0,0 +1,375 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache 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/stencilTables.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;
|
||||
}
|
||||
|
||||
D3D11StencilTables::D3D11StencilTables(Far::StencilTables const *stencilTables,
|
||||
ID3D11DeviceContext *deviceContext)
|
||||
{
|
||||
ID3D11Device *device = NULL;
|
||||
deviceContext->GetDevice(&device);
|
||||
assert(device);
|
||||
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
// convert unsigned char sizes buffer to ints
|
||||
// (HLSL does not have uint8 type)
|
||||
std::vector<int> const sizes(stencilTables->GetSizes().begin(),
|
||||
stencilTables->GetSizes().end());
|
||||
|
||||
_sizesBuffer = createBuffer(sizes, device);
|
||||
_offsetsBuffer = createBuffer(stencilTables->GetOffsets(), device);
|
||||
_indicesBuffer = createBuffer(stencilTables->GetControlIndices(), device);
|
||||
_weightsBuffer = createBuffer(stencilTables->GetWeights(), device);
|
||||
|
||||
_sizes = createSRV(_sizesBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTables->GetSizes().size());
|
||||
_offsets = createSRV(_offsetsBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTables->GetOffsets().size());
|
||||
_indices = createSRV(_indicesBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTables->GetControlIndices().size());
|
||||
_weights= createSRV(_weightsBuffer, DXGI_FORMAT_R32_FLOAT, device,
|
||||
stencilTables->GetWeights().size());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
_sizesBuffer = _offsetsBuffer = _indicesBuffer = _weightsBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11StencilTables::~D3D11StencilTables() {
|
||||
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(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
(void)deviceContext; // not used
|
||||
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(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor 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
|
||||
| D3D10_SHADER_RESOURCES_MAY_ALIAS;
|
||||
#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,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
ID3D11UnorderedAccessView *dstUAV,
|
||||
VertexBufferDescriptor 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 tables
|
||||
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 tables 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
|
227
opensubdiv/osd/d3d11ComputeEvaluator.h
Normal file
227
opensubdiv/osd/d3d11ComputeEvaluator.h
Normal file
@ -0,0 +1,227 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_D3D11_COMPUTE_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_D3D11_COMPUTE_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
struct ID3D11DeviceContext;
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11ComputeShader;
|
||||
struct ID3D11ClassLinkage;
|
||||
struct ID3D11ClassInstance;
|
||||
struct ID3D11ShaderResourceView;
|
||||
struct ID3D11UnorderedAccessView;
|
||||
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief D3D11 stencil tables
|
||||
///
|
||||
/// This class is a D3D11 Shader Resource View representation of
|
||||
/// Far::StencilTables.
|
||||
///
|
||||
/// D3D11ComputeEvaluator consumes this table to apply stencils
|
||||
///
|
||||
class D3D11StencilTables {
|
||||
public:
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static D3D11StencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
DEVICE_CONTEXT context) {
|
||||
return new D3D11StencilTables(stencilTables, context->GetDeviceContext());
|
||||
}
|
||||
|
||||
static D3D11StencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
return new D3D11StencilTables(stencilTables, deviceContext);
|
||||
}
|
||||
|
||||
D3D11StencilTables(Far::StencilTables const *stencilTables,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
~D3D11StencilTables();
|
||||
|
||||
// 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:
|
||||
typedef bool Instantiatable;
|
||||
static D3D11ComputeEvaluator * Create(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
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 stencilTables 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 VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
D3D11ComputeEvaluator const *instance,
|
||||
ID3D11DeviceContext * deviceContext) {
|
||||
if (instance) {
|
||||
return instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable,
|
||||
deviceContext);
|
||||
} else {
|
||||
// Create an instace on demand (slow)
|
||||
(void)deviceContext; // unused
|
||||
instance = Create(srcDesc, dstDesc, deviceContext);
|
||||
if (instance) {
|
||||
bool r = instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, 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 VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
ID3D11DeviceContext *deviceContext) const {
|
||||
return EvalStencils(srcVertexBuffer->BindD3D11UAV(deviceContext),
|
||||
srcDesc,
|
||||
dstVertexBuffer->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,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
ID3D11UnorderedAccessView *dstUAV,
|
||||
VertexBufferDescriptor 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(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor 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 paramaeters for kernels
|
||||
|
||||
int _workGroupSize;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_D3D11_COMPUTE_EVALUATOR_H
|
@ -41,7 +41,7 @@ namespace Osd {
|
||||
/// \brief Concrete vertex buffer class for DirectX subvision and DirectX drawing.
|
||||
///
|
||||
/// D3D11VertexBuffer implements D3D11VertexBufferInterface. An instance
|
||||
/// of this buffer class can be passed to D3D11ComputeController.
|
||||
/// of this buffer class can be passed to D3D11ComputeEvaluator.
|
||||
///
|
||||
class D3D11VertexBuffer {
|
||||
public:
|
||||
|
@ -1,44 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/evalLimitContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
EvalLimitContext::EvalLimitContext(Far::PatchTables const & patchTables) {
|
||||
|
||||
_adaptive = patchTables.IsFeatureAdaptive();
|
||||
}
|
||||
|
||||
EvalLimitContext::~EvalLimitContext() {
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,100 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_EVAL_LIMIT_CONTEXT_H
|
||||
#define OSD_EVAL_LIMIT_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/patchTables.h"
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
|
||||
/// \brief Coordinates set on a limit surface
|
||||
///
|
||||
struct LimitLocation {
|
||||
|
||||
LimitLocation() { }
|
||||
|
||||
/// \brief Constructor
|
||||
///
|
||||
/// @param f Ptex face id
|
||||
///
|
||||
/// @param x parametric location on face
|
||||
///
|
||||
/// @param y parametric location on face
|
||||
///
|
||||
LimitLocation(int f, float x, float y) : ptexIndex(f), s(x), t(y) { }
|
||||
|
||||
int ptexIndex; ///< ptex face index
|
||||
|
||||
float s, t; ///< parametric location on face
|
||||
};
|
||||
|
||||
class LimitLocationsArray {
|
||||
|
||||
public:
|
||||
|
||||
/// \brief Constructor
|
||||
LimitLocationsArray() : ptexIndex(-1), numLocations(0), s(0), t(0) { }
|
||||
|
||||
int ptexIndex, ///< ptex face index
|
||||
numLocations; ///< number of (u,v) coordinates in the array
|
||||
|
||||
float const * s, ///< array of u coordinates
|
||||
* t; ///< array of v coordinates
|
||||
};
|
||||
|
||||
|
||||
/// \brief LimitEval Context
|
||||
///
|
||||
/// A stub class to derive LimitEval context classes.
|
||||
///
|
||||
class EvalLimitContext : private NonCopyable<EvalLimitContext> {
|
||||
|
||||
public:
|
||||
/// \brief Destructor.
|
||||
virtual ~EvalLimitContext();
|
||||
|
||||
protected:
|
||||
explicit EvalLimitContext(Far::PatchTables const & patchTables);
|
||||
|
||||
private:
|
||||
bool _adaptive;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* OSD_EVAL_LIMIT_CONTEXT_H */
|
224
opensubdiv/osd/glComputeEvaluator.cpp
Normal file
224
opensubdiv/osd/glComputeEvaluator.cpp
Normal file
@ -0,0 +1,224 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/glComputeEvaluator.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
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) {
|
||||
GLuint devicePtr = 0;
|
||||
glGenBuffers(1, &devicePtr);
|
||||
|
||||
#if defined(GL_EXT_direct_state_access)
|
||||
if (glNamedBufferDataEXT) {
|
||||
glNamedBufferDataEXT(devicePtr, src.size()*sizeof(T),
|
||||
&src.at(0), GL_STATIC_DRAW);
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
GLint prev = 0;
|
||||
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &prev);
|
||||
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;
|
||||
}
|
||||
|
||||
GLStencilTablesSSBO::GLStencilTablesSSBO(
|
||||
Far::StencilTables const *stencilTables) {
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createSSBO(stencilTables->GetSizes());
|
||||
_offsets = createSSBO(stencilTables->GetOffsets());
|
||||
_indices = createSSBO(stencilTables->GetControlIndices());
|
||||
_weights = createSSBO(stencilTables->GetWeights());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLStencilTablesSSBO::~GLStencilTablesSSBO() {
|
||||
if (_sizes) glDeleteBuffers(1, &_sizes);
|
||||
if (_offsets) glDeleteBuffers(1, &_offsets);
|
||||
if (_weights) glDeleteBuffers(1, &_weights);
|
||||
if (_indices) glDeleteBuffers(1, &_indices);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
GLComputeEvaluator::GLComputeEvaluator() :
|
||||
_program(0), _workGroupSize(64) {
|
||||
}
|
||||
|
||||
GLComputeEvaluator::~GLComputeEvaluator() {
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GLComputeEvaluator::Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
_program = 0;
|
||||
}
|
||||
_program = glCreateProgram();
|
||||
|
||||
GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
|
||||
|
||||
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";
|
||||
std::string defineStr = defines.str();
|
||||
|
||||
const char *shaderSources[3] = {"#version 430\n", 0, 0};
|
||||
shaderSources[1] = defineStr.c_str();
|
||||
shaderSources[2] = shaderSource;
|
||||
glShaderSource(shader, 3, 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);
|
||||
_program = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
// store uniform locations for the compute kernel program.
|
||||
_uniformSizes = glGetUniformLocation(_program, "stencilSizes");
|
||||
_uniformOffsets = glGetUniformLocation(_program, "stencilOffsets");
|
||||
_uniformIndices = glGetUniformLocation(_program, "stencilIndices");
|
||||
_uniformWeights = glGetUniformLocation(_program, "stencilIWeights");
|
||||
|
||||
_uniformStart = glGetUniformLocation(_program, "batchStart");
|
||||
_uniformEnd = glGetUniformLocation(_program, "batchEnd");
|
||||
|
||||
_uniformSrcOffset = glGetUniformLocation(_program, "srcOffset");
|
||||
_uniformDstOffset = glGetUniformLocation(_program, "dstOffset");
|
||||
|
||||
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(GLuint srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
GLuint dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
GLuint sizesBuffer,
|
||||
GLuint offsetsBuffer,
|
||||
GLuint indicesBuffer,
|
||||
GLuint weightsBuffer,
|
||||
int start,
|
||||
int end) const {
|
||||
if (!_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, sizesBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, offsetsBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, indicesBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, weightsBuffer);
|
||||
|
||||
glUseProgram(_program);
|
||||
|
||||
glUniform1i(_uniformStart, start);
|
||||
glUniform1i(_uniformEnd, end);
|
||||
glUniform1i(_uniformSrcOffset, srcDesc.offset);
|
||||
glUniform1i(_uniformDstOffset, dstDesc.offset);
|
||||
|
||||
glDispatchCompute((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
|
||||
glUseProgram(0);
|
||||
|
||||
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
|
||||
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);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
215
opensubdiv/osd/glComputeEvaluator.h
Normal file
215
opensubdiv/osd/glComputeEvaluator.h
Normal file
@ -0,0 +1,215 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_GL_COMPUTE_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_GL_COMPUTE_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/opengl.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief GL stencil tables (Shader Storage buffer)
|
||||
///
|
||||
/// This class is a GLSL SSBO representation of Far::StencilTables.
|
||||
///
|
||||
/// GLSLComputeKernel consumes this table to apply stencils
|
||||
///
|
||||
class GLStencilTablesSSBO {
|
||||
public:
|
||||
static GLStencilTablesSSBO *Create(Far::StencilTables const *stencilTables,
|
||||
void *deviceContext = NULL) {
|
||||
(void)deviceContext; // unused
|
||||
return new GLStencilTablesSSBO(stencilTables);
|
||||
}
|
||||
|
||||
explicit GLStencilTablesSSBO(Far::StencilTables const *stencilTables);
|
||||
~GLStencilTablesSSBO();
|
||||
|
||||
// interfaces needed for GLSLComputeKernel
|
||||
GLuint GetSizesBuffer() const { return _sizes; }
|
||||
GLuint GetOffsetsBuffer() const { return _offsets; }
|
||||
GLuint GetIndicesBuffer() const { return _indices; }
|
||||
GLuint GetWeightsBuffer() const { return _weights; }
|
||||
int GetNumStencils() const { return _numStencils; }
|
||||
|
||||
private:
|
||||
GLuint _sizes;
|
||||
GLuint _offsets;
|
||||
GLuint _indices;
|
||||
GLuint _weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class GLComputeEvaluator {
|
||||
public:
|
||||
typedef bool Instantiatable;
|
||||
static GLComputeEvaluator * Create(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
void * deviceContext = NULL) {
|
||||
(void)deviceContext; // not used
|
||||
GLComputeEvaluator *instance = new GLComputeEvaluator();
|
||||
if (instance->Compile(srcDesc, dstDesc)) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
GLComputeEvaluator();
|
||||
|
||||
/// Destructor. note that the GL context must be made current.
|
||||
~GLComputeEvaluator();
|
||||
|
||||
/// \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 evaluator 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 not used in the GLSL kernel
|
||||
///
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
GLComputeEvaluator const *instance,
|
||||
void * deviceContext = NULL) {
|
||||
if (instance) {
|
||||
return instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable);
|
||||
} else {
|
||||
// Create a kernel on demand (slow)
|
||||
(void)deviceContext; // unused
|
||||
instance = Create(srcDesc, dstDesc);
|
||||
if (instance) {
|
||||
bool r = instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatch the GLSL compute kernel on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable) const {
|
||||
return EvalStencils(srcVertexBuffer->BindVBO(),
|
||||
srcDesc,
|
||||
dstVertexBuffer->BindVBO(),
|
||||
dstDesc,
|
||||
stencilTable->GetSizesBuffer(),
|
||||
stencilTable->GetOffsetsBuffer(),
|
||||
stencilTable->GetIndicesBuffer(),
|
||||
stencilTable->GetWeightsBuffer(),
|
||||
/* start = */ 0,
|
||||
/* end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
/// Dispatch the GLSL compute kernel on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
bool EvalStencils(GLuint srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
GLuint dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
GLuint sizesBuffer,
|
||||
GLuint offsetsBuffer,
|
||||
GLuint indicesBuffer,
|
||||
GLuint weightsBuffer,
|
||||
int start,
|
||||
int end) const;
|
||||
|
||||
/// Configure GLSL kernel. A valid GL context must be made current before
|
||||
/// calling this function. Returns false if it fails to compile the kernel.
|
||||
bool Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc);
|
||||
|
||||
/// Wait the dispatched kernel finishes.
|
||||
static void Synchronize(void *deviceContext);
|
||||
|
||||
private:
|
||||
GLuint _program;
|
||||
|
||||
GLuint _uniformSizes, // stencil tables
|
||||
_uniformOffsets,
|
||||
_uniformIndices,
|
||||
_uniformWeights,
|
||||
|
||||
_uniformStart, // range
|
||||
_uniformEnd,
|
||||
|
||||
_uniformSrcOffset, // src buffer offset (in elements)
|
||||
_uniformDstOffset; // dst buffer offset (in elements)
|
||||
|
||||
int _workGroupSize;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_GL_COMPUTE_EVALUATOR_H
|
@ -39,8 +39,7 @@ namespace Osd {
|
||||
/// \brief Concrete vertex buffer class for GLSL subvision and OpenGL drawing.
|
||||
///
|
||||
/// GLVertexBuffer implements GLVertexBufferInterface. An instance
|
||||
/// of this buffer class can be passed to OsdGLComputeController
|
||||
/// and OsdGLDrawController
|
||||
/// of this buffer class can be passed to OsdGLComputeEvaluator.
|
||||
///
|
||||
class GLVertexBuffer {
|
||||
public:
|
||||
|
353
opensubdiv/osd/glXFBEvaluator.cpp
Normal file
353
opensubdiv/osd/glXFBEvaluator.cpp
Normal file
@ -0,0 +1,353 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/glXFBEvaluator.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTables.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) {
|
||||
GLint size = static_cast<int>(src.size()*sizeof(T));
|
||||
void const * ptr = &src.at(0);
|
||||
|
||||
GLuint buffer;
|
||||
glGenBuffers(1, &buffer);
|
||||
|
||||
GLuint devicePtr;
|
||||
glGenTextures(1, &devicePtr);
|
||||
|
||||
#if defined(GL_EXT_direct_state_access)
|
||||
if (glNamedBufferDataEXT && glTextureBufferEXT) {
|
||||
glNamedBufferDataEXT(buffer, size, ptr, GL_STATIC_DRAW);
|
||||
glTextureBufferEXT(devicePtr, GL_TEXTURE_BUFFER, type, buffer);
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
GLint prev = 0;
|
||||
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev);
|
||||
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);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, devicePtr);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, type, buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, prev);
|
||||
}
|
||||
|
||||
glDeleteBuffers(1, &buffer);
|
||||
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
GLStencilTablesTBO::GLStencilTablesTBO(
|
||||
Far::StencilTables const *stencilTables) {
|
||||
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createGLTextureBuffer(stencilTables->GetSizes(), GL_R8UI);
|
||||
_offsets = createGLTextureBuffer(
|
||||
stencilTables->GetOffsets(), GL_R32I);
|
||||
_indices = createGLTextureBuffer(
|
||||
stencilTables->GetControlIndices(), GL_R32I);
|
||||
_weights = createGLTextureBuffer(stencilTables->GetWeights(), GL_R32F);
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLStencilTablesTBO::~GLStencilTablesTBO() {
|
||||
if (_sizes) glDeleteTextures(1, &_sizes);
|
||||
if (_offsets) glDeleteTextures(1, &_offsets);
|
||||
if (_weights) glDeleteTextures(1, &_weights);
|
||||
if (_indices) glDeleteTextures(1, &_indices);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
GLXFBEvaluator::GLXFBEvaluator() :
|
||||
_program(0), _srcBufferTexture(0),
|
||||
_uniformSrcBufferTexture(0), _uniformSizesTexture(0),
|
||||
_uniformOffsetsTexture(0), _uniformIndicesTexture(0),
|
||||
_uniformWeightsTexture(0), _uniformStart(0), _uniformEnd(0),
|
||||
_uniformSrcOffset(0) {
|
||||
}
|
||||
|
||||
GLXFBEvaluator::~GLXFBEvaluator() {
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
}
|
||||
if (_srcBufferTexture) {
|
||||
glDeleteTextures(1, &_srcBufferTexture);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GLXFBEvaluator::Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc) {
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
_program = 0;
|
||||
}
|
||||
_program = glCreateProgram();
|
||||
|
||||
GLuint shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
|
||||
std::ostringstream defines;
|
||||
defines << "#define LENGTH " << srcDesc.length << "\n"
|
||||
<< "#define SRC_STRIDE " << srcDesc.stride << "\n";
|
||||
std::string defineStr = defines.str();
|
||||
|
||||
const char *shaderSources[3] = {"#version 410\n", NULL, NULL};
|
||||
|
||||
shaderSources[1] = defineStr.c_str();
|
||||
shaderSources[2] = shaderSource;
|
||||
glShaderSource(shader, 3, shaderSources, NULL);
|
||||
glCompileShader(shader);
|
||||
glAttachShader(_program, shader);
|
||||
|
||||
std::vector<std::string> outputs;
|
||||
std::vector<const char *> pOutputs;
|
||||
{
|
||||
// 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.
|
||||
//
|
||||
char attrName[32];
|
||||
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");
|
||||
}
|
||||
|
||||
// convert to char* array
|
||||
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(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);
|
||||
_program = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
// set uniform locations for compute kernels
|
||||
_uniformSrcBufferTexture = glGetUniformLocation(_program, "vertexBuffer");
|
||||
|
||||
_uniformSizesTexture = glGetUniformLocation(_program, "sizes");
|
||||
_uniformOffsetsTexture = glGetUniformLocation(_program, "offsets");
|
||||
_uniformIndicesTexture = glGetUniformLocation(_program, "indices");
|
||||
_uniformWeightsTexture = glGetUniformLocation(_program, "weights");
|
||||
|
||||
_uniformStart = glGetUniformLocation(_program, "batchStart");
|
||||
_uniformEnd = glGetUniformLocation(_program, "batchEnd");
|
||||
|
||||
_uniformSrcOffset = glGetUniformLocation(_program, "srcOffset");
|
||||
|
||||
// create a texture for input buffer
|
||||
if (!_srcBufferTexture) {
|
||||
glGenTextures(1, &_srcBufferTexture);
|
||||
}
|
||||
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(GLuint srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
GLuint dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
GLuint sizesTexture,
|
||||
GLuint offsetsTexture,
|
||||
GLuint indicesTexture,
|
||||
GLuint weightsTexture,
|
||||
int start,
|
||||
int end) const {
|
||||
if (!_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(_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(_uniformSrcBufferTexture, _srcBufferTexture, 0);
|
||||
|
||||
// bind stencil tables textures.
|
||||
bindTexture(_uniformSizesTexture, sizesTexture, 1);
|
||||
bindTexture(_uniformOffsetsTexture, offsetsTexture, 2);
|
||||
bindTexture(_uniformIndicesTexture, indicesTexture, 3);
|
||||
bindTexture(_uniformWeightsTexture, weightsTexture, 4);
|
||||
|
||||
// set batch range
|
||||
glUniform1i(_uniformStart, start);
|
||||
glUniform1i(_uniformEnd, end);
|
||||
glUniform1i(_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.offset - (dstDesc.offset % dstDesc.stride);
|
||||
|
||||
// bind destination buffer
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
0, dstBuffer,
|
||||
dstBufferBindOffset * sizeof(float),
|
||||
count * dstDesc.stride * sizeof(float));
|
||||
|
||||
glBeginTransformFeedback(GL_POINTS);
|
||||
glDrawArrays(GL_POINTS, 0, count);
|
||||
glEndTransformFeedback();
|
||||
|
||||
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
|
||||
|
||||
for (int i = 0; i < 5; ++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;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
215
opensubdiv/osd/glXFBEvaluator.h
Normal file
215
opensubdiv/osd/glXFBEvaluator.h
Normal file
@ -0,0 +1,215 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_GL_XFB_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_GL_XFB_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/opengl.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief GL TextureBuffer stencil tables
|
||||
///
|
||||
/// This class is a GL Texture Buffer representation of Far::StencilTables.
|
||||
///
|
||||
/// GLSLTransformFeedback consumes this table to apply stencils
|
||||
///
|
||||
///
|
||||
class GLStencilTablesTBO {
|
||||
public:
|
||||
static GLStencilTablesTBO *Create(
|
||||
Far::StencilTables const *stencilTables, void *deviceContext = NULL) {
|
||||
(void)deviceContext; // unused
|
||||
return new GLStencilTablesTBO(stencilTables);
|
||||
}
|
||||
|
||||
explicit GLStencilTablesTBO(Far::StencilTables const *stencilTables);
|
||||
~GLStencilTablesTBO();
|
||||
|
||||
// interfaces needed for GLSLTransformFeedbackKernel
|
||||
GLuint GetSizesTexture() const { return _sizes; }
|
||||
GLuint GetOffsetsTexture() const { return _offsets; }
|
||||
GLuint GetIndicesTexture() const { return _indices; }
|
||||
GLuint GetWeightsTexture() const { return _weights; }
|
||||
int GetNumStencils() const { return _numStencils; }
|
||||
|
||||
private:
|
||||
GLuint _sizes;
|
||||
GLuint _offsets;
|
||||
GLuint _indices;
|
||||
GLuint _weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class GLXFBEvaluator {
|
||||
public:
|
||||
typedef bool Instantiatable;
|
||||
static GLXFBEvaluator * Create(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
void * deviceContext = NULL) {
|
||||
(void)deviceContext; // not used
|
||||
GLXFBEvaluator *instance = new GLXFBEvaluator();
|
||||
if (instance->Compile(srcDesc, dstDesc)) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
GLXFBEvaluator();
|
||||
|
||||
/// Destructor. note that the GL context must be made current.
|
||||
~GLXFBEvaluator();
|
||||
|
||||
/// \brief Generic static stencil 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
|
||||
/// Texture Buffer Object 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 not used in the GLSLTransformFeedback kernel
|
||||
///
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
GLXFBEvaluator const *instance,
|
||||
void * deviceContext = NULL) {
|
||||
if (instance) {
|
||||
return instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable);
|
||||
} else {
|
||||
// Create an instance on demand (slow)
|
||||
(void)deviceContext; // unused
|
||||
instance = Create(srcDesc, dstDesc);
|
||||
if (instance) {
|
||||
bool r = instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatch the GLSL compute kernel on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable) const {
|
||||
return EvalStencils(srcVertexBuffer->BindVBO(),
|
||||
srcDesc,
|
||||
dstVertexBuffer->BindVBO(),
|
||||
dstDesc,
|
||||
stencilTable->GetSizesTexture(),
|
||||
stencilTable->GetOffsetsTexture(),
|
||||
stencilTable->GetIndicesTexture(),
|
||||
stencilTable->GetWeightsTexture(),
|
||||
/* start = */ 0,
|
||||
/* end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
/// Dispatch the GLSL compute kernel on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
bool EvalStencils(GLuint srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
GLuint dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
GLuint sizesBuffer,
|
||||
GLuint offsetsBuffer,
|
||||
GLuint indicesBuffer,
|
||||
GLuint weightsBuffer,
|
||||
int start,
|
||||
int end) const;
|
||||
|
||||
/// Configure GLSL kernel. A valid GL context must be made current before
|
||||
/// calling this function. Returns false if it fails to compile the kernel.
|
||||
bool Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc);
|
||||
|
||||
/// Wait the dispatched kernel finishes.
|
||||
static void Synchronize(void *kernel);
|
||||
|
||||
private:
|
||||
GLuint _program;
|
||||
|
||||
GLuint _srcBufferTexture;
|
||||
|
||||
GLuint _uniformSrcBufferTexture;
|
||||
GLuint _uniformSizesTexture;
|
||||
GLuint _uniformOffsetsTexture;
|
||||
GLuint _uniformIndicesTexture;
|
||||
GLuint _uniformWeightsTexture;
|
||||
|
||||
GLuint _uniformStart; // range
|
||||
GLuint _uniformEnd;
|
||||
GLuint _uniformSrcOffset; // src buffer offset (in elements)
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_GL_XFB_EVALUATOR_H
|
@ -1,229 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
//#include "../osd/debug.h"
|
||||
#include "../osd/glslComputeContext.h"
|
||||
#include "../osd/opengl.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template <class T> GLuint
|
||||
createGLSLBuffer(std::vector<T> const & src) {
|
||||
|
||||
GLuint devicePtr=0;
|
||||
|
||||
glGenBuffers(1, &devicePtr);
|
||||
|
||||
#if defined(GL_EXT_direct_state_access)
|
||||
if (glNamedBufferDataEXT) {
|
||||
glNamedBufferDataEXT(devicePtr, src.size()*sizeof(T), &src.at(0), GL_STATIC_DRAW);
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
GLint prev = 0;
|
||||
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &prev);
|
||||
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);
|
||||
}
|
||||
|
||||
//OSD_DEBUG_CHECK_GL_ERROR("createGLSLBuffer size %ld", src.size());
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class GLSLComputeContext::GLSLStencilTables {
|
||||
|
||||
public:
|
||||
|
||||
GLSLStencilTables(Far::StencilTables const & stencilTables) {
|
||||
_numStencils = stencilTables.GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createGLSLBuffer(stencilTables.GetSizes());
|
||||
_offsets = createGLSLBuffer(stencilTables.GetOffsets());
|
||||
_indices = createGLSLBuffer(stencilTables.GetControlIndices());
|
||||
_weights = createGLSLBuffer(stencilTables.GetWeights());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~GLSLStencilTables() {
|
||||
if (_sizes) glDeleteBuffers(1, &_sizes);
|
||||
if (_offsets) glDeleteBuffers(1, &_offsets);
|
||||
if (_weights) glDeleteBuffers(1, &_weights);
|
||||
if (_indices) glDeleteBuffers(1, &_indices);
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return _sizes and _offsets and _indices and _weights;
|
||||
}
|
||||
|
||||
GLuint GetSizes() const {
|
||||
return _sizes;
|
||||
}
|
||||
|
||||
GLuint GetOffsets() const {
|
||||
return _offsets;
|
||||
}
|
||||
|
||||
GLuint GetIndices() const {
|
||||
return _indices;
|
||||
}
|
||||
|
||||
GLuint GetWeights() const {
|
||||
return _weights;
|
||||
}
|
||||
|
||||
int GetNumStencils() const {
|
||||
return _numStencils;
|
||||
}
|
||||
|
||||
void Bind() const {
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, _sizes);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, _offsets);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, _indices);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, _weights);
|
||||
}
|
||||
|
||||
static void Unbind() {
|
||||
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);
|
||||
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
GLuint _sizes,
|
||||
_offsets,
|
||||
_indices,
|
||||
_weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
GLSLComputeContext::GLSLComputeContext(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables) :
|
||||
_vertexStencilTables(0), _varyingStencilTables(0),
|
||||
_numControlVertices(0),
|
||||
_numStencils(0) {
|
||||
|
||||
if (vertexStencilTables) {
|
||||
_vertexStencilTables = new GLSLStencilTables(*vertexStencilTables);
|
||||
_numControlVertices = vertexStencilTables->GetNumControlVertices();
|
||||
}
|
||||
|
||||
if (varyingStencilTables) {
|
||||
_varyingStencilTables = new GLSLStencilTables(*varyingStencilTables);
|
||||
|
||||
if (_numControlVertices) {
|
||||
assert(_numControlVertices==varyingStencilTables->GetNumControlVertices());
|
||||
} else {
|
||||
_numControlVertices = varyingStencilTables->GetNumControlVertices();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLSLComputeContext::~GLSLComputeContext() {
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
GLSLComputeContext::HasVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
GLSLComputeContext::HasVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
int
|
||||
GLSLComputeContext::GetNumStencilsInVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetNumStencils() : false;
|
||||
}
|
||||
|
||||
int
|
||||
GLSLComputeContext::GetNumStencilsInVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetNumStencils() : false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
GLSLComputeContext::BindVertexStencilTables() const {
|
||||
if (_vertexStencilTables) {
|
||||
_vertexStencilTables->Bind();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLSLComputeContext::BindVaryingStencilTables() const {
|
||||
if (_varyingStencilTables) {
|
||||
_varyingStencilTables->Bind();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLSLComputeContext::UnbindStencilTables() const {
|
||||
GLSLStencilTables::Unbind();
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
GLSLComputeContext *
|
||||
GLSLComputeContext::Create(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
GLSLComputeContext *result =
|
||||
new GLSLComputeContext(vertexStencilTables, varyingStencilTables);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,126 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_GLSL_COMPUTE_CONTEXT_H
|
||||
#define OSD_GLSL_COMPUTE_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/opengl.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far{ class StencilTables; }
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief GLSL-Compute Refine Context
|
||||
///
|
||||
/// The GLSL-Compute implementation of the Refine module contextual functionality.
|
||||
///
|
||||
/// Contexts interface the serialized topological data pertaining to the
|
||||
/// geometric primitives with the capabilities of the selected discrete
|
||||
/// compute device.
|
||||
///
|
||||
class GLSLComputeContext {
|
||||
|
||||
public:
|
||||
/// Creates an GLSLComputeContext instance
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
/// @param deviceContext (not used)
|
||||
///
|
||||
static GLSLComputeContext * Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Destructor
|
||||
virtual ~GLSLComputeContext();
|
||||
|
||||
/// Returns true if the Context has a 'vertex' interpolation stencil table
|
||||
bool HasVertexStencilTables() const;
|
||||
|
||||
/// Returns true if the Context has a 'varying' interpolation stencil table
|
||||
bool HasVaryingStencilTables() const;
|
||||
|
||||
/// Returns the number of control vertices
|
||||
int GetNumControlVertices() const {
|
||||
return _numControlVertices;
|
||||
}
|
||||
|
||||
/// Returns the number of stencils in vertex stencil table
|
||||
int GetNumStencilsInVertexStencilTables() const;
|
||||
|
||||
/// Returns the number of stencils in varying stencil table
|
||||
int GetNumStencilsInVaryingStencilTables() const;
|
||||
|
||||
/// Returns the GL buffer containing vertex-stencil stencil sizes
|
||||
GLuint GetVertexStencilTablesSizes() const;
|
||||
|
||||
/// Returns the GL buffer containing vertex-stencil stencil offsets
|
||||
GLuint GetVertexStencilTablesOffsets() const;
|
||||
|
||||
/// Binds GL buffers containing stencils for 'vertex' interpolation
|
||||
void BindVertexStencilTables() const;
|
||||
|
||||
/// Binds GL buffers containing stencils for 'varying' interpolation
|
||||
void BindVaryingStencilTables() const;
|
||||
|
||||
/// Unbinds GL stencil buffers
|
||||
void UnbindStencilTables() const;
|
||||
|
||||
protected:
|
||||
explicit GLSLComputeContext(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables);
|
||||
|
||||
private:
|
||||
class GLSLStencilTables;
|
||||
|
||||
GLSLStencilTables * _vertexStencilTables,
|
||||
* _varyingStencilTables;
|
||||
|
||||
int _numControlVertices;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_GLSL_COMPUTE_CONTEXT_H
|
@ -1,292 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/glslComputeController.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
#include "../osd/opengl.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static const char *shaderSource =
|
||||
#include "../osd/glslComputeKernel.gen.h"
|
||||
;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class GLSLComputeController::KernelBundle :
|
||||
NonCopyable<GLSLComputeController::KernelBundle> {
|
||||
|
||||
public:
|
||||
|
||||
KernelBundle() :
|
||||
_program(0),
|
||||
_uniformSizes(0),
|
||||
_uniformOffsets(0),
|
||||
_uniformIndices(0),
|
||||
_uniformWeights(0),
|
||||
_uniformStart(0),
|
||||
_uniformEnd(0),
|
||||
_uniformSrcOffset(0),
|
||||
_uniformDstOffset(0),
|
||||
_workGroupSize(64) { }
|
||||
|
||||
~KernelBundle() {
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
}
|
||||
}
|
||||
|
||||
void UseProgram() const {
|
||||
glUseProgram(_program);
|
||||
}
|
||||
|
||||
bool Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc) {
|
||||
|
||||
// XXX: only store srcDesc.
|
||||
// this is ok since currently this kernel doesn't get called with
|
||||
// different strides for src and dst. This function will be
|
||||
// refactored soon.
|
||||
_desc = VertexBufferDescriptor(0, srcDesc.length, srcDesc.stride);
|
||||
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
_program=0;
|
||||
}
|
||||
_program = glCreateProgram();
|
||||
|
||||
GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
|
||||
|
||||
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";
|
||||
std::string defineStr = defines.str();
|
||||
|
||||
const char *shaderSources[3] = {"#version 430\n", 0, 0};
|
||||
shaderSources[1] = defineStr.c_str();
|
||||
shaderSources[2] = shaderSource;
|
||||
glShaderSource(shader, 3, 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);
|
||||
_program = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
// set uniform locations for compute kernels
|
||||
_uniformSizes = glGetUniformLocation(_program, "stencilSizes");
|
||||
_uniformOffsets = glGetUniformLocation(_program, "stencilOffsets");
|
||||
_uniformIndices = glGetUniformLocation(_program, "stencilIndices");
|
||||
_uniformWeights = glGetUniformLocation(_program, "stencilIWeights");
|
||||
|
||||
_uniformStart = glGetUniformLocation(_program, "batchStart");
|
||||
_uniformEnd = glGetUniformLocation(_program, "batchEnd");
|
||||
|
||||
_uniformSrcOffset = glGetUniformLocation(_program, "srcOffset");
|
||||
_uniformDstOffset = glGetUniformLocation(_program, "dstOffset");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ApplyStencilTableKernel(int srcOffset, int dstOffset,
|
||||
int start, int end) const {
|
||||
|
||||
dispatchCompute(srcOffset, dstOffset, start, end);
|
||||
}
|
||||
|
||||
struct Match {
|
||||
|
||||
Match(VertexBufferDescriptor const & d) : desc(d) { }
|
||||
|
||||
bool operator() (KernelBundle const * kernel) {
|
||||
return (desc.length==kernel->_desc.length and
|
||||
desc.stride==kernel->_desc.stride);
|
||||
}
|
||||
|
||||
VertexBufferDescriptor desc;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
void dispatchCompute(int srcOffset, int dstOffset, int start, int end) const {
|
||||
|
||||
int count = end - start;
|
||||
if (count<=0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
glUniform1i(_uniformStart, start);
|
||||
glUniform1i(_uniformEnd, end);
|
||||
|
||||
glUniform1i(_uniformSrcOffset, srcOffset);
|
||||
glUniform1i(_uniformDstOffset, dstOffset);
|
||||
|
||||
glDispatchCompute((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
|
||||
// sync for later reading.
|
||||
// XXX: in theory, just SHADER_STORAGE_BARRIER is needed here. However
|
||||
// we found a problem (issue #295) with nvidia driver 331.49 / Quadro4000
|
||||
// resulting in invalid vertices.
|
||||
// Apparently adding TEXTURE_FETCH_BARRIER after a kernel fixes it.
|
||||
// The workaroud is commented out, since it looks fixed as of driver 334.xx.
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||
|
||||
//OSD_DEBUG_CHECK_GL_ERROR("dispatchCompute");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
GLuint _program;
|
||||
|
||||
GLuint _uniformSizes, // uniform paramaeters for kernels
|
||||
_uniformOffsets,
|
||||
_uniformIndices,
|
||||
_uniformWeights,
|
||||
|
||||
_uniformStart, // batch
|
||||
_uniformEnd,
|
||||
|
||||
_uniformSrcOffset, // src buffer offset (in elements)
|
||||
_uniformDstOffset; // dst buffer offset (in elements)
|
||||
|
||||
VertexBufferDescriptor _desc; // primvar buffer descriptor
|
||||
|
||||
int _workGroupSize;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
GLSLComputeController::ApplyStencilTableKernel(
|
||||
ComputeContext const *context, int numStencils) const {
|
||||
|
||||
assert(context);
|
||||
|
||||
// Note: GLSLComputeContext has a state, knowing whether vertex or
|
||||
// varying stencil tables are being bound. GetNumStencils() reflects it.
|
||||
// This structure will likely be revisited.
|
||||
|
||||
int start = 0;
|
||||
int end = numStencils;
|
||||
|
||||
_currentBindState.kernelBundle->ApplyStencilTableKernel(
|
||||
_currentBindState.desc.offset,
|
||||
_currentBindState.desc.offset + context->GetNumControlVertices() * _currentBindState.desc.stride,
|
||||
start, end);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
GLSLComputeController::GLSLComputeController() { }
|
||||
|
||||
GLSLComputeController::~GLSLComputeController() {
|
||||
for (KernelRegistry::iterator it = _kernelRegistry.begin();
|
||||
it != _kernelRegistry.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
GLSLComputeController::Synchronize() {
|
||||
|
||||
glFinish();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GLSLComputeController::KernelBundle const *
|
||||
GLSLComputeController::getKernel(VertexBufferDescriptor const &desc) {
|
||||
|
||||
KernelRegistry::iterator it =
|
||||
std::find_if(_kernelRegistry.begin(), _kernelRegistry.end(),
|
||||
KernelBundle::Match(desc));
|
||||
|
||||
if (it != _kernelRegistry.end()) {
|
||||
return *it;
|
||||
} else {
|
||||
KernelBundle * kernelBundle = new KernelBundle();
|
||||
kernelBundle->Compile(desc, desc);
|
||||
_kernelRegistry.push_back(kernelBundle);
|
||||
return kernelBundle;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLSLComputeController::bindBufferAndProgram() {
|
||||
|
||||
if (_currentBindState.buffer) {
|
||||
// src
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, _currentBindState.buffer);
|
||||
// dst
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, _currentBindState.buffer);
|
||||
}
|
||||
|
||||
_currentBindState.kernelBundle->UseProgram();
|
||||
|
||||
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
|
||||
}
|
||||
|
||||
void
|
||||
GLSLComputeController::unbindBufferAndProgram() {
|
||||
|
||||
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,210 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_GLSL_COMPUTE_CONTROLLER_H
|
||||
#define OSD_GLSL_COMPUTE_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/glslComputeContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Compute controller for launching GLSL Compute subdivision kernels.
|
||||
///
|
||||
/// GLSLComputeController is a compute controller class to launch
|
||||
/// GLSLCompute transfrom feedback subdivision kernels. It requires
|
||||
/// GLVertexBufferInterface as arguments of Refine function.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class GLSLComputeController {
|
||||
public:
|
||||
typedef GLSLComputeContext ComputeContext;
|
||||
|
||||
/// Constructor.
|
||||
GLSLComputeController();
|
||||
|
||||
/// Destructor.
|
||||
~GLSLComputeController();
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The OsdGLSLContext to apply refinement operations to
|
||||
///
|
||||
/// @param batches Vector of batches of vertices organized by operative
|
||||
/// kernel
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param vertexDesc The descriptor of vertex elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
/// @param varyingBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param varyingDesc The descriptor of varying elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void Compute( GLSLComputeContext const * context,
|
||||
VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc=NULL,
|
||||
VertexBufferDescriptor const * varyingDesc=NULL ){
|
||||
|
||||
if (vertexBuffer) {
|
||||
bind(vertexBuffer, vertexDesc);
|
||||
|
||||
context->BindVertexStencilTables();
|
||||
|
||||
ApplyStencilTableKernel(
|
||||
context, context->GetNumStencilsInVertexStencilTables());
|
||||
}
|
||||
|
||||
if (varyingBuffer) {
|
||||
bind(varyingBuffer, varyingDesc);
|
||||
|
||||
context->BindVaryingStencilTables();
|
||||
|
||||
ApplyStencilTableKernel(
|
||||
context, context->GetNumStencilsInVaryingStencilTables());
|
||||
}
|
||||
|
||||
context->UnbindStencilTables();
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The OsdGLSLContext to apply refinement operations to
|
||||
///
|
||||
/// @param batches Vector of batches of vertices organized by operative
|
||||
/// kernel
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
template<class VERTEX_BUFFER>
|
||||
void Compute(GLSLComputeContext const * context,
|
||||
VERTEX_BUFFER *vertexBuffer) {
|
||||
|
||||
Compute<VERTEX_BUFFER>(context, vertexBuffer, (VERTEX_BUFFER*)0);
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
protected:
|
||||
|
||||
void ApplyStencilTableKernel(ComputeContext const *context,
|
||||
int numStencils) const;
|
||||
|
||||
template<class BUFFER>
|
||||
void bind( BUFFER * buffer,
|
||||
VertexBufferDescriptor const * desc ) {
|
||||
|
||||
assert(buffer);
|
||||
|
||||
// if the vertex buffer descriptor is specified, use it
|
||||
// otherwise, assumes the data is tightly packed in the vertex buffer.
|
||||
if (desc) {
|
||||
_currentBindState.desc = *desc;
|
||||
} else {
|
||||
int numElements = buffer ? buffer->GetNumElements() : 0;
|
||||
_currentBindState.desc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
_currentBindState.buffer = buffer->BindVBO();
|
||||
|
||||
_currentBindState.kernelBundle = getKernel(_currentBindState.desc);
|
||||
|
||||
bindBufferAndProgram();
|
||||
}
|
||||
|
||||
|
||||
// Unbinds any previously bound vertex and varying data buffers.
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
unbindBufferAndProgram();
|
||||
}
|
||||
|
||||
// binds the primvar data buffer and compute program
|
||||
void bindBufferAndProgram();
|
||||
|
||||
// unbinds the primvar data buffer and compute program
|
||||
void unbindBufferAndProgram();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
class KernelBundle;
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of the vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : buffer(0), kernelBundle(0) { }
|
||||
|
||||
void Reset() {
|
||||
buffer = 0;
|
||||
desc.Reset();
|
||||
kernelBundle = 0;
|
||||
}
|
||||
|
||||
GLuint buffer;
|
||||
|
||||
VertexBufferDescriptor desc;
|
||||
|
||||
KernelBundle const * kernelBundle;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
|
||||
typedef std::vector<KernelBundle *> KernelRegistry;
|
||||
|
||||
KernelBundle const * getKernel(VertexBufferDescriptor const &desc);
|
||||
|
||||
KernelRegistry _kernelRegistry;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_GLSL_COMPUTE_CONTROLLER_H
|
@ -1,253 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
//#define OSD_DEBUG_BUILD
|
||||
//#include "../osd/debug.h"
|
||||
#include "../osd/glslTransformFeedbackComputeContext.h"
|
||||
#include "../osd/opengl.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template <class T> GLuint
|
||||
createGLTextureBuffer(std::vector<T> const & src, GLenum type) {
|
||||
|
||||
int size = (int)src.size()*sizeof(T);
|
||||
void const * ptr = &src.at(0);
|
||||
|
||||
GLuint buffer;
|
||||
glGenBuffers(1, &buffer);
|
||||
|
||||
GLuint devicePtr;
|
||||
glGenTextures(1, &devicePtr);
|
||||
|
||||
#if defined(GL_EXT_direct_state_access)
|
||||
if (glNamedBufferDataEXT and glTextureBufferEXT) {
|
||||
glNamedBufferDataEXT(buffer, size, ptr, GL_STATIC_DRAW);
|
||||
glTextureBufferEXT(devicePtr, GL_TEXTURE_BUFFER, type, buffer);
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
GLint prev = 0;
|
||||
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev);
|
||||
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);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, devicePtr);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, type, buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, prev);
|
||||
}
|
||||
|
||||
glDeleteBuffers(1, &buffer);
|
||||
|
||||
//OSD_DEBUG_CHECK_GL_ERROR("createGLTextureBuffer end\n");
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class GLSLTransformFeedbackComputeContext::GLStencilTables {
|
||||
|
||||
public:
|
||||
|
||||
GLStencilTables(Far::StencilTables const & stencilTables) {
|
||||
_numStencils = stencilTables.GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createGLTextureBuffer(stencilTables.GetSizes(), GL_R8UI);
|
||||
_offsets = createGLTextureBuffer(stencilTables.GetOffsets(), GL_R32I);
|
||||
_indices = createGLTextureBuffer(stencilTables.GetControlIndices(), GL_R32I);
|
||||
_weights = createGLTextureBuffer(stencilTables.GetWeights(), GL_R32F);
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~GLStencilTables() {
|
||||
if (_sizes) glDeleteTextures(1, &_sizes);
|
||||
if (_offsets) glDeleteTextures(1, &_offsets);
|
||||
if (_weights) glDeleteTextures(1, &_weights);
|
||||
if (_indices) glDeleteTextures(1, &_indices);
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return _sizes and _offsets and _indices and _weights;
|
||||
}
|
||||
|
||||
GLuint GetSizes() const {
|
||||
return _sizes;
|
||||
}
|
||||
|
||||
GLuint GetOffsets() const {
|
||||
return _offsets;
|
||||
}
|
||||
|
||||
GLuint GetIndices() const {
|
||||
return _indices;
|
||||
}
|
||||
|
||||
GLuint GetWeights() const {
|
||||
return _weights;
|
||||
}
|
||||
|
||||
int GetNumStencils() const {
|
||||
return _numStencils;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
GLuint _sizes,
|
||||
_offsets,
|
||||
_indices,
|
||||
_weights;
|
||||
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
GLSLTransformFeedbackComputeContext::GLSLTransformFeedbackComputeContext(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables) :
|
||||
_vertexStencilTables(0), _varyingStencilTables(0),
|
||||
_numControlVertices(0) {
|
||||
|
||||
if (vertexStencilTables) {
|
||||
_vertexStencilTables = new GLStencilTables(*vertexStencilTables);
|
||||
_numControlVertices = vertexStencilTables->GetNumControlVertices();
|
||||
}
|
||||
|
||||
if (varyingStencilTables) {
|
||||
_varyingStencilTables = new GLStencilTables(*varyingStencilTables);
|
||||
|
||||
if (_numControlVertices) {
|
||||
assert(_numControlVertices==varyingStencilTables->GetNumControlVertices());
|
||||
} else {
|
||||
_numControlVertices = varyingStencilTables->GetNumControlVertices();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLSLTransformFeedbackComputeContext::~GLSLTransformFeedbackComputeContext() {
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
GLSLTransformFeedbackComputeContext::HasVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
GLSLTransformFeedbackComputeContext::HasVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
int
|
||||
GLSLTransformFeedbackComputeContext::GetNumStencilsInVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
int
|
||||
GLSLTransformFeedbackComputeContext::GetNumStencilsInVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GLuint
|
||||
GLSLTransformFeedbackComputeContext::GetVertexStencilTablesSizes() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetSizes() : 0;
|
||||
}
|
||||
|
||||
GLuint
|
||||
GLSLTransformFeedbackComputeContext::GetVertexStencilTablesOffsets() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetOffsets() : 0;
|
||||
}
|
||||
|
||||
GLuint
|
||||
GLSLTransformFeedbackComputeContext::GetVertexStencilTablesIndices() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetIndices() : 0;
|
||||
}
|
||||
|
||||
GLuint
|
||||
GLSLTransformFeedbackComputeContext::GetVertexStencilTablesWeights() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetWeights() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
GLuint
|
||||
GLSLTransformFeedbackComputeContext::GetVaryingStencilTablesSizes() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetSizes() : 0;
|
||||
}
|
||||
|
||||
GLuint
|
||||
GLSLTransformFeedbackComputeContext::GetVaryingStencilTablesOffsets() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetOffsets() : 0;
|
||||
}
|
||||
|
||||
GLuint
|
||||
GLSLTransformFeedbackComputeContext::GetVaryingStencilTablesIndices() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetIndices() : 0;
|
||||
}
|
||||
|
||||
GLuint
|
||||
GLSLTransformFeedbackComputeContext::GetVaryingStencilTablesWeights() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetWeights() : 0;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
GLSLTransformFeedbackComputeContext *
|
||||
GLSLTransformFeedbackComputeContext::Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
GLSLTransformFeedbackComputeContext *result =
|
||||
new GLSLTransformFeedbackComputeContext(
|
||||
vertexStencilTables, varyingStencilTables);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,134 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_GLSL_TRANSFORM_FEEDBACK_COMPUTE_CONTEXT_H
|
||||
#define OSD_GLSL_TRANSFORM_FEEDBACK_COMPUTE_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/opengl.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far{ class StencilTables; }
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief GLSL-Compute(transform-feedback) Refine Context
|
||||
///
|
||||
/// The GLSL (transform-feedback) implementation of the Refine module contextual functionality.
|
||||
///
|
||||
/// Contexts interface the serialized topological data pertaining to the
|
||||
/// geometric primitives with the capabilities of the selected discrete
|
||||
/// compute device.
|
||||
///
|
||||
class GLSLTransformFeedbackComputeContext {
|
||||
public:
|
||||
/// Creates an GLSLTransformFeedbackComputeContext instance
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
static GLSLTransformFeedbackComputeContext * Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Destructor
|
||||
virtual ~GLSLTransformFeedbackComputeContext();
|
||||
|
||||
/// Returns true if the Context has a 'vertex' interpolation stencil table
|
||||
bool HasVertexStencilTables() const;
|
||||
|
||||
/// Returns true if the Context has a 'varying' interpolation stencil table
|
||||
bool HasVaryingStencilTables() const;
|
||||
|
||||
/// Returns the number of control vertices
|
||||
int GetNumControlVertices() const {
|
||||
return _numControlVertices;
|
||||
}
|
||||
|
||||
/// Returns the number of stencils in vertex stencil table
|
||||
int GetNumStencilsInVertexStencilTables() const;
|
||||
|
||||
/// Returns the number of stencils in varying stencil table
|
||||
int GetNumStencilsInVaryingStencilTables() const;
|
||||
|
||||
/// Returns the GL texture buffer containing vertex-stencil stencil sizes
|
||||
GLuint GetVertexStencilTablesSizes() const;
|
||||
|
||||
/// Returns the GL texture buffer containing vertex-stencil stencil offsets
|
||||
GLuint GetVertexStencilTablesOffsets() const;
|
||||
|
||||
/// Returns the GL texture buffer containing vertex-stencil stencil indices
|
||||
GLuint GetVertexStencilTablesIndices() const;
|
||||
|
||||
/// Returns the GL texture buffer containing vertex-stencil stencil weights
|
||||
GLuint GetVertexStencilTablesWeights() const;
|
||||
|
||||
|
||||
/// Returns the GL texture buffer containing Varying-stencil stencil sizes
|
||||
GLuint GetVaryingStencilTablesSizes() const;
|
||||
|
||||
/// Returns the GL texture buffer containing Varying-stencil stencil offsets
|
||||
GLuint GetVaryingStencilTablesOffsets() const;
|
||||
|
||||
/// Returns the GL texture buffer containing Varying-stencil stencil indices
|
||||
GLuint GetVaryingStencilTablesIndices() const;
|
||||
|
||||
/// Returns the GL texture buffer containing Varying-stencil stencil weights
|
||||
GLuint GetVaryingStencilTablesWeights() const;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
explicit GLSLTransformFeedbackComputeContext(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables);
|
||||
|
||||
private:
|
||||
|
||||
class GLStencilTables;
|
||||
|
||||
GLStencilTables * _vertexStencilTables,
|
||||
* _varyingStencilTables;
|
||||
|
||||
int _numControlVertices;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_GLSL_TRANSFORM_FEEDBACK_COMPUTE_CONTEXT_H
|
@ -1,456 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//#define OSD_DEBUG_BUILD
|
||||
#include "../osd/debug.h"
|
||||
#include "../osd/glslTransformFeedbackComputeController.h"
|
||||
#include "../osd/glslTransformFeedbackComputeContext.h"
|
||||
#include "../osd/opengl.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#if _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static const char *shaderSource =
|
||||
#include "../osd/glslTransformFeedbackKernel.gen.h"
|
||||
;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
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);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class GLSLTransformFeedbackComputeController::KernelBundle :
|
||||
NonCopyable<GLSLTransformFeedbackComputeController::KernelBundle> {
|
||||
|
||||
public:
|
||||
|
||||
KernelBundle() :
|
||||
_program(0),
|
||||
_uniformSizes(0),
|
||||
_uniformOffsets(0),
|
||||
_uniformIndices(0),
|
||||
_uniformWeights(0),
|
||||
_uniformStart(0),
|
||||
_uniformEnd(0),
|
||||
_uniformSrcOffset(0) { }
|
||||
|
||||
~KernelBundle() {
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
}
|
||||
}
|
||||
|
||||
void UseProgram() const {
|
||||
glUseProgram(_program);
|
||||
}
|
||||
|
||||
bool Compile(VertexBufferDescriptor const & srcDesc,
|
||||
VertexBufferDescriptor const & dstDesc) {
|
||||
|
||||
// XXX: only store srcDesc.
|
||||
// this is ok since currently this kernel doesn't get called with
|
||||
// different strides for src and dst. This function will be
|
||||
// refactored soon.
|
||||
_desc = VertexBufferDescriptor(0, srcDesc.length, dstDesc.stride);
|
||||
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
_program=0;
|
||||
}
|
||||
_program = glCreateProgram();
|
||||
|
||||
GLuint shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
|
||||
std::ostringstream defines;
|
||||
defines << "#define LENGTH " << srcDesc.length << "\n"
|
||||
<< "#define SRC_STRIDE " << srcDesc.stride << "\n";
|
||||
std::string defineStr = defines.str();
|
||||
|
||||
const char *shaderSources[3] = {"#version 410\n", 0, 0};
|
||||
|
||||
shaderSources[1] = defineStr.c_str();
|
||||
shaderSources[2] = shaderSource;
|
||||
glShaderSource(shader, 3, shaderSources, NULL);
|
||||
glCompileShader(shader);
|
||||
glAttachShader(_program, shader);
|
||||
|
||||
std::vector<std::string> outputs;
|
||||
std::vector<const char *> pOutputs;
|
||||
{
|
||||
// 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.
|
||||
//
|
||||
char attrName[32];
|
||||
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, 32, "outVertexBuffer[%d]", i);
|
||||
outputs.push_back(attrName);
|
||||
}
|
||||
for (int i = primvarOffset + dstDesc.length; i < dstDesc.stride; ++i) {
|
||||
outputs.push_back("gl_SkipComponents1");
|
||||
}
|
||||
|
||||
// convert to char* array
|
||||
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(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);
|
||||
_program = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
// set uniform locations for compute kernels
|
||||
_primvarBuffer = glGetUniformLocation(_program, "vertexBuffer");
|
||||
|
||||
_uniformSizes = glGetUniformLocation(_program, "sizes");
|
||||
_uniformOffsets = glGetUniformLocation(_program, "offsets");
|
||||
_uniformIndices = glGetUniformLocation(_program, "indices");
|
||||
_uniformWeights = glGetUniformLocation(_program, "weights");
|
||||
|
||||
_uniformStart = glGetUniformLocation(_program, "batchStart");
|
||||
_uniformEnd = glGetUniformLocation(_program, "batchEnd");
|
||||
|
||||
_uniformSrcOffset = glGetUniformLocation(_program, "srcOffset");
|
||||
|
||||
OSD_DEBUG_CHECK_GL_ERROR("KernelBundle::Compile");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLint GetPrimvarBufferLocation() const {
|
||||
return _primvarBuffer;
|
||||
}
|
||||
|
||||
GLint GetSizesLocation() const {
|
||||
return _uniformSizes;
|
||||
}
|
||||
|
||||
GLint GetOffsetsLocation() const {
|
||||
return _uniformOffsets;
|
||||
}
|
||||
GLint GetIndicesLocation() const {
|
||||
return _uniformIndices;
|
||||
}
|
||||
GLint GetWeightsLocation() const {
|
||||
return _uniformWeights;
|
||||
}
|
||||
|
||||
void ApplyStencilTableKernel(GLuint srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
GLuint dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
int start, int end) const {
|
||||
|
||||
assert(end >= start);
|
||||
|
||||
(void)srcBuffer; // already bound in bindBufferAndProgram().
|
||||
|
||||
// set batch range
|
||||
glUniform1i(_uniformStart, start);
|
||||
glUniform1i(_uniformEnd, end);
|
||||
glUniform1i(_uniformSrcOffset, srcDesc.offset);
|
||||
|
||||
int count = end - start;
|
||||
|
||||
// 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.offset - (dstDesc.offset % dstDesc.stride);
|
||||
|
||||
// bind destination buffer
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER,
|
||||
0, dstBuffer,
|
||||
dstBufferBindOffset * sizeof(float),
|
||||
count * dstDesc.stride * sizeof(float));
|
||||
|
||||
glBeginTransformFeedback(GL_POINTS);
|
||||
glDrawArrays(GL_POINTS, 0, count);
|
||||
glEndTransformFeedback();
|
||||
|
||||
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
|
||||
|
||||
//OSD_DEBUG_CHECK_GL_ERROR("TransformPrimvarBuffer\n");
|
||||
}
|
||||
|
||||
|
||||
struct Match {
|
||||
|
||||
Match(VertexBufferDescriptor const & d) : desc(d) { }
|
||||
|
||||
bool operator() (KernelBundle const * kernel) {
|
||||
return (desc.length==kernel->_desc.length and
|
||||
desc.stride==kernel->_desc.stride);
|
||||
}
|
||||
|
||||
VertexBufferDescriptor desc;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
GLuint _program;
|
||||
|
||||
GLint _primvarBuffer;
|
||||
|
||||
GLint _uniformSizes, // uniform paramaeters for kernels
|
||||
_uniformOffsets,
|
||||
_uniformIndices,
|
||||
_uniformWeights,
|
||||
|
||||
_uniformStart, // batch
|
||||
_uniformEnd,
|
||||
|
||||
_uniformSrcOffset;
|
||||
|
||||
VertexBufferDescriptor _desc; // primvar buffer descriptor
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void
|
||||
GLSLTransformFeedbackComputeController::bindBufferAndProgram(
|
||||
GLuint & feedbackTexture) {
|
||||
|
||||
glEnable(GL_RASTERIZER_DISCARD);
|
||||
_currentBindState.kernelBundle->UseProgram();
|
||||
|
||||
if (not feedbackTexture) {
|
||||
glGenTextures(1, &feedbackTexture);
|
||||
#if defined(GL_EXT_direct_state_access)
|
||||
if (glTextureBufferEXT) {
|
||||
glTextureBufferEXT(feedbackTexture, GL_TEXTURE_BUFFER, GL_R32F,
|
||||
_currentBindState.buffer);
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
glBindTexture(GL_TEXTURE_BUFFER, feedbackTexture);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, _currentBindState.buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bindTexture(
|
||||
_currentBindState.kernelBundle->GetPrimvarBufferLocation(), feedbackTexture, 0);
|
||||
|
||||
// bind vertex array
|
||||
// always create new one, to be safe with multiple contexts.
|
||||
glGenVertexArrays(1, &_vao);
|
||||
glBindVertexArray(_vao);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
GLSLTransformFeedbackComputeController::bindContextStencilTables(
|
||||
ComputeContext const *context, bool varying) {
|
||||
|
||||
GLint sizesLocation = _currentBindState.kernelBundle->GetSizesLocation(),
|
||||
offsetsLocation = _currentBindState.kernelBundle->GetOffsetsLocation(),
|
||||
indicesLocation = _currentBindState.kernelBundle->GetIndicesLocation(),
|
||||
weightsLocation = _currentBindState.kernelBundle->GetWeightsLocation();
|
||||
|
||||
if (not varying) {
|
||||
bindTexture(sizesLocation, context->GetVertexStencilTablesSizes(), 1);
|
||||
bindTexture(offsetsLocation, context->GetVertexStencilTablesOffsets(), 2);
|
||||
bindTexture(indicesLocation, context->GetVertexStencilTablesIndices(), 3);
|
||||
bindTexture(weightsLocation, context->GetVertexStencilTablesWeights(), 4);
|
||||
} else {
|
||||
bindTexture(sizesLocation, context->GetVaryingStencilTablesSizes(), 1);
|
||||
bindTexture(offsetsLocation, context->GetVaryingStencilTablesOffsets(), 2);
|
||||
bindTexture(indicesLocation, context->GetVaryingStencilTablesIndices(), 3);
|
||||
bindTexture(weightsLocation, context->GetVaryingStencilTablesWeights(), 4);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
GLSLTransformFeedbackComputeController::unbindResources() {
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
|
||||
glDisable(GL_RASTERIZER_DISCARD);
|
||||
glUseProgram(0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glDeleteVertexArrays(1, &_vao);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
GLSLTransformFeedbackComputeController::KernelBundle const *
|
||||
GLSLTransformFeedbackComputeController::getKernel(
|
||||
VertexBufferDescriptor const &desc) {
|
||||
|
||||
KernelRegistry::iterator it =
|
||||
std::find_if(_kernelRegistry.begin(), _kernelRegistry.end(),
|
||||
KernelBundle::Match(desc));
|
||||
|
||||
if (it != _kernelRegistry.end()) {
|
||||
return *it;
|
||||
} else {
|
||||
KernelBundle * kernelBundle = new KernelBundle();
|
||||
kernelBundle->Compile(desc, desc);
|
||||
_kernelRegistry.push_back(kernelBundle);
|
||||
return kernelBundle;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
GLSLTransformFeedbackComputeController::ApplyStencilTableKernel(
|
||||
GLSLTransformFeedbackComputeContext const *context, int numStencils) const {
|
||||
|
||||
assert(context);
|
||||
|
||||
int start = 0;
|
||||
int end = numStencils;
|
||||
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.desc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += context->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
_currentBindState.kernelBundle->ApplyStencilTableKernel(
|
||||
_currentBindState.buffer,
|
||||
srcDesc,
|
||||
_currentBindState.buffer,
|
||||
dstDesc,
|
||||
start,
|
||||
end);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
GLSLTransformFeedbackComputeController::GLSLTransformFeedbackComputeController() :
|
||||
_vertexTexture(0), _varyingTexture(0), _vao(0) {
|
||||
}
|
||||
|
||||
GLSLTransformFeedbackComputeController::~GLSLTransformFeedbackComputeController() {
|
||||
|
||||
for (KernelRegistry::iterator it = _kernelRegistry.begin();
|
||||
it != _kernelRegistry.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
if (_vertexTexture) {
|
||||
glDeleteTextures(1, &_vertexTexture);
|
||||
}
|
||||
if (_varyingTexture) {
|
||||
glDeleteTextures(1, &_varyingTexture);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
GLSLTransformFeedbackComputeController::Synchronize() {
|
||||
glFinish();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,214 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_GLSL_TRANSFORM_FEEDBACK_COMPUTE_CONTROLLER_H
|
||||
#define OSD_GLSL_TRANSFORM_FEEDBACK_COMPUTE_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/glslTransformFeedbackComputeContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class GLSLTransformFeedbackKernelBundle;
|
||||
|
||||
/// \brief Compute controller for launching GLSLTransformFeedback transform feedback
|
||||
/// subdivision kernels.
|
||||
///
|
||||
/// GLSLTransformFeedbackComputeController is a compute controller class to launch
|
||||
/// GLSLTransformFeedback transfrom feedback subdivision kernels. It requires
|
||||
/// GLVertexBufferInterface as arguments of Refine function.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class GLSLTransformFeedbackComputeController {
|
||||
public:
|
||||
typedef GLSLTransformFeedbackComputeContext ComputeContext;
|
||||
|
||||
/// Constructor.
|
||||
GLSLTransformFeedbackComputeController();
|
||||
|
||||
/// Destructor.
|
||||
~GLSLTransformFeedbackComputeController();
|
||||
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The GLSLTransformFeedbackComputeContext to apply
|
||||
/// refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param vertexDesc The descriptor of vertex elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
/// @param varyingBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param varyingDesc The descriptor of varying elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void Compute( GLSLTransformFeedbackComputeContext const * context,
|
||||
VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc=NULL,
|
||||
VertexBufferDescriptor const * varyingDesc=NULL ){
|
||||
|
||||
if (vertexBuffer) {
|
||||
|
||||
bind(vertexBuffer, vertexDesc, _vertexTexture);
|
||||
|
||||
bindContextStencilTables(context, false);
|
||||
|
||||
ApplyStencilTableKernel(
|
||||
context, context->GetNumStencilsInVertexStencilTables());
|
||||
}
|
||||
|
||||
if (varyingBuffer) {
|
||||
|
||||
bind(varyingBuffer, varyingDesc, _varyingTexture);
|
||||
|
||||
bindContextStencilTables(context, true);
|
||||
|
||||
ApplyStencilTableKernel(
|
||||
context, context->GetNumStencilsInVaryingStencilTables());
|
||||
}
|
||||
unbind();
|
||||
}
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The GLSLTransformFeedbackComputeContext to apply
|
||||
/// refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
template<class VERTEX_BUFFER>
|
||||
void Compute(GLSLTransformFeedbackComputeContext const * context,
|
||||
VERTEX_BUFFER *vertexBuffer) {
|
||||
|
||||
Compute<VERTEX_BUFFER>(context, vertexBuffer, (VERTEX_BUFFER*)0);
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
protected:
|
||||
|
||||
void ApplyStencilTableKernel(ComputeContext const *context,
|
||||
int numStencils) const;
|
||||
|
||||
template<class BUFFER>
|
||||
void bind( BUFFER * buffer, VertexBufferDescriptor const * desc,
|
||||
GLuint feedbackTexture ) {
|
||||
|
||||
assert(buffer);
|
||||
|
||||
// if the vertex buffer descriptor is specified, use it
|
||||
// otherwise, assumes the data is tightly packed in the vertex buffer.
|
||||
if (desc) {
|
||||
_currentBindState.desc = *desc;
|
||||
} else {
|
||||
int numElements = buffer ? buffer->GetNumElements() : 0;
|
||||
_currentBindState.desc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
_currentBindState.buffer = buffer->BindVBO();
|
||||
|
||||
_currentBindState.kernelBundle = getKernel(_currentBindState.desc);
|
||||
|
||||
bindBufferAndProgram(feedbackTexture);
|
||||
}
|
||||
|
||||
// Unbinds any previously bound vertex and varying data buffers.
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
unbindResources();
|
||||
}
|
||||
|
||||
// binds the primvar data buffer and compute program
|
||||
void bindBufferAndProgram(GLuint & texture);
|
||||
|
||||
// binds the stencil tables for 'vertex' interpolation
|
||||
void bindContextStencilTables(ComputeContext const *context, bool varying=false);
|
||||
|
||||
// unbinds the primvar data buffer and compute program
|
||||
void unbindResources();
|
||||
|
||||
private:
|
||||
|
||||
class KernelBundle;
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of the vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : buffer(0), kernelBundle(0) { }
|
||||
|
||||
void Reset() {
|
||||
buffer = 0;
|
||||
desc.Reset();
|
||||
kernelBundle = 0;
|
||||
}
|
||||
|
||||
GLuint buffer;
|
||||
|
||||
VertexBufferDescriptor desc;
|
||||
|
||||
KernelBundle const * kernelBundle;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
|
||||
typedef std::vector<KernelBundle *> KernelRegistry;
|
||||
|
||||
KernelBundle const * getKernel(VertexBufferDescriptor const &desc);
|
||||
|
||||
KernelRegistry _kernelRegistry;
|
||||
|
||||
GLuint _vertexTexture,
|
||||
_varyingTexture,
|
||||
_vao;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_GLSL_TRANSFORM_FEEDBACK_COMPUTE_CONTROLLER_H
|
@ -39,6 +39,8 @@
|
||||
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
@ -80,13 +82,6 @@ public:
|
||||
|
||||
virtual void Refine() = 0;
|
||||
|
||||
virtual void Refine(VertexBufferDescriptor const *vertexDesc,
|
||||
VertexBufferDescriptor const *varyingDesc) = 0;
|
||||
|
||||
virtual void Refine(VertexBufferDescriptor const *vertexDesc,
|
||||
VertexBufferDescriptor const *varyingDesc,
|
||||
bool interleaved) = 0;
|
||||
|
||||
virtual void Synchronize() = 0;
|
||||
|
||||
virtual DrawContext * GetDrawContext() = 0;
|
||||
@ -119,25 +114,143 @@ protected:
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <class VERTEX_BUFFER,
|
||||
class COMPUTE_CONTROLLER,
|
||||
class DRAW_CONTEXT,
|
||||
class DEVICE_CONTEXT = void>
|
||||
template <typename STENCIL_TABLES, typename DEVICE_CONTEXT>
|
||||
STENCIL_TABLES const *
|
||||
convertToCompatibleStencilTables(
|
||||
Far::StencilTables const *table, DEVICE_CONTEXT *context) {
|
||||
if (not table) return NULL;
|
||||
return STENCIL_TABLES::Create(table, context);
|
||||
}
|
||||
|
||||
template <>
|
||||
Far::StencilTables const *
|
||||
convertToCompatibleStencilTables<Far::StencilTables, void>(
|
||||
Far::StencilTables const *table, void * /*context*/) {
|
||||
// no need for conversion
|
||||
// XXX: We don't want to even copy.
|
||||
if (not table) return NULL;
|
||||
return new Far::StencilTables(*table);
|
||||
}
|
||||
|
||||
template <>
|
||||
Far::StencilTables const *
|
||||
convertToCompatibleStencilTables<Far::StencilTables, ID3D11DeviceContext>(
|
||||
Far::StencilTables const *table, ID3D11DeviceContext * /*context*/) {
|
||||
// no need for conversion
|
||||
// XXX: We don't want to even copy.
|
||||
if (not table) return NULL;
|
||||
return new Far::StencilTables(*table);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
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(VertexBufferDescriptor const &sd,
|
||||
VertexBufferDescriptor const &dd,
|
||||
EVALUATOR *e) : srcDesc(sd), dstDesc(dd), evaluator(e) {}
|
||||
VertexBufferDescriptor srcDesc, dstDesc;
|
||||
EVALUATOR *evaluator;
|
||||
};
|
||||
typedef std::vector<Entry> Evaluators;
|
||||
|
||||
template <typename DEVICE_CONTEXT>
|
||||
EVALUATOR *GetEvaluator(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
DEVICE_CONTEXT *deviceContext) {
|
||||
|
||||
for(typename Evaluators::iterator it = _evaluators.begin();
|
||||
it != _evaluators.end(); ++it) {
|
||||
if (it->srcDesc.length == srcDesc.length and
|
||||
it->srcDesc.stride == srcDesc.stride and
|
||||
it->dstDesc.length == dstDesc.length and
|
||||
it->dstDesc.stride == dstDesc.stride) {
|
||||
return it->evaluator;
|
||||
}
|
||||
}
|
||||
EVALUATOR *e = EVALUATOR::Create(srcDesc, dstDesc, deviceContext);
|
||||
_evaluators.push_back(Entry(srcDesc, dstDesc, e));
|
||||
return e;
|
||||
}
|
||||
|
||||
private:
|
||||
Evaluators _evaluators;
|
||||
};
|
||||
|
||||
|
||||
// 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> { };
|
||||
|
||||
// extract a kernel from cache if available
|
||||
template <typename EVALUATOR, typename DEVICE_CONTEXT>
|
||||
static EVALUATOR *GetEvaluator(
|
||||
EvaluatorCacheT<EVALUATOR> *cache,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor 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, deviceContext);
|
||||
}
|
||||
|
||||
// fallback
|
||||
template <typename EVALUATOR, typename DEVICE_CONTEXT>
|
||||
static EVALUATOR *GetEvaluator(
|
||||
EvaluatorCacheT<EVALUATOR> *,
|
||||
VertexBufferDescriptor const &,
|
||||
VertexBufferDescriptor const &,
|
||||
DEVICE_CONTEXT,
|
||||
typename enable_if<!instantiatable<EVALUATOR>::value, void>::type*t=0) {
|
||||
(void)t;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <typename VERTEX_BUFFER,
|
||||
typename STENCIL_TABLES,
|
||||
typename EVALUATOR,
|
||||
typename DRAW_CONTEXT,
|
||||
typename DEVICE_CONTEXT = void>
|
||||
class Mesh : public MeshInterface<DRAW_CONTEXT> {
|
||||
public:
|
||||
typedef VERTEX_BUFFER VertexBuffer;
|
||||
typedef COMPUTE_CONTROLLER ComputeController;
|
||||
typedef EVALUATOR Evaluator;
|
||||
typedef STENCIL_TABLES StencilTables;
|
||||
typedef DRAW_CONTEXT DrawContext;
|
||||
typedef DEVICE_CONTEXT DeviceContext;
|
||||
typedef typename ComputeController::ComputeContext ComputeContext;
|
||||
typedef EvaluatorCacheT<Evaluator> EvaluatorCache;
|
||||
typedef typename DrawContext::VertexBufferBinding VertexBufferBinding;
|
||||
|
||||
Mesh(ComputeController * computeController,
|
||||
Far::TopologyRefiner * refiner,
|
||||
Mesh(Far::TopologyRefiner * refiner,
|
||||
int numVertexElements,
|
||||
int numVaryingElements,
|
||||
int level,
|
||||
MeshBitset bits = MeshBitset(),
|
||||
EvaluatorCache * evaluatorCache = NULL,
|
||||
DeviceContext * deviceContext = NULL) :
|
||||
|
||||
_refiner(refiner),
|
||||
@ -145,8 +258,9 @@ public:
|
||||
_numVertices(0),
|
||||
_vertexBuffer(NULL),
|
||||
_varyingBuffer(NULL),
|
||||
_computeContext(NULL),
|
||||
_computeController(computeController),
|
||||
_vertexStencilTables(NULL),
|
||||
_varyingStencilTables(NULL),
|
||||
_evaluatorCache(evaluatorCache),
|
||||
_drawContext(NULL),
|
||||
_deviceContext(deviceContext) {
|
||||
|
||||
@ -157,18 +271,34 @@ public:
|
||||
bits.test(MeshAdaptive),
|
||||
bits.test(MeshUseSingleCreasePatch));
|
||||
|
||||
int numVertexElementsInterleaved = numVertexElements +
|
||||
int vertexBufferStride = numVertexElements +
|
||||
(bits.test(MeshInterleaveVarying) ? numVaryingElements : 0);
|
||||
int numVaryingElementsNonInterleaved =
|
||||
int varyingBufferStride =
|
||||
(bits.test(MeshInterleaveVarying) ? 0 : numVaryingElements);
|
||||
|
||||
initializeContext(numVertexElements,
|
||||
numVaryingElements,
|
||||
numVertexElementsInterleaved, level, bits);
|
||||
vertexBufferStride, level, bits);
|
||||
|
||||
initializeVertexBuffers(_numVertices,
|
||||
numVertexElementsInterleaved,
|
||||
numVaryingElementsNonInterleaved);
|
||||
vertexBufferStride,
|
||||
varyingBufferStride);
|
||||
|
||||
// configure vertex buffer descriptor
|
||||
_vertexDesc = VertexBufferDescriptor(0,
|
||||
numVertexElements,
|
||||
vertexBufferStride);
|
||||
if (bits.test(MeshInterleaveVarying)) {
|
||||
_varyingDesc = VertexBufferDescriptor(numVertexElements,
|
||||
numVaryingElements,
|
||||
vertexBufferStride);
|
||||
} else {
|
||||
_varyingDesc = VertexBufferDescriptor(0,
|
||||
numVaryingElements,
|
||||
varyingBufferStride);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// will retire
|
||||
_drawContext->UpdateVertexTexture(_vertexBuffer, _deviceContext);
|
||||
@ -179,9 +309,10 @@ public:
|
||||
delete _patchTables;
|
||||
delete _vertexBuffer;
|
||||
delete _varyingBuffer;
|
||||
delete _computeContext;
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
delete _drawContext;
|
||||
// devicecontext and computecontroller are not owned by this class.
|
||||
// deviceContext and evaluatorCache are not owned by this class.
|
||||
}
|
||||
|
||||
virtual void UpdateVertexBuffer(float const *vertexData,
|
||||
@ -197,29 +328,50 @@ public:
|
||||
}
|
||||
|
||||
virtual void Refine() {
|
||||
_computeController->Compute(_computeContext,
|
||||
_vertexBuffer, _varyingBuffer);
|
||||
}
|
||||
|
||||
virtual void Refine(VertexBufferDescriptor const *vertexDesc,
|
||||
VertexBufferDescriptor const *varyingDesc) {
|
||||
_computeController->Compute(_computeContext,
|
||||
_vertexBuffer, _varyingBuffer,
|
||||
vertexDesc, varyingDesc);
|
||||
}
|
||||
int numControlVertices = _refiner->GetNumVertices(0);
|
||||
|
||||
virtual void Refine(VertexBufferDescriptor const *vertexDesc,
|
||||
VertexBufferDescriptor const *varyingDesc,
|
||||
bool interleaved) {
|
||||
_computeController->Compute(_computeContext,
|
||||
_vertexBuffer,
|
||||
(interleaved ?
|
||||
_vertexBuffer : _varyingBuffer),
|
||||
vertexDesc, varyingDesc);
|
||||
VertexBufferDescriptor srcDesc = _vertexDesc;
|
||||
VertexBufferDescriptor 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,
|
||||
_vertexStencilTables,
|
||||
instance, _deviceContext);
|
||||
|
||||
if (_varyingDesc.length > 0) {
|
||||
VertexBufferDescriptor srcDesc = _varyingDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += numControlVertices * dstDesc.stride;
|
||||
|
||||
instance = GetEvaluator<Evaluator>(
|
||||
_evaluatorCache, srcDesc, dstDesc, _deviceContext);
|
||||
|
||||
if (_varyingBuffer) {
|
||||
// non-interleaved
|
||||
Evaluator::EvalStencils(_varyingBuffer, srcDesc,
|
||||
_varyingBuffer, dstDesc,
|
||||
_varyingStencilTables,
|
||||
instance, _deviceContext);
|
||||
} else {
|
||||
// interleaved
|
||||
Evaluator::EvalStencils(_vertexBuffer, srcDesc,
|
||||
_vertexBuffer, dstDesc,
|
||||
_varyingStencilTables,
|
||||
instance, _deviceContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Synchronize() {
|
||||
_computeController->Synchronize();
|
||||
Evaluator::Synchronize(_deviceContext);
|
||||
}
|
||||
|
||||
virtual DrawContext * GetDrawContext() {
|
||||
@ -333,14 +485,20 @@ private:
|
||||
|
||||
_drawContext = DrawContext::Create(_patchTables, numElements,
|
||||
_deviceContext);
|
||||
_computeContext = ComputeContext::Create(vertexStencils,
|
||||
varyingStencils,
|
||||
_deviceContext);
|
||||
|
||||
// numvertices = coarse verts + refined verts + gregory basis verts
|
||||
_numVertices = vertexStencils->GetNumControlVertices()
|
||||
+ vertexStencils->GetNumStencils();
|
||||
|
||||
// convert to device stenciltables if necessary.
|
||||
_vertexStencilTables =
|
||||
convertToCompatibleStencilTables<StencilTables>(
|
||||
vertexStencils, _deviceContext);
|
||||
_varyingStencilTables =
|
||||
convertToCompatibleStencilTables<StencilTables>(
|
||||
varyingStencils, _deviceContext);
|
||||
|
||||
// FIXME: we do extra copyings for Far::Stencils.
|
||||
delete vertexStencils;
|
||||
delete varyingStencils;
|
||||
}
|
||||
@ -365,14 +523,17 @@ private:
|
||||
|
||||
int _numVertices;
|
||||
|
||||
VertexBuffer * _vertexBuffer,
|
||||
* _varyingBuffer;
|
||||
VertexBuffer * _vertexBuffer;
|
||||
VertexBuffer * _varyingBuffer;
|
||||
|
||||
ComputeContext * _computeContext;
|
||||
ComputeController * _computeController;
|
||||
VertexBufferDescriptor _vertexDesc;
|
||||
VertexBufferDescriptor _varyingDesc;
|
||||
|
||||
StencilTables const * _vertexStencilTables;
|
||||
StencilTables const * _varyingStencilTables;
|
||||
EvaluatorCache * _evaluatorCache;
|
||||
|
||||
DrawContext *_drawContext;
|
||||
|
||||
DeviceContext *_deviceContext;
|
||||
};
|
||||
|
||||
|
@ -1,104 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../osd/ompComputeController.h"
|
||||
#include "../osd/ompKernel.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
OmpComputeController::OmpComputeController(int numThreads) {
|
||||
|
||||
_numThreads = (numThreads == -1) ? omp_get_max_threads() : numThreads;
|
||||
}
|
||||
|
||||
void
|
||||
OmpComputeController::ApplyStencilTableKernel(
|
||||
ComputeContext const *context) const {
|
||||
|
||||
assert(context);
|
||||
|
||||
Far::StencilTables const * vertexStencils = context->GetVertexStencilTables();
|
||||
|
||||
if (vertexStencils and _currentBindState.vertexBuffer) {
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.vertexDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += vertexStencils->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
int start = 0;
|
||||
int end = vertexStencils->GetNumStencils();
|
||||
|
||||
if (end > start) {
|
||||
OmpComputeStencils(_currentBindState.vertexBuffer,
|
||||
srcDesc,
|
||||
_currentBindState.vertexBuffer,
|
||||
dstDesc,
|
||||
&vertexStencils->GetSizes().at(0),
|
||||
&vertexStencils->GetOffsets().at(0),
|
||||
&vertexStencils->GetControlIndices().at(0),
|
||||
&vertexStencils->GetWeights().at(0),
|
||||
start,
|
||||
end);
|
||||
}
|
||||
}
|
||||
|
||||
Far::StencilTables const * varyingStencils = context->GetVaryingStencilTables();
|
||||
|
||||
if (varyingStencils and _currentBindState.varyingBuffer) {
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.varyingDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += varyingStencils->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
int start = 0;
|
||||
int end = varyingStencils->GetNumStencils();
|
||||
|
||||
if (end > start) {
|
||||
OmpComputeStencils(_currentBindState.varyingBuffer,
|
||||
srcDesc,
|
||||
_currentBindState.varyingBuffer,
|
||||
dstDesc,
|
||||
&varyingStencils->GetSizes().at(0),
|
||||
&varyingStencils->GetOffsets().at(0),
|
||||
&varyingStencils->GetControlIndices().at(0),
|
||||
&varyingStencils->GetWeights().at(0),
|
||||
start,
|
||||
end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OmpComputeController::Synchronize() {
|
||||
// XXX:
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,184 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_OMP_COMPUTE_CONTROLLER_H
|
||||
#define OSD_OMP_COMPUTE_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/cpuComputeContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Compute controller for launching OpenMP subdivision kernels.
|
||||
///
|
||||
/// OmpComputeController is a compute controller class to launch OpenMP
|
||||
/// threaded subdivision kernels. It requires CpuVertexBufferInterface
|
||||
/// as arguments of Refine function.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class OmpComputeController {
|
||||
public:
|
||||
typedef CpuComputeContext ComputeContext;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param numThreads specifies how many openmp parallel threads to use.
|
||||
/// -1 attempts to use all available processors.
|
||||
///
|
||||
explicit OmpComputeController(int numThreads=-1);
|
||||
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CpuContext to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param vertexDesc The descriptor of vertex elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
/// @param varyingBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param varyingDesc The descriptor of varying elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void Compute( CpuComputeContext const * context,
|
||||
VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc=NULL,
|
||||
VertexBufferDescriptor const * varyingDesc=NULL ){
|
||||
|
||||
omp_set_num_threads(_numThreads);
|
||||
|
||||
bind(vertexBuffer, varyingBuffer, vertexDesc, varyingDesc);
|
||||
|
||||
ApplyStencilTableKernel(context);
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CpuContext to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
template<class VERTEX_BUFFER>
|
||||
void Compute(CpuComputeContext const * context,
|
||||
VERTEX_BUFFER *vertexBuffer) {
|
||||
|
||||
Compute<VERTEX_BUFFER>(context, vertexBuffer, (VERTEX_BUFFER*)0);
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
protected:
|
||||
|
||||
void ApplyStencilTableKernel(ComputeContext const *context) const;
|
||||
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void bind( VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc,
|
||||
VertexBufferDescriptor const * varyingDesc ) {
|
||||
|
||||
// if the vertex buffer descriptor is specified, use it.
|
||||
// otherwise, assumes the data is tightly packed in the vertex buffer.
|
||||
if (vertexDesc) {
|
||||
_currentBindState.vertexDesc = *vertexDesc;
|
||||
} else {
|
||||
int numElements = vertexBuffer ? vertexBuffer->GetNumElements() : 0;
|
||||
_currentBindState.vertexDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
if (varyingDesc) {
|
||||
_currentBindState.varyingDesc = *varyingDesc;
|
||||
} else {
|
||||
int numElements = varyingBuffer ? varyingBuffer->GetNumElements() : 0;
|
||||
_currentBindState.varyingDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
_currentBindState.vertexBuffer = vertexBuffer ?
|
||||
vertexBuffer->BindCpuBuffer() : 0;
|
||||
|
||||
_currentBindState.varyingBuffer = varyingBuffer ?
|
||||
varyingBuffer->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of the vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : vertexBuffer(0), varyingBuffer(0) { }
|
||||
|
||||
void Reset() {
|
||||
vertexBuffer = varyingBuffer = 0;
|
||||
vertexDesc.Reset();
|
||||
varyingDesc.Reset();
|
||||
}
|
||||
|
||||
float * vertexBuffer,
|
||||
* varyingBuffer;
|
||||
|
||||
VertexBufferDescriptor vertexDesc,
|
||||
varyingDesc;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
int _numThreads;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_OMP_COMPUTE_CONTROLLER_H
|
@ -1,155 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/ompEvalStencilsController.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
OmpEvalStencilsController::OmpEvalStencilsController(int numThreads) {
|
||||
|
||||
_numThreads = (numThreads == -1) ? omp_get_num_procs() : numThreads;
|
||||
}
|
||||
|
||||
OmpEvalStencilsController::~OmpEvalStencilsController() {
|
||||
}
|
||||
|
||||
int
|
||||
OmpEvalStencilsController::_UpdateValues( CpuEvalStencilsContext * context ) {
|
||||
|
||||
int result=0;
|
||||
|
||||
Far::LimitStencilTables const * stencils = context->GetStencilTables();
|
||||
|
||||
int nstencils = stencils->GetNumStencils();
|
||||
if (not nstencils)
|
||||
return result;
|
||||
|
||||
VertexBufferDescriptor ctrlDesc = _currentBindState.controlDataDesc,
|
||||
outDesc = _currentBindState.outputDataDesc;
|
||||
|
||||
// make sure that we have control data to work with
|
||||
if (not ctrlDesc.CanEval(outDesc))
|
||||
return 0;
|
||||
|
||||
float const * ctrl = _currentBindState.controlData + ctrlDesc.offset;
|
||||
|
||||
if (not ctrl)
|
||||
return result;
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int i=0; i<nstencils; ++i) {
|
||||
|
||||
int size = stencils->GetSizes()[i];
|
||||
Far::Index offset = stencils->GetOffsets()[i];
|
||||
|
||||
Far::Index const * index = &stencils->GetControlIndices().at(offset);
|
||||
|
||||
float const * weight = &stencils->GetWeights().at(offset);
|
||||
|
||||
float * out = _currentBindState.outputData + i * outDesc.stride + outDesc.offset;
|
||||
|
||||
memset(out, 0, outDesc.length*sizeof(float));
|
||||
|
||||
for (int j=0; j<size; ++j, ++index, ++weight) {
|
||||
|
||||
float const * cv = ctrl + (*index)*ctrlDesc.stride;
|
||||
|
||||
for (int k=0; k<outDesc.length; ++k) {
|
||||
out[k] += cv[k] * (*weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nstencils;
|
||||
}
|
||||
|
||||
int
|
||||
OmpEvalStencilsController::_UpdateDerivs( CpuEvalStencilsContext * context ) {
|
||||
|
||||
int result=0;
|
||||
|
||||
Far::LimitStencilTables const * stencils = context->GetStencilTables();
|
||||
|
||||
int nstencils = stencils->GetNumStencils();
|
||||
if (not nstencils)
|
||||
return result;
|
||||
|
||||
VertexBufferDescriptor ctrlDesc = _currentBindState.controlDataDesc,
|
||||
duDesc = _currentBindState.outputDuDesc,
|
||||
dvDesc = _currentBindState.outputDvDesc;
|
||||
|
||||
// make sure that we have control data to work with
|
||||
if (not (ctrlDesc.CanEval(duDesc) and ctrlDesc.CanEval(dvDesc)))
|
||||
return 0;
|
||||
|
||||
float const * ctrl = _currentBindState.controlData + ctrlDesc.offset;
|
||||
|
||||
if (not ctrl)
|
||||
return result;
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int i=0; i<nstencils; ++i) {
|
||||
|
||||
int size = stencils->GetSizes()[i];
|
||||
Far::Index offset = stencils->GetOffsets()[i];
|
||||
|
||||
Far::Index const * index = &stencils->GetControlIndices().at(offset);
|
||||
|
||||
float const * duweight = &stencils->GetDuWeights().at(offset),
|
||||
* dvweight = &stencils->GetDvWeights().at(offset);
|
||||
|
||||
float * du = _currentBindState.outputUDeriv + i * duDesc.stride + duDesc.offset,
|
||||
* dv = _currentBindState.outputVDeriv + i * dvDesc.stride + dvDesc.offset;
|
||||
|
||||
memset(du, 0, duDesc.length*sizeof(float));
|
||||
memset(dv, 0, dvDesc.length*sizeof(float));
|
||||
|
||||
for (int j=0; j<size; ++j, ++index, ++duweight, ++dvweight) {
|
||||
|
||||
float const * cv = ctrl + (*index)*ctrlDesc.stride;
|
||||
|
||||
for (int k=0; k<duDesc.length; ++k) {
|
||||
du[k] += cv[k] * (*duweight);
|
||||
dv[k] += cv[k] * (*dvweight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nstencils;
|
||||
}
|
||||
|
||||
void
|
||||
OmpEvalStencilsController::Synchronize() {
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,221 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef FAR_OMP_EVALSTENCILS_CONTROLLER_H
|
||||
#define FAR_OMP_EVALSTENCILS_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/cpuEvalStencilsContext.h"
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief CPU stencils evaluation controller
|
||||
///
|
||||
/// CpuStencilsController is a compute controller class to launch
|
||||
/// single threaded CPU stencil evalution kernels.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class OmpEvalStencilsController {
|
||||
public:
|
||||
|
||||
/// \brief Constructor.
|
||||
///
|
||||
/// @param numThreads specifies how many openmp parallel threads to use.
|
||||
/// -1 attempts to use all available processors.
|
||||
///
|
||||
OmpEvalStencilsController(int numThreads=-1);
|
||||
|
||||
/// \brief Destructor.
|
||||
~OmpEvalStencilsController();
|
||||
|
||||
|
||||
/// \brief Applies stencil weights to the control vertex data
|
||||
///
|
||||
/// Applies the stencil weights to the control vertex data to evaluate the
|
||||
/// interpolated limit positions at the parametric locations of the stencils
|
||||
///
|
||||
/// @param context the CpuEvalStencilsContext with the stencil weights
|
||||
///
|
||||
/// @param controlDataDesc vertex buffer descriptor for the control vertex data
|
||||
///
|
||||
/// @param controlVertices vertex buffer with the control vertices data
|
||||
///
|
||||
/// @param outputDataDesc vertex buffer descriptor for the output vertex data
|
||||
///
|
||||
/// @param outputData output vertex buffer for the interpolated data
|
||||
///
|
||||
template<class CONTROL_BUFFER, class OUTPUT_BUFFER>
|
||||
int UpdateValues( CpuEvalStencilsContext * context,
|
||||
VertexBufferDescriptor const & controlDataDesc, CONTROL_BUFFER *controlVertices,
|
||||
VertexBufferDescriptor const & outputDataDesc, OUTPUT_BUFFER *outputData ) {
|
||||
|
||||
if (not context->GetStencilTables()->GetNumStencils())
|
||||
return 0;
|
||||
|
||||
omp_set_num_threads(_numThreads);
|
||||
|
||||
bindControlData( controlDataDesc, controlVertices );
|
||||
|
||||
bindOutputData( outputDataDesc, outputData );
|
||||
|
||||
int n = _UpdateValues( context );
|
||||
|
||||
unbind();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/// \brief Applies derivative stencil weights to the control vertex data
|
||||
///
|
||||
/// Computes the U and V derivative stencils to the control vertex data at
|
||||
/// the parametric locations contained in each stencil
|
||||
///
|
||||
/// @param context the CpuEvalStencilsContext with the stencil weights
|
||||
///
|
||||
/// @param controlDataDesc vertex buffer descriptor for the control vertex data
|
||||
///
|
||||
/// @param controlVertices vertex buffer with the control vertices data
|
||||
///
|
||||
/// @param outputDuDesc vertex buffer descriptor for the U derivative output data
|
||||
///
|
||||
/// @param outputDuData output vertex buffer for the U derivative data
|
||||
///
|
||||
/// @param outputDvDesc vertex buffer descriptor for the V deriv output data
|
||||
///
|
||||
/// @param outputDvData output vertex buffer for the V derivative data
|
||||
///
|
||||
template<class CONTROL_BUFFER, class OUTPUT_BUFFER>
|
||||
int UpdateDerivs( CpuEvalStencilsContext * context,
|
||||
VertexBufferDescriptor const & controlDataDesc, CONTROL_BUFFER *controlVertices,
|
||||
VertexBufferDescriptor const & outputDuDesc, OUTPUT_BUFFER *outputDuData,
|
||||
VertexBufferDescriptor const & outputDvDesc, OUTPUT_BUFFER *outputDvData ) {
|
||||
|
||||
if (not context->GetStencilTables()->GetNumStencils())
|
||||
return 0;
|
||||
|
||||
bindControlData( controlDataDesc, controlVertices );
|
||||
|
||||
bindOutputDerivData( outputDuDesc, outputDuData, outputDvDesc, outputDvData );
|
||||
|
||||
int n = _UpdateDerivs( context );
|
||||
|
||||
unbind();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
protected:
|
||||
|
||||
/// \brief Binds control vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindControlData(VertexBufferDescriptor const & controlDataDesc, VERTEX_BUFFER *controlData ) {
|
||||
|
||||
_currentBindState.controlData = controlData ? controlData->BindCpuBuffer() : 0;
|
||||
_currentBindState.controlDataDesc = controlDataDesc;
|
||||
|
||||
}
|
||||
|
||||
/// \brief Binds output vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindOutputData( VertexBufferDescriptor const & outputDataDesc, VERTEX_BUFFER *outputData ) {
|
||||
|
||||
_currentBindState.outputData = outputData ? outputData->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputDataDesc = outputDataDesc;
|
||||
}
|
||||
|
||||
/// \brief Binds output derivative vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindOutputDerivData( VertexBufferDescriptor const & outputDuDesc, VERTEX_BUFFER *outputDu,
|
||||
VertexBufferDescriptor const & outputDvDesc, VERTEX_BUFFER *outputDv ) {
|
||||
|
||||
_currentBindState.outputUDeriv = outputDu ? outputDu ->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputVDeriv = outputDv ? outputDv->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputDuDesc = outputDuDesc;
|
||||
_currentBindState.outputDvDesc = outputDvDesc;
|
||||
}
|
||||
|
||||
/// \brief Unbinds any previously bound vertex and varying data buffers.
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int _UpdateValues( CpuEvalStencilsContext * context );
|
||||
int _UpdateDerivs( CpuEvalStencilsContext * context );
|
||||
|
||||
int _numThreads;
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : controlData(0), outputData(0), outputUDeriv(0), outputVDeriv(0) { }
|
||||
|
||||
void Reset() {
|
||||
controlData = outputData = outputUDeriv = outputVDeriv = NULL;
|
||||
controlDataDesc.Reset();
|
||||
outputDataDesc.Reset();
|
||||
outputDuDesc.Reset();
|
||||
outputDvDesc.Reset();
|
||||
}
|
||||
|
||||
// transient mesh data
|
||||
VertexBufferDescriptor controlDataDesc,
|
||||
outputDataDesc,
|
||||
outputDuDesc,
|
||||
outputDvDesc;
|
||||
|
||||
float * controlData,
|
||||
* outputData,
|
||||
* outputUDeriv,
|
||||
* outputVDeriv;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // FAR_OMP_EVALSTENCILS_CONTROLLER_H
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
@ -22,23 +22,48 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cpuEvalStencilsContext.h"
|
||||
#include "../osd/ompEvaluator.h"
|
||||
#include "../osd/ompKernel.h"
|
||||
#include <omp.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuEvalStencilsContext::CpuEvalStencilsContext(Far::LimitStencilTables const *stencils) :
|
||||
_stencils(stencils) {
|
||||
/* static */
|
||||
bool
|
||||
OmpEvaluator::EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start, int end) {
|
||||
if (end <= start) return true;
|
||||
|
||||
// we can probably expand cpuKernel.cpp to here.
|
||||
OmpEvalStencils(src, srcDesc, dst, dstDesc,
|
||||
sizes, offsets, indices, weights, start, end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CpuEvalStencilsContext *
|
||||
CpuEvalStencilsContext::Create(Far::LimitStencilTables const *stencils) {
|
||||
return new CpuEvalStencilsContext(stencils);
|
||||
/* static */
|
||||
void
|
||||
OmpEvaluator::Synchronize(void * /*deviceContext*/) {
|
||||
// we use "omp parallel for" and it synchronizes by itself
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
/* static */
|
||||
void
|
||||
OmpEvaluator::SetNumThreads(int numThreads) {
|
||||
omp_set_num_threads(numThreads);
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
114
opensubdiv/osd/ompEvaluator.h
Normal file
114
opensubdiv/osd/ompEvaluator.h
Normal file
@ -0,0 +1,114 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_OMP_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_OMP_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class OmpEvaluator {
|
||||
public:
|
||||
/// \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 BindCpuBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTable stencil table to be applied.
|
||||
///
|
||||
/// @param instance not used in the omp kernel
|
||||
/// (declared as a typed pointer to prevent
|
||||
/// undesirable template resolution)
|
||||
///
|
||||
/// @param deviceContext not used in the omp kernel
|
||||
///
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
OmpEvaluator const * instance = NULL,
|
||||
void * deviceContext = NULL) {
|
||||
(void)instance; // unused;
|
||||
(void)deviceContext; // unused;
|
||||
|
||||
return EvalStencils(srcVertexBuffer->BindCpuBuffer(),
|
||||
srcDesc,
|
||||
dstVertexBuffer->BindCpuBuffer(),
|
||||
dstDesc,
|
||||
&stencilTable->GetSizes()[0],
|
||||
&stencilTable->GetOffsets()[0],
|
||||
&stencilTable->GetControlIndices()[0],
|
||||
&stencilTable->GetWeights()[0],
|
||||
/*start = */ 0,
|
||||
/*end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
/// stencil compute function.
|
||||
static bool EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end);
|
||||
|
||||
static void Synchronize(void *deviceContext = NULL);
|
||||
|
||||
static void SetNumThreads(int numThreads);
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_OMP_EVALUATOR_H
|
@ -73,16 +73,15 @@ copy(float *dst, int dstIndex, const float *src,
|
||||
// XXXX manuelk this should be optimized further by using SIMD - considering
|
||||
// OMP is somewhat obsolete - this is probably not worth it.
|
||||
void
|
||||
OmpComputeStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end) {
|
||||
|
||||
OmpEvalStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end) {
|
||||
if (start > 0) {
|
||||
sizes += start;
|
||||
indices += offsets[start];
|
||||
|
@ -22,8 +22,8 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_OMP_KERNEL_H
|
||||
#define OSD_OMP_KERNEL_H
|
||||
#ifndef OPENSUBDIV_OSD_OMP_KERNEL_H
|
||||
#define OPENSUBDIV_OSD_OMP_KERNEL_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
@ -35,15 +35,15 @@ namespace Osd {
|
||||
struct VertexBufferDescriptor;
|
||||
|
||||
void
|
||||
OmpComputeStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end);
|
||||
OmpEvalStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end);
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
@ -52,4 +52,4 @@ using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_OMP_KERNEL_H
|
||||
#endif // OPENSUBDIV_OSD_OMP_KERNEL_H
|
||||
|
@ -1,185 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/ompSmoothNormalController.h"
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
inline void
|
||||
cross(float *n, const float *p0, const float *p1, const float *p2) {
|
||||
|
||||
float a[3] = { p1[0]-p0[0], p1[1]-p0[1], p1[2]-p0[2] };
|
||||
float b[3] = { p2[0]-p0[0], p2[1]-p0[1], p2[2]-p0[2] };
|
||||
n[0] = a[1]*b[2]-a[2]*b[1];
|
||||
n[1] = a[2]*b[0]-a[0]*b[2];
|
||||
n[2] = a[0]*b[1]-a[1]*b[0];
|
||||
|
||||
float rn = 1.0f/sqrtf(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
|
||||
n[0] *= rn;
|
||||
n[1] *= rn;
|
||||
n[2] *= rn;
|
||||
}
|
||||
|
||||
void OmpSmoothNormalController::_smootheNormals(
|
||||
CpuSmoothNormalContext * context) {
|
||||
|
||||
VertexBufferDescriptor const & iDesc = context->GetInputVertexDescriptor(),
|
||||
& oDesc = context->GetOutputVertexDescriptor();
|
||||
|
||||
assert(iDesc.length==3 and oDesc.length==3);
|
||||
|
||||
float * oBuffer = context->GetCurrentOutputVertexBuffer() + oDesc.offset;
|
||||
if (context->GetResetMemory()) {
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int j=0; j<context->GetNumVertices(); ++j) {
|
||||
float * ptr = oBuffer + j * oDesc.stride;
|
||||
memset(ptr, 0, oDesc.length*sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
{ // note: quads only !
|
||||
float const * iBuffer = context->GetCurrentInputVertexBuffer() + iDesc.offset;
|
||||
|
||||
Far::Index const * fverts = context->GetFaceVertices();
|
||||
|
||||
int nfaces = context->GetNumFaces();
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int i=0; i<nfaces; ++i) {
|
||||
|
||||
int idx = i*4;
|
||||
|
||||
float const * p0 = iBuffer + fverts[idx+0]*iDesc.stride,
|
||||
* p1 = iBuffer + fverts[idx+1]*iDesc.stride,
|
||||
* p2 = iBuffer + fverts[idx+2]*iDesc.stride;
|
||||
|
||||
// compute face normal
|
||||
float n[3];
|
||||
cross( n, p0, p1, p2 );
|
||||
|
||||
// add normal to all vertices of the face
|
||||
for (int j=0; j<4; ++j) {
|
||||
float * dst = oBuffer + fverts[idx+j]*oDesc.stride;
|
||||
dst[0] += n[0];
|
||||
dst[1] += n[1];
|
||||
dst[2] += n[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void OmpSmoothNormalController::_smootheNormals(
|
||||
CpuSmoothNormalContext * context) {
|
||||
|
||||
VertexBufferDescriptor const & iDesc = context->GetInputVertexDescriptor(),
|
||||
& oDesc = context->GetOutputVertexDescriptor();
|
||||
|
||||
assert(iDesc.length==3 and oDesc.length==3);
|
||||
|
||||
float const * iBuffer = context->GetCurrentInputVertexBuffer() + iDesc.offset;
|
||||
float * oBuffer = context->GetCurrentOutputVertexBuffer() + oDesc.offset;
|
||||
|
||||
Far::PatchTables::PTable const & verts = context->GetControlVertices();
|
||||
|
||||
Far::PatchTables::PatchArrayVector const & parrays = context->GetPatchArrayVector();
|
||||
|
||||
if (verts.empty() or parrays.empty() or (not iBuffer) or (not oBuffer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0; i<(int)parrays.size(); ++i) {
|
||||
|
||||
Far::PatchTables::PatchArray const & pa = parrays[i];
|
||||
|
||||
Far::PatchTables::Type type = pa.GetDescriptor().GetType();
|
||||
|
||||
|
||||
if (type==Far::PatchTables::QUADS or type==Far::PatchTables::TRIANGLES) {
|
||||
|
||||
int nv = Far::PatchTables::Descriptor::GetNumControlVertices(type);
|
||||
|
||||
// if necessary, reset all normal values to 0
|
||||
if (context->GetResetMemory()) {
|
||||
#pragma omp parallel for
|
||||
for (int j=0; j<context->GetNumVertices(); ++j) {
|
||||
float * ptr = oBuffer + j * oDesc.stride;
|
||||
memset(ptr, 0, oDesc.length*sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int j=0; j<(int)pa.GetNumPatches(); ++j) {
|
||||
|
||||
int idx = pa.GetVertIndex() + j*nv;
|
||||
|
||||
float const * p0 = iBuffer + verts[idx+0]*iDesc.stride,
|
||||
* p1 = iBuffer + verts[idx+1]*iDesc.stride,
|
||||
* p2 = iBuffer + verts[idx+2]*iDesc.stride;
|
||||
|
||||
// compute face normal
|
||||
float n[3];
|
||||
cross( n, p0, p1, p2 );
|
||||
|
||||
// add normal to all vertices of the face
|
||||
for (int k=0; k<nv; ++k) {
|
||||
|
||||
float * dst = oBuffer + verts[idx+k]*oDesc.stride;
|
||||
|
||||
dst[0] += n[0];
|
||||
dst[1] += n[1];
|
||||
dst[2] += n[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
OmpSmoothNormalController::OmpSmoothNormalController() {
|
||||
}
|
||||
|
||||
OmpSmoothNormalController::~OmpSmoothNormalController() {
|
||||
}
|
||||
|
||||
void
|
||||
OmpSmoothNormalController::Synchronize() {
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,78 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_OMP_SMOOTHNORMAL_CONTROLLER_H
|
||||
#define OSD_OMP_SMOOTHNORMAL_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/cpuSmoothNormalContext.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class OmpSmoothNormalController {
|
||||
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
OmpSmoothNormalController();
|
||||
|
||||
/// Destructor
|
||||
~OmpSmoothNormalController();
|
||||
|
||||
/// Computes smooth vertex normals
|
||||
template<class VERTEX_BUFFER>
|
||||
void SmootheNormals( CpuSmoothNormalContext * context,
|
||||
VERTEX_BUFFER * iBuffer, int iOfs,
|
||||
VERTEX_BUFFER * oBuffer, int oOfs ) {
|
||||
|
||||
if (not context) return;
|
||||
|
||||
context->Bind(iBuffer, iOfs, oBuffer, oOfs);
|
||||
|
||||
_smootheNormals(context);
|
||||
|
||||
context->Unbind();
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
private:
|
||||
|
||||
void _smootheNormals(CpuSmoothNormalContext * context);
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_OMP_SMOOTHNORMAL_CONTROLLER_H
|
@ -1,114 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../osd/cpuComputeContext.h"
|
||||
#include "../osd/tbbComputeController.h"
|
||||
#include "../osd/tbbKernel.h"
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
#endif
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
TbbComputeController::TbbComputeController(int numThreads)
|
||||
: _numThreads(numThreads) {
|
||||
|
||||
if(_numThreads == -1)
|
||||
tbb::task_scheduler_init init;
|
||||
else
|
||||
tbb::task_scheduler_init init(numThreads);
|
||||
}
|
||||
|
||||
void
|
||||
TbbComputeController::ApplyStencilTableKernel(
|
||||
ComputeContext const *context) const {
|
||||
|
||||
assert(context);
|
||||
|
||||
Far::StencilTables const * vertexStencils = context->GetVertexStencilTables();
|
||||
|
||||
if (vertexStencils and _currentBindState.vertexBuffer) {
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.vertexDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += vertexStencils->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
int start = 0;
|
||||
int end = vertexStencils->GetNumStencils();
|
||||
|
||||
if (end > start) {
|
||||
TbbComputeStencils(_currentBindState.vertexBuffer,
|
||||
srcDesc,
|
||||
_currentBindState.vertexBuffer,
|
||||
dstDesc,
|
||||
&vertexStencils->GetSizes().at(0),
|
||||
&vertexStencils->GetOffsets().at(0),
|
||||
&vertexStencils->GetControlIndices().at(0),
|
||||
&vertexStencils->GetWeights().at(0),
|
||||
start,
|
||||
end);
|
||||
}
|
||||
}
|
||||
|
||||
Far::StencilTables const * varyingStencils = context->GetVaryingStencilTables();
|
||||
|
||||
if (varyingStencils and _currentBindState.varyingBuffer) {
|
||||
VertexBufferDescriptor srcDesc = _currentBindState.varyingDesc;
|
||||
VertexBufferDescriptor dstDesc(srcDesc);
|
||||
dstDesc.offset += varyingStencils->GetNumControlVertices() * dstDesc.stride;
|
||||
|
||||
int start = 0;
|
||||
int end = varyingStencils->GetNumStencils();
|
||||
|
||||
if (end > start) {
|
||||
TbbComputeStencils(_currentBindState.varyingBuffer,
|
||||
srcDesc,
|
||||
_currentBindState.varyingBuffer,
|
||||
dstDesc,
|
||||
&varyingStencils->GetSizes().at(0),
|
||||
&varyingStencils->GetOffsets().at(0),
|
||||
&varyingStencils->GetControlIndices().at(0),
|
||||
&varyingStencils->GetWeights().at(0),
|
||||
start,
|
||||
end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TbbComputeController::Synchronize() {
|
||||
// XXX:
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
|
@ -1,177 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_TBB_COMPUTE_CONTROLLER_H
|
||||
#define OSD_TBB_COMPUTE_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/cpuComputeContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Compute controller for launching TBB subdivision kernels.
|
||||
///
|
||||
/// TbbComputeController is a compute controller class to launch TBB
|
||||
/// threaded subdivision kernels. It requires CpuVertexBufferInterface
|
||||
/// as arguments of Refine function.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class TbbComputeController {
|
||||
public:
|
||||
typedef CpuComputeContext ComputeContext;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param numThreads specifies how many openmp parallel threads to use.
|
||||
/// -1 attempts to use all available processors.
|
||||
///
|
||||
explicit TbbComputeController(int numThreads=-1);
|
||||
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CpuContext to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param vertexDesc The descriptor of vertex elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
/// @param varyingBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param varyingDesc The descriptor of varying elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void Compute( CpuComputeContext const * context,
|
||||
VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc=NULL,
|
||||
VertexBufferDescriptor const * varyingDesc=NULL ){
|
||||
|
||||
bind(vertexBuffer, varyingBuffer, vertexDesc, varyingDesc);
|
||||
|
||||
ApplyStencilTableKernel(context);
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CpuContext to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
template<class VERTEX_BUFFER>
|
||||
void Compute(CpuComputeContext const * context,
|
||||
VERTEX_BUFFER *vertexBuffer) {
|
||||
|
||||
Compute<VERTEX_BUFFER>(context, vertexBuffer, (VERTEX_BUFFER*)0);
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
protected:
|
||||
|
||||
void ApplyStencilTableKernel(ComputeContext const *context) const;
|
||||
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void bind( VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc,
|
||||
VertexBufferDescriptor const * varyingDesc ) {
|
||||
|
||||
// if the vertex buffer descriptor is specified, use it.
|
||||
// otherwise, assumes the data is tightly packed in the vertex buffer.
|
||||
if (vertexDesc) {
|
||||
_currentBindState.vertexDesc = *vertexDesc;
|
||||
} else {
|
||||
int numElements = vertexBuffer ? vertexBuffer->GetNumElements() : 0;
|
||||
_currentBindState.vertexDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
if (varyingDesc) {
|
||||
_currentBindState.varyingDesc = *varyingDesc;
|
||||
} else {
|
||||
int numElements = varyingBuffer ? varyingBuffer->GetNumElements() : 0;
|
||||
_currentBindState.varyingDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
_currentBindState.vertexBuffer = vertexBuffer ?
|
||||
vertexBuffer->BindCpuBuffer(): 0;
|
||||
|
||||
_currentBindState.varyingBuffer = varyingBuffer ?
|
||||
varyingBuffer->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of the vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : vertexBuffer(0), varyingBuffer(0) { }
|
||||
|
||||
void Reset() {
|
||||
vertexBuffer = varyingBuffer = 0;
|
||||
vertexDesc.Reset();
|
||||
varyingDesc.Reset();
|
||||
}
|
||||
|
||||
float * vertexBuffer,
|
||||
* varyingBuffer;
|
||||
|
||||
VertexBufferDescriptor vertexDesc,
|
||||
varyingDesc;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
int _numThreads;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_TBB_COMPUTE_CONTROLLER_H
|
@ -1,200 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/tbbEvalStencilsController.h"
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
#define grain_size 200
|
||||
|
||||
TbbEvalStencilsController::TbbEvalStencilsController(int numThreads) {
|
||||
|
||||
_numThreads = numThreads > 0 ? numThreads : tbb::task_scheduler_init::automatic;
|
||||
|
||||
tbb::task_scheduler_init init(numThreads);
|
||||
}
|
||||
|
||||
TbbEvalStencilsController::~TbbEvalStencilsController() {
|
||||
}
|
||||
|
||||
|
||||
class StencilKernel {
|
||||
|
||||
public:
|
||||
enum Mode { UNDEFINED, POINT, U_DERIV, V_DERIV };
|
||||
|
||||
StencilKernel( Far::LimitStencilTables const * stencils,
|
||||
VertexBufferDescriptor ctrlDesc,
|
||||
float const * ctrlData ) :
|
||||
_stencils(stencils),
|
||||
_mode(UNDEFINED),
|
||||
_ctrlDesc(ctrlDesc),
|
||||
_length(0),
|
||||
_outStride(0),
|
||||
_outData(0) {
|
||||
|
||||
_ctrlData = ctrlData + ctrlDesc.offset;
|
||||
}
|
||||
|
||||
bool SetOutput(Mode mode, VertexBufferDescriptor outDesc, float * outData) {
|
||||
|
||||
if (_ctrlDesc.CanEval(outDesc)) {
|
||||
_mode = mode;
|
||||
_length = outDesc.length;
|
||||
_outStride = outDesc.stride;
|
||||
_outData = outData + outDesc.offset;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void operator() (tbb::blocked_range<int> const &r) const {
|
||||
|
||||
assert(_stencils and _ctrlData and _length and _outStride and _outData);
|
||||
|
||||
Far::Index offset = _stencils->GetOffsets()[r.begin()];
|
||||
|
||||
unsigned char const * sizes = &_stencils->GetSizes()[r.begin()];
|
||||
Far::Index const * index = &_stencils->GetControlIndices()[offset];
|
||||
|
||||
float const * weight;
|
||||
|
||||
switch (_mode) {
|
||||
case POINT : weight = &_stencils->GetWeights()[offset]; break;
|
||||
case U_DERIV : weight = &_stencils->GetDuWeights()[offset]; break;
|
||||
case V_DERIV : weight = &_stencils->GetDvWeights()[offset]; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
assert( weight);
|
||||
|
||||
float * out = _outData + r.begin() * _outStride;
|
||||
|
||||
for (int i=r.begin(); i<r.end(); ++i, ++sizes) {
|
||||
|
||||
memset( out, 0, _length * sizeof(float) );
|
||||
|
||||
for (int j=0; j<(*sizes); ++j, ++index, ++weight) {
|
||||
|
||||
float const * cv = _ctrlData + (*index)*_ctrlDesc.stride;
|
||||
|
||||
for (int k=0; k<_length; ++k) {
|
||||
out[k] += cv[k] * (*weight);
|
||||
}
|
||||
}
|
||||
out+=_outStride;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Far::LimitStencilTables const * _stencils;
|
||||
|
||||
Mode _mode;
|
||||
|
||||
VertexBufferDescriptor _ctrlDesc;
|
||||
float const * _ctrlData;
|
||||
|
||||
int _length,
|
||||
_outStride;
|
||||
|
||||
float * _outData;
|
||||
};
|
||||
|
||||
int
|
||||
TbbEvalStencilsController::_UpdateValues( CpuEvalStencilsContext * context ) {
|
||||
|
||||
Far::LimitStencilTables const * stencils = context->GetStencilTables();
|
||||
if (not stencils)
|
||||
return 0;
|
||||
|
||||
int nstencils = stencils->GetNumStencils();
|
||||
if (not nstencils)
|
||||
return 0;
|
||||
|
||||
StencilKernel kernel( stencils, _currentBindState.controlDataDesc,
|
||||
_currentBindState.controlData );
|
||||
|
||||
|
||||
if (not kernel.SetOutput( StencilKernel::POINT,
|
||||
_currentBindState.outputDataDesc,
|
||||
_currentBindState.outputData ))
|
||||
return 0;
|
||||
|
||||
tbb::blocked_range<int> range(0, nstencils, grain_size);
|
||||
|
||||
tbb::parallel_for(range, kernel);
|
||||
|
||||
return nstencils;
|
||||
}
|
||||
|
||||
int
|
||||
TbbEvalStencilsController::_UpdateDerivs( CpuEvalStencilsContext * context ) {
|
||||
|
||||
Far::LimitStencilTables const * stencils = context->GetStencilTables();
|
||||
if (not stencils)
|
||||
return 0;
|
||||
|
||||
int nstencils = stencils->GetNumStencils();
|
||||
if (not nstencils)
|
||||
return 0;
|
||||
|
||||
tbb::blocked_range<int> range(0, nstencils, grain_size);
|
||||
|
||||
StencilKernel kernel( stencils, _currentBindState.controlDataDesc,
|
||||
_currentBindState.controlData );
|
||||
|
||||
if (not kernel.SetOutput( StencilKernel::U_DERIV,
|
||||
_currentBindState.outputDuDesc,
|
||||
_currentBindState.outputUDeriv ) )
|
||||
return 0;
|
||||
|
||||
tbb::parallel_for(range, kernel);
|
||||
|
||||
if (not kernel.SetOutput( StencilKernel::V_DERIV,
|
||||
_currentBindState.outputDvDesc,
|
||||
_currentBindState.outputVDeriv ) )
|
||||
return 0;
|
||||
|
||||
tbb::parallel_for(range, kernel);
|
||||
|
||||
return nstencils;
|
||||
}
|
||||
|
||||
void
|
||||
TbbEvalStencilsController::Synchronize() {
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,216 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef FAR_TBB_EVALSTENCILS_CONTROLLER_H
|
||||
#define FAR_TBB_EVALSTENCILS_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/cpuEvalStencilsContext.h"
|
||||
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief CPU stencils evaluation controller
|
||||
///
|
||||
/// CpuStencilsController is a compute controller class to launch
|
||||
/// single threaded CPU stencil evalution kernels.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class TbbEvalStencilsController {
|
||||
public:
|
||||
|
||||
/// \brief Constructor.
|
||||
///
|
||||
/// @param numThreads specifies how many openmp parallel threads to use.
|
||||
/// -1 attempts to use all available processors.
|
||||
///
|
||||
TbbEvalStencilsController(int numThreads=-1);
|
||||
|
||||
/// \brief Destructor.
|
||||
~TbbEvalStencilsController();
|
||||
|
||||
|
||||
/// \brief Applies stencil weights to the control vertex data
|
||||
///
|
||||
/// Applies the stencil weights to the control vertex data to evaluate the
|
||||
/// interpolated limit positions at the parametric locations of the stencils
|
||||
///
|
||||
/// @param context the CpuEvalStencilsContext with the stencil weights
|
||||
///
|
||||
/// @param controlDataDesc vertex buffer descriptor for the control vertex data
|
||||
///
|
||||
/// @param controlVertices vertex buffer with the control vertices data
|
||||
///
|
||||
/// @param outputDataDesc vertex buffer descriptor for the output vertex data
|
||||
///
|
||||
/// @param outputData output vertex buffer for the interpolated data
|
||||
///
|
||||
template<class CONTROL_BUFFER, class OUTPUT_BUFFER>
|
||||
int UpdateValues( CpuEvalStencilsContext * context,
|
||||
VertexBufferDescriptor const & controlDataDesc, CONTROL_BUFFER *controlVertices,
|
||||
VertexBufferDescriptor const & outputDataDesc, OUTPUT_BUFFER *outputData ) {
|
||||
|
||||
if (not context->GetStencilTables()->GetNumStencils())
|
||||
return 0;
|
||||
|
||||
bindControlData( controlDataDesc, controlVertices );
|
||||
|
||||
bindOutputData( outputDataDesc, outputData );
|
||||
|
||||
int n = _UpdateValues( context );
|
||||
|
||||
unbind();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/// \brief Applies derivative stencil weights to the control vertex data
|
||||
///
|
||||
/// Computes the U and V derivative stencils to the control vertex data at
|
||||
/// the parametric locations contained in each stencil
|
||||
///
|
||||
/// @param context the CpuEvalStencilsContext with the stencil weights
|
||||
///
|
||||
/// @param controlDataDesc vertex buffer descriptor for the control vertex data
|
||||
///
|
||||
/// @param controlVertices vertex buffer with the control vertices data
|
||||
///
|
||||
/// @param outputDuDesc vertex buffer descriptor for the U derivative output data
|
||||
///
|
||||
/// @param outputDuData output vertex buffer for the U derivative data
|
||||
///
|
||||
/// @param outputDvDesc vertex buffer descriptor for the V deriv output data
|
||||
///
|
||||
/// @param outputDvData output vertex buffer for the V derivative data
|
||||
///
|
||||
template<class CONTROL_BUFFER, class OUTPUT_BUFFER>
|
||||
int UpdateDerivs( CpuEvalStencilsContext * context,
|
||||
VertexBufferDescriptor const & controlDataDesc, CONTROL_BUFFER *controlVertices,
|
||||
VertexBufferDescriptor const & outputDuDesc, OUTPUT_BUFFER *outputDuData,
|
||||
VertexBufferDescriptor const & outputDvDesc, OUTPUT_BUFFER *outputDvData ) {
|
||||
|
||||
if (not context->GetStencilTables()->GetNumStencils())
|
||||
return 0;
|
||||
|
||||
bindControlData( controlDataDesc, controlVertices );
|
||||
|
||||
bindOutputDerivData( outputDuDesc, outputDuData, outputDvDesc, outputDvData );
|
||||
|
||||
int n = _UpdateDerivs( context );
|
||||
|
||||
unbind();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
protected:
|
||||
|
||||
/// \brief Binds control vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindControlData(VertexBufferDescriptor const & controlDataDesc, VERTEX_BUFFER *controlData ) {
|
||||
|
||||
_currentBindState.controlData = controlData ? controlData->BindCpuBuffer() : 0;
|
||||
_currentBindState.controlDataDesc = controlDataDesc;
|
||||
|
||||
}
|
||||
|
||||
/// \brief Binds output vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindOutputData( VertexBufferDescriptor const & outputDataDesc, VERTEX_BUFFER *outputData ) {
|
||||
|
||||
_currentBindState.outputData = outputData ? outputData->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputDataDesc = outputDataDesc;
|
||||
}
|
||||
|
||||
/// \brief Binds output derivative vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindOutputDerivData( VertexBufferDescriptor const & outputDuDesc, VERTEX_BUFFER *outputDu,
|
||||
VertexBufferDescriptor const & outputDvDesc, VERTEX_BUFFER *outputDv ) {
|
||||
|
||||
_currentBindState.outputUDeriv = outputDu ? outputDu ->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputVDeriv = outputDv ? outputDv->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputDuDesc = outputDuDesc;
|
||||
_currentBindState.outputDvDesc = outputDvDesc;
|
||||
}
|
||||
|
||||
/// \brief Unbinds any previously bound vertex and varying data buffers.
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int _UpdateValues( CpuEvalStencilsContext * context );
|
||||
int _UpdateDerivs( CpuEvalStencilsContext * context );
|
||||
|
||||
int _numThreads;
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : controlData(0), outputData(0), outputUDeriv(0), outputVDeriv(0) { }
|
||||
|
||||
void Reset() {
|
||||
controlData = outputData = outputUDeriv = outputVDeriv = NULL;
|
||||
controlDataDesc.Reset();
|
||||
outputDataDesc.Reset();
|
||||
outputDuDesc.Reset();
|
||||
outputDvDesc.Reset();
|
||||
}
|
||||
|
||||
// transient mesh data
|
||||
VertexBufferDescriptor controlDataDesc,
|
||||
outputDataDesc,
|
||||
outputDuDesc,
|
||||
outputDvDesc;
|
||||
|
||||
float * controlData,
|
||||
* outputData,
|
||||
* outputUDeriv,
|
||||
* outputVDeriv;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // FAR_TBB_EVALSTENCILS_CONTROLLER_H
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
@ -22,46 +22,51 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_COMPUTE_CONTROLLER_H
|
||||
#define OSD_COMPUTE_CONTROLLER_H
|
||||
#include "../osd/tbbEvaluator.h"
|
||||
#include "../osd/tbbKernel.h"
|
||||
|
||||
#include "../version.h"
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/*!
|
||||
\page sequence_page API sequence diagrams
|
||||
/* static */
|
||||
bool
|
||||
TbbEvaluator::EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start, int end) {
|
||||
if (end <= start) return true;
|
||||
|
||||
This section describes the typical sequence of initialization and drawing
|
||||
animated prims using OpenSubdiv.
|
||||
TbbEvalStencils(src, srcDesc, dst, dstDesc,
|
||||
sizes, offsets, indices, weights, start, end);
|
||||
|
||||
\section init_sec Initialize
|
||||
return true;
|
||||
}
|
||||
|
||||
\image html OsdCreateSequence.png
|
||||
/* static */
|
||||
void
|
||||
TbbEvaluator::Synchronize(void *) {
|
||||
}
|
||||
|
||||
\section draw_sec Refine and Draw
|
||||
|
||||
\image html OsdRefineDrawSequence.png
|
||||
|
||||
*/
|
||||
|
||||
// XXX: do we really need this base class?
|
||||
class ComputeController {
|
||||
public:
|
||||
virtual ~ComputeController() {}
|
||||
|
||||
protected:
|
||||
ComputeController() {}
|
||||
};
|
||||
/* static */
|
||||
void
|
||||
TbbEvaluator::SetNumThreads(int numThreads) {
|
||||
if (numThreads == -1) {
|
||||
tbb::task_scheduler_init init;
|
||||
} else {
|
||||
tbb::task_scheduler_init init(numThreads);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_COMPUTE_CONTROLLER_H
|
112
opensubdiv/osd/tbbEvaluator.h
Normal file
112
opensubdiv/osd/tbbEvaluator.h
Normal file
@ -0,0 +1,112 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_TBB_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_TBB_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class TbbEvaluator {
|
||||
public:
|
||||
/// \brief Generic static stencil eval 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 BindCpuBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTable stencil table to be applied.
|
||||
///
|
||||
/// @param instance not used in the tbb kernel
|
||||
/// (declared as a typed pointer to prevent
|
||||
/// undesirable template resolution)
|
||||
///
|
||||
/// @param deviceContext not used in the tbb kernel
|
||||
///
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
TbbEvaluator const *instance = NULL,
|
||||
void *deviceContext = NULL) {
|
||||
(void)instance; // unused
|
||||
(void)deviceContext; // unused
|
||||
|
||||
return EvalStencils(srcVertexBuffer->BindCpuBuffer(),
|
||||
srcDesc,
|
||||
dstVertexBuffer->BindCpuBuffer(),
|
||||
dstDesc,
|
||||
&stencilTable->GetSizes()[0],
|
||||
&stencilTable->GetOffsets()[0],
|
||||
&stencilTable->GetControlIndices()[0],
|
||||
&stencilTable->GetWeights()[0],
|
||||
/*start = */ 0,
|
||||
/*end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
static bool EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char *sizes,
|
||||
const int *offsets,
|
||||
const int *indices,
|
||||
const float *weights,
|
||||
int start,
|
||||
int end);
|
||||
|
||||
static void Synchronize(void *deviceContext = NULL);
|
||||
|
||||
static void SetNumThreads(int numThreads);
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_TBB_EVALUATOR_H
|
@ -161,15 +161,15 @@ public:
|
||||
};
|
||||
|
||||
void
|
||||
TbbComputeStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end) {
|
||||
TbbEvalStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end) {
|
||||
|
||||
if (start > 0) {
|
||||
sizes += start;
|
||||
|
@ -22,8 +22,8 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_TBB_KERNEL_H
|
||||
#define OSD_TBB_KERNEL_H
|
||||
#ifndef OPENSUBDIV_OSD_TBB_KERNEL_H
|
||||
#define OPENSUBIDV_OSD_TBB_KERNEL_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
@ -35,15 +35,15 @@ namespace Osd {
|
||||
struct VertexBufferDescriptor;
|
||||
|
||||
void
|
||||
TbbComputeStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end);
|
||||
TbbEvalStencils(float const * src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float * dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
unsigned char const * sizes,
|
||||
int const * offsets,
|
||||
int const * indices,
|
||||
float const * weights,
|
||||
int start, int end);
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
@ -52,4 +52,4 @@ using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_TBB_KERNEL_H
|
||||
#endif // OPENSUBDIV_OSD_TBB_KERNEL_H
|
||||
|
@ -46,9 +46,9 @@ GLFWwindow* g_window=0;
|
||||
#include <stdio.h>
|
||||
#include <cassert>
|
||||
|
||||
#include <osd/cpuEvaluator.h>
|
||||
#include <osd/cpuVertexBuffer.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
|
||||
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
|
||||
@ -268,17 +268,10 @@ static int
|
||||
checkMeshCPU( FarTopologyRefiner *refiner,
|
||||
const std::vector<xyzVV>& coarseverts,
|
||||
xyzmesh * refmesh) {
|
||||
|
||||
static Osd::CpuComputeController *controller =
|
||||
new Osd::CpuComputeController();
|
||||
|
||||
|
||||
Far::StencilTables const *vertexStencils;
|
||||
Far::StencilTables const *varyingStencils;
|
||||
buildStencilTables(*refiner, &vertexStencils, &varyingStencils);
|
||||
Osd::CpuComputeContext *context = Osd::CpuComputeContext::Create(
|
||||
vertexStencils, varyingStencils);
|
||||
|
||||
|
||||
assert(coarseverts.size() == (size_t)refiner->GetNumVerticesTotal());
|
||||
|
||||
@ -287,12 +280,16 @@ checkMeshCPU( FarTopologyRefiner *refiner,
|
||||
|
||||
vb->UpdateData( coarseverts[0].GetPos(), 0, (int)coarseverts.size() );
|
||||
|
||||
controller->Compute( context, vb );
|
||||
Osd::CpuEvaluator::EvalStencils(
|
||||
vb,
|
||||
Osd::VertexBufferDescriptor(0, 3, 3),
|
||||
vb,
|
||||
Osd::VertexBufferDescriptor(refiner->GetNumVertices(0)*3, 3, 3),
|
||||
vertexStencils);
|
||||
|
||||
int result = checkVertexBuffer(*refiner, refmesh, vb->BindCpuBuffer(),
|
||||
vb->GetNumElements());
|
||||
|
||||
delete context;
|
||||
delete vertexStencils;
|
||||
delete varyingStencils;
|
||||
delete vb;
|
||||
@ -305,28 +302,26 @@ static int
|
||||
checkMeshCPUGL(FarTopologyRefiner *refiner,
|
||||
const std::vector<xyzVV>& coarseverts,
|
||||
xyzmesh * refmesh) {
|
||||
|
||||
static Osd::CpuComputeController *controller =
|
||||
new Osd::CpuComputeController();
|
||||
|
||||
|
||||
Far::StencilTables const *vertexStencils;
|
||||
Far::StencilTables const *varyingStencils;
|
||||
buildStencilTables(*refiner, &vertexStencils, &varyingStencils);
|
||||
Osd::CpuComputeContext *context = Osd::CpuComputeContext::Create(
|
||||
vertexStencils, varyingStencils);
|
||||
|
||||
|
||||
Osd::CpuGLVertexBuffer *vb = Osd::CpuGLVertexBuffer::Create(3,
|
||||
refiner->GetNumVerticesTotal());
|
||||
|
||||
vb->UpdateData( coarseverts[0].GetPos(), 0, (int)coarseverts.size() );
|
||||
|
||||
controller->Compute( context, vb );
|
||||
|
||||
Osd::CpuEvaluator::EvalStencils(
|
||||
vb,
|
||||
Osd::VertexBufferDescriptor(0, 3, 3),
|
||||
vb,
|
||||
Osd::VertexBufferDescriptor(refiner->GetNumVertices(0)*3, 3, 3),
|
||||
vertexStencils);
|
||||
|
||||
int result = checkVertexBuffer(*refiner, refmesh,
|
||||
vb->BindCpuBuffer(), vb->GetNumElements());
|
||||
|
||||
delete context;
|
||||
delete vertexStencils;
|
||||
delete varyingStencils;
|
||||
delete vb;
|
||||
|
@ -32,8 +32,7 @@
|
||||
|
||||
#include <opensubdiv/far/topologyRefinerFactory.h>
|
||||
#include <opensubdiv/far/stencilTablesFactory.h>
|
||||
#include <opensubdiv/osd/cpuComputeContext.h>
|
||||
#include <opensubdiv/osd/cpuComputeController.h>
|
||||
#include <opensubdiv/osd/cpuEvaluator.h>
|
||||
#include <opensubdiv/osd/cpuVertexBuffer.h>
|
||||
|
||||
#include <cstdio>
|
||||
@ -73,11 +72,10 @@ int main(int, char **) {
|
||||
nCoarseVerts=0,
|
||||
nRefinedVerts=0;
|
||||
|
||||
Osd::CpuComputeContext * context=0;
|
||||
|
||||
//
|
||||
// Setup phase
|
||||
//
|
||||
Far::StencilTables const * stencilTables = NULL;
|
||||
{ // Setup Context
|
||||
Far::TopologyRefiner const * refiner = createTopologyRefiner(maxlevel);
|
||||
|
||||
@ -87,24 +85,15 @@ int main(int, char **) {
|
||||
options.generateOffsets=true;
|
||||
options.generateIntermediateLevels=false;
|
||||
|
||||
Far::StencilTables const * stencilTables =
|
||||
Far::StencilTablesFactory::Create(*refiner, options);
|
||||
|
||||
// Create an Osd Compute Context from the stencil tables
|
||||
context = Osd::CpuComputeContext::Create(stencilTables,
|
||||
/*vayingStencil=*/NULL);
|
||||
stencilTables = Far::StencilTablesFactory::Create(*refiner, options);
|
||||
|
||||
nCoarseVerts = refiner->GetNumVertices(0);
|
||||
nRefinedVerts = stencilTables->GetNumStencils();
|
||||
|
||||
// We are done with Far: cleanup tables
|
||||
delete refiner;
|
||||
delete stencilTables;
|
||||
}
|
||||
|
||||
// Setup Controller
|
||||
Osd::CpuComputeController controller;
|
||||
|
||||
// Setup a buffer for vertex primvar data:
|
||||
Osd::CpuVertexBuffer * vbuffer =
|
||||
Osd::CpuVertexBuffer::Create(3, nCoarseVerts + nRefinedVerts);
|
||||
@ -117,8 +106,14 @@ int main(int, char **) {
|
||||
// and update every time control data changes
|
||||
vbuffer->UpdateData(g_verts, 0, nCoarseVerts);
|
||||
|
||||
|
||||
Osd::VertexBufferDescriptor srcDesc(0, 3, 3);
|
||||
Osd::VertexBufferDescriptor dstDesc(nCoarseVerts*3, 3, 3);
|
||||
|
||||
// Launch the computation
|
||||
controller.Compute(context, vbuffer);
|
||||
Osd::CpuEvaluator::EvalStencils(vbuffer, srcDesc,
|
||||
vbuffer, dstDesc,
|
||||
stencilTables);
|
||||
}
|
||||
|
||||
{ // Visualization with Maya : print a MEL script that generates particles
|
||||
@ -133,8 +128,8 @@ int main(int, char **) {
|
||||
printf("-c 1;\n");
|
||||
}
|
||||
|
||||
delete stencilTables;
|
||||
delete vbuffer;
|
||||
delete context;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user