Merge branch 'upstream-dev' into dev

Conflicts:
	examples/glViewer/glViewer.cpp
This commit is contained in:
Ignacio Lillo 2015-05-13 23:15:06 -03:00
commit a305f31a30
148 changed files with 5910 additions and 13737 deletions

View File

@ -25,6 +25,8 @@
set(EXAMPLES_COMMON_SHADER_FILES
framebuffer.glsl
ssao.glsl
glslPtexCommon.glsl
hlslPtexCommon.hlsl
)
set(EXAMPLES_COMMON_SOURCE_FILES
@ -107,6 +109,36 @@ if(CUDA_FOUND)
)
endif()
#-------------------------------------------------------------------------------
if( PTEX_FOUND )
list(APPEND EXAMPLES_COMMON_HEADER_FILES
ptexMipmapTextureLoader.h
)
list(APPEND EXAMPLES_COMMON_SOURCE_FILES
ptexMipmapTextureLoader.cpp
)
if( OPENGL_FOUND )
list(APPEND EXAMPLES_COMMON_SOURCE_FILES
glPtexMipmapTexture.cpp
)
list(APPEND EXAMPLES_COMMON_HEADER_FILES
glPtexMipmapTexture.h
)
endif()
if( DXSDK_FOUND )
list(APPEND EXAMPLES_COMMON_SOURCE_FILES
d3d11PtexMipmapTexture.cpp
)
list(APPEND EXAMPLES_COMMON_HEADER_FILES
d3d11PtexMipmapTexture.h
)
endif()
include_directories( "${PTEX_INCLUDE_DIR}" )
list(APPEND PLATFORM_CPU_LIBRARIES
${PTEX_LIBRARY}
)
endif()
#-------------------------------------------------------------------------------
include_directories(
"${PROJECT_SOURCE_DIR}/opensubdiv"

View File

@ -22,19 +22,14 @@
// language governing permissions and limitations under the Apache License.
//
#include "../osd/d3d11PtexMipmapTexture.h"
#include "../osd/ptexMipmapTextureLoader.h"
#include "../far/error.h"
#include "d3d11PtexMipmapTexture.h"
#include "ptexMipmapTextureLoader.h"
#include <far/error.h> // XXX: to be replaced
#include <Ptexture.h>
#include <D3D11.h>
#include <cassert>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
D3D11PtexMipmapTexture::D3D11PtexMipmapTexture()
: _width(0), _height(0), _depth(0),
_layout(0), _texels(0),
@ -51,6 +46,16 @@ D3D11PtexMipmapTexture::~D3D11PtexMipmapTexture()
if (_texelsSRV) _texelsSRV->Release();
}
/*static*/
const char *
D3D11PtexMipmapTexture::GetShaderSource()
{
static const char *ptexShaderSource =
#include "hlslPtexCommon.gen.h"
;
return ptexShaderSource;
}
static ID3D11Buffer *
genTextureBuffer(ID3D11DeviceContext *deviceContext, int size, void const * data) {
@ -68,7 +73,7 @@ genTextureBuffer(ID3D11DeviceContext *deviceContext, int size, void const * data
deviceContext->GetDevice(&device);
hr = device->CreateBuffer(&hBufferDesc, NULL, &buffer);
if (FAILED(hr)) {
Far::Error(Far::FAR_RUNTIME_ERROR,
OpenSubdiv::Far::Error(OpenSubdiv::Far::FAR_RUNTIME_ERROR,
"Fail in CreateBuffer\n");
return 0;
}
@ -77,7 +82,7 @@ genTextureBuffer(ID3D11DeviceContext *deviceContext, int size, void const * data
hr = deviceContext->Map(buffer, 0,
D3D11_MAP_WRITE_DISCARD, 0, &resource);
if (FAILED(hr)) {
Far::Error(Far::FAR_RUNTIME_ERROR,
OpenSubdiv::Far::Error(OpenSubdiv::Far::FAR_RUNTIME_ERROR,
"Fail in Map buffer\n");
buffer->Release();
return 0;
@ -98,7 +103,7 @@ D3D11PtexMipmapTexture::Create(ID3D11DeviceContext *deviceContext,
int maxNumPages = D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
// Read the ptex data and pack the texels
Osd::PtexMipmapTextureLoader loader(reader, maxNumPages, maxLevels);
PtexMipmapTextureLoader loader(reader, maxNumPages, maxLevels);
int numFaces = loader.GetNumFaces();
@ -216,8 +221,3 @@ D3D11PtexMipmapTexture::Create(ID3D11DeviceContext *deviceContext,
return result;
}
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -22,12 +22,10 @@
// language governing permissions and limitations under the Apache License.
//
#ifndef OSD_D3D11_PTEX_MIPMAP_TEXTURE_H
#define OSD_D3D11_PTEX_MIPMAP_TEXTURE_H
#ifndef OPENSUBDIV_EXAMPLES_D3D11_PTEX_MIPMAP_TEXTURE_H
#define OPENSUBDIV_EXAMPLES_D3D11_PTEX_MIPMAP_TEXTURE_H
#include "../version.h"
#include "../osd/nonCopyable.h"
#include <osd/nonCopyable.h>
class PtexTexture;
struct ID3D11Buffer;
@ -35,17 +33,15 @@ struct ID3D11Texture2D;
struct ID3D11DeviceContext;
struct ID3D11ShaderResourceView;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
class D3D11PtexMipmapTexture : NonCopyable<D3D11PtexMipmapTexture> {
class D3D11PtexMipmapTexture : OpenSubdiv::Osd::NonCopyable<D3D11PtexMipmapTexture> {
public:
static D3D11PtexMipmapTexture * Create(ID3D11DeviceContext *deviceContext,
PtexTexture * reader,
int maxLevels=10);
/// Returns GLSL shader snippet to fetch ptex
static const char *GetShaderSource();
/// Returns the texture buffer containing the layout of the ptex faces
/// in the texels texture array.
ID3D11Buffer *GetLayoutTextureBuffer() const { return _layout; }
@ -74,11 +70,4 @@ private:
ID3D11ShaderResourceView *_texelsSRV;
};
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv
#endif // OSD_D3D11_PTEX_TEXTURE_H
#endif // OPENSUBDIV_EXAMPLES_D3D11_PTEX_TEXTURE_H

View File

@ -22,18 +22,13 @@
// language governing permissions and limitations under the Apache License.
//
#include "../osd/glPtexMipmapTexture.h"
#include "../osd/ptexMipmapTextureLoader.h"
#include "glPtexMipmapTexture.h"
#include "ptexMipmapTextureLoader.h"
#include "../osd/opengl.h"
#include <osd/opengl.h>
#include <Ptexture.h>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
GLPtexMipmapTexture::GLPtexMipmapTexture()
: _width(0), _height(0), _depth(0), _layout(0), _texels(0), _memoryUsage(0)
{
@ -48,6 +43,16 @@ GLPtexMipmapTexture::~GLPtexMipmapTexture()
glDeleteTextures(1, &_texels);
}
/*static*/
const char *
GLPtexMipmapTexture::GetShaderSource()
{
static const char *ptexShaderSource =
#include "glslPtexCommon.gen.h"
;
return ptexShaderSource;
}
static GLuint
genTextureBuffer(GLenum format, GLsizeiptr size, GLvoid const * data)
{
@ -154,8 +159,3 @@ GLPtexMipmapTexture::Create(PtexTexture * reader,
return result;
}
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -22,29 +22,25 @@
// language governing permissions and limitations under the Apache License.
//
#ifndef OSD_GL_PTEX_MIPMAP_TEXTURE_H
#define OSD_GL_PTEX_MIPMAP_TEXTURE_H
#ifndef OPENSUBDIV_EXAMPLES_GL_PTEX_MIPMAP_TEXTURE_H
#define OPENSUBDIV_EXAMPLES_GL_PTEX_MIPMAP_TEXTURE_H
#include "../version.h"
#include "../osd/nonCopyable.h"
#include "../osd/opengl.h"
#include <osd/nonCopyable.h>
#include <osd/opengl.h>
#include <stdlib.h>
class PtexTexture;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
class GLPtexMipmapTexture : NonCopyable<GLPtexMipmapTexture> {
class GLPtexMipmapTexture : OpenSubdiv::Osd::NonCopyable<GLPtexMipmapTexture> {
public:
static GLPtexMipmapTexture * Create(PtexTexture * reader,
int maxLevels=-1,
size_t targetMemory=0);
/// Returns GLSL shader snippet to fetch ptex
static const char *GetShaderSource();
/// Returns the texture buffer containing the layout of the ptex faces
/// in the texels texture array.
GLuint GetLayoutTextureBuffer() const { return _layout; }
@ -72,11 +68,4 @@ private:
size_t _memoryUsage; // total amount of memory used (estimate)
};
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv
#endif // OSD_GL_PTEX_MIPMAP_TEXTURE_H
#endif // OPENSUBDIV_EXAMPLES_GL_PTEX_MIPMAP_TEXTURE_H

View File

@ -40,9 +40,3 @@ getAdaptivePatchColor(Descriptor const & desc) {
return _colors[(int)(desc.GetType()-Descriptor::REGULAR)];
}
float const *
getAdaptivePatchColor(OpenSubdiv::Osd::DrawContext::PatchDescriptor const & desc) {
return _colors[(int)(desc.GetType()-Descriptor::REGULAR)];
}

View File

@ -30,8 +30,6 @@
#include <far/patchTables.h>
// returns a unique color for each type of feature-adaptive patches
float const * getAdaptivePatchColor(OpenSubdiv::Osd::DrawContext::PatchDescriptor const & desc);
float const * getAdaptivePatchColor(OpenSubdiv::Far::PatchDescriptor const & desc);

View File

@ -22,7 +22,7 @@
// language governing permissions and limitations under the Apache License.
//
#include "../osd/ptexMipmapTextureLoader.h"
#include "ptexMipmapTextureLoader.h"
#include <Ptexture.h>
#include <vector>
@ -32,11 +32,6 @@
#include <cstring>
#include <cassert>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
// sample neighbor pixels and populate around blocks
void
PtexMipmapTextureLoader::Block::guttering(PtexMipmapTextureLoader *loader,
@ -997,9 +992,3 @@ PtexMipmapTextureLoader::generateBuffers()
fclose(fp);
#endif
}
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -22,10 +22,8 @@
// language governing permissions and limitations under the Apache License.
//
#ifndef OSD_PTEX_MIPMAP_TEXTURE_LOADER_H
#define OSD_PTEX_MIPMAP_TEXTURE_LOADER_H
#include "../version.h"
#ifndef OPENSUBDIV_EXAMPLES_PTEX_MIPMAP_TEXTURE_LOADER_H
#define OPENSUBDIV_EXAMPLES_PTEX_MIPMAP_TEXTURE_LOADER_H
#include <stdlib.h>
#include <stdint.h>
@ -33,11 +31,6 @@
class PtexTexture;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
class PtexMipmapTextureLoader {
public:
PtexMipmapTextureLoader(PtexTexture *ptex,
@ -158,12 +151,4 @@ private:
size_t _memoryUsage;
};
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv
#endif // OSD_PTEX_MIPMAP_TEXTURE_LOADER_H
#endif // OPENSUBDIV_EXAMPLES_PTEX_MIPMAP_TEXTURE_LOADER_H

View File

@ -25,48 +25,33 @@
#include <D3D11.h>
#include <D3Dcompiler.h>
#include <osd/vertex.h>
#include <osd/d3d11DrawContext.h>
#include <osd/d3d11DrawRegistry.h>
#include <osd/d3d11PtexMipmapTexture.h>
#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;
@ -78,6 +63,7 @@ OpenSubdiv::Osd::D3D11MeshInterface *g_mesh;
#include "../common/stopwatch.h"
#include "../common/simple_math.h"
#include "../common/d3d11_hud.h"
#include "../common/d3d11PtexMipmapTexture.h"
static const char *g_shaderSource =
#include "shader.gen.h"
@ -214,10 +200,10 @@ float g_animTime = 0;
std::vector<float> g_positions,
g_normals;
OpenSubdiv::Osd::D3D11PtexMipmapTexture * g_osdPTexImage = 0;
OpenSubdiv::Osd::D3D11PtexMipmapTexture * g_osdPTexDisplacement = 0;
OpenSubdiv::Osd::D3D11PtexMipmapTexture * g_osdPTexOcclusion = 0;
OpenSubdiv::Osd::D3D11PtexMipmapTexture * g_osdPTexSpecular = 0;
D3D11PtexMipmapTexture * g_osdPTexImage = 0;
D3D11PtexMipmapTexture * g_osdPTexDisplacement = 0;
D3D11PtexMipmapTexture * g_osdPTexOcclusion = 0;
D3D11PtexMipmapTexture * g_osdPTexSpecular = 0;
const char * g_ptexColorFilename;
ID3D11Device * g_pd3dDevice = NULL;
@ -427,14 +413,28 @@ union Effect {
}
};
typedef std::pair<OpenSubdiv::Osd::DrawContext::PatchDescriptor, Effect> EffectDesc;
struct EffectDesc {
EffectDesc(OpenSubdiv::Far::PatchDescriptor desc,
Effect effect) : desc(desc), effect(effect),
maxValence(0), numElements(0) { }
OpenSubdiv::Far::PatchDescriptor desc;
Effect effect;
int maxValence;
int numElements;
bool operator < (const EffectDesc &e) const {
return desc < e.desc || (desc == e.desc &&
(maxValence < e.maxValence || ((maxValence == e.maxValence) &&
(effect < e.effect))));
}
};
class EffectDrawRegistry : public OpenSubdiv::Osd::D3D11DrawRegistry<EffectDesc> {
protected:
virtual ConfigType *
_CreateDrawConfig(DescType const & desc,
_CreateDrawConfig(EffectDesc const & desc,
SourceConfigType const * sconfig,
ID3D11Device * pd3dDevice,
ID3D11InputLayout ** ppInputLayout,
@ -442,20 +442,33 @@ protected:
int numInputElements);
virtual SourceConfigType *
_CreateDrawSourceConfig(DescType const & desc, ID3D11Device * pd3dDevice);
_CreateDrawSourceConfig(EffectDesc const & desc, ID3D11Device * pd3dDevice);
};
EffectDrawRegistry::SourceConfigType *
EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc, ID3D11Device *pd3dDevice)
EffectDrawRegistry::_CreateDrawSourceConfig(EffectDesc const &effectDesc, ID3D11Device *pd3dDevice)
{
Effect effect = desc.second;
SetPtexEnabled(true);
Effect effect = effectDesc.effect;
SourceConfigType * sconfig =
BaseRegistry::_CreateDrawSourceConfig(desc.first, pd3dDevice);
BaseRegistry::_CreateDrawSourceConfig(effectDesc.desc, pd3dDevice);
assert(sconfig);
// legacy gregory patch requires OSD_MAX_VALENCE and OSD_NUM_ELEMENTS defined
if (effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::GREGORY or
effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::GREGORY_BOUNDARY) {
std::ostringstream ss;
ss << effectDesc.maxValence;
sconfig->commonShader.AddDefine("OSD_MAX_VALENCE", ss.str());
ss.str("");
ss << effectDesc.numElements;
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
}
// add ptex functions
sconfig->commonShader.source += D3D11PtexMipmapTexture::GetShaderSource();
if (effect.patchCull)
sconfig->commonShader.AddDefine("OSD_ENABLE_PATCH_CULL");
if (effect.screenSpaceTess)
@ -464,8 +477,8 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc, ID3D11Device
sconfig->commonShader.AddDefine("OSD_FRACTIONAL_ODD_SPACING");
bool quad = true;
if (desc.first.GetType() == OpenSubdiv::Far::PatchDescriptor::QUADS ||
desc.first.GetType() == OpenSubdiv::Far::PatchDescriptor::TRIANGLES) {
if (effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::QUADS ||
effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::TRIANGLES) {
sconfig->vertexShader.source = g_shaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main";
@ -583,14 +596,14 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc, ID3D11Device
EffectDrawRegistry::ConfigType *
EffectDrawRegistry::_CreateDrawConfig(
DescType const & desc,
EffectDesc const & effectDesc,
SourceConfigType const * sconfig,
ID3D11Device * pd3dDevice,
ID3D11InputLayout ** ppInputLayout,
D3D11_INPUT_ELEMENT_DESC const * pInputElementDescs,
int numInputElements) {
ConfigType * config = BaseRegistry::_CreateDrawConfig(desc.first, sconfig,
ConfigType * config = BaseRegistry::_CreateDrawConfig(effectDesc.desc, sconfig,
pd3dDevice, ppInputLayout, pInputElementDescs, numInputElements);
assert(config);
@ -600,7 +613,7 @@ EffectDrawRegistry::_CreateDrawConfig(
EffectDrawRegistry effectRegistry;
//------------------------------------------------------------------------------
OpenSubdiv::Osd::D3D11PtexMipmapTexture *
D3D11PtexMipmapTexture *
createPtex(const char *filename) {
Ptex::String ptexError;
@ -620,9 +633,8 @@ createPtex(const char *filename) {
printf("Error in reading %s\n", filename);
exit(1);
}
OpenSubdiv::Osd::D3D11PtexMipmapTexture *osdPtex =
OpenSubdiv::Osd::D3D11PtexMipmapTexture::Create(g_pd3dDeviceContext,
ptex, g_maxMipmapLevels);
D3D11PtexMipmapTexture *osdPtex = D3D11PtexMipmapTexture::Create(
g_pd3dDeviceContext, ptex, g_maxMipmapLevels);
ptex->release();
@ -636,6 +648,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) {
@ -685,86 +699,87 @@ createOsdMesh(int level, int kernel) {
OpenSubdiv::Osd::MeshBitset bits;
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
bits.set(OpenSubdiv::Osd::MeshPtexData, true);
// gregory basis hasn't supported yet in D3D11Mesh
bits.set(OpenSubdiv::Osd::MeshEndCapLegacyGregory, true);
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));
}
@ -778,6 +793,17 @@ bindProgram(Effect effect, OpenSubdiv::Osd::DrawContext::PatchArray const & patc
EffectDesc effectDesc(patch.GetDescriptor(), effect);
// only legacy gregory needs maxValence and numElements
int maxValence = g_mesh->GetDrawContext()->GetMaxValence();
int numElements = 6;
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
if (patch.GetDescriptor().GetType() == Descriptor::GREGORY or
patch.GetDescriptor().GetType() == Descriptor::GREGORY_BOUNDARY) {
effectDesc.maxValence = maxValence;
effectDesc.numElements = numElements;
}
// input layout
const D3D11_INPUT_ELEMENT_DESC hInElementDesc[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
@ -919,10 +945,13 @@ bindProgram(Effect effect, OpenSubdiv::Osd::DrawContext::PatchArray const & patc
if (g_mesh->GetDrawContext()->quadOffsetBufferSRV) {
g_pd3dDeviceContext->HSSetShaderResources(2, 1, &g_mesh->GetDrawContext()->quadOffsetBufferSRV);
}
if (g_mesh->GetDrawContext()->ptexCoordinateBufferSRV) {
g_pd3dDeviceContext->HSSetShaderResources(3, 1, &g_mesh->GetDrawContext()->ptexCoordinateBufferSRV);
g_pd3dDeviceContext->DSSetShaderResources(3, 1, &g_mesh->GetDrawContext()->ptexCoordinateBufferSRV);
g_pd3dDeviceContext->GSSetShaderResources(3, 1, &g_mesh->GetDrawContext()->ptexCoordinateBufferSRV);
if (g_mesh->GetDrawContext()->patchParamBufferSRV) {
g_pd3dDeviceContext->HSSetShaderResources(
3, 1, &g_mesh->GetDrawContext()->patchParamBufferSRV);
g_pd3dDeviceContext->DSSetShaderResources(
3, 1, &g_mesh->GetDrawContext()->patchParamBufferSRV);
g_pd3dDeviceContext->GSSetShaderResources(
3, 1, &g_mesh->GetDrawContext()->patchParamBufferSRV);
}
g_pd3dDeviceContext->PSSetShaderResources(4, 1, g_osdPTexImage->GetTexelsSRV());
@ -1123,22 +1152,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);
}

View File

@ -114,19 +114,10 @@ float4 displacement(float4 position, float3 normal, float4 patchCoord)
}
#endif
#line 20117
float4 GeneratePatchCoord(float2 localUV, int primitiveID) // for non-adpative
float4 GeneratePatchCoord(float2 uv, int primitiveID) // for non-adaptive
{
int2 ptexIndex = OsdPatchParamBuffer[GetPrimitiveID(primitiveID)].xy;
int faceID = ptexIndex.x;
int lv = 1 << ((ptexIndex.y & 0xf) - ((ptexIndex.y >> 4) & 1));
int u = (ptexIndex.y >> 17) & 0x3ff;
int v = (ptexIndex.y >> 7) & 0x3ff;
float2 uv = localUV;
uv = (uv * float2(1, 1)/lv) + float2(u, v)/lv;
return float4(uv.x, uv.y, lv+0.5, faceID+0.5);
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
return OsdInterpolatePatchCoord(uv, OsdGetPatchCoord(patchParam));
}
// ---------------------------------------------------------------------------
@ -139,6 +130,11 @@ void vs_main( in InputVertex input,
output.positionOut = mul(ModelViewProjectionMatrix, input.position);
output.position = mul(ModelViewMatrix, input.position);
output.normal = mul(ModelViewMatrix,float4(input.normal, 0)).xyz;
output.patchCoord = float4(0,0,0,0);
output.tangent = float3(0,0,0);
output.bitangent = float3(0,0,0);
output.edgeDistance = float4(0,0,0,0);
}
// ---------------------------------------------------------------------------

View File

@ -25,52 +25,37 @@
#include <D3D11.h>
#include <D3Dcompiler.h>
#include <osd/vertex.h>
#include <osd/d3d11DrawContext.h>
#include <osd/d3d11DrawRegistry.h>
#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;
@ -273,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),
@ -317,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));
}
@ -472,14 +444,28 @@ union Effect {
}
};
struct EffectDesc {
EffectDesc(OpenSubdiv::Far::PatchDescriptor desc,
Effect effect) : desc(desc), effect(effect),
maxValence(0), numElements(0) { }
typedef std::pair<OpenSubdiv::Osd::DrawContext::PatchDescriptor, Effect> EffectDesc;
OpenSubdiv::Far::PatchDescriptor desc;
Effect effect;
int maxValence;
int numElements;
bool operator < (const EffectDesc &e) const {
return desc < e.desc || (desc == e.desc &&
(maxValence < e.maxValence || ((maxValence == e.maxValence) &&
(effect < e.effect))));
}
};
class EffectDrawRegistry : public OpenSubdiv::Osd::D3D11DrawRegistry<EffectDesc> {
protected:
virtual ConfigType *
_CreateDrawConfig(DescType const & desc,
_CreateDrawConfig(EffectDesc const & desc,
SourceConfigType const * sconfig,
ID3D11Device * pd3dDevice,
ID3D11InputLayout ** ppInputLayout,
@ -487,28 +473,40 @@ protected:
int numInputElements);
virtual SourceConfigType *
_CreateDrawSourceConfig(DescType const & desc, ID3D11Device * pd3dDevice);
_CreateDrawSourceConfig(EffectDesc const & desc, ID3D11Device * pd3dDevice);
};
EffectDrawRegistry::SourceConfigType *
EffectDrawRegistry::_CreateDrawSourceConfig(
DescType const & desc, ID3D11Device * pd3dDevice) {
EffectDesc const &effectDesc, ID3D11Device * pd3dDevice) {
Effect effect = desc.second;
Effect effect = effectDesc.effect;
SourceConfigType * sconfig =
BaseRegistry::_CreateDrawSourceConfig(desc.first, pd3dDevice);
BaseRegistry::_CreateDrawSourceConfig(effectDesc.desc, pd3dDevice);
sconfig->commonShader.AddDefine("OSD_ENABLE_PATCH_CULL");
sconfig->commonShader.AddDefine("OSD_ENABLE_SCREENSPACE_TESSELLATION");
// legacy gregory patch requires OSD_MAX_VALENCE and OSD_NUM_ELEMENTS defined
if (effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::GREGORY or
effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::GREGORY_BOUNDARY) {
std::ostringstream ss;
ss << effectDesc.maxValence;
sconfig->commonShader.AddDefine("OSD_MAX_VALENCE", ss.str());
ss.str("");
ss << effectDesc.numElements;
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
}
bool smoothNormals = false;
if (desc.first.GetType() == OpenSubdiv::Far::PatchDescriptor::QUADS ||
desc.first.GetType() == OpenSubdiv::Far::PatchDescriptor::TRIANGLES) {
if (effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::QUADS ||
effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::TRIANGLES) {
sconfig->vertexShader.source = shaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main";
} else if (desc.first.GetType() == OpenSubdiv::Far::PatchDescriptor::TRIANGLES) {
} else if (effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::TRIANGLES) {
if (effect.displayStyle == kQuadWire) effect.displayStyle = kTriWire;
if (effect.displayStyle == kQuadFill) effect.displayStyle = kTriFill;
if (effect.displayStyle == kQuadLine) effect.displayStyle = kTriLine;
@ -612,7 +610,7 @@ EffectDrawRegistry::_CreateDrawConfig(
D3D11_INPUT_ELEMENT_DESC const * pInputElementDescs,
int numInputElements) {
ConfigType * config = BaseRegistry::_CreateDrawConfig(desc.first, sconfig,
ConfigType * config = BaseRegistry::_CreateDrawConfig(desc.desc, sconfig,
pd3dDevice, ppInputLayout, pInputElementDescs, numInputElements);
assert(config);
@ -640,6 +638,17 @@ bindProgram(Effect effect, OpenSubdiv::Osd::DrawContext::PatchArray const & patc
EffectDesc effectDesc(patch.GetDescriptor(), effect);
// only legacy gregory needs maxValence and numElements
int maxValence = g_mesh->GetDrawContext()->GetMaxValence();
int numElements = 6;
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
if (patch.GetDescriptor().GetType() == Descriptor::GREGORY or
patch.GetDescriptor().GetType() == Descriptor::GREGORY_BOUNDARY) {
effectDesc.maxValence = maxValence;
effectDesc.numElements = numElements;
}
// input layout
const D3D11_INPUT_ELEMENT_DESC hInElementDesc[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
@ -790,9 +799,11 @@ bindProgram(Effect effect, OpenSubdiv::Osd::DrawContext::PatchArray const & patc
if (g_mesh->GetDrawContext()->quadOffsetBufferSRV) {
g_pd3dDeviceContext->HSSetShaderResources(2, 1, &g_mesh->GetDrawContext()->quadOffsetBufferSRV);
}
if (g_mesh->GetDrawContext()->ptexCoordinateBufferSRV) {
g_pd3dDeviceContext->HSSetShaderResources(3, 1, &g_mesh->GetDrawContext()->ptexCoordinateBufferSRV);
g_pd3dDeviceContext->DSSetShaderResources(3, 1, &g_mesh->GetDrawContext()->ptexCoordinateBufferSRV);
if (g_mesh->GetDrawContext()->patchParamBufferSRV) {
g_pd3dDeviceContext->HSSetShaderResources(
3, 1, &g_mesh->GetDrawContext()->patchParamBufferSRV);
g_pd3dDeviceContext->DSSetShaderResources(
3, 1, &g_mesh->GetDrawContext()->patchParamBufferSRV);
}
}
@ -847,7 +858,7 @@ display() {
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
patchCount[patchType] += patch.GetNumPatches();
@ -857,7 +868,7 @@ display() {
if (g_mesh->GetDrawContext()->IsAdaptive()) {
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
switch (desc.GetNumControlVertices()) {
case 4:
@ -909,10 +920,6 @@ display() {
patchCount[Descriptor::QUADS]); y += 20;
g_hud->DrawString(x, y, "Regular : %d",
patchCount[Descriptor::REGULAR]); y+= 20;
g_hud->DrawString(x, y, "Boundary : %d",
patchCount[Descriptor::BOUNDARY]); y+= 20;
g_hud->DrawString(x, y, "Corner : %d",
patchCount[Descriptor::CORNER]); y+= 20;
g_hud->DrawString(x, y, "Gregory : %d",
patchCount[Descriptor::GREGORY]); y+= 20;
g_hud->DrawString(x, y, "Boundary Gregory : %d",
@ -996,26 +1003,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);
}

View File

@ -42,20 +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 <osd/vertex.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>
@ -139,7 +137,7 @@ int g_nparticles=0,
g_nsamples=101,
g_nsamplesFound=0;
bool g_randomStart=true;
bool g_randomStart=false;
GLuint g_cageEdgeVAO = 0,
g_cageEdgeVBO = 0,
@ -199,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 ),
@ -246,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);
@ -256,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();
@ -336,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));
@ -351,7 +337,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
// location samples (ptex face index, (s,t) and updates them between frames.
// Note: the number of limit locations can be entirely arbitrary
delete g_particles;
g_particles = new STParticles(*g_topologyRefiner, g_nsamples, g_randomStart);
g_particles = new STParticles(*g_topologyRefiner, g_nsamples, !g_randomStart);
g_nparticles = g_particles->GetNumParticles();
g_particles->SetSpeed(speed);
@ -410,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
@ -911,7 +896,7 @@ callbackFreeze(bool checked, int /* f */) {
//------------------------------------------------------------------------------
static void
callbackCentered(bool checked, int /* f */) {
g_randomStart = !checked;
g_randomStart = checked;
createOsdMesh(g_defaultShapes[g_currentShape], g_level);
}
@ -954,7 +939,7 @@ initHUD() {
g_hud.AddCheckBox("Animate vertices (M)", g_moveScale != 0, 10, 50, callbackAnimate, 0, 'm');
g_hud.AddCheckBox("Freeze (spc)", false, 10, 70, callbackFreeze, 0, ' ');
g_hud.AddCheckBox("Random Start", false, 10, 120, callbackCentered, 0);
g_hud.AddCheckBox("Random Start", false, 10, 120, callbackCentered, g_randomStart);
int shading_pulldown = g_hud.AddPullDown("Shading (W)", 250, 10, 250, callbackDisplayVaryingColors, 'w');
g_hud.AddPullDownButton(shading_pulldown, "Random", kRANDOM, g_drawMode==kRANDOM);

View File

@ -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);

View File

@ -42,15 +42,12 @@
GLFWwindow* g_window = 0;
GLFWmonitor* g_primary = 0;
#include <osd/vertex.h>
#include <osd/glDrawContext.h>
#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;
@ -359,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;
@ -537,25 +529,40 @@ union Effect {
}
};
typedef std::pair<OpenSubdiv::Osd::DrawContext::PatchDescriptor, Effect> EffectDesc;
struct EffectDesc {
EffectDesc(OpenSubdiv::Far::PatchDescriptor desc,
Effect effect) : desc(desc), effect(effect),
maxValence(0), numElements(0) { }
OpenSubdiv::Far::PatchDescriptor desc;
Effect effect;
int maxValence;
int numElements;
bool operator < (const EffectDesc &e) const {
return desc < e.desc || (desc == e.desc &&
(maxValence < e.maxValence || ((maxValence == e.maxValence) &&
(effect < e.effect))));
}
};
class EffectDrawRegistry : public OpenSubdiv::Osd::GLDrawRegistry<EffectDesc> {
protected:
virtual ConfigType *
_CreateDrawConfig(DescType const & desc, SourceConfigType const * sconfig);
_CreateDrawConfig(EffectDesc const & desc, SourceConfigType const * sconfig);
virtual SourceConfigType *
_CreateDrawSourceConfig(DescType const & desc);
_CreateDrawSourceConfig(EffectDesc const & desc);
};
EffectDrawRegistry::SourceConfigType *
EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
EffectDrawRegistry::_CreateDrawSourceConfig(EffectDesc const & effectDesc) {
Effect effect = desc.second;
Effect effect = effectDesc.effect;
SourceConfigType * sconfig =
BaseRegistry::_CreateDrawSourceConfig(desc.first);
BaseRegistry::_CreateDrawSourceConfig(effectDesc.desc);
assert(sconfig);
@ -567,8 +574,20 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
if (desc.first.GetType() == Descriptor::QUADS or
desc.first.GetType() == Descriptor::TRIANGLES) {
// legacy gregory patch requires OSD_MAX_VALENCE and OSD_NUM_ELEMENTS defined
if (effectDesc.desc.GetType() == Descriptor::GREGORY or
effectDesc.desc.GetType() == Descriptor::GREGORY_BOUNDARY) {
std::ostringstream ss;
ss << effectDesc.maxValence;
sconfig->commonShader.AddDefine("OSD_MAX_VALENCE", ss.str());
ss.str("");
ss << effectDesc.numElements;
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
}
if (effectDesc.desc.GetType() == Descriptor::QUADS or
effectDesc.desc.GetType() == Descriptor::TRIANGLES) {
sconfig->vertexShader.source = shaderSource;
sconfig->vertexShader.version = glslVersion;
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
@ -587,12 +606,12 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
sconfig->commonShader.AddDefine("OSD_FVAR_WIDTH", "2");
if (desc.first.GetType() == Descriptor::QUADS) {
if (effectDesc.desc.GetType() == Descriptor::QUADS) {
// uniform catmark, bilinear
sconfig->geometryShader.AddDefine("PRIM_QUAD");
sconfig->fragmentShader.AddDefine("PRIM_QUAD");
sconfig->commonShader.AddDefine("UNIFORM_SUBDIVISION");
} else if (desc.first.GetType() == Descriptor::TRIANGLES) {
} else if (effectDesc.desc.GetType() == Descriptor::TRIANGLES) {
// uniform loop
sconfig->geometryShader.AddDefine("PRIM_TRI");
sconfig->fragmentShader.AddDefine("PRIM_TRI");
@ -630,10 +649,10 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
EffectDrawRegistry::ConfigType *
EffectDrawRegistry::_CreateDrawConfig(
DescType const & desc,
DescType const & effectDesc,
SourceConfigType const * sconfig) {
ConfigType * config = BaseRegistry::_CreateDrawConfig(desc.first, sconfig);
ConfigType * config = BaseRegistry::_CreateDrawConfig(effectDesc.desc, sconfig);
assert(config);
GLuint uboIndex;
@ -701,6 +720,18 @@ static GLuint
bindProgram(Effect effect, OpenSubdiv::Osd::DrawContext::PatchArray const & patch) {
EffectDesc effectDesc(patch.GetDescriptor(), effect);
// only legacy gregory needs maxValence and numElements
int maxValence = g_mesh->GetDrawContext()->GetMaxValence();
int numElements = 3;
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
if (patch.GetDescriptor().GetType() == Descriptor::GREGORY or
patch.GetDescriptor().GetType() == Descriptor::GREGORY_BOUNDARY) {
effectDesc.maxValence = maxValence;
effectDesc.numElements = numElements;
}
EffectDrawRegistry::ConfigType *
config = effectRegistry.GetDrawConfig(effectDesc);
@ -822,7 +853,7 @@ display() {
for (int i = 0; i < (int)patches.size(); ++i) {
OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
GLenum primType;
@ -889,7 +920,7 @@ display() {
for (int i = 0; i < (int)patches.size(); ++i) {
OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
GLenum primType;
@ -1009,8 +1040,6 @@ uninitGL() {
if (g_mesh)
delete g_mesh;
delete g_cpuComputeController;
}
//------------------------------------------------------------------------------

View File

@ -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
}
@ -461,7 +425,7 @@ void runTest(ShapeDesc const &shapeDesc, std::string const &kernel,
for (int i=0; i<(int)patches.size(); ++i) {
Osd::DrawContext::PatchArray const & patch = patches[i];
Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
Far::PatchDescriptor desc = patch.GetDescriptor();
Far::PatchDescriptor::Type patchType = desc.GetType();
GLenum primType;

View File

@ -42,16 +42,13 @@
GLFWwindow* g_window=0;
GLFWmonitor* g_primary=0;
#include <osd/vertex.h>
#include <osd/glDrawContext.h>
#include <osd/glDrawRegistry.h>
#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;
@ -239,16 +236,12 @@ createOsdMesh() {
bool doAdaptive = true;
OpenSubdiv::Osd::MeshBitset bits;
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};
@ -347,25 +340,54 @@ union Effect {
}
};
typedef std::pair<OpenSubdiv::Osd::DrawContext::PatchDescriptor,Effect> EffectDesc;
struct EffectDesc {
EffectDesc(OpenSubdiv::Far::PatchDescriptor desc,
Effect effect) : desc(desc), effect(effect),
maxValence(0), numElements(0) { }
OpenSubdiv::Far::PatchDescriptor desc;
Effect effect;
int maxValence;
int numElements;
bool operator < (const EffectDesc &e) const {
return desc < e.desc || (desc == e.desc &&
(maxValence < e.maxValence || ((maxValence == e.maxValence) &&
(effect < e.effect))));
}
};
class EffectDrawRegistry : public OpenSubdiv::Osd::GLDrawRegistry<EffectDesc> {
protected:
virtual ConfigType *
_CreateDrawConfig(DescType const & desc, SourceConfigType const * sconfig);
_CreateDrawConfig(EffectDesc const & desc, SourceConfigType const * sconfig);
virtual SourceConfigType *
_CreateDrawSourceConfig(DescType const & desc);
_CreateDrawSourceConfig(EffectDesc const & desc);
};
EffectDrawRegistry::SourceConfigType *
EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
EffectDrawRegistry::_CreateDrawSourceConfig(EffectDesc const & effectDesc) {
Effect effect = desc.second;
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
Effect effect = effectDesc.effect;
SourceConfigType * sconfig =
BaseRegistry::_CreateDrawSourceConfig(desc.first);
BaseRegistry::_CreateDrawSourceConfig(effectDesc.desc);
// legacy gregory patch requires OSD_MAX_VALENCE and OSD_NUM_ELEMENTS defined
if (effectDesc.desc.GetType() == Descriptor::GREGORY or
effectDesc.desc.GetType() == Descriptor::GREGORY_BOUNDARY) {
std::ostringstream ss;
ss << effectDesc.maxValence;
sconfig->commonShader.AddDefine("OSD_MAX_VALENCE", ss.str());
ss.str("");
ss << effectDesc.numElements;
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
}
sconfig->commonShader.AddDefine("USE_PTEX_COORD");
@ -423,10 +445,10 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
EffectDrawRegistry::ConfigType *
EffectDrawRegistry::_CreateDrawConfig(
DescType const & desc,
DescType const & effectDesc,
SourceConfigType const * sconfig) {
ConfigType * config = BaseRegistry::_CreateDrawConfig(desc.first, sconfig);
ConfigType * config = BaseRegistry::_CreateDrawConfig(effectDesc.desc, sconfig);
assert(config);
GLuint uboIndex;
@ -652,7 +674,7 @@ display() {
// patch drawing
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
GLenum primType = GL_PATCHES;
glPatchParameteri(GL_PATCH_VERTICES, desc.GetNumControlVertices());
@ -823,7 +845,7 @@ drawStroke(int x, int y) {
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
GLenum primType = GL_PATCHES;
glPatchParameteri(GL_PATCH_VERTICES, desc.GetNumControlVertices());
@ -1096,8 +1118,6 @@ uninitGL() {
if (g_mesh)
delete g_mesh;
delete g_cpuComputeController;
}
//------------------------------------------------------------------------------

View File

@ -52,59 +52,41 @@ GLFWmonitor* g_primary = 0;
#include <osd/glDrawContext.h>
#include <osd/glDrawRegistry.h>
#include <osd/glPtexMipmapTexture.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>
@ -120,6 +102,7 @@ OpenSubdiv::Osd::GLMeshInterface *g_mesh;
#include "../common/patchColors.h"
#include "../common/hdr_reader.h"
#include "../common/stb_image_write.h"
#include "../common/glPtexMipmapTexture.h"
static const char *g_defaultShaderSource =
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
@ -328,10 +311,10 @@ struct ImageShader {
//------------------------------------------------------------------------------
OpenSubdiv::Osd::GLPtexMipmapTexture * g_osdPTexImage = 0;
OpenSubdiv::Osd::GLPtexMipmapTexture * g_osdPTexDisplacement = 0;
OpenSubdiv::Osd::GLPtexMipmapTexture * g_osdPTexOcclusion = 0;
OpenSubdiv::Osd::GLPtexMipmapTexture * g_osdPTexSpecular = 0;
GLPtexMipmapTexture * g_osdPTexImage = 0;
GLPtexMipmapTexture * g_osdPTexDisplacement = 0;
GLPtexMipmapTexture * g_osdPTexOcclusion = 0;
GLPtexMipmapTexture * g_osdPTexSpecular = 0;
const char * g_ptexColorFilename;
size_t g_ptexMemoryUsage = 0;
@ -636,7 +619,7 @@ static GLuint compileShader(GLenum shaderType,
//------------------------------------------------------------------------------
int bindPTexture(GLint program, OpenSubdiv::Osd::GLPtexMipmapTexture *osdPTex,
int bindPTexture(GLint program, GLPtexMipmapTexture *osdPTex,
GLuint data, GLuint packing, int samplerUnit) {
#if defined(GL_ARB_separate_shader_objects) || defined(GL_VERSION_4_1)
@ -681,30 +664,45 @@ union Effect {
}
};
typedef std::pair<OpenSubdiv::Osd::DrawContext::PatchDescriptor, Effect> EffectDesc;
struct EffectDesc {
EffectDesc(OpenSubdiv::Far::PatchDescriptor desc,
Effect effect) : desc(desc), effect(effect),
maxValence(0), numElements(0) { }
OpenSubdiv::Far::PatchDescriptor desc;
Effect effect;
int maxValence;
int numElements;
bool operator < (const EffectDesc &e) const {
return desc < e.desc || (desc == e.desc &&
(maxValence < e.maxValence || ((maxValence == e.maxValence) &&
(effect < e.effect))));
}
};
class EffectDrawRegistry : public OpenSubdiv::Osd::GLDrawRegistry<EffectDesc> {
protected:
virtual ConfigType *
_CreateDrawConfig(DescType const & desc, SourceConfigType const * sconfig);
_CreateDrawConfig(EffectDesc const & desc, SourceConfigType const * sconfig);
virtual SourceConfigType *
_CreateDrawSourceConfig(DescType const & desc);
_CreateDrawSourceConfig(EffectDesc const & desc);
};
//------------------------------------------------------------------------------
EffectDrawRegistry::SourceConfigType *
EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
EffectDrawRegistry::_CreateDrawSourceConfig(EffectDesc const & effectDesc) {
Effect effect = desc.second;
SetPtexEnabled(true);
Effect effect = effectDesc.effect;
SourceConfigType * sconfig =
BaseRegistry::_CreateDrawSourceConfig(desc.first);
BaseRegistry::_CreateDrawSourceConfig(effectDesc.desc);
// add ptex functions
sconfig->commonShader.source += GLPtexMipmapTexture::GetShaderSource();
if (effect.patchCull)
sconfig->commonShader.AddDefine("OSD_ENABLE_PATCH_CULL");
@ -719,15 +717,27 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
const char *glslVersion = "#version 330\n";
#endif
// legacy gregory patch requires OSD_MAX_VALENCE and OSD_NUM_ELEMENTS defined
if (effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::GREGORY or
effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::GREGORY_BOUNDARY) {
std::ostringstream ss;
ss << effectDesc.maxValence;
sconfig->commonShader.AddDefine("OSD_MAX_VALENCE", ss.str());
ss.str("");
ss << effectDesc.numElements;
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
}
int nverts = 4;
if (desc.first.GetType() == OpenSubdiv::Far::PatchDescriptor::QUADS) {
if (effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::QUADS) {
sconfig->vertexShader.source = g_shaderSource;
sconfig->vertexShader.version = glslVersion;
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
if (effect.displacement) {
sconfig->geometryShader.AddDefine("FLAT_NORMALS");
}
} else if (desc.first.GetType() == OpenSubdiv::Far::PatchDescriptor::LINES) {
} else if (effectDesc.desc.GetType() == OpenSubdiv::Far::PatchDescriptor::LINES) {
nverts = 2;
sconfig->vertexShader.source = g_shaderSource;
sconfig->vertexShader.version = glslVersion;
@ -848,10 +858,10 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
EffectDrawRegistry::ConfigType *
EffectDrawRegistry::_CreateDrawConfig(
DescType const & desc,
DescType const & effectDesc,
SourceConfigType const * sconfig) {
ConfigType * config = BaseRegistry::_CreateDrawConfig(desc.first, sconfig);
ConfigType * config = BaseRegistry::_CreateDrawConfig(effectDesc.desc, sconfig);
assert(config);
// XXXdyu can use layout(binding=) with GLSL 4.20 and beyond
@ -910,10 +920,18 @@ EffectDrawRegistry effectRegistry;
EffectDrawRegistry::ConfigType *
getInstance(Effect effect,
OpenSubdiv::Osd::DrawContext::PatchDescriptor const & patchDesc) {
OpenSubdiv::Far::PatchDescriptor const & patchDesc) {
EffectDesc desc(patchDesc, effect);
// only legacy gregory needs maxValence and numElements
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
if (patchDesc.GetType() == Descriptor::GREGORY or
patchDesc.GetType() == Descriptor::GREGORY_BOUNDARY) {
desc.maxValence = g_mesh->GetDrawContext()->GetMaxValence();
desc.numElements = 3;
}
EffectDrawRegistry::ConfigType * config =
effectRegistry.GetDrawConfig(desc);
assert(config);
@ -922,7 +940,7 @@ getInstance(Effect effect,
}
//------------------------------------------------------------------------------
OpenSubdiv::Osd::GLPtexMipmapTexture *
GLPtexMipmapTexture *
createPtex(const char *filename, int memLimit) {
Ptex::String ptexError;
@ -945,10 +963,8 @@ createPtex(const char *filename, int memLimit) {
size_t targetMemory = memLimit * 1024 * 1024; // MB
OpenSubdiv::Osd::GLPtexMipmapTexture *osdPtex =
OpenSubdiv::Osd::GLPtexMipmapTexture::Create(ptex,
g_maxMipmapLevels,
targetMemory);
GLPtexMipmapTexture *osdPtex = GLPtexMipmapTexture::Create(
ptex, g_maxMipmapLevels, targetMemory);
GLuint texture = osdPtex->GetTexelsTexture();
glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
@ -1024,33 +1040,26 @@ createOsdMesh(int level, int kernel) {
OpenSubdiv::Osd::MeshBitset bits;
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
bits.set(OpenSubdiv::Osd::MeshPtexData, true);
bits.set(OpenSubdiv::Osd::MeshEndCapGregoryBasis, true);
int numVertexElements = 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::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,
@ -1058,13 +1067,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,
@ -1072,30 +1078,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,
@ -1103,32 +1104,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));
@ -1492,7 +1490,7 @@ updateUniformBlocks() {
//------------------------------------------------------------------------------
static GLuint
bindProgram(Effect effect, OpenSubdiv::Osd::DrawContext::PatchDescriptor const &desc) {
bindProgram(Effect effect, OpenSubdiv::Far::PatchDescriptor const &desc) {
EffectDrawRegistry::ConfigType *
config = getInstance(effect, desc);
@ -1574,7 +1572,7 @@ drawModel() {
for (int i = 0; i < (int)patches.size(); ++i) {
OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
GLenum primType;
@ -1749,8 +1747,7 @@ drawCageEdges() {
typedef OpenSubdiv::Far::PatchDescriptor FDesc;
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc(
FDesc(FDesc::LINES), 0, 0);
FDesc desc(FDesc::LINES);
EffectDrawRegistry::ConfigType *config = getInstance(effect, desc);
glUseProgram(config->program);
@ -1979,32 +1976,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)

View File

@ -21,7 +21,6 @@
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#line 25
//--------------------------------------------------------------
// Common
@ -30,17 +29,10 @@
uniform float displacementScale = 1.0;
uniform float mipmapBias = 0;
vec4 GeneratePatchCoord(vec2 localUV, int primitiveID) // for non-adpative
vec4 GeneratePatchCoord(vec2 uv, int primitiveID) // for non-adaptive
{
ivec2 ptexIndex = texelFetch(OsdPatchParamBuffer, primitiveID).xy;
int faceID = ptexIndex.x;
int lv = 1 << ((ptexIndex.y & 0xf) - ((ptexIndex.y >> 4) & 1));
int u = (ptexIndex.y >> 17) & 0x3ff;
int v = (ptexIndex.y >> 7) & 0x3ff;
vec2 uv = localUV;
uv = (uv * vec2(1.0)/lv) + vec2(u, v)/lv;
return vec4(uv.x, uv.y, lv+0.5, faceID+0.5);
ivec3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
return OsdInterpolatePatchCoord(uv, OsdGetPatchCoord(patchParam));
}
#if defined(DISPLACEMENT_HW_BILINEAR) \
@ -490,14 +482,14 @@ GetOverrideColor(int patchParam)
#elif defined OSD_PATCH_GREGORY_BASIS
patchType = 6;
#endif
int edgeCount = bitCount((patchParam >> 4) & 0xf);
int edgeCount = bitCount(OsdGetPatchBoundaryMask(patchParam));
if (edgeCount == 1) {
patchType = 2; // BOUNDARY
}
if (edgeCount == 2) {
patchType = 3; // CORNER
}
int pattern = bitCount((patchParam >> 8) & 0xf);
int pattern = bitCount(OsdGetPatchTransitionMask(patchParam));
int offset = 7*patchType + pattern;
return patchColors[offset];
}
@ -675,7 +667,7 @@ main()
textureImage_Data,
textureImage_Packing);
#elif defined COLOR_PATCHTYPE
vec4 texColor = edgeColor(lighting(GetOverrideColor(GetPatchParam()), inpt.v.position.xyz, normal, 1, 0));
vec4 texColor = edgeColor(lighting(GetOverrideColor(OsdGetPatchParam(OsdGetPatchIndex(gl_PrimitiveID))), inpt.v.position.xyz, normal, 1, 0));
outColor = texColor;
return;
#elif defined COLOR_PATCHCOORD

View File

@ -42,60 +42,46 @@
GLFWwindow* g_window=0;
GLFWmonitor* g_primary=0;
#include <osd/vertex.h>
#include <osd/glDrawContext.h>
#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
@ -172,7 +158,6 @@ public:
if (interleaved) {
assert(vertexDesc.stride == varyingDesc.stride);
_vertexBuffer = createVertexBuffer(
vertexDesc.stride, numInstances * numVertices);
} else {
@ -260,62 +245,61 @@ public:
return _restPosition;
}
int GetNumVertices() const {
int GetNumVertices() const { // total (control + refined)
return _numVertices;
}
int GetNumControlVertices() const {
return _numControlVertices;
}
protected:
TopologyBase(Far::PatchTables const * patchTables) {
_drawContext = Osd::GLDrawContext::Create(patchTables, 7);
}
void updateVertexBufferStride(int stride) {
// modifying patchArrays in drawcontext.
Osd::DrawContext::PatchArrayVector &patchArrays =
_drawContext->GetPatchArrays();
for (int i = 0; i < (int)patchArrays.size(); ++i) {
Osd::DrawContext::PatchDescriptor desc = patchArrays[i].GetDescriptor();
desc.SetNumElements(stride);
patchArrays[i].SetDescriptor(desc);
}
_drawContext = Osd::GLDrawContext::Create(patchTables);
}
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) {
@ -330,21 +314,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);
}
}
}
}
@ -360,20 +382,19 @@ public:
}
virtual void Synchronize() {
_computeController->Synchronize();
Evaluator::Synchronize(_deviceContext);
}
virtual void UpdateVertexTexture(InstancesBase *instances) {
Instances<VERTEX_BUFFER, DEVICE_CONTEXT> *typedInstance =
static_cast<Instances<VERTEX_BUFFER, DEVICE_CONTEXT> *>(instances);
GetDrawContext()->UpdateVertexTexture(typedInstance->GetVertexBuffer());
updateVertexBufferStride(typedInstance->GetVertexBuffer()->GetNumElements());
}
private:
ComputeController *_computeController;
ComputeContext *_computeContext;
StencilTables const *_vertexStencils;
StencilTables const *_varyingStencils;
EvaluatorCache * _evaluatorCache;
DeviceContext *_deviceContext;
};
@ -645,81 +666,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
@ -771,25 +796,40 @@ union Effect {
}
};
typedef std::pair<Osd::DrawContext::PatchDescriptor, Effect> EffectDesc;
struct EffectDesc {
EffectDesc(OpenSubdiv::Far::PatchDescriptor desc,
Effect effect) : desc(desc), effect(effect),
maxValence(0), numElements(0) { }
OpenSubdiv::Far::PatchDescriptor desc;
Effect effect;
int maxValence;
int numElements;
bool operator < (const EffectDesc &e) const {
return desc < e.desc || (desc == e.desc &&
(maxValence < e.maxValence || ((maxValence == e.maxValence) &&
(effect < e.effect))));
}
};
class EffectDrawRegistry : public Osd::GLDrawRegistry<EffectDesc> {
protected:
virtual ConfigType *
_CreateDrawConfig(DescType const & desc, SourceConfigType const * sconfig);
_CreateDrawConfig(EffectDesc const & desc, SourceConfigType const * sconfig);
virtual SourceConfigType *
_CreateDrawSourceConfig(DescType const & desc);
_CreateDrawSourceConfig(EffectDesc const & desc);
};
EffectDrawRegistry::SourceConfigType *
EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
EffectDrawRegistry::_CreateDrawSourceConfig(EffectDesc const & effectDesc) {
Effect effect = desc.second;
Effect effect = effectDesc.effect;
SourceConfigType * sconfig =
BaseRegistry::_CreateDrawSourceConfig(desc.first);
BaseRegistry::_CreateDrawSourceConfig(effectDesc.desc);
assert(sconfig);
@ -799,8 +839,20 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
const char *glslVersion = "#version 330\n";
#endif
if (desc.first.GetType() == Far::PatchDescriptor::QUADS or
desc.first.GetType() == Far::PatchDescriptor::TRIANGLES) {
// legacy gregory patch requires OSD_MAX_VALENCE and OSD_NUM_ELEMENTS defined
if (effectDesc.desc.GetType() == Far::PatchDescriptor::GREGORY or
effectDesc.desc.GetType() == Far::PatchDescriptor::GREGORY_BOUNDARY) {
std::ostringstream ss;
ss << effectDesc.maxValence;
sconfig->commonShader.AddDefine("OSD_MAX_VALENCE", ss.str());
ss.str("");
ss << effectDesc.numElements;
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
}
if (effectDesc.desc.GetType() == Far::PatchDescriptor::QUADS or
effectDesc.desc.GetType() == Far::PatchDescriptor::TRIANGLES) {
sconfig->vertexShader.source = shaderSource;
sconfig->vertexShader.version = glslVersion;
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
@ -816,12 +868,12 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc) {
sconfig->fragmentShader.version = glslVersion;
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
if (desc.first.GetType() == Far::PatchDescriptor::QUADS) {
if (effectDesc.desc.GetType() == Far::PatchDescriptor::QUADS) {
// uniform catmark, bilinear
sconfig->geometryShader.AddDefine("PRIM_QUAD");
sconfig->fragmentShader.AddDefine("PRIM_QUAD");
sconfig->commonShader.AddDefine("UNIFORM_SUBDIVISION");
} else if (desc.first.GetType() == Far::PatchDescriptor::TRIANGLES) {
} else if (effectDesc.desc.GetType() == Far::PatchDescriptor::TRIANGLES) {
// uniform loop
sconfig->geometryShader.AddDefine("PRIM_TRI");
sconfig->fragmentShader.AddDefine("PRIM_TRI");
@ -865,7 +917,7 @@ EffectDrawRegistry::_CreateDrawConfig(
DescType const & desc,
SourceConfigType const * sconfig) {
ConfigType * config = BaseRegistry::_CreateDrawConfig(desc.first, sconfig);
ConfigType * config = BaseRegistry::_CreateDrawConfig(desc.desc, sconfig);
assert(config);
GLuint uboIndex;
@ -938,6 +990,18 @@ static GLuint
bindProgram(Effect effect, Osd::DrawContext::PatchArray const & patch) {
EffectDesc effectDesc(patch.GetDescriptor(), effect);
// only legacy gregory needs maxValence and numElements
int maxValence = g_topology->GetDrawContext()->GetMaxValence();
int numElements = (g_displayStyle == kVaryingInterleaved ? 7 : 3);
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
if (patch.GetDescriptor().GetType() == Descriptor::GREGORY or
patch.GetDescriptor().GetType() == Descriptor::GREGORY_BOUNDARY) {
effectDesc.maxValence = maxValence;
effectDesc.numElements = numElements;
}
EffectDrawRegistry::ConfigType *
config = effectRegistry.GetDrawConfig(effectDesc);
@ -1054,7 +1118,7 @@ drawPatches(Osd::DrawContext::PatchArrayVector const &patches,
Osd::DrawContext::PatchArray const & patch = patches[i];
Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
Far::PatchDescriptor desc = patch.GetDescriptor();
Far::PatchDescriptor::Type patchType = desc.GetType();
GLenum primType;
@ -1292,28 +1356,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
}
//------------------------------------------------------------------------------
@ -1454,7 +1496,7 @@ static void
callbackDisplayStyle(int b) {
g_displayStyle = b;
rebuildInstances();
rebuildOsdMesh();
}
static void

View File

@ -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);

View File

@ -43,59 +43,44 @@ GLFWwindow* g_window=0;
GLFWmonitor* g_primary=0;
#include <far/error.h>
#include <osd/vertex.h>
#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>
@ -450,13 +435,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);
@ -493,7 +472,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;
@ -505,12 +485,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),
@ -545,117 +525,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));
@ -847,35 +814,63 @@ union Effect {
}
};
typedef std::pair<OpenSubdiv::Osd::DrawContext::PatchDescriptor, Effect> EffectDesc;
struct EffectDesc {
EffectDesc(OpenSubdiv::Far::PatchDescriptor desc,
Effect effect) : desc(desc), effect(effect),
maxValence(0), numElements(0) { }
OpenSubdiv::Far::PatchDescriptor desc;
Effect effect;
int maxValence;
int numElements;
bool operator < (const EffectDesc &e) const {
return desc < e.desc || (desc == e.desc &&
(maxValence < e.maxValence || ((maxValence == e.maxValence) &&
(effect < e.effect))));
}
};
class EffectDrawRegistry : public OpenSubdiv::Osd::GLDrawRegistry<EffectDesc> {
protected:
virtual ConfigType *
_CreateDrawConfig(DescType const & desc, SourceConfigType const * sconfig);
_CreateDrawConfig(EffectDesc const & desc, SourceConfigType const * sconfig);
virtual SourceConfigType *
_CreateDrawSourceConfig(DescType const & desc);
_CreateDrawSourceConfig(EffectDesc const & desc);
};
EffectDrawRegistry::SourceConfigType *
EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc)
EffectDrawRegistry::_CreateDrawSourceConfig(EffectDesc const & effectDesc)
{
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
Effect effect = desc.second;
Effect effect = effectDesc.effect;
SourceConfigType * sconfig =
BaseRegistry::_CreateDrawSourceConfig(desc.first);
BaseRegistry::_CreateDrawSourceConfig(effectDesc.desc);
assert(sconfig);
const std::string glslVersionStr = get_shader_version_include();
const char *glslVersion = glslVersionStr.c_str();
if (desc.first.GetType() == Descriptor::QUADS or
desc.first.GetType() == Descriptor::TRIANGLES) {
// legacy gregory patch requires OSD_MAX_VALENCE and OSD_NUM_ELEMENTS defined
if (effectDesc.desc.GetType() == Descriptor::GREGORY or
effectDesc.desc.GetType() == Descriptor::GREGORY_BOUNDARY) {
std::ostringstream ss;
ss << effectDesc.maxValence;
sconfig->commonShader.AddDefine("OSD_MAX_VALENCE", ss.str());
ss.str("");
ss << effectDesc.numElements;
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
}
if (effectDesc.desc.GetType() == Descriptor::QUADS or
effectDesc.desc.GetType() == Descriptor::TRIANGLES) {
sconfig->vertexShader.source = shaderSource();
sconfig->vertexShader.version = glslVersion;
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
@ -891,12 +886,12 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc)
sconfig->fragmentShader.version = glslVersion;
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
if (desc.first.GetType() == Descriptor::QUADS) {
if (effectDesc.desc.GetType() == Descriptor::QUADS) {
// uniform catmark, bilinear
sconfig->geometryShader.AddDefine("PRIM_QUAD");
sconfig->fragmentShader.AddDefine("PRIM_QUAD");
sconfig->commonShader.AddDefine("UNIFORM_SUBDIVISION");
} else if (desc.first.GetType() == Descriptor::TRIANGLES) {
} else if (effectDesc.desc.GetType() == Descriptor::TRIANGLES) {
// uniform loop
sconfig->geometryShader.AddDefine("PRIM_TRI");
sconfig->fragmentShader.AddDefine("PRIM_TRI");
@ -956,7 +951,7 @@ EffectDrawRegistry::_CreateDrawConfig(
DescType const & desc,
SourceConfigType const * sconfig)
{
ConfigType * config = BaseRegistry::_CreateDrawConfig(desc.first, sconfig);
ConfigType * config = BaseRegistry::_CreateDrawConfig(desc.desc, sconfig);
assert(config);
GLuint uboIndex;
@ -1042,6 +1037,18 @@ static GLuint
bindProgram(Effect effect, OpenSubdiv::Osd::DrawContext::PatchArray const & patch)
{
EffectDesc effectDesc(patch.GetDescriptor(), effect);
// only legacy gregory needs maxValence and numElements
int maxValence = g_mesh->GetDrawContext()->GetMaxValence();
int numElements = (g_displayStyle == kInterleavedVaryingColor ? 7 : 3);
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
if (patch.GetDescriptor().GetType() == Descriptor::GREGORY or
patch.GetDescriptor().GetType() == Descriptor::GREGORY_BOUNDARY) {
effectDesc.maxValence = maxValence;
effectDesc.numElements = numElements;
}
EffectDrawRegistry::ConfigType *
config = effectRegistry.GetDrawConfig(effectDesc);
@ -1204,7 +1211,7 @@ display() {
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
patchCount[patchType] += patch.GetNumPatches();
@ -1320,10 +1327,6 @@ display() {
patchCount[Descriptor::QUADS]); y += 20;
g_hud.DrawString(x, y, "Regular : %d",
patchCount[Descriptor::REGULAR]); y+= 20;
g_hud.DrawString(x, y, "Boundary : %d",
patchCount[Descriptor::BOUNDARY]); y+= 20;
g_hud.DrawString(x, y, "Corner : %d",
patchCount[Descriptor::CORNER]); y+= 20;
g_hud.DrawString(x, y, "Gregory : %d",
patchCount[Descriptor::GREGORY]); y+= 20;
g_hud.DrawString(x, y, "Boundary Gregory : %d",
@ -1410,28 +1413,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
}
//------------------------------------------------------------------------------

View File

@ -388,7 +388,7 @@ edgeColor(vec4 Cfill, vec4 edgeDistance)
}
vec4
getAdaptivePatchColor(int patchParam)
getAdaptivePatchColor(ivec3 patchParam)
{
const vec4 patchColors[7*6] = vec4[7*6](
vec4(1.0f, 1.0f, 1.0f, 1.0f), // regular
@ -450,7 +450,7 @@ getAdaptivePatchColor(int patchParam)
patchType = 6;
#endif
int edgeCount = bitCount((patchParam >> 4) & 0xf);
int edgeCount = bitCount(OsdGetPatchBoundaryMask(patchParam));
if (edgeCount == 1) {
patchType = 2; // BOUNDARY
}
@ -458,7 +458,7 @@ getAdaptivePatchColor(int patchParam)
patchType = 3; // CORNER
}
int pattern = bitCount((patchParam >> 8) & 0xf);
int pattern = bitCount(OsdGetPatchTransitionMask(patchParam));
#ifdef OSD_PATCH_ENABLE_SINGLE_CREASE
if (inpt.sharpness > 0) pattern += 6;
#endif
@ -480,7 +480,7 @@ main()
int(floor(20*inpt.color.r)+floor(20*inpt.color.g))&1, 1);
#else
//vec4 color = diffuseColor;
vec4 color = getAdaptivePatchColor(GetPatchParam());
vec4 color = getAdaptivePatchColor(OsdGetPatchParam(OsdGetPatchIndex(gl_PrimitiveID)));
#endif
vec4 Cf = lighting(color, inpt.v.position.xyz, N);

View File

@ -64,8 +64,6 @@
#include <far/stencilTablesFactory.h>
#include <osd/mesh.h>
#include <osd/cpuComputeContext.h>
#include <osd/cpuComputeController.h>
#include <osd/cpuVertexBuffer.h>

View File

@ -708,16 +708,6 @@ GLMesh::initializeBuffers(Options options, TopologyRefiner const & refiner,
eao[face*4+1] = cvs[ 6];
eao[face*4+2] = cvs[10];
eao[face*4+3] = cvs[ 9];
} else if (desc.GetType()==Descriptor::BOUNDARY) {
eao[face*4 ] = cvs[ 2];
eao[face*4+1] = cvs[ 6];
eao[face*4+2] = cvs[ 5];
eao[face*4+3] = cvs[ 1];
} else if (desc.GetType()==Descriptor::CORNER) {
eao[face*4 ] = cvs[ 1];
eao[face*4+1] = cvs[ 2];
eao[face*4+2] = cvs[ 5];
eao[face*4+3] = cvs[ 4];
} else {
memcpy(&eao[face*4], cvs.begin(), 4*sizeof(OpenSubdiv::Far::Index));
}

View File

@ -28,7 +28,6 @@
#include <common/vtr_utils.h>
#include <common/hbr_utils.h>
#include <far/patchTables.h>
#include <osd/vertex.h>
#include "../common/gl_common.h"

View File

@ -455,8 +455,6 @@ private:
template<class TYPE> struct PatchTypes {
TYPE R, // regular patch
B, // boundary patch (4 rotations)
C, // corner patch (4 rotations)
G, // gregory patch
GB, // gregory boundary patch
GP; // gregory basis
@ -484,8 +482,6 @@ Far::PatchTablesFactory::PatchTypes<TYPE>::getValue( Far::PatchDescriptor desc )
switch (desc.GetType()) {
case Far::PatchDescriptor::REGULAR : return R;
case Far::PatchDescriptor::BOUNDARY : return B;
case Far::PatchDescriptor::CORNER : return C;
case Far::PatchDescriptor::GREGORY : return G;
case Far::PatchDescriptor::GREGORY_BOUNDARY : return GB;
case Far::PatchDescriptor::GREGORY_BASIS : return GP;
@ -500,10 +496,9 @@ Far::PatchTablesFactory::PatchTypes<TYPE>::getNumPatchArrays() const {
int result=0;
if (R) ++result;
if (B) ++result;
if (C) ++result;
if (G) ++result;
if (GB) ++result;
if (GP) ++result;
return result;
}
@ -690,12 +685,12 @@ Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) {
case 2 : { // Boundary patch
f->_adaptiveFlags.rots=computeBoundaryPatchRotation(f);
patchCtr.B++;
patchCtr.R++;
} break;
case 3 : { // Corner patch
f->_adaptiveFlags.rots=computeCornerPatchRotation(f);
patchCtr.C++;
patchCtr.R++;
} break;
default : break;
@ -784,7 +779,7 @@ Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) {
f->_adaptiveFlags.rots=rot; // override the transition rotation
patchCtr.B++;
patchCtr.R++;
} break;
case 3 : { // corner patch
@ -794,7 +789,7 @@ Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) {
f->_adaptiveFlags.rots=rot; // override the transition rotation
patchCtr.C++;
patchCtr.R++;
} break;
default : assert(0); break;
@ -808,8 +803,8 @@ Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) {
static const Far::Index remapRegular [16] = {5,6,10,9,4,0,1,2,3,7,11,15,14,13,12,8};
static const Far::Index remapRegularBoundary[12] = {1,2,6,5,0,3,7,11,10,9,8,4};
static const Far::Index remapRegularCorner [ 9] = {1,2,5,4,0,8,7,6,3};
static const Far::Index remapRegularBoundary[16] = {5,6,10,9,4,7,11,15,14,13,12,8,0,1,2,3};
static const Far::Index remapRegularCorner [16] = {5,6,10,9,7,11,15,14,13,12,8,4,0,1,2,3};
int fvarwidth=0;
@ -878,16 +873,16 @@ Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) {
case 2 : { // Boundary Patch (12 CVs)
f->_adaptiveFlags.brots = (f->_adaptiveFlags.rots+1)%4;
iptrs.B = getOneRing(f, 12, remapRegularBoundary, iptrs.B);
pptrs.B = computePatchParam(f, pptrs.B);
//fptrs.B[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.B[0][0], /*isAdaptive=*/true);
iptrs.R = getOneRing(f, 12, remapRegularBoundary, iptrs.R);
pptrs.R = computePatchParam(f, pptrs.R);
//fptrs.R[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.R[0][0], /*isAdaptive=*/true);
} break;
case 3 : { // Corner Patch (9 CVs)
f->_adaptiveFlags.brots = (f->_adaptiveFlags.rots+1)%4;
iptrs.C = getOneRing(f, 9, remapRegularCorner, iptrs.C);
pptrs.C = computePatchParam(f, pptrs.C);
//fptrs.C[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.C[0][0], /*isAdaptive=*/true);
iptrs.R = getOneRing(f, 9, remapRegularCorner, iptrs.R);
pptrs.R = computePatchParam(f, pptrs.R);
//fptrs.R[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.R[0][0], /*isAdaptive=*/true);
} break;
default : assert(0);
@ -938,16 +933,16 @@ Far::PatchTablesFactory::Create(Hmesh & mesh, int maxvalence) {
case 2 : { // Boundary Transition Patch (12 CVs)
//unsigned rot = f->_adaptiveFlags.brots;
iptrs.B = getOneRing(f, 12, remapRegularBoundary, iptrs.B);
pptrs.B = computePatchParam(f, pptrs.B);
//fptrs.B[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.B[pattern][rot], /*isAdaptive=*/true);
iptrs.R = getOneRing(f, 12, remapRegularBoundary, iptrs.R);
pptrs.R = computePatchParam(f, pptrs.R);
//fptrs.R[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.R[pattern][rot], /*isAdaptive=*/true);
} break;
case 3 : { // Corner Transition Patch (9 CVs)
//unsigned rot = f->_adaptiveFlags.brots;
iptrs.C = getOneRing(f, 9, remapRegularCorner, iptrs.C);
pptrs.C = computePatchParam(f, pptrs.C);
//fptrs.C[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.C[pattern][rot], /*isAdaptive=*/true);
iptrs.R = getOneRing(f, 9, remapRegularCorner, iptrs.R);
pptrs.R = computePatchParam(f, pptrs.R);
//fptrs.R[pattern][rot] = computeFVarData(f, fvarwidth, fptrs.R[pattern][rot], /*isAdaptive=*/true);
} break;
}
} else
@ -1106,10 +1101,10 @@ Far::PatchTablesFactory::getOneRing(Hface const * f,
// Boundary case
//
// 4 0 3 5
// 4 0 1 5
// ---- o ---- o ---- o ---- o ----
// | | | |
// | 11 | 1 | 2 | 6
// | 11 | 3 | 2 | 6
// ---- o ---- o ---- o ---- o ----
// | | | |
// | 10 | 9 | 8 | 7
@ -1141,7 +1136,10 @@ Far::PatchTablesFactory::getOneRing(Hface const * f,
result[remap[idx++ % ringsize]] = e->GetOrgVertex()->GetID();
}
result += 12;
for (int i=12; i<16; ++i) {
result[remap[idx++]] = result[0];
}
result += 16;
} else if (ringsize==9) {
@ -1176,10 +1174,13 @@ Far::PatchTablesFactory::getOneRing(Hface const * f,
result[remap[idx++ % ringsize]] = e->GetOrgVertex()->GetID();
}
result += 9;
for (int i=9; i<16; ++i) {
result[remap[idx++]] = result[0];
}
result += 16;
}
assert(idx==ringsize);
assert(idx==16);
return result;
}

View File

@ -46,7 +46,6 @@ GLFWmonitor* g_primary=0;
#define snprintf _snprintf
#endif
#include <osd/vertex.h>
#include <osd/cpuGLVertexBuffer.h>
#include <far/gregoryBasis.h>
@ -710,8 +709,6 @@ createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
static char buf[16];
static int regular[4] = {5, 6, 9, 10},
boundary[4] = {1, 2, 5, 6},
corner[4] = {1, 2, 4, 5},
gregory[4] = {0, 1, 2, 3};
for (int array=0; array<(int)patchTables.GetNumPatchArrays(); ++array) {
@ -724,8 +721,6 @@ createPtexNumbers(OpenSubdiv::Far::PatchTables const & patchTables,
int * remap = 0;
switch (patchTables.GetPatchArrayDescriptor(array).GetType()) {
case Descriptor::REGULAR: remap = regular; break;
case Descriptor::BOUNDARY: remap = boundary; break;
case Descriptor::CORNER: remap = corner; break;
case Descriptor::GREGORY:
case Descriptor::GREGORY_BOUNDARY:
case Descriptor::GREGORY_BASIS: remap = gregory; break;

View File

@ -53,66 +53,59 @@ public:
// patch weights
static void GetPatchWeights(PatchParam::BitField bits,
float s, float t, float point[], float deriv1[], float deriv2[]);
// adjust patch weights for boundary (and corner) edges
static void AdjustBoundaryWeights(PatchParam::BitField bits,
float sWeights[4], float tWeights[4]);
};
template <>
inline void Spline<BASIS_BEZIER>::GetWeights(
float t, float point[4], float deriv[3]) {
float t, float point[4], float deriv[4]) {
// The weights for the four uniform cubic Bezier basis functions are:
// (1 - t)^3
// 3 * t * (1-t)
// 3 * t^2 * (1-t)
// t^3
float t2 = t*t,
w0 = 1.0f - t,
w2 = w0 * w0;
// The four uniform cubic Bezier basis functions (in terms of t and its
// complement tC) evaluated at t:
float t2 = t*t;
float tC = 1.0f - t;
float tC2 = tC * tC;
assert(point);
point[0] = w0*w2;
point[1] = 3.0f * t * w2;
point[2] = 3.0f * t2 * w0;
point[3] = t * t2;
point[0] = tC2 * tC;
point[1] = tC2 * t * 3.0f;
point[2] = t2 * tC * 3.0f;
point[3] = t2 * t;
// The weights for the three uniform quadratic basis functions are:
// (1-t)^2
// 2 * t * (1-t)
// t^2
// Derivatives of the above four basis functions at t:
if (deriv) {
deriv[0] = w2;
deriv[1] = 2.0f * t * w0;
deriv[2] = t2;
deriv[0] = -3.0f * tC2;
deriv[1] = 9.0f * t2 - 12.0f * t + 3.0f;
deriv[2] = -9.0f * t2 + 6.0f * t;
deriv[3] = 3.0f * t2;
}
}
template <>
inline void Spline<BASIS_BSPLINE>::GetWeights(
float t, float point[4], float deriv[3]) {
float t, float point[4], float deriv[4]) {
// The weights for the four uniform cubic B-Spline basis functions are:
// (1/6)(1 - t)^3
// (1/6)(3t^3 - 6t^2 + 4)
// (1/6)(-3t^3 + 3t^2 + 3t + 1)
// (1/6)t^3
float t2 = t*t,
t3 = 3.0f*t2*t,
w0 = 1.0f-t;
// The four uniform cubic B-Spline basis functions evaluated at t:
float const one6th = 1.0f / 6.0f;
float t2 = t * t;
float t3 = t * t2;
assert(point);
point[0] = (w0*w0*w0) / 6.0f;
point[1] = (t3 - 6.0f*t2 + 4.0f) / 6.0f;
point[2] = (3.0f*t2 - t3 + 3.0f*t + 1.0f) / 6.0f;
point[3] = t3 / 18.0f;
point[0] = one6th * (1.0f - 3.0f*(t - t2) - t3);
point[1] = one6th * (4.0f - 6.0f*t2 + 3.0f*t3);
point[2] = one6th * (1.0f + 3.0f*(t + t2 - t3));
point[3] = one6th * ( t3);
// The weights for the three uniform quadratic basis functions are:
// (1/2)(1-t)^2
// (1/2)(1 + 2t - 2t^2)
// (1/2)t^2
// Derivatives of the above four basis functions at t:
if (deriv) {
deriv[0] = 0.5f * w0 * w0;
deriv[1] = 0.5f + t - t2;
deriv[2] = 0.5f * t2;
deriv[0] = -0.5f*t2 + t - 0.5f;
deriv[1] = 1.5f*t2 - 2.0f*t;
deriv[2] = -1.5f*t2 + t + 0.5f;
deriv[3] = 0.5f*t2;
}
}
@ -173,119 +166,99 @@ template <>
inline void Spline<BASIS_BILINEAR>::GetPatchWeights(PatchParam::BitField bits,
float s, float t, float point[4], float deriv1[4], float deriv2[4]) {
static int const rots[4][4] =
{ { 0, 1, 2, 3 },
{ 3, 0, 1, 2 },
{ 2, 3, 0, 1 },
{ 1, 2, 3, 0 } };
assert(bits.GetRotation()<4);
int const * rot = rots[bits.GetRotation()];
bits.Normalize(s,t);
float os = 1.0f - s,
ot = 1.0f - t;
if (point) {
point[rot[0]] = os*ot;
point[rot[1]] = s*ot;
point[rot[2]] = s*t;
point[rot[3]] = os*t;
point[0] = os*ot;
point[1] = s*ot;
point[2] = s*t;
point[3] = os*t;
}
if (deriv1 and deriv2) {
deriv1[rot[0]] = t-1.0f;
deriv1[rot[1]] = ot;
deriv1[rot[2]] = t;
deriv1[rot[3]] = -t;
deriv1[0] = t-1.0f;
deriv1[1] = ot;
deriv1[2] = t;
deriv1[3] = -t;
deriv2[rot[0]] = s-1.0f;
deriv2[rot[1]] = -s;
deriv2[rot[2]] = s;
deriv2[rot[3]] = os;
deriv2[0] = s-1.0f;
deriv2[1] = -s;
deriv2[2] = s;
deriv2[3] = os;
}
}
template <SplineBasis BASIS>
void Spline<BASIS>::AdjustBoundaryWeights(PatchParam::BitField bits,
float sWeights[4], float tWeights[4]) {
int boundary = bits.GetBoundary();
if (boundary & 1) {
tWeights[2] -= tWeights[0];
tWeights[1] += 2*tWeights[0];
tWeights[0] = 0;
}
if (boundary & 2) {
sWeights[1] -= sWeights[3];
sWeights[2] += 2*sWeights[3];
sWeights[3] = 0;
}
if (boundary & 4) {
tWeights[1] -= tWeights[3];
tWeights[2] += 2*tWeights[3];
tWeights[3] = 0;
}
if (boundary & 8) {
sWeights[2] -= sWeights[0];
sWeights[1] += 2*sWeights[0];
sWeights[0] = 0;
}
}
template <SplineBasis BASIS>
void Spline<BASIS>::GetPatchWeights(PatchParam::BitField bits,
float s, float t, float point[16], float deriv1[16], float deriv2[16]) {
float s, float t, float point[16], float derivS[16], float derivT[16]) {
static int const rots[4][16] =
{ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 12, 8, 4, 0, 13, 9, 5, 1, 14, 10, 6, 2, 15, 11, 7, 3 },
{ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
{ 3, 7, 11, 15, 2, 6, 10, 14, 1, 5, 9, 13, 0, 4, 8, 12 } };
assert(bits.GetRotation()<4);
int const * rot = rots[bits.GetRotation()];
float sWeights[4], tWeights[4], d1Weights[3], d2Weights[3];
float sWeights[4], tWeights[4], dsWeights[4], dtWeights[4];
bits.Normalize(s,t);
Spline<BASIS>::GetWeights(s, point ? sWeights : 0, deriv1 ? d1Weights : 0);
Spline<BASIS>::GetWeights(t, point ? tWeights : 0, deriv2 ? d2Weights : 0);
Spline<BASIS>::GetWeights(s, point ? sWeights : 0, derivS ? dsWeights : 0);
Spline<BASIS>::GetWeights(t, point ? tWeights : 0, derivT ? dtWeights : 0);
int boundary = bits.GetBoundary();
if (point) {
// Compute the tensor product weight corresponding to each control
// vertex
memset(point, 0, 16*sizeof(float));
// Compute the tensor product weight of the (s,t) basis function
// corresponding to each control vertex:
AdjustBoundaryWeights(bits, sWeights, tWeights);
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
point[rot[4*i+j]] += sWeights[j] * tWeights[i];
point[4*i+j] = sWeights[j] * tWeights[i];
}
}
}
if (deriv1 and deriv2) {
// Compute the tangent stencil. This is done by taking the tensor
// product between the quadratic weights computed for s and the cubic
// weights computed for t. The stencil is constructed using
// differences between consecutive vertices in each row (i.e.
// in the s direction).
memset(deriv1, 0, 16*sizeof(float));
for (int i = 0, k = 0; i < 4; ++i) {
float prevWeight = 0.0f;
for (int j = 0; j < 3; ++j) {
float weight = d1Weights[j]*tWeights[i];
deriv1[rot[k++]] += prevWeight - weight;
prevWeight = weight;
}
deriv1[rot[k++]]+=prevWeight;
}
if (derivS and derivT) {
// Compute the tensor product weight of the differentiated (s,t) basis
// function corresponding to each control vertex (scaled accordingly):
memset(deriv2, 0, 16*sizeof(float));
#define FASTER_TENSOR
#ifdef FASTER_TENSOR
// XXXX manuelk this might be slightly more efficient ?
float dW[4];
dW[0] = - d2Weights[0];
dW[1] = d2Weights[0] - d2Weights[1];
dW[2] = d2Weights[1] - d2Weights[2];
dW[3] = d2Weights[2];
for (int i = 0, k = 0; i < 4; ++i) {
float dScale = (float)(1 << bits.GetDepth());
AdjustBoundaryWeights(bits, dsWeights, dtWeights);
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
deriv2[rot[k++]] = sWeights[j] * dW[i];
derivS[4*i+j] = dsWeights[j] * tWeights[i] * dScale;
derivT[4*i+j] = sWeights[j] * dtWeights[i] * dScale;
}
}
#else
for (int j = 0; j < 4; ++j) {
float prevWeight = 0.0f;
for (int i = 0; i < 3; ++i) {
float weight = sWeights[j]*d2Weights[i];
deriv2[rot[4*i+j]]+=prevWeight - weight;
prevWeight = weight;
}
deriv2[rot[12+j]] += prevWeight;
}
#endif
// Scale derivatives up based on level of subdivision
float scale = float(1 << bits.GetDepth());
for (int k=0; k<16; ++k) {
deriv1[k] *= scale;
deriv2[k] *= scale;
}
}
}
@ -307,6 +280,96 @@ void GetBSplineWeights(PatchParam::BitField bits,
Spline<BASIS_BSPLINE>::GetPatchWeights(bits, s, t, point, deriv1, deriv2);
}
void GetGregoryWeights(PatchParam::BitField bits,
float s, float t, float point[20], float deriv1[20], float deriv2[20]) {
//
// P3 e3- e2+ P2
// 15------17-------11--------10
// | | | |
// | | | |
// | | f3- | f2+ |
// | 19 13 |
// e3+ 16-----18 14-----12 e2-
// | f3+ f2- |
// | |
// | |
// | f0- f1+ |
// e0- 2------4 8------6 e1+
// | 3 9 |
// | | f0+ | f1- |
// | | | |
// | | | |
// O--------1--------7--------5
// P0 e0+ e1- P1
//
// Indices of boundary and interior points and their corresponding Bezier points:
//
static int const boundaryGregory[12] = { 0, 1, 7, 5, 2, 6, 16, 12, 15, 17, 11, 10 };
static int const boundaryBezier[12] = { 0, 1, 2, 3, 4, 7, 8, 11, 12, 13, 14, 15 };
static int const interiorGregory[8] = { 3, 4, 8, 9, 13, 14, 18, 19 };
static int const interiorBezier[8] = { 5, 5, 6, 6, 10, 10, 9, 9 };
// Rational multipliers of the Bezier basis functions (note we need a set of weights
// for each derivative for proper differentiation -- TBD):
//
float sComp = 1.0f - s;
float tComp = 1.0f - t;
// Use <= here to avoid compiler warnings -- the sums should always be non-negative:
float df0 = s + t; if (df0 <= 0.0f) df0 = 1.0f;
float df1 = sComp + t; if (df1 <= 0.0f) df1 = 1.0f;
float df2 = sComp + tComp; if (df2 <= 0.0f) df2 = 1.0f;
float df3 = s + tComp; if (df3 <= 0.0f) df3 = 1.0f;
float interiorPointBasis[8] = { s/df0, t/df0,
t/df1, sComp/df1,
sComp/df2, tComp/df2,
tComp/df3, s/df3 };
// Weights from a bicubic Bezier patch:
//
float bezierPoint[16], bezierDeriv1[16], bezierDeriv2[16];
GetBezierWeights(bits, s, t, bezierPoint, bezierDeriv1, bezierDeriv2);
// Copy basis functions (weights) for boundary points and scale the interior basis
// functions by their rational multipliers:
//
for (int i = 0; i < 12; ++i) {
point[boundaryGregory[i]] = bezierPoint[boundaryBezier[i]];
}
for (int i = 0; i < 8; ++i) {
point[interiorGregory[i]] = bezierPoint[interiorBezier[i]] * interiorPointBasis[i];
}
if (deriv1 and deriv2) {
// Copy the differentiated basis functions for Bezier to the boundary points:
//
for (int i = 0; i < 12; ++i) {
deriv1[boundaryGregory[i]] = bezierDeriv1[boundaryBezier[i]];
deriv2[boundaryGregory[i]] = bezierDeriv2[boundaryBezier[i]];
}
// XXX barry: NOTE -- THIS IS NOT CORRECT (the correction is pending)...
//
// The basis functions for the interior points are rational and require appropriate
// differentiation wrt each parametric direction. So we will need the Bezier basis
// functions in each of s and t rather than for (s,t) combined. The correction will
// also need to support higher order derivatives and so will be combined with that
// extension.
//
// What follows preserves what has been done with Gregory derivatives to this point.
//
for (int i = 0; i < 8; ++i) {
deriv1[interiorGregory[i]] = bezierDeriv1[interiorBezier[i]] * interiorPointBasis[i];
deriv2[interiorGregory[i]] = bezierDeriv2[interiorBezier[i]] * interiorPointBasis[i];
}
}
}
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION

View File

@ -52,6 +52,9 @@ void GetBezierWeights(PatchParam::BitField bits,
void GetBSplineWeights(PatchParam::BitField bits,
float s, float t, float point[16], float deriv1[16], float deriv2[16]);
void GetGregoryWeights(PatchParam::BitField bits,
float s, float t, float point[20], float deriv1[20], float deriv2[20]);
/// \brief Interpolate the (s,t) parametric location of a bilinear (quad)
/// patch

View File

@ -47,11 +47,7 @@ PatchDescriptor::GetAdaptivePatchDescriptors(Sdc::SchemeType type) {
};
static PatchDescriptor _catmarkDescriptors[] = {
// XXXdyu-patch-drawing
PatchDescriptor(REGULAR),
PatchDescriptor(BOUNDARY),
PatchDescriptor(CORNER),
PatchDescriptor(GREGORY),
PatchDescriptor(GREGORY_BOUNDARY),
PatchDescriptor(GREGORY_BASIS),
@ -75,9 +71,8 @@ PatchDescriptor::GetAdaptivePatchDescriptors(Sdc::SchemeType type) {
void
PatchDescriptor::print() const {
static char const * types[13] = {
"NON_PATCH", "POINTS", "LINES", "QUADS", "TRIANGLES", "LOOP", "REGULAR",
"SINGLE_CREASE", "BOUNDARY", "CORNER", "GREGORY",
"GREGORY_BOUNDARY", "GREGORY_BASIS" };
"NON_PATCH", "POINTS", "LINES", "QUADS", "TRIANGLES", "LOOP",
"REGULAR", "GREGORY", "GREGORY_BOUNDARY", "GREGORY_BASIS" };
printf(" type %s\n",
types[_type]);

View File

@ -45,7 +45,7 @@ namespace Far {
/// or TRIANGLES
///
/// * Adaptively subdivided meshes contain bicubic patches of types REGULAR,
/// BOUNDARY, CORNER, GREGORY, GREGORY_BOUNDARY, GREGOYR_BASIS.
/// GREGORY, GREGORY_BOUNDARY, GREGORY_BASIS.
/// These bicubic patches are also further distinguished by a transition
/// pattern as well as a rotational orientation.
///
@ -71,8 +71,6 @@ public:
LOOP, ///< Loop patch
REGULAR, ///< feature-adaptive bicubic patches
BOUNDARY,
CORNER,
GREGORY,
GREGORY_BOUNDARY,
GREGORY_BASIS
@ -128,12 +126,6 @@ public:
/// \brief Number of control vertices of Regular Patches in table.
static short GetRegularPatchSize() { return 16; }
/// \brief Number of control vertices of Boundary Patches in table.
static short GetBoundaryPatchSize() { return 16; }
/// \brief Number of control vertices of Boundary Patches in table.
static short GetCornerPatchSize() { return 16; }
/// \brief Number of control vertices of Gregory (and Gregory Boundary) Patches in table.
static short GetGregoryPatchSize() { return 4; }
@ -169,8 +161,6 @@ PatchDescriptor::GetNumControlVertices( Type type ) {
case GREGORY :
case GREGORY_BOUNDARY : return GetGregoryPatchSize();
case GREGORY_BASIS : return GetGregoryBasisPatchSize();
case BOUNDARY : return GetBoundaryPatchSize();
case CORNER : return GetCornerPatchSize();
case TRIANGLES : return 3;
case LINES : return 2;
case POINTS : return 1;
@ -185,8 +175,6 @@ PatchDescriptor::GetNumFVarControlVertices( Type type ) {
case REGULAR : return GetRegularPatchSize();
case QUADS : return 4;
case TRIANGLES : return 3;
case BOUNDARY : return GetBoundaryPatchSize();
case CORNER : return GetCornerPatchSize();
case LINES : return 2;
case POINTS : return 1;
case GREGORY_BASIS : assert(0); return GetGregoryBasisPatchSize();

View File

@ -90,9 +90,6 @@ struct PatchParam {
/// \brief Returns the boundary edge encoding for the patch.
unsigned short GetBoundary() const { return (unsigned short)((field >> 4) & 0xf); }
/// \brief Deprecated XXXdyu-patch-drawing (patches rotated when gathered from refiner)
unsigned char GetRotation() const { return 0; }
/// \brief True if the parent coarse face is a non-quad
bool NonQuadRoot() const { return (field >> 3) & 0x1; }

View File

@ -470,14 +470,10 @@ PatchTables::Evaluate(PatchHandle const & handle, float s, float t,
if (ptype==PatchDescriptor::REGULAR) {
GetBSplineWeights(bits, s, t, Q, Qd1, Qd2);
ConstIndexArray cvs = GetPatchVertices(handle);
GetBSplineWeights(bits, s, t, Q, Qd1, Qd2);
InterpolateRegularPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
// XXXdyu bits InterpolateBoundaryPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
// XXXdyu bits InterpolateCornerPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
} else if (ptype==PatchDescriptor::GREGORY_BASIS) {
@ -526,8 +522,6 @@ PatchTables::EvaluateFaceVarying(int channel, PatchHandle const & handle,
case PatchDescriptor::REGULAR:
GetBSplineWeights(bits, s, t, Q, Qd1, Qd2);
InterpolateRegularPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
// XXXdyu bits InterpolateBoundaryPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
// XXXdyu bits InterpolateCornerPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
break;
default:
assert(0);

View File

@ -47,8 +47,6 @@ struct PatchTypes {
TYPE R, // regular patch
B, // boundary patch (4 rotations)
C, // corner patch (4 rotations)
G, // gregory patch
GB, // gregory boundary patch
GP; // gregory basis patch
@ -59,8 +57,6 @@ struct PatchTypes {
TYPE & getValue( Far::PatchDescriptor desc ) {
switch (desc.GetType()) {
case Far::PatchDescriptor::REGULAR : return R;
case Far::PatchDescriptor::BOUNDARY : return B;
case Far::PatchDescriptor::CORNER : return C;
case Far::PatchDescriptor::GREGORY : return G;
case Far::PatchDescriptor::GREGORY_BOUNDARY : return GB;
case Far::PatchDescriptor::GREGORY_BASIS : return GP;
@ -75,8 +71,6 @@ struct PatchTypes {
int getNumPatchArrays() const {
int result=0;
if (R) ++result;
if (B) ++result;
if (C) ++result;
if (G) ++result;
if (GB) ++result;
if (GP) ++result;
@ -573,10 +567,6 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level,
// compute the 20 cvs basis)
fvarPatchType = context.options.useFVarQuadEndCaps ?
PatchDescriptor::QUADS : PatchDescriptor::GREGORY_BASIS;
} else if (fvarPatchTag._boundaryCount > 1) {
fvarPatchType = PatchDescriptor::CORNER;
} else if (fvarPatchTag._boundaryCount == 1) {
fvarPatchType = PatchDescriptor::BOUNDARY;
} else if (fvarPatchTag._isSingleCrease) {
fvarPatchType = PatchDescriptor::REGULAR;
}
@ -596,17 +586,31 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level,
// revisited...
int orientationIndex = fvarPatchTag._boundaryIndex;
if (fvarPatchType == PatchDescriptor::REGULAR) {
static int const permuteRegular[16] = { 5, 6, 7, 8, 4, 0, 1, 9, 15, 3, 2, 10, 14, 13, 12, 11 };
vtxLevel.gatherQuadRegularInteriorPatchPoints(faceIndex, patchVerts, orientationIndex, *fvc);
permutation = permuteRegular;
} else if (fvarPatchType == PatchDescriptor::CORNER) {
static int const permuteCorner[9] = { 8, 3, 0, 7, 2, 1, 6, 5, 4 };
vtxLevel.gatherQuadRegularCornerPatchPoints(faceIndex, patchVerts, orientationIndex, *fvc);
permutation = permuteCorner;
} else if (fvarPatchType == PatchDescriptor::BOUNDARY) {
static int const permuteBoundary[12] = { 11, 3, 0, 4, 10, 2, 1, 5, 9, 8, 7, 6 };
vtxLevel.gatherQuadRegularBoundaryPatchPoints(faceIndex, patchVerts, orientationIndex, *fvc);
permutation = permuteBoundary;
if (fvarPatchTag._boundaryCount == 0) {
static int const permuteRegular[16] = { 5, 6, 7, 8, 4, 0, 1, 9, 15, 3, 2, 10, 14, 13, 12, 11 };
permutation = permuteRegular;
vtxLevel.gatherQuadRegularInteriorPatchPoints(faceIndex, patchVerts, orientationIndex, *fvc);
} else if (fvarPatchTag._boundaryCount == 1) {
// Expand boundary patch vertices and rotate to restore correct orientation.
static int const permuteBoundary[4][16] = {
{ -1, -1, -1, -1, 11, 3, 0, 4, 10, 2, 1, 5, 9, 8, 7, 6 },
{ 9, 10, 11, -1, 8, 2, 3, -1, 7, 1, 0, -1, 6, 5, 4, -1 },
{ 6, 7, 8, 9, 5, 1, 2, 10, 4, 0, 3, 11, -1, -1, -1, -1 },
{ -1, 4, 5, 6, -1, 0, 1, 7, -1, 3, 2, 8, -1, 11, 10, 9 } };
permutation = permuteBoundary[orientationIndex];
vtxLevel.gatherQuadRegularBoundaryPatchPoints(faceIndex, patchVerts, orientationIndex);
} else if (fvarPatchTag._boundaryCount == 2) {
// Expand corner patch vertices and rotate to restore correct orientation.
static int const permuteCorner[4][16] = {
{ -1, -1, -1, -1, -1, 0, 1, 4, -1, 3, 2, 5, -1, 8, 7, 6 },
{ -1, -1, -1, -1, 8, 3, 0, -1, 7, 2, 1, -1, 6, 5, 4, -1 },
{ 6, 7, 8, -1, 5, 2, 3, -1, 4, 1, 0, -1, -1, -1, -1, -1 },
{ -1, 4, 5, 6, -1, 1, 2, 7, -1, 0, 3, 8, -1, -1, -1, -1 } };
permutation = permuteCorner[orientationIndex];
vtxLevel.gatherQuadRegularCornerPatchPoints(faceIndex, patchVerts, orientationIndex, *fvc);
} else {
assert(fvarPatchTag._boundaryCount >=0 && fvarPatchTag._boundaryCount <= 2);
}
} else if (fvarPatchType == PatchDescriptor::QUADS) {
vtxLevel.gatherQuadLinearPatchPoints(faceIndex, patchVerts, orientationIndex, *fvc);
permutation = 0;

View File

@ -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,91 +41,31 @@ 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
drawContext.h
drawRegistry.h
vertex.h
vertexDescriptor.h
)
set(DOXY_HEADER_FILES ${PUBLIC_HEADER_FILES})
#-------------------------------------------------------------------------------
set(GL_PTEX_PUBLIC_HEADERS
glPtexTexture.h
glPtexMipmapTexture.h
)
set(DX_PTEX_PUBLIC_HEADERS
d3d11PtexTexture.h
d3d11PtexMipmapTexture.h
)
if( PTEX_FOUND )
list(APPEND PUBLIC_HEADER_FILES
ptexTextureLoader.h
ptexMipmapTextureLoader.h
)
list(APPEND CPU_SOURCE_FILES
ptexTextureLoader.cpp
ptexMipmapTextureLoader.cpp
)
if( OPENGL_FOUND )
list(APPEND GPU_SOURCE_FILES
glPtexTexture.cpp
glPtexMipmapTexture.cpp
)
list(APPEND PUBLIC_HEADER_FILES
${GL_PTEX_PUBLIC_HEADERS}
)
endif()
if( DXSDK_FOUND )
list(APPEND GPU_SOURCE_FILES
d3d11PtexTexture.cpp
d3d11PtexMipmapTexture.cpp
)
list(APPEND PUBLIC_HEADER_FILES
${DX_PTEX_PUBLIC_HEADERS}
)
endif()
include_directories( "${PTEX_INCLUDE_DIR}" )
list(APPEND PLATFORM_CPU_LIBRARIES
${PTEX_LIBRARY}
)
endif()
list(APPEND DOXY_HEADER_FILES ${GL_PTEX_PUBLIC_HEADERS} ${DX_PTEX_PUBLIC_HEADERS})
#-------------------------------------------------------------------------------
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})
@ -148,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})
@ -201,8 +128,6 @@ if( OPENGL_FOUND OR OPENGLES_FOUND )
glslPatchBSpline.glsl
glslPatchGregory.glsl
glslPatchGregoryBasis.glsl
glslPatchTransition.glsl
glslPtexCommon.glsl
)
endif()
endif()
@ -213,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}
@ -238,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
@ -262,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
@ -272,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
@ -284,8 +203,6 @@ if( DXSDK_FOUND )
hlslPatchCommon.hlsl
hlslPatchBSpline.hlsl
hlslPatchGregory.hlsl
hlslPatchTransition.hlsl
hlslPtexCommon.hlsl
)
list(APPEND PLATFORM_GPU_LIBRARIES
${DXSDK_LIBRARIES}
@ -297,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})
@ -337,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})

View File

@ -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

View File

@ -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

View File

@ -1,271 +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 & desc) {
cl_int errNum;
_desc = VertexBufferDescriptor(0, desc.length, desc.stride);
std::ostringstream defines;
defines << "#define OFFSET " << _desc.offset << "\n"
<< "#define LENGTH " << _desc.length << "\n"
<< "#define STRIDE " << _desc.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;
int ncvs = context->GetNumControlVertices();
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();
clSetKernelArg(kernel, 0, sizeof(cl_mem), &_currentBindState.vertexBuffer);
clSetKernelArg(kernel, 1, sizeof(cl_mem), &sizes);
clSetKernelArg(kernel, 2, sizeof(cl_mem), &offsets);
clSetKernelArg(kernel, 3, sizeof(cl_mem), &indices);
clSetKernelArg(kernel, 4, sizeof(cl_mem), &weights);
clSetKernelArg(kernel, 5, sizeof(int), &start);
clSetKernelArg(kernel, 6, sizeof(int), &end);
clSetKernelArg(kernel, 7, sizeof(int), &_currentBindState.vertexDesc.offset);
clSetKernelArg(kernel, 8, sizeof(int), &ncvs);
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();
clSetKernelArg(kernel, 0, sizeof(cl_mem), &_currentBindState.varyingBuffer);
clSetKernelArg(kernel, 1, sizeof(cl_mem), &sizes);
clSetKernelArg(kernel, 2, sizeof(cl_mem), &offsets);
clSetKernelArg(kernel, 3, sizeof(cl_mem), &indices);
clSetKernelArg(kernel, 4, sizeof(cl_mem), &weights);
clSetKernelArg(kernel, 5, sizeof(int), &start);
clSetKernelArg(kernel, 6, sizeof(int), &end);
clSetKernelArg(kernel, 7, sizeof(int), &_currentBindState.varyingDesc.offset);
clSetKernelArg(kernel, 8, sizeof(int), &ncvs);
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);
_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

View File

@ -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
View File

View 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:

View 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

View 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

View File

@ -36,7 +36,7 @@ static void addWithWeight(struct Vertex *dst,
__global float *srcOrigin,
int index, float weight) {
__global float *src = srcOrigin + index * STRIDE;
__global float *src = srcOrigin + index * SRC_STRIDE;
for (int i = 0; i < LENGTH; ++i) {
dst->v[i] += src[i] * weight;
}
@ -46,40 +46,42 @@ static void writeVertex(__global float *dstOrigin,
int index,
struct Vertex *src) {
__global float *dst = dstOrigin + index * STRIDE;
__global float *dst = dstOrigin + index * DST_STRIDE;
for (int i = 0; i < LENGTH; ++i) {
dst[i] = src->v[i];
}
}
__kernel void computeStencils( __global float * vertexBuffer,
__global unsigned char * sizes,
__global int * offsets,
__global int * indices,
__global float * weights,
int batchStart,
int batchEnd,
int primvarOffset,
int numCVs ) {
__kernel void computeStencils(__global float * src,
int srcOffset,
__global float * dst,
int dstOffset,
__global unsigned char * sizes,
__global int * offsets,
__global int * indices,
__global float * weights,
int batchStart,
int batchEnd) {
int current = get_global_id(0) + batchStart;
if (current>=batchEnd) {
return;
}
struct Vertex dst;
clear(&dst);
if (current>=batchEnd) {
return;
}
struct Vertex v;
clear(&v);
int size = (int)sizes[current],
offset = offsets[current];
vertexBuffer += primvarOffset;
src += srcOffset;
dst += dstOffset;
for (int i=0; i<size; ++i) {
addWithWeight(&dst, vertexBuffer, indices[offset+i], weights[offset+i]);
addWithWeight(&v, src, indices[offset+i], weights[offset+i]);
}
writeVertex(vertexBuffer, numCVs+current, &dst);
writeVertex(dst, current, &v);
}

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -1,110 +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 const & desc = _currentBindState.vertexDesc;
float const * srcBuffer = _currentBindState.vertexBuffer + desc.offset;
float * destBuffer = _currentBindState.vertexBuffer + desc.offset +
vertexStencils->GetNumControlVertices() * desc.stride;
int start = 0;
int end = vertexStencils->GetNumStencils();
if (end > start) {
CpuComputeStencils(_currentBindState.vertexDesc,
srcBuffer, destBuffer,
&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 const & desc = _currentBindState.varyingDesc;
float const * srcBuffer = _currentBindState.varyingBuffer + desc.offset;
float * destBuffer = _currentBindState.varyingBuffer + desc.offset +
varyingStencils->GetNumControlVertices() * desc.stride;
int start = 0;
int end = varyingStencils->GetNumStencils();
if (end > start) {
CpuComputeStencils(_currentBindState.varyingDesc,
srcBuffer, destBuffer,
&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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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/cpuEvalStencilsContext.h"
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
CpuEvalStencilsContext::CpuEvalStencilsContext(Far::LimitStencilTables const *stencils) :
_stencils(stencils) {
}
CpuEvalStencilsContext *
CpuEvalStencilsContext::Create(Far::LimitStencilTables const *stencils) {
return new CpuEvalStencilsContext(stencils);
}
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View 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

View File

@ -70,14 +70,15 @@ copy(float *dst, int dstIndex, const float *src,
}
void
CpuComputeStencils(VertexBufferDescriptor const &vertexDesc,
float const * vertexSrc,
float * vertexDst,
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);
@ -87,37 +88,94 @@ CpuComputeStencils(VertexBufferDescriptor const &vertexDesc,
weights += offsets[start];
}
if (vertexDesc.length==4 and vertexDesc.stride==4) {
src += srcDesc.offset;
dst += dstDesc.offset;
if (srcDesc.length == 4 and dstDesc.length == 4 and
srcDesc.stride == 4 and dstDesc.stride == 4) {
// SIMD fast path for aligned primvar data (8 floats)
ComputeStencilKernel<4>(vertexSrc, vertexDst,
ComputeStencilKernel<4>(src, dst,
sizes, indices, weights, start, end);
} else if(vertexDesc.length==8 and vertexDesc.stride==8) {
} else if (srcDesc.length == 8 and dstDesc.length == 8 and
srcDesc.stride == 8 and dstDesc.stride == 8) {
// SIMD fast path for aligned primvar data (8 floats)
ComputeStencilKernel<8>(vertexSrc, vertexDst,
ComputeStencilKernel<8>(src, dst,
sizes, indices, weights, start, end);
}
else {
} else {
// Slow path for non-aligned data
float * result = (float*)alloca(vertexDesc.length * sizeof(float));
float * result = (float*)alloca(srcDesc.length * sizeof(float));
int nstencils = end-start;
for (int i=0; i<nstencils; ++i, ++sizes) {
clear(result, vertexDesc);
clear(result, srcDesc);
for (int j=0; j<*sizes; ++j) {
addWithWeight(result, vertexSrc, *indices++, *weights++, vertexDesc);
addWithWeight(result, src, *indices++, *weights++, srcDesc);
}
copy(vertexDst, i, result, vertexDesc);
copy(dst, i, result, dstDesc);
}
}
}
void
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];
weights += offsets[start];
duWeights += offsets[start];
dvWeights += offsets[start];
}
src += srcDesc.offset;
dst += dstDesc.offset;
dstDu += dstDuDesc.offset;
dstDv += dstDvDesc.offset;
int nOutLength = dstDesc.length + dstDuDesc.length + dstDvDesc.length;
float * result = (float*)alloca(nOutLength * sizeof(float));
float * resultDu = result + dstDesc.length;
float * resultDv = resultDu + dstDuDesc.length;
int nStencils = end - start;
for (int i = 0; i < nStencils; ++i, ++sizes) {
// clear
memset(result, 0, nOutLength * sizeof(float));
for (int j=0; j<*sizes; ++j) {
addWithWeight(result, src, *indices, *weights++, srcDesc);
addWithWeight(resultDu, src, *indices, *duWeights++, srcDesc);
addWithWeight(resultDv, src, *indices, *dvWeights++, srcDesc);
++indices;
}
copy(dst, i, result, dstDesc);
copy(dstDu, i, resultDu, dstDuDesc);
copy(dstDv, i, resultDv, dstDvDesc);
}
}
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION

View File

@ -22,31 +22,46 @@
// 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 "../osd/vertexDescriptor.h"
#include <cstring>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
struct VertexDescriptor;
struct VertexBufferDescriptor;
void
CpuComputeStencils(VertexBufferDescriptor const &vertexDesc,
float const * vertexSrc,
float * vertexDst,
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
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

View File

@ -29,7 +29,6 @@
#include "../osd/nonCopyable.h"
#include "../osd/vertexDescriptor.h"
#include "../osd/vertex.h"
#include "../far/types.h"
#include <vector>

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -1,118 +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(float const *src, float * dst,
int length, int stride,
unsigned char const * sizes,
int const * offsets,
int const * indices,
float const * weights,
int start, int end);
}
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
void
CudaComputeController::ApplyStencilTableKernel(
ComputeContext const *context) const {
assert(context);
if (context->HasVertexStencilTables()) {
int length = _currentBindState.vertexDesc.length,
stride = _currentBindState.vertexDesc.stride;
int start = 0;
int end = context->GetNumStencilsInVertexStencilTables();
float const * src = _currentBindState.GetVertexBufferAtOffset();
float * dst = const_cast<float *>(src) +
context->GetNumControlVertices() * stride;
if (end > start) {
CudaComputeStencils(src, dst, length, stride,
(unsigned char const *)context->GetVertexStencilTablesSizes(),
(int const *)context->GetVertexStencilTablesOffsets(),
(int const *)context->GetVertexStencilTablesIndices(),
(float const *)context->GetVertexStencilTablesWeights(),
start,
end);
}
}
if (context->HasVaryingStencilTables()) {
int length = _currentBindState.varyingDesc.length,
stride = _currentBindState.varyingDesc.stride;
int start = 0;
int end = context->GetNumStencilsInVaryingStencilTables();
float const * src = _currentBindState.GetVaryingBufferAtOffset();
float * dst = const_cast<float *>(src) +
context->GetNumControlVertices() * stride;
if (end > start) {
CudaComputeStencils(src, dst, length, 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

View File

@ -1,188 +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 *GetVertexBufferAtOffset() const {
return vertexBuffer ? vertexBuffer + vertexDesc.offset : 0;
}
float *GetVaryingBufferAtOffset() const {
return varyingBuffer ? varyingBuffer + varyingDesc.offset : 0;
}
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

View 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

View 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

View File

@ -98,12 +98,14 @@ computeStencils(float const * cvs, float * vbuffer,
__global__ void
computeStencils(float const * cvs, float * dst,
int length, int stride,
unsigned char const * sizes,
int const * offsets,
int const * indices,
float const * weights,
int start, int end) {
int length,
int srcStride,
int dstStride,
unsigned char const * sizes,
int const * offsets,
int const * indices,
float const * weights,
int start, int end) {
int first = start + threadIdx.x + blockIdx.x*blockDim.x;
@ -112,12 +114,12 @@ computeStencils(float const * cvs, float * dst,
int const * lindices = indices + offsets[i];
float const * lweights = weights + offsets[i];
float * dstVert = dst + i*stride;
float * dstVert = dst + i*dstStride;
clear(dstVert, length);
for (int j=0; j<sizes[i]; ++j) {
float const * srcVert = cvs + lindices[j]*stride;
float const * srcVert = cvs + lindices[j]*srcStride;
addWithWeight(dstVert, srcVert, lweights[j], length);
}
@ -220,7 +222,7 @@ __global__ void computeStencilsNv_v4(float const *__restrict cvs,
for( int j = offsets[i], j_end = offsets[i]+sizes[i] ; j < j_end ; ++j )
{
float w = weights[j];
float4 tmp = reinterpret_cast<const float4 *__restrict>(cvs)[indices[j]];
float4 tmp = reinterpret_cast<const float4 *>(cvs)[indices[j]];
x.x += w*tmp.x;
x.y += w*tmp.y;
x.z += w*tmp.z;
@ -239,14 +241,14 @@ __global__ void computeStencilsNv_v4(float const *__restrict cvs,
#include "../version.h"
#define OPT_KERNEL(NUM_ELEMENTS, KERNEL, X, Y, ARG) \
if (length==NUM_ELEMENTS && stride==length) { \
if (length==NUM_ELEMENTS && srcStride==length && dstStride==length) { \
KERNEL<NUM_ELEMENTS><<<X,Y>>>ARG; \
return; \
}
#ifdef USE_NVIDIA_OPTIMIZATION
#define OPT_KERNEL_NVIDIA(NUM_ELEMENTS, KERNEL, X, Y, ARG) \
if (length==NUM_ELEMENTS && stride==length) { \
if (length==NUM_ELEMENTS && srcStride==length && dstStride==length) { \
int gridDim = min(X, (end-start+Y-1)/Y); \
KERNEL<NUM_ELEMENTS, Y><<<gridDim, Y>>>ARG; \
return; \
@ -255,35 +257,45 @@ __global__ void computeStencilsNv_v4(float const *__restrict cvs,
extern "C" {
void
CudaComputeStencils(float const *cvs, float * dst,
int length, int stride,
unsigned char const * sizes,
int const * offsets,
int const * indices,
float const * 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));
// assert(cvs and dst and sizes and offsets and indices and weights and (end>=start));
if (length==0 or stride==0) {
if (length == 0 or srcStride == 0 or dstStride == 0 or (end <= start)) {
return;
}
#ifdef USE_NVIDIA_OPTIMIZATION
OPT_KERNEL_NVIDIA(3, computeStencilsNv, 2048, 256, (cvs, dst, sizes, offsets, indices, weights, start, end));
//OPT_KERNEL_NVIDIA(4, computeStencilsNv, 2048, 256, (cvs, dst, sizes, offsets, indices, weights, start, end));
if( length==4 && stride==length ) {
OPT_KERNEL_NVIDIA(3, computeStencilsNv, 2048, 256,
(src, dst, sizes, offsets, indices, weights, start, end));
//OPT_KERNEL_NVIDIA(4, computeStencilsNv, 2048, 256,
// (cvs, dst, sizes, offsets, indices, weights, start, end));
if (length == 4 && srcStride == length && dstStride == length) {
int gridDim = min(2048, (end-start+256-1)/256);
computeStencilsNv_v4<256><<<gridDim, 256>>>(cvs, dst, sizes, offsets, indices, weights, start, end);
computeStencilsNv_v4<256><<<gridDim, 256>>>(
src, dst, sizes, offsets, indices, weights, start, end);
return;
}
#else
OPT_KERNEL(3, computeStencils, 512, 32, (cvs, dst, sizes, offsets, indices, weights, start, end));
OPT_KERNEL(4, computeStencils, 512, 32, (cvs, dst, sizes, offsets, indices, weights, start, end));
OPT_KERNEL(3, computeStencils, 512, 32,
(src, dst, sizes, offsets, indices, weights, start, end));
OPT_KERNEL(4, computeStencils, 512, 32,
(src, dst, sizes, offsets, indices, weights, start, end));
#endif
computeStencils <<<512, 32>>>(cvs, dst, length, stride,
// generic case (slow)
computeStencils <<<512, 32>>>(
src, dst, length, srcStride, dstStride,
sizes, offsets, indices, weights, start, end);
}

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -1,338 +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 uniformStart, // batch
uniformEnd,
uniformOffset, // primvar buffer descriptor
uniformNumCVs; // number of const control vertices padded at
};
// ----------------------------------------------------------------------------
class D3D11ComputeController::KernelBundle :
NonCopyable<D3D11ComputeController::KernelBundle> {
public:
KernelBundle() :
_computeShader(0),
_classLinkage(0),
_subStencilKernel(0),
_uniformArgs(0),
_workGroupSize(64) { }
~KernelBundle() {
SAFE_RELEASE(_computeShader);
SAFE_RELEASE(_classLinkage);
SAFE_RELEASE(_subStencilKernel);
SAFE_RELEASE(_uniformArgs);
}
bool Compile(ID3D11DeviceContext *deviceContext,
VertexBufferDescriptor const &desc) {
_desc = VertexBufferDescriptor(0, desc.length, desc.stride);
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _DEBUG
dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif
std::ostringstream ss;
ss << _desc.offset; std::string offsetValue(ss.str()); ss.str("");
ss << _desc.length; std::string lengthValue(ss.str()); ss.str("");
ss << _desc.stride; std::string strideValue(ss.str()); ss.str("");
ss << _workGroupSize; std::string workgroupSizeValue(ss.str()); ss.str("");
D3D_SHADER_MACRO defines[] =
{ "OFFSET", offsetValue.c_str(),
"LENGTH", lengthValue.c_str(),
"STRIDE", strideValue.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("computeStencil", 0, &_subStencilKernel);
assert(_subStencilKernel);
return true;
}
void ApplyStencilTableKernel(ID3D11DeviceContext *deviceContext,
int offset, int numCVs, int start, int end) {
KernelUniformArgs args;
args.uniformStart = start;
args.uniformEnd = end;
args.uniformOffset = offset;
args.uniformNumCVs = numCVs;
dispatchCompute(deviceContext, _subStencilKernel, args);
}
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:
void dispatchCompute(ID3D11DeviceContext *deviceContext,
ID3D11ClassInstance * kernel, KernelUniformArgs const & args) {
assert(deviceContext);
int count = args.uniformEnd - args.uniformStart;
if (count <= 0) return;
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, &kernel, 1);
deviceContext->Dispatch((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
}
private:
ID3D11ComputeShader * _computeShader;
ID3D11ClassLinkage * _classLinkage;
ID3D11ClassInstance * _subStencilKernel; // stencil compute kernel HLSL subroutine
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(_deviceContext, desc);
_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);
bundle->ApplyStencilTableKernel(
_deviceContext,
_currentBindState.desc.offset,
context->GetNumControlVertices(),
0,
numStencils);
}
// ----------------------------------------------------------------------------
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

View File

@ -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

View 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

View 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

View File

@ -33,10 +33,11 @@ namespace OPENSUBDIV_VERSION {
namespace Osd {
D3D11DrawContext::D3D11DrawContext() :
D3D11DrawContext::D3D11DrawContext(int maxValence) :
DrawContext(maxValence),
patchIndexBuffer(NULL),
ptexCoordinateBuffer(NULL),
ptexCoordinateBufferSRV(NULL),
patchParamBuffer(NULL),
patchParamBufferSRV(NULL),
fvarDataBuffer(NULL),
fvarDataBufferSRV(NULL),
vertexBufferSRV(NULL),
@ -50,8 +51,8 @@ D3D11DrawContext::D3D11DrawContext() :
D3D11DrawContext::~D3D11DrawContext()
{
if (patchIndexBuffer) patchIndexBuffer->Release();
if (ptexCoordinateBuffer) ptexCoordinateBuffer->Release();
if (ptexCoordinateBufferSRV) ptexCoordinateBufferSRV->Release();
if (patchParamBuffer) patchParamBuffer->Release();
if (patchParamBufferSRV) patchParamBufferSRV->Release();
if (fvarDataBuffer) fvarDataBuffer->Release();
if (fvarDataBufferSRV) fvarDataBufferSRV->Release();
if (vertexBufferSRV) vertexBufferSRV->Release();
@ -63,11 +64,11 @@ D3D11DrawContext::~D3D11DrawContext()
D3D11DrawContext *
D3D11DrawContext::Create(Far::PatchTables const *patchTables,
int numVertexElements,
ID3D11DeviceContext *pd3d11DeviceContext)
{
D3D11DrawContext * result = new D3D11DrawContext();
if (result->create(*patchTables, numVertexElements, pd3d11DeviceContext))
int maxValence = patchTables->GetMaxValence();
D3D11DrawContext * result = new D3D11DrawContext(maxValence);
if (result->create(*patchTables, pd3d11DeviceContext))
return result;
delete result;
@ -76,7 +77,6 @@ D3D11DrawContext::Create(Far::PatchTables const *patchTables,
bool
D3D11DrawContext::create(Far::PatchTables const &patchTables,
int numVertexElements,
ID3D11DeviceContext *pd3d11DeviceContext)
{
// adaptive patches
@ -111,12 +111,11 @@ D3D11DrawContext::create(Far::PatchTables const &patchTables,
pd3d11DeviceContext->Unmap(patchIndexBuffer, 0);
DrawContext::ConvertPatchArrays(patchTables, _patchArrays,
patchTables.GetMaxValence(), numVertexElements);
DrawContext::ConvertPatchArrays(patchTables, _patchArrays);
// allocate and initialize additional buffer data
// create ptex coordinate buffer
// create patch param buffer
Far::PatchParamTable const & patchParamTables =
patchTables.GetPatchParamTable();
@ -144,7 +143,7 @@ D3D11DrawContext::create(Far::PatchTables const &patchTables,
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
bd.StructureByteStride = sizeof(unsigned int);
hr = pd3d11Device->CreateBuffer(&bd, NULL, &ptexCoordinateBuffer);
hr = pd3d11Device->CreateBuffer(&bd, NULL, &patchParamBuffer);
if (FAILED(hr)) {
return false;
}
@ -155,17 +154,18 @@ D3D11DrawContext::create(Far::PatchTables const &patchTables,
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srvd.Buffer.FirstElement = 0;
srvd.Buffer.NumElements = numElements;
hr = pd3d11Device->CreateShaderResourceView(ptexCoordinateBuffer, &srvd, &ptexCoordinateBufferSRV);
hr = pd3d11Device->CreateShaderResourceView(
patchParamBuffer, &srvd, &patchParamBufferSRV);
if (FAILED(hr)) {
return false;
}
hr = pd3d11DeviceContext->Map(ptexCoordinateBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
hr = pd3d11DeviceContext->Map(patchParamBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(hr)) {
return false;
}
unsigned int * ptexBuffer = (unsigned int *) mappedResource.pData;
memcpy(ptexBuffer, values, numElements * elementSize);
pd3d11DeviceContext->Unmap(ptexCoordinateBuffer, 0);
unsigned int *dst = (unsigned int *) mappedResource.pData;
memcpy(dst, values, numElements * elementSize);
pd3d11DeviceContext->Unmap(patchParamBuffer, 0);
}
// create vertex valence buffer and vertex texture
@ -277,9 +277,9 @@ D3D11DrawContext::SetFVarDataTexture(Far::PatchTables const & patchTables,
void
D3D11DrawContext::updateVertexTexture(ID3D11Buffer *vbo,
ID3D11DeviceContext *pd3d11DeviceContext,
int numVertices,
int numVertexElements)
ID3D11DeviceContext *pd3d11DeviceContext,
int numVertices,
int numVertexElements)
{
ID3D11Device *pd3d11Device = NULL;
pd3d11DeviceContext->GetDevice(&pd3d11Device);

View File

@ -29,7 +29,6 @@
#include "../far/patchTables.h"
#include "../osd/drawContext.h"
#include "../osd/vertex.h"
#include <map>
@ -72,18 +71,14 @@ public:
///
/// @param pd3d11DeviceContext A device context
///
/// @param numVertexElements The number of vertex elements
///
static D3D11DrawContext *Create(Far::PatchTables const *patchTables,
int numVertexElements,
ID3D11DeviceContext *pd3d11DeviceContext);
/// template version for custom context (OpenCL) used by OsdMesh
template<typename DEVICE_CONTEXT>
static D3D11DrawContext *Create(Far::PatchTables const *patchtables,
int numVertexElements,
DEVICE_CONTEXT context) {
return Create(patchtables, numVertexElements, context->GetDeviceContext());
return Create(patchtables, context->GetDeviceContext());
}
/// Set vbo as a vertex texture (for gregory patch drawing)
@ -109,8 +104,8 @@ public:
ID3D11Buffer *patchIndexBuffer;
ID3D11Buffer *ptexCoordinateBuffer;
ID3D11ShaderResourceView *ptexCoordinateBufferSRV;
ID3D11Buffer *patchParamBuffer;
ID3D11ShaderResourceView *patchParamBufferSRV;
ID3D11Buffer *fvarDataBuffer;
ID3D11ShaderResourceView *fvarDataBufferSRV;
@ -147,12 +142,11 @@ public:
}
private:
D3D11DrawContext();
D3D11DrawContext(int maxValence);
// allocate buffers from patchTables
bool create(Far::PatchTables const &patchTables,
int numVertexElements,
ID3D11DeviceContext *pd3d11DeviceContext);
void updateVertexTexture(ID3D11Buffer *vbo,

View File

@ -47,58 +47,34 @@ D3D11DrawConfig::~D3D11DrawConfig()
static const char *commonShaderSource =
#include "hlslPatchCommon.gen.h"
;
static const char *ptexShaderSource =
#include "hlslPtexCommon.gen.h"
;
static const char *bsplineShaderSource =
#include "hlslPatchBSpline.gen.h"
;
static const char *gregoryShaderSource =
#include "hlslPatchGregory.gen.h"
;
static const char *transitionShaderSource =
#include "hlslPatchTransition.gen.h"
;
D3D11DrawRegistryBase::~D3D11DrawRegistryBase() {}
D3D11DrawSourceConfig *
D3D11DrawRegistryBase::_CreateDrawSourceConfig(
DrawContext::PatchDescriptor const & desc, ID3D11Device * pd3dDevice)
Far::PatchDescriptor const & desc, ID3D11Device * pd3dDevice)
{
D3D11DrawSourceConfig * sconfig = _NewDrawSourceConfig();
sconfig->commonShader.source = commonShaderSource;
if (IsPtexEnabled()) {
sconfig->commonShader.source += ptexShaderSource;
}
{
std::ostringstream ss;
ss << (int)desc.GetMaxValence();
sconfig->commonShader.AddDefine("OSD_MAX_VALENCE", ss.str());
ss.str("");
ss << (int)desc.GetNumElements();
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
}
switch (desc.GetType()) {
case Far::PatchDescriptor::REGULAR:
case Far::PatchDescriptor::BOUNDARY:
case Far::PatchDescriptor::CORNER:
sconfig->commonShader.AddDefine("OSD_PATCH_BSPLINE");
sconfig->commonShader.AddDefine("OSD_PATCH_ENABLE_SINGLE_CREASE");
sconfig->vertexShader.source =
std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->vertexShader.source = bsplineShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source =
std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->hullShader.source = bsplineShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source =
std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->domainShader.source = bsplineShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
break;

View File

@ -29,7 +29,6 @@
#include "../far/patchTables.h"
#include "../osd/drawRegistry.h"
#include "../osd/vertex.h"
#include <map>
@ -81,22 +80,14 @@ struct D3D11DrawSourceConfig {
class D3D11DrawRegistryBase {
public:
typedef DrawContext::PatchDescriptor DescType;
typedef Far::PatchDescriptor DescType;
typedef D3D11DrawConfig ConfigType;
typedef D3D11DrawSourceConfig SourceConfigType;
D3D11DrawRegistryBase(bool enablePtex=false) : _enablePtex(enablePtex) { }
D3D11DrawRegistryBase() { }
virtual ~D3D11DrawRegistryBase();
bool IsPtexEnabled() const {
return _enablePtex;
}
void SetPtexEnabled(bool b) {
_enablePtex=b;
}
protected:
virtual ConfigType * _NewDrawConfig() { return new ConfigType(); }
virtual ConfigType *
@ -110,14 +101,11 @@ protected:
virtual SourceConfigType * _NewDrawSourceConfig() { return new SourceConfigType(); }
virtual SourceConfigType *
_CreateDrawSourceConfig(DescType const & desc, ID3D11Device * pd3dDevice);
private:
bool _enablePtex;
};
//------------------------------------------------------------------------------
template <class DESC_TYPE = DrawContext::PatchDescriptor,
template <class DESC_TYPE = Far::PatchDescriptor,
class CONFIG_TYPE = D3D11DrawConfig,
class SOURCE_CONFIG_TYPE = D3D11DrawSourceConfig>
class D3D11DrawRegistry : public D3D11DrawRegistryBase {

View File

@ -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.
//
#include "../osd/d3d11PtexTexture.h"
#include "../osd/ptexTextureLoader.h"
#include "../far/error.h"
#include <Ptexture.h>
#include <D3D11.h>
#include <cassert>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
D3D11PtexTexture::D3D11PtexTexture()
: _width(0), _height(0), _depth(0), _pages(0), _layout(0), _texels(0) {
}
D3D11PtexTexture::~D3D11PtexTexture() {
// delete pages lookup ---------------------------------
if (_pages) _pages->Release();
// delete layout lookup --------------------------------
if (_layout) _layout->Release();
// delete textures lookup ------------------------------
if (_texels) _texels->Release();
}
static ID3D11Buffer *
genTextureBuffer(ID3D11DeviceContext *deviceContext, int size, void const * data) {
D3D11_BUFFER_DESC hBufferDesc;
hBufferDesc.ByteWidth = size;
hBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
hBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_SHADER_RESOURCE;
hBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
hBufferDesc.MiscFlags = 0;
hBufferDesc.StructureByteStride = sizeof(float);
HRESULT hr;
ID3D11Buffer *buffer;
ID3D11Device *device;
deviceContext->GetDevice(&device);
hr = device->CreateBuffer(&hBufferDesc, NULL, &buffer);
if (FAILED(hr)) {
Far::Error(Far::FAR_RUNTIME_ERROR,
"Fail in CreateBuffer\n");
return 0;
}
D3D11_MAPPED_SUBRESOURCE resource;
hr = deviceContext->Map(buffer, 0,
D3D11_MAP_WRITE_DISCARD, 0, &resource);
if (FAILED(hr)) {
Far::Error(Far::FAR_RUNTIME_ERROR,
"Fail in Map buffer\n");
buffer->Release();
return 0;
}
memcpy(resource.pData, data, size);
deviceContext->Unmap(buffer, 0);
return buffer;
}
D3D11PtexTexture *
D3D11PtexTexture::Create(ID3D11DeviceContext *deviceContext,
PtexTexture * reader,
unsigned long int targetMemory,
int gutterWidth,
int pageMargin) {
D3D11PtexTexture * result = NULL;
// Read the ptex data and pack the texels
PtexTextureLoader ldr(reader, gutterWidth, pageMargin);
unsigned long int nativeSize = ldr.GetNativeUncompressedSize(),
targetSize = targetMemory;
if (targetSize != 0 && targetSize != nativeSize)
ldr.OptimizeResolution(targetSize);
int maxnumpages = D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
ldr.OptimizePacking(maxnumpages);
if (!ldr.GenerateBuffers())
return result;
// Setup GPU memory
unsigned long int nfaces = ldr.GetNumBlocks();
ID3D11Buffer *pages = genTextureBuffer(deviceContext,
nfaces * sizeof(int),
ldr.GetIndexBuffer());
ID3D11Buffer *layout = genTextureBuffer(deviceContext,
nfaces * 4 * sizeof(float),
ldr.GetLayoutBuffer());
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
int bpp = 0;
int numChannels = reader->numChannels();
switch (reader->dataType()) {
case Ptex::dt_uint16:
switch (numChannels) {
case 1: format = DXGI_FORMAT_R16_UINT; break;
case 2: format = DXGI_FORMAT_R16G16_UINT; break;
case 3: assert(false); break;
case 4: format = DXGI_FORMAT_R16G16B16A16_UINT; break;
}
bpp = numChannels * 2;
break;
case Ptex::dt_float:
switch (numChannels) {
case 1: format = DXGI_FORMAT_R32_FLOAT; break;
case 2: format = DXGI_FORMAT_R32G32_FLOAT; break;
case 3: format = DXGI_FORMAT_R32G32B32_FLOAT; break;
case 4: format = DXGI_FORMAT_R32G32B32A32_FLOAT; break;
}
bpp = numChannels * 4;
break;
case Ptex::dt_half:
switch (numChannels) {
case 1: format = DXGI_FORMAT_R16_FLOAT; break;
case 2: format = DXGI_FORMAT_R16G16_FLOAT; break;
case 3:assert(false); break;
case 4: format = DXGI_FORMAT_R16G16B16A16_FLOAT; break;
}
bpp = numChannels * 2;
break;
default:
switch (numChannels) {
case 1: format = DXGI_FORMAT_R8_UINT; break;
case 2: format = DXGI_FORMAT_R8G8_UINT; break;
case 3: assert(false); break;
case 4: format = DXGI_FORMAT_R8G8B8A8_UINT; break;
}
bpp = numChannels;
break;
}
// actual texels texture array
D3D11_TEXTURE2D_DESC desc;
desc.Width = ldr.GetPageSize();
desc.Height = ldr.GetPageSize();
desc.MipLevels = 1;
desc.ArraySize = ldr.GetNumPages();
desc.Format = format;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = ldr.GetTexelBuffer();
initData.SysMemPitch = ldr.GetPageSize() * bpp;
initData.SysMemSlicePitch = ldr.GetPageSize() * ldr.GetPageSize() * bpp;
ID3D11Device *device;
ID3D11Texture2D *texels;
deviceContext->GetDevice(&device);
HRESULT hr = device->CreateTexture2D(&desc, &initData, &texels);
ldr.ClearBuffers();
// Return the Osd PtexTexture object
result = new D3D11PtexTexture;
result->_width = ldr.GetPageSize();
result->_height = ldr.GetPageSize();
result->_depth = ldr.GetNumPages();
result->_format = format;
result->_pages = pages;
result->_layout = layout;
result->_texels = texels;
return result;
}
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -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.
//
#ifndef OSD_D3D11_PTEX_TEXTURE_H
#define OSD_D3D11_PTEX_TEXTURE_H
#include "../version.h"
#include "../osd/nonCopyable.h"
class PtexTexture;
struct ID3D11Buffer;
struct ID3D11Texture2D;
struct ID3D11DeviceContext;
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Osd {
/// D3D11PtexTexture : implements simple support for ptex textures
///
/// The current implementation declares _texels as a TEXTURE2D_ARRAY of
/// n pages of a resolution that matches that of the largest face in the PTex file.
///
/// Two TEXTURE_BUFFER constructs are used
/// as lookup tables :
/// * _pages stores the array index in which a given face is located
/// * _layout stores 4 float coordinates : top-left corner and width/height for each face
///
/// GLSL fragments use SV_PrimitiveID and SV_DomainLocation to access the _pages and _layout
/// indirection tables, which provide then texture coordinates for the texels stored in
/// the _texels texture array.
///
/// Hbr provides per-face support for a ptex face indexing scheme. D3D11DrawContext
/// class provides ptex face index lookup table as a texture buffer object that
/// can be accessed by HLSL shaders.
///
class D3D11PtexTexture : NonCopyable<D3D11PtexTexture> {
public:
static D3D11PtexTexture * Create(ID3D11DeviceContext *deviceContext,
PtexTexture * reader,
unsigned long int targetMemory = 0,
int gutterWidth = 0,
int pageMargin = 0);
/// Returns the texture buffer containing the lookup table associate each ptex
/// face index with its 3D texture page in the texels texture array.
ID3D11Buffer *GetPagesTextureBuffer() const { return _pages; }
/// Returns the texture buffer containing the layout of the ptex faces in the
/// texels texture array.
ID3D11Buffer *GetLayoutTextureBuffer() const { return _layout; }
/// Returns the texels texture array.
ID3D11Texture2D *GetTexelsTexture() const { return _texels; }
~D3D11PtexTexture();
private:
D3D11PtexTexture();
int _width, // widht / height / depth of the 3D texel buffer
_height,
_depth;
int _format; // texel color format
ID3D11Buffer *_pages, // per-face page indices into the texel array
*_layout; // per-face lookup table
// (vec4 : top-left corner & width / height)
ID3D11Texture2D *_texels; // texel data
};
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv
#endif // OSD_D3D11_PTEX_TEXTURE_H

View File

@ -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:

View File

@ -37,7 +37,7 @@ DrawContext::~DrawContext() {}
void
DrawContext::ConvertPatchArrays(Far::PatchTables const &patchTables,
PatchArrayVector &osdPatchArrays, int maxValence, int numElements) {
PatchArrayVector &osdPatchArrays) {
int narrays = patchTables.GetNumPatchArrays();
@ -47,17 +47,16 @@ DrawContext::ConvertPatchArrays(Far::PatchTables const &patchTables,
for (int array=0, pidx=0, vidx=0, qidx=0; array<narrays; ++array) {
Far::PatchDescriptor srcDesc = patchTables.GetPatchArrayDescriptor(array);
Far::PatchDescriptor desc = patchTables.GetPatchArrayDescriptor(array);
int npatches = patchTables.GetNumPatches(array),
nverts = srcDesc.GetNumControlVertices();
nverts = desc.GetNumControlVertices();
PatchDescriptor desc(srcDesc, maxValence, numElements);
osdPatchArrays.push_back(PatchArray(desc, npatches, vidx, pidx, qidx));
vidx += npatches * nverts;
pidx += npatches;
qidx += (srcDesc.GetType() == Far::PatchDescriptor::GREGORY) ? npatches*nverts : 0;
qidx += (desc.GetType() == Far::PatchDescriptor::GREGORY) ? npatches*nverts : 0;
}
}

View File

@ -59,60 +59,6 @@ namespace Osd {
class DrawContext {
public:
class PatchDescriptor {
public:
/// Constructor
///
/// @param farDesc Patch type descriptor
///
/// @param maxValence Highest vertex valence in the primitive
///
/// @param numElements The size of the vertex and varying data per-vertex
/// (in floats)
///
PatchDescriptor(Far::PatchDescriptor farDesc, unsigned char maxValence, unsigned char numElements) :
_farDesc(farDesc), _maxValence(maxValence), _numElements(numElements) { }
/// Returns the type of the patch
Far::PatchDescriptor::Type GetType() const {
return _farDesc.GetType();
}
/// Returns the number of control vertices expected for a patch of the
/// type described
int GetNumControlVertices() const {
return _farDesc.GetNumControlVertices();
}
/// Returns the max valence
int GetMaxValence() const {
return _maxValence;
}
/// Returns the number of vertex elements
int GetNumElements() const {
return _numElements;
}
/// Set the number of vertex elements
void SetNumElements(int numElements) {
_numElements = (unsigned char)numElements;
}
/// Allows ordering of patches by type
bool operator < ( PatchDescriptor const other ) const;
/// True if the descriptors are identical
bool operator == ( PatchDescriptor const other ) const;
private:
Far::PatchDescriptor _farDesc;
unsigned char _maxValence;
unsigned char _numElements;
};
typedef Far::Index Index;
class PatchArray {
@ -130,18 +76,18 @@ public:
///
/// @param qoIndex Index of the first quad-offset entry
///
PatchArray(PatchDescriptor desc, int npatches,
PatchArray(Far::PatchDescriptor desc, int npatches,
Index vertIndex, Index patchIndex, Index qoIndex) :
_desc(desc), _npatches(npatches),
_vertIndex(vertIndex), _patchIndex(patchIndex), _quadOffsetIndex(qoIndex) { }
/// Returns a patch descriptor defining the type of patches in the array
PatchDescriptor GetDescriptor() const {
Far::PatchDescriptor GetDescriptor() const {
return _desc;
}
/// Update a patch descriptor
void SetDescriptor(PatchDescriptor desc) {
void SetDescriptor(Far::PatchDescriptor desc) {
_desc = desc;
}
@ -178,7 +124,7 @@ public:
}
private:
PatchDescriptor _desc;
Far::PatchDescriptor _desc;
int _npatches;
Index _vertIndex,
_patchIndex,
@ -186,7 +132,7 @@ public:
};
/// Constructor
DrawContext() : _isAdaptive(false) {}
DrawContext(int maxValence) : _isAdaptive(false), _maxValence(maxValence) {}
/// Descrtuctor
virtual ~DrawContext();
@ -212,11 +158,16 @@ public:
// processes FarPatchArrays and inserts requisite sub-patches for the arrays
// containing transition patches
static void ConvertPatchArrays(Far::PatchTables const &patchTables,
DrawContext::PatchArrayVector &osdPatchArrays, int maxValence, int numElements);
DrawContext::PatchArrayVector &osdPatchArrays);
// maxValence is needed for legacy gregorypatch drawing
int GetMaxValence() const {
return _maxValence;
}
typedef std::vector<float> FVarData;
protected:
static void packPatchVerts(Far::PatchTables const & patchTables,
@ -232,28 +183,10 @@ protected:
PatchArrayVector _patchArrays;
bool _isAdaptive;
int _maxValence;
};
// Allows ordering of patches by type
inline bool
DrawContext::PatchDescriptor::operator < ( PatchDescriptor const other ) const
{
return _farDesc < other._farDesc or (_farDesc == other._farDesc and
(_maxValence < other._maxValence or ((_maxValence == other._maxValence) and
(_numElements < other._numElements))));
}
// True if the descriptors are identical
inline bool
DrawContext::PatchDescriptor::operator == ( PatchDescriptor const other ) const
{
return _farDesc == other._farDesc and
_maxValence == other._maxValence and
_numElements == other._numElements;
}
} // end namespace Osd
} // end namespace OPENSUBDIV_VERSION

View File

@ -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

View File

@ -1,101 +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"
#include "../osd/vertex.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 */

View 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

View 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

View File

@ -32,7 +32,8 @@ namespace OPENSUBDIV_VERSION {
namespace Osd {
GLDrawContext::GLDrawContext() :
GLDrawContext::GLDrawContext(int maxValence) :
DrawContext(maxValence),
_patchIndexBuffer(0), _patchParamTextureBuffer(0), _fvarDataTextureBuffer(0),
_vertexTextureBuffer(0), _vertexValenceTextureBuffer(0), _quadOffsetsTextureBuffer(0)
{
@ -98,14 +99,14 @@ createTextureBuffer(T const &data, GLint format, int offset=0)
}
GLDrawContext *
GLDrawContext::Create(Far::PatchTables const * patchTables,
int numVertexElements, void * /*deviceContext*/) {
GLDrawContext::Create(Far::PatchTables const * patchTables, void * /*deviceContext*/) {
if (patchTables) {
GLDrawContext * result = new GLDrawContext();
int maxValence = patchTables->GetMaxValence();
GLDrawContext * result = new GLDrawContext(maxValence);
if (result->create(*patchTables, numVertexElements)) {
if (result->create(*patchTables)) {
return result;
} else {
delete result;
@ -115,7 +116,7 @@ GLDrawContext::Create(Far::PatchTables const * patchTables,
}
bool
GLDrawContext::create(Far::PatchTables const & patchTables, int numVertexElements) {
GLDrawContext::create(Far::PatchTables const & patchTables) {
_isAdaptive = patchTables.IsFeatureAdaptive();
@ -138,8 +139,7 @@ GLDrawContext::create(Far::PatchTables const & patchTables, int numVertexElement
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
DrawContext::ConvertPatchArrays(patchTables, _patchArrays,
patchTables.GetMaxValence(), numVertexElements);
DrawContext::ConvertPatchArrays(patchTables, _patchArrays);
// allocate and initialize additional buffer data

View File

@ -58,10 +58,9 @@ public:
///
/// @param patchTables a valid set of Far::PatchTables
///
/// @param numVertexElements the number of vertex elements
/// @param deviceContext not used in GLDrawContext
///
static GLDrawContext * Create(Far::PatchTables const * patchTables,
int numVertexElements,
void *deviceContext = NULL);
/// Set vbo as a vertex texture (for gregory patch drawing)
@ -137,10 +136,10 @@ protected:
GLuint _vertexValenceTextureBuffer;
GLuint _quadOffsetsTextureBuffer;
GLDrawContext();
GLDrawContext(int maxValence);
// allocate buffers from patchTables
bool create(Far::PatchTables const & patchTables, int numElements);
bool create(Far::PatchTables const & patchTables);
void updateVertexTexture(GLuint vbo);
};

View File

@ -43,9 +43,6 @@ GLDrawConfig::~GLDrawConfig()
static const char *commonShaderSource =
#include "glslPatchCommon.gen.h"
;
static const char *ptexShaderSource =
#include "glslPtexCommon.gen.h"
;
static const char *bsplineShaderSource =
#include "glslPatchBSpline.gen.h"
;
@ -55,50 +52,29 @@ static const char *gregoryShaderSource =
static const char *gregoryBasisShaderSource =
#include "glslPatchGregoryBasis.gen.h"
;
static const char *transitionShaderSource =
#include "glslPatchTransition.gen.h"
;
#endif
GLDrawRegistryBase::~GLDrawRegistryBase() {}
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
GLDrawSourceConfig *
GLDrawRegistryBase::_CreateDrawSourceConfig(
DrawContext::PatchDescriptor const & desc)
GLDrawRegistryBase::_CreateDrawSourceConfig(Far::PatchDescriptor const & desc)
{
GLDrawSourceConfig * sconfig = _NewDrawSourceConfig();
sconfig->commonShader.source = commonShaderSource;
if (IsPtexEnabled()) {
sconfig->commonShader.source += ptexShaderSource;
}
{
std::ostringstream ss;
ss << (int)desc.GetMaxValence();
sconfig->commonShader.AddDefine("OSD_MAX_VALENCE", ss.str());
ss.str("");
ss << (int)desc.GetNumElements();
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
}
switch (desc.GetType()) {
case Far::PatchDescriptor::REGULAR:
case Far::PatchDescriptor::BOUNDARY:
case Far::PatchDescriptor::CORNER:
sconfig->commonShader.AddDefine("OSD_PATCH_BSPLINE");
sconfig->commonShader.AddDefine("OSD_PATCH_ENABLE_SINGLE_CREASE");
sconfig->vertexShader.source = bsplineShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER");
sconfig->tessControlShader.source =
std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->tessControlShader.source = bsplineShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER");
sconfig->tessEvalShader.source =
std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->tessEvalShader.source = bsplineShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER");
break;
@ -148,8 +124,7 @@ GLDrawRegistryBase::_CreateDrawSourceConfig(
}
#else
GLDrawSourceConfig *
GLDrawRegistryBase::_CreateDrawSourceConfig(
DrawContext::PatchDescriptor const &)
GLDrawRegistryBase::_CreateDrawSourceConfig(Far::PatchDescriptor const &)
{
return _NewDrawSourceConfig();
}
@ -202,7 +177,7 @@ _CompileShader(
GLDrawConfig *
GLDrawRegistryBase::_CreateDrawConfig(
DrawContext::PatchDescriptor const & /* desc */,
Far::PatchDescriptor const & /* desc */,
GLDrawSourceConfig const * sconfig)
{
assert(sconfig);

View File

@ -28,8 +28,6 @@
#include "../version.h"
#include "../osd/drawRegistry.h"
#include "../osd/vertex.h"
#include "../osd/opengl.h"
#include <map>
@ -65,22 +63,14 @@ struct GLDrawSourceConfig : public DrawSourceConfig {
class GLDrawRegistryBase {
public:
typedef DrawContext::PatchDescriptor DescType;
typedef Far::PatchDescriptor DescType;
typedef GLDrawConfig ConfigType;
typedef GLDrawSourceConfig SourceConfigType;
GLDrawRegistryBase(bool enablePtex=false) : _enablePtex(enablePtex) { }
GLDrawRegistryBase() { }
virtual ~GLDrawRegistryBase();
bool IsPtexEnabled() const {
return _enablePtex;
}
void SetPtexEnabled(bool b) {
_enablePtex=b;
}
protected:
virtual ConfigType * _NewDrawConfig() {
return new ConfigType();
@ -92,16 +82,13 @@ protected:
virtual SourceConfigType * _NewDrawSourceConfig() {
return new SourceConfigType();
}
virtual SourceConfigType * _CreateDrawSourceConfig(DescType const & desc);
private:
bool _enablePtex;
virtual SourceConfigType * _CreateDrawSourceConfig(DescType const & desc);
};
//------------------------------------------------------------------------------
template <class DESC_TYPE = DrawContext::PatchDescriptor,
template <class DESC_TYPE = Far::PatchDescriptor,
class CONFIG_TYPE = GLDrawConfig,
class SOURCE_CONFIG_TYPE = GLDrawSourceConfig >

Some files were not shown because too many files have changed in this diff Show More