mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-23 08:20:06 +00:00
Merge branch 'upstream-dev' into dev
Conflicts: examples/glViewer/glViewer.cpp
This commit is contained in:
commit
a305f31a30
@ -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"
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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)];
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -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);
|
||||
|
@ -64,8 +64,6 @@
|
||||
#include <far/stencilTablesFactory.h>
|
||||
|
||||
#include <osd/mesh.h>
|
||||
#include <osd/cpuComputeContext.h>
|
||||
#include <osd/cpuComputeController.h>
|
||||
#include <osd/cpuVertexBuffer.h>
|
||||
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
|
@ -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();
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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})
|
||||
|
@ -1,233 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/clComputeContext.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template <class T> cl_mem
|
||||
createCLBuffer(std::vector<T> const & src, cl_context clContext) {
|
||||
|
||||
cl_mem devicePtr = 0;
|
||||
cl_int errNum = 0;
|
||||
|
||||
devicePtr = clCreateBuffer(clContext,
|
||||
CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,
|
||||
src.size()*sizeof(T),
|
||||
(void*)(&src.at(0)),
|
||||
&errNum);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clCreateBuffer: %d", errNum);
|
||||
}
|
||||
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class CLComputeContext::CLStencilTables {
|
||||
|
||||
public:
|
||||
CLStencilTables(Far::StencilTables const & stencilTables,
|
||||
cl_context clContext) {
|
||||
_numStencils = stencilTables.GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCLBuffer(stencilTables.GetSizes(), clContext);
|
||||
_offsets = createCLBuffer(stencilTables.GetOffsets(), clContext);
|
||||
_indices = createCLBuffer(stencilTables.GetControlIndices(),
|
||||
clContext);
|
||||
_weights = createCLBuffer(stencilTables.GetWeights(), clContext);
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
~CLStencilTables() {
|
||||
if (_sizes) clReleaseMemObject(_sizes);
|
||||
if (_offsets) clReleaseMemObject(_offsets);
|
||||
if (_indices) clReleaseMemObject(_indices);
|
||||
if (_weights) clReleaseMemObject(_weights);
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return _sizes and _offsets and _indices and _weights;
|
||||
}
|
||||
|
||||
cl_mem GetSizes() const {
|
||||
return _sizes;
|
||||
}
|
||||
|
||||
cl_mem GetOffsets() const {
|
||||
return _offsets;
|
||||
}
|
||||
|
||||
cl_mem GetIndices() const {
|
||||
return _indices;
|
||||
}
|
||||
|
||||
cl_mem GetWeights() const {
|
||||
return _weights;
|
||||
}
|
||||
|
||||
int GetNumStencils() const {
|
||||
return _numStencils;
|
||||
}
|
||||
|
||||
private:
|
||||
cl_mem _sizes,
|
||||
_offsets,
|
||||
_indices,
|
||||
_weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
CLComputeContext::CLComputeContext(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
cl_context clContext) :
|
||||
_vertexStencilTables(0), _varyingStencilTables(0),
|
||||
_numControlVertices(0) {
|
||||
|
||||
if (vertexStencilTables) {
|
||||
_vertexStencilTables = new CLStencilTables(*vertexStencilTables,
|
||||
clContext);
|
||||
_numControlVertices = vertexStencilTables->GetNumControlVertices();
|
||||
}
|
||||
|
||||
if (varyingStencilTables) {
|
||||
_varyingStencilTables = new CLStencilTables(*varyingStencilTables,
|
||||
clContext);
|
||||
|
||||
if (_numControlVertices) {
|
||||
assert(_numControlVertices
|
||||
== varyingStencilTables->GetNumControlVertices());
|
||||
} else {
|
||||
_numControlVertices = varyingStencilTables->GetNumControlVertices();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CLComputeContext::~CLComputeContext() {
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
CLComputeContext::HasVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
CLComputeContext::HasVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
int
|
||||
CLComputeContext::GetNumStencilsInVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
int
|
||||
CLComputeContext::GetNumStencilsInVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVertexStencilTablesSizes() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetSizes() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVertexStencilTablesOffsets() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetOffsets() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVertexStencilTablesIndices() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetIndices() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVertexStencilTablesWeights() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetWeights() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVaryingStencilTablesSizes() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetSizes() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVaryingStencilTablesOffsets() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetOffsets() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVaryingStencilTablesIndices() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetIndices() : 0;
|
||||
}
|
||||
|
||||
cl_mem
|
||||
CLComputeContext::GetVaryingStencilTablesWeights() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetWeights() : 0;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
CLComputeContext *
|
||||
CLComputeContext::Create(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
cl_context clContext) {
|
||||
|
||||
CLComputeContext *result =
|
||||
new CLComputeContext(
|
||||
vertexStencilTables, varyingStencilTables, clContext);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,155 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CL_COMPUTE_CONTEXT_H
|
||||
#define OSD_CL_COMPUTE_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/opencl.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far { class StencilTables; }
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief OpenCL Refine Context
|
||||
///
|
||||
/// The OpenCL-Compute implementation of the Refine module contextual functionality.
|
||||
///
|
||||
/// Contexts interface the serialized topological data pertaining to the
|
||||
/// geometric primitives with the capabilities of the selected discrete
|
||||
/// compute device.
|
||||
///
|
||||
class CLComputeContext : public NonCopyable<CLComputeContext> {
|
||||
|
||||
public:
|
||||
/// Creates an CLComputeContext instance
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
/// @param clContext An active OpenCL compute context
|
||||
///
|
||||
static CLComputeContext * Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
cl_context clContext);
|
||||
|
||||
/// Creates an CLComputeContext instance (template version)
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
/// @param context A user defined class to provide cl_context.
|
||||
/// must implement GetContext()
|
||||
///
|
||||
template<typename DEVICE_CONTEXT>
|
||||
static CLComputeContext * Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
DEVICE_CONTEXT context) {
|
||||
return Create(vertexStencilTables, varyingStencilTables,
|
||||
context->GetContext());
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~CLComputeContext();
|
||||
|
||||
|
||||
/// Returns true if the Context has a 'vertex' interpolation stencil table
|
||||
bool HasVertexStencilTables() const;
|
||||
|
||||
/// Returns true if the Context has a 'varying' interpolation stencil table
|
||||
bool HasVaryingStencilTables() const;
|
||||
|
||||
/// Returns the number of control vertices
|
||||
int GetNumControlVertices() const {
|
||||
return _numControlVertices;
|
||||
}
|
||||
|
||||
/// Returns the number of stencils in vertex stencil table
|
||||
int GetNumStencilsInVertexStencilTables() const;
|
||||
|
||||
/// Returns the number of stencils in varying stencil table
|
||||
int GetNumStencilsInVaryingStencilTables() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil sizes
|
||||
cl_mem GetVertexStencilTablesSizes() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil offsets
|
||||
cl_mem GetVertexStencilTablesOffsets() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil indices
|
||||
cl_mem GetVertexStencilTablesIndices() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil weights
|
||||
cl_mem GetVertexStencilTablesWeights() const;
|
||||
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil sizes
|
||||
cl_mem GetVaryingStencilTablesSizes() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil offsets
|
||||
cl_mem GetVaryingStencilTablesOffsets() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil indices
|
||||
cl_mem GetVaryingStencilTablesIndices() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil weights
|
||||
cl_mem GetVaryingStencilTablesWeights() const;
|
||||
|
||||
|
||||
protected:
|
||||
explicit CLComputeContext(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
cl_context clContext);
|
||||
|
||||
private:
|
||||
class CLStencilTables;
|
||||
|
||||
CLStencilTables * _vertexStencilTables,
|
||||
* _varyingStencilTables;
|
||||
|
||||
int _numControlVertices;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_CL_COMPUTE_CONTEXT_H
|
@ -1,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
|
@ -1,204 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CL_COMPUTE_CONTROLLER_H
|
||||
#define OSD_CL_COMPUTE_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/clComputeContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
#include "../osd/opencl.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class CLKernelBundle;
|
||||
|
||||
/// \brief Compute controller for launching OpenCL Compute subdivision kernels.
|
||||
///
|
||||
/// CLComputeController is a compute controller class to launch
|
||||
/// OpenCL subdivision kernels. It requires CLVertexBufferInterface
|
||||
/// as arguments of Refine function.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class CLComputeController {
|
||||
public:
|
||||
typedef CLComputeContext ComputeContext;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param clContext a valid instanciated OpenCL context
|
||||
///
|
||||
/// @param queue a valid non-zero OpenCL command queue
|
||||
///
|
||||
CLComputeController(cl_context clContext, cl_command_queue queue);
|
||||
|
||||
/// Destructor.
|
||||
~CLComputeController();
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CLContext to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param vertexDesc The descriptor of vertex elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
/// @param varyingBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param varyingDesc The descriptor of varying elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void Compute( CLComputeContext const * context,
|
||||
VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc=NULL,
|
||||
VertexBufferDescriptor const * varyingDesc=NULL ){
|
||||
|
||||
bind(vertexBuffer, varyingBuffer, vertexDesc, varyingDesc);
|
||||
|
||||
ApplyStencilTableKernel(context);
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CLContext to apply refinement operations to
|
||||
///
|
||||
/// @param batches Vector of batches of vertices organized by operative
|
||||
/// kernel
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
template<class VERTEX_BUFFER>
|
||||
void Compute(CLComputeContext const * context,
|
||||
VERTEX_BUFFER *vertexBuffer) {
|
||||
|
||||
Compute<VERTEX_BUFFER>(context, vertexBuffer, (VERTEX_BUFFER*)0);
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
/// Returns CL context
|
||||
cl_context GetContext() const { return _clContext; }
|
||||
|
||||
/// Returns CL command queue
|
||||
cl_command_queue GetCommandQueue() const { return _clQueue; }
|
||||
|
||||
protected:
|
||||
|
||||
void ApplyStencilTableKernel(ComputeContext const *context);
|
||||
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void bind( VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc,
|
||||
VertexBufferDescriptor const * varyingDesc ) {
|
||||
|
||||
// if the vertex buffer descriptor is specified, use it.
|
||||
// otherwise, assumes the data is tightly packed in the vertex buffer.
|
||||
if (vertexDesc) {
|
||||
_currentBindState.vertexDesc = *vertexDesc;
|
||||
} else {
|
||||
int numElements = vertexBuffer ? vertexBuffer->GetNumElements() : 0;
|
||||
_currentBindState.vertexDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
if (varyingDesc) {
|
||||
_currentBindState.varyingDesc = *varyingDesc;
|
||||
} else {
|
||||
int numElements = varyingBuffer ? varyingBuffer->GetNumElements() : 0;
|
||||
_currentBindState.varyingDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
_currentBindState.vertexBuffer = vertexBuffer ?
|
||||
vertexBuffer->BindCLBuffer(_clQueue) : 0;
|
||||
_currentBindState.varyingBuffer = varyingBuffer ?
|
||||
varyingBuffer->BindCLBuffer(_clQueue) : 0;
|
||||
}
|
||||
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
class KernelBundle;
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of the vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : vertexBuffer(0), varyingBuffer(0) { }
|
||||
|
||||
void Reset() {
|
||||
vertexBuffer = varyingBuffer = NULL;
|
||||
vertexDesc.Reset();
|
||||
varyingDesc.Reset();
|
||||
}
|
||||
|
||||
cl_mem vertexBuffer,
|
||||
varyingBuffer;
|
||||
|
||||
VertexBufferDescriptor vertexDesc,
|
||||
varyingDesc;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
|
||||
KernelBundle const * getKernel(VertexBufferDescriptor const &desc);
|
||||
|
||||
typedef std::vector<KernelBundle *> KernelRegistry;
|
||||
|
||||
KernelRegistry _kernelRegistry;
|
||||
|
||||
cl_context _clContext;
|
||||
cl_command_queue _clQueue;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_COMPUTE_CONTROLLER_H
|
0
opensubdiv/osd/clD3D11VertexBuffer.cpp
Executable file → Normal file
0
opensubdiv/osd/clD3D11VertexBuffer.cpp
Executable file → Normal file
@ -51,7 +51,7 @@ namespace Osd {
|
||||
/// D3D11VertexBuffer implements CLVertexBufferInterface and
|
||||
/// D3D11VertexBufferInterface.
|
||||
///
|
||||
/// An instance of this buffer class can be passed to D3D11ComputeController.
|
||||
/// An instance of this buffer class can be passed to D3D11ComputeEvaluator.
|
||||
///
|
||||
class CLD3D11VertexBuffer {
|
||||
public:
|
||||
|
206
opensubdiv/osd/clEvaluator.cpp
Normal file
206
opensubdiv/osd/clEvaluator.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/clEvaluator.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../osd/opencl.h"
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static const char *clSource =
|
||||
#include "clKernel.gen.h"
|
||||
;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
template <class T> cl_mem
|
||||
createCLBuffer(std::vector<T> const & src, cl_context clContext) {
|
||||
cl_int errNum = 0;
|
||||
cl_mem devicePtr = clCreateBuffer(clContext,
|
||||
CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR,
|
||||
src.size()*sizeof(T),
|
||||
(void*)(&src.at(0)),
|
||||
&errNum);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clCreateBuffer: %d", errNum);
|
||||
}
|
||||
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CLStencilTables::CLStencilTables(Far::StencilTables const *stencilTables,
|
||||
cl_context clContext) {
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCLBuffer(stencilTables->GetSizes(), clContext);
|
||||
_offsets = createCLBuffer(stencilTables->GetOffsets(), clContext);
|
||||
_indices = createCLBuffer(stencilTables->GetControlIndices(),
|
||||
clContext);
|
||||
_weights = createCLBuffer(stencilTables->GetWeights(), clContext);
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CLStencilTables::~CLStencilTables() {
|
||||
if (_sizes) clReleaseMemObject(_sizes);
|
||||
if (_offsets) clReleaseMemObject(_offsets);
|
||||
if (_indices) clReleaseMemObject(_indices);
|
||||
if (_weights) clReleaseMemObject(_weights);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
CLEvaluator::CLEvaluator(cl_context context, cl_command_queue queue)
|
||||
: _clContext(context), _clCommandQueue(queue),
|
||||
_program(NULL), _stencilsKernel(NULL) {
|
||||
}
|
||||
|
||||
CLEvaluator::~CLEvaluator() {
|
||||
if (_stencilsKernel) clReleaseKernel(_stencilsKernel);
|
||||
if (_program) clReleaseProgram(_program);
|
||||
}
|
||||
|
||||
bool
|
||||
CLEvaluator::Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc) {
|
||||
if (srcDesc.length > dstDesc.length) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"srcDesc length must be less than or equal to "
|
||||
"dstDesc length.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
cl_int errNum;
|
||||
|
||||
std::ostringstream defines;
|
||||
defines << "#define LENGTH " << srcDesc.length << "\n"
|
||||
<< "#define SRC_STRIDE " << srcDesc.stride << "\n"
|
||||
<< "#define DST_STRIDE " << dstDesc.stride << "\n";
|
||||
std::string defineStr = defines.str();
|
||||
|
||||
const char *sources[] = { defineStr.c_str(), clSource };
|
||||
_program = clCreateProgramWithSource(_clContext, 2, sources, 0, &errNum);
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"clCreateProgramWithSource (%d)", errNum);
|
||||
}
|
||||
|
||||
errNum = clBuildProgram(_program, 0, NULL, NULL, NULL, NULL);
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "clBuildProgram (%d) \n", errNum);
|
||||
|
||||
cl_int numDevices = 0;
|
||||
clGetContextInfo(
|
||||
_clContext, CL_CONTEXT_NUM_DEVICES,
|
||||
sizeof(cl_uint), &numDevices, NULL);
|
||||
|
||||
cl_device_id *devices = new cl_device_id[numDevices];
|
||||
clGetContextInfo(_clContext, CL_CONTEXT_DEVICES,
|
||||
sizeof(cl_device_id)*numDevices, devices, NULL);
|
||||
|
||||
for (int i = 0; i < numDevices; ++i) {
|
||||
char cBuildLog[10240];
|
||||
clGetProgramBuildInfo(
|
||||
_program, devices[i],
|
||||
CL_PROGRAM_BUILD_LOG, sizeof(cBuildLog), cBuildLog, NULL);
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, cBuildLog);
|
||||
}
|
||||
delete[] devices;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_stencilsKernel = clCreateKernel(_program, "computeStencils", &errNum);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, "buildKernel (%d)\n", errNum);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CLEvaluator::EvalStencils(cl_mem src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
cl_mem dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
cl_mem sizes,
|
||||
cl_mem offsets,
|
||||
cl_mem indices,
|
||||
cl_mem weights,
|
||||
int start,
|
||||
int end) const {
|
||||
if (end <= start) return true;
|
||||
|
||||
size_t globalWorkSize = (size_t)(end - start);
|
||||
|
||||
clSetKernelArg(_stencilsKernel, 0, sizeof(cl_mem), &src);
|
||||
clSetKernelArg(_stencilsKernel, 1, sizeof(int), &srcDesc.offset);
|
||||
clSetKernelArg(_stencilsKernel, 2, sizeof(cl_mem), &dst);
|
||||
clSetKernelArg(_stencilsKernel, 3, sizeof(int), &dstDesc.offset);
|
||||
clSetKernelArg(_stencilsKernel, 4, sizeof(cl_mem), &sizes);
|
||||
clSetKernelArg(_stencilsKernel, 5, sizeof(cl_mem), &offsets);
|
||||
clSetKernelArg(_stencilsKernel, 6, sizeof(cl_mem), &indices);
|
||||
clSetKernelArg(_stencilsKernel, 7, sizeof(cl_mem), &weights);
|
||||
clSetKernelArg(_stencilsKernel, 8, sizeof(int), &start);
|
||||
clSetKernelArg(_stencilsKernel, 9, sizeof(int), &end);
|
||||
|
||||
cl_int errNum = clEnqueueNDRangeKernel(
|
||||
_clCommandQueue, _stencilsKernel, 1, NULL,
|
||||
&globalWorkSize, NULL, 0, NULL, NULL);
|
||||
|
||||
if (errNum != CL_SUCCESS) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"ApplyStencilTableKernel (%d) ", errNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
clFinish(_clCommandQueue);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
CLEvaluator::Synchronize(cl_command_queue clCommandQueue) {
|
||||
clFinish(clCommandQueue);
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
230
opensubdiv/osd/clEvaluator.h
Normal file
230
opensubdiv/osd/clEvaluator.h
Normal file
@ -0,0 +1,230 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_CL_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_CL_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/opencl.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief OpenCL stencil tables
|
||||
///
|
||||
/// This class is an OpenCL buffer representation of Far::StencilTables.
|
||||
///
|
||||
/// CLCompute consumes this table to apply stencils
|
||||
///
|
||||
///
|
||||
class CLStencilTables {
|
||||
public:
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static CLStencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
DEVICE_CONTEXT context) {
|
||||
return new CLStencilTables(stencilTables, context->GetContext());
|
||||
}
|
||||
|
||||
CLStencilTables(Far::StencilTables const *stencilTables,
|
||||
cl_context clContext);
|
||||
~CLStencilTables();
|
||||
|
||||
// interfaces needed for CLComputeKernel
|
||||
cl_mem GetSizesBuffer() const { return _sizes; }
|
||||
cl_mem GetOffsetsBuffer() const { return _offsets; }
|
||||
cl_mem GetIndicesBuffer() const { return _indices; }
|
||||
cl_mem GetWeightsBuffer() const { return _weights; }
|
||||
int GetNumStencils() const { return _numStencils; }
|
||||
|
||||
private:
|
||||
cl_mem _sizes;
|
||||
cl_mem _offsets;
|
||||
cl_mem _indices;
|
||||
cl_mem _weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// \brief OpenCL stencil kernel
|
||||
///
|
||||
///
|
||||
class CLEvaluator {
|
||||
public:
|
||||
typedef bool Instantiatable;
|
||||
/// Constructor.
|
||||
CLEvaluator(cl_context context, cl_command_queue queue);
|
||||
|
||||
/// Desctructor.
|
||||
~CLEvaluator();
|
||||
|
||||
/// Generic creator template.
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static CLEvaluator *Create(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
DEVICE_CONTEXT deviceContext) {
|
||||
return Create(srcDesc, dstDesc,
|
||||
deviceContext->GetContext(),
|
||||
deviceContext->GetCommandQueue());
|
||||
}
|
||||
|
||||
static CLEvaluator * Create(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
cl_context clContext,
|
||||
cl_command_queue clCommandQueue) {
|
||||
CLEvaluator *kernel = new CLEvaluator(clContext, clCommandQueue);
|
||||
if (kernel->Compile(srcDesc, dstDesc)) return kernel;
|
||||
delete kernel;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// \brief Generic static compute function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently from OsdMesh template interface.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindCLBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCLBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTables stencil table to be applied. The table must have
|
||||
/// OpenCL memory interfaces.
|
||||
///
|
||||
/// @param instance cached compiled instance. Clients are supposed to
|
||||
/// pre-compile an instance of this class and provide
|
||||
/// to this function. If it's null the kernel still
|
||||
/// compute by instantiating on-demand kernel although
|
||||
/// it may cause a performance problem.
|
||||
///
|
||||
/// @param deviceContext client providing context class which supports
|
||||
/// cL_context GetContext()
|
||||
/// cl_command_queue GetCommandQueue()
|
||||
/// methods.
|
||||
///
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE,
|
||||
typename DEVICE_CONTEXT>
|
||||
static bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
CLEvaluator const *instance,
|
||||
DEVICE_CONTEXT deviceContext) {
|
||||
if (instance) {
|
||||
return instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable);
|
||||
} else {
|
||||
// Create an instance on demand (slow)
|
||||
instance = Create(srcDesc, dstDesc, deviceContext);
|
||||
if (instance) {
|
||||
bool r = instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic compute function.
|
||||
/// Dispatch the CL compute kernel asynchronously.
|
||||
/// Returns false if the kernel hasn't been compiled yet.
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable) const {
|
||||
return EvalStencils(srcVertexBuffer->BindCLBuffer(_clCommandQueue),
|
||||
srcDesc,
|
||||
dstVertexBuffer->BindCLBuffer(_clCommandQueue),
|
||||
dstDesc,
|
||||
stencilTable->GetSizesBuffer(),
|
||||
stencilTable->GetOffsetsBuffer(),
|
||||
stencilTable->GetIndicesBuffer(),
|
||||
stencilTable->GetWeightsBuffer(),
|
||||
0,
|
||||
stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
/// Dispatch the CL compute kernel asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
bool EvalStencils(cl_mem src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
cl_mem dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
cl_mem sizes,
|
||||
cl_mem offsets,
|
||||
cl_mem indices,
|
||||
cl_mem weights,
|
||||
int start,
|
||||
int end) const;
|
||||
|
||||
/// Configure OpenCL kernel.
|
||||
/// Returns false if it fails to compile the kernel.
|
||||
bool Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc);
|
||||
|
||||
/// Wait the OpenCL kernels finish.
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static void Synchronize(DEVICE_CONTEXT deviceContext) {
|
||||
Synchronize(deviceContext->GetCommandQueue());
|
||||
}
|
||||
|
||||
static void Synchronize(cl_command_queue queue);
|
||||
|
||||
private:
|
||||
cl_context _clContext;
|
||||
cl_command_queue _clCommandQueue;
|
||||
cl_program _program;
|
||||
cl_kernel _stencilsKernel;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_CL_EVALUATOR_H
|
@ -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);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ namespace Osd {
|
||||
/// \brief Concrete vertex buffer class for OpenCL subvision.
|
||||
///
|
||||
/// CLVertexBuffer implements CLVertexBufferInterface. An instance of this
|
||||
/// buffer class can be passed to CLComputeController
|
||||
/// buffer class can be passed to CLEvaluator
|
||||
///
|
||||
class CLVertexBuffer {
|
||||
|
||||
|
@ -1,77 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
#include "../osd/cpuComputeContext.h"
|
||||
#include "../osd/cpuKernel.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CpuComputeContext::CpuComputeContext(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables) :
|
||||
_vertexStencilTables(0), _varyingStencilTables(0) {
|
||||
|
||||
// XXXX manuelk we do not own the tables, so use copy-constructor for now
|
||||
// smart pointers eventually
|
||||
if (vertexStencilTables) {
|
||||
_vertexStencilTables = new Far::StencilTables(*vertexStencilTables);
|
||||
}
|
||||
|
||||
if (varyingStencilTables) {
|
||||
_varyingStencilTables = new Far::StencilTables(*varyingStencilTables);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CpuComputeContext::~CpuComputeContext() {
|
||||
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CpuComputeContext *
|
||||
CpuComputeContext::Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
return new CpuComputeContext(vertexStencilTables, varyingStencilTables);
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,102 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CPU_COMPUTE_CONTEXT_H
|
||||
#define OSD_CPU_COMPUTE_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far { class StencilTables; }
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief CPU Compute Context
|
||||
///
|
||||
/// The CPU implementation of the Compute module contextual functionality.
|
||||
///
|
||||
/// The Osd Compute module provides functionality to interpolate primitive
|
||||
/// variable data according to a subdivision scheme.
|
||||
///
|
||||
/// Contexts provide an interface between the serialized topological data
|
||||
/// of a geometric primitive and the computation resources of a compute device.
|
||||
///
|
||||
class CpuComputeContext : private NonCopyable<CpuComputeContext> {
|
||||
public:
|
||||
/// Creates an CpuComputeContext instance
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
/// @param deviceContext (not used)
|
||||
///
|
||||
static CpuComputeContext * Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Destructor
|
||||
virtual ~CpuComputeContext();
|
||||
|
||||
/// Returns the stencils data applied by this context for vertex
|
||||
/// interpolation
|
||||
Far::StencilTables const * GetVertexStencilTables() const {
|
||||
return _vertexStencilTables;
|
||||
}
|
||||
|
||||
/// Returns the stencils data applied by this context for varying
|
||||
/// interpolation
|
||||
Far::StencilTables const * GetVaryingStencilTables() const {
|
||||
return _varyingStencilTables;
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit CpuComputeContext(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables);
|
||||
|
||||
private:
|
||||
Far::StencilTables const * _vertexStencilTables,
|
||||
* _varyingStencilTables;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_CPU_COMPUTE_CONTEXT_H
|
||||
|
||||
|
@ -1,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
|
@ -1,179 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CPU_COMPUTE_CONTROLLER_H
|
||||
#define OSD_CPU_COMPUTE_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/cpuComputeContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Compute controller for launching CPU subdivision kernels.
|
||||
///
|
||||
/// CpuComputeController is a compute controller class to launch
|
||||
/// single threaded CPU subdivision kernels. It requires
|
||||
/// CpuVertexBufferInterface as arguments of the Refine() function.
|
||||
///
|
||||
/// The Osd Compute module provides functionality to interpolate primitive
|
||||
/// variable data according to a subdivision scheme.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class CpuComputeController {
|
||||
public:
|
||||
typedef CpuComputeContext ComputeContext;
|
||||
|
||||
/// Constructor.
|
||||
CpuComputeController();
|
||||
|
||||
/// Destructor.
|
||||
~CpuComputeController();
|
||||
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CpuContext to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param vertexDesc The descriptor of vertex elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
/// @param varyingBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param varyingDesc The descriptor of varying elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void Compute( CpuComputeContext const * context,
|
||||
VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc=NULL,
|
||||
VertexBufferDescriptor const * varyingDesc=NULL ){
|
||||
|
||||
bind(vertexBuffer, varyingBuffer, vertexDesc, varyingDesc);
|
||||
|
||||
ApplyStencilTableKernel(context);
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The CpuContext to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
template<class VERTEX_BUFFER>
|
||||
void Compute(CpuComputeContext const * context,
|
||||
VERTEX_BUFFER *vertexBuffer) {
|
||||
|
||||
Compute<VERTEX_BUFFER>(context, vertexBuffer, (VERTEX_BUFFER*)0);
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void ApplyStencilTableKernel(ComputeContext const *context) const;
|
||||
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void bind( VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc,
|
||||
VertexBufferDescriptor const * varyingDesc ) {
|
||||
|
||||
// if the vertex buffer descriptor is specified, use it.
|
||||
// otherwise, assumes the data is tightly packed in the vertex buffer.
|
||||
if (vertexDesc) {
|
||||
_currentBindState.vertexDesc = *vertexDesc;
|
||||
} else {
|
||||
int numElements = vertexBuffer ? vertexBuffer->GetNumElements() : 0;
|
||||
_currentBindState.vertexDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
if (varyingDesc) {
|
||||
_currentBindState.varyingDesc = *varyingDesc;
|
||||
} else {
|
||||
int numElements = varyingBuffer ? varyingBuffer->GetNumElements() : 0;
|
||||
_currentBindState.varyingDesc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
_currentBindState.vertexBuffer = vertexBuffer ?
|
||||
vertexBuffer->BindCpuBuffer() : 0;
|
||||
|
||||
_currentBindState.varyingBuffer = varyingBuffer ?
|
||||
varyingBuffer->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of the vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : vertexBuffer(0), varyingBuffer(0) { }
|
||||
|
||||
void Reset() {
|
||||
vertexBuffer = varyingBuffer = 0;
|
||||
vertexDesc.Reset();
|
||||
varyingDesc.Reset();
|
||||
}
|
||||
|
||||
float * vertexBuffer,
|
||||
* varyingBuffer;
|
||||
|
||||
VertexBufferDescriptor vertexDesc,
|
||||
varyingDesc;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_CPU_COMPUTE_CONTROLLER_H
|
@ -43,7 +43,7 @@ namespace Osd {
|
||||
/// CpuD3D11VertexBuffer implements CpuVertexBufferInterface and
|
||||
/// D3D11VertexBufferInterface.
|
||||
///
|
||||
/// An instance of this buffer class can be passed to CpuComputeController.
|
||||
/// An instance of this buffer class can be passed to CpuEvaluator.
|
||||
///
|
||||
class CpuD3D11VertexBuffer {
|
||||
public:
|
||||
|
@ -1,57 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cpuEvalLimitContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuEvalLimitContext *
|
||||
CpuEvalLimitContext::Create(Far::PatchTables const & patchTables) {
|
||||
|
||||
// there is no limit with uniform subdivision
|
||||
if (not patchTables.IsFeatureAdaptive())
|
||||
return NULL;
|
||||
|
||||
return new CpuEvalLimitContext(patchTables);
|
||||
}
|
||||
|
||||
CpuEvalLimitContext::CpuEvalLimitContext(Far::PatchTables const & patchTables) :
|
||||
EvalLimitContext(patchTables),
|
||||
_patchTables(patchTables),
|
||||
_patchMap(patchTables) {
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,80 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CPU_EVAL_LIMIT_CONTEXT_H
|
||||
#define OSD_CPU_EVAL_LIMIT_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/evalLimitContext.h"
|
||||
#include "../far/patchTables.h"
|
||||
#include "../far/patchMap.h"
|
||||
|
||||
#include <map>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
class CpuEvalLimitContext : public EvalLimitContext {
|
||||
public:
|
||||
|
||||
/// \brief Factory
|
||||
/// Returns an EvalLimitContext from the given far patch tables.
|
||||
/// Note : the patchtables is expected to be feature-adaptive and have ptex
|
||||
/// coordinates tables.
|
||||
///
|
||||
/// @param patchTables a pointer to an initialized Far::PatchTables
|
||||
///
|
||||
static CpuEvalLimitContext * Create(Far::PatchTables const &patchTables);
|
||||
|
||||
Far::PatchTables const & GetPatchTables() const {
|
||||
return _patchTables;
|
||||
}
|
||||
|
||||
Far::PatchMap const & GetPatchMap() const {
|
||||
return _patchMap;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
explicit CpuEvalLimitContext(Far::PatchTables const & patchTables);
|
||||
|
||||
private:
|
||||
|
||||
Far::PatchTables const _patchTables; // Patch topology data
|
||||
Far::PatchMap const _patchMap; // Patch search accelerator
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* OSD_CPU_EVAL_LIMIT_CONTEXT_H */
|
@ -1,288 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cpuEvalLimitController.h"
|
||||
#include "../osd/cpuEvalLimitContext.h"
|
||||
#include "../osd/cpuEvalLimitKernel.h"
|
||||
#include "../far/patchTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuEvalLimitController::CpuEvalLimitController() {
|
||||
}
|
||||
|
||||
CpuEvalLimitController::~CpuEvalLimitController() {
|
||||
}
|
||||
|
||||
// Vertex interpolation of a sample at the limit
|
||||
int
|
||||
CpuEvalLimitController::EvalLimitSample( LimitLocation const & coord,
|
||||
CpuEvalLimitContext * context,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV ) const {
|
||||
typedef Far::PatchDescriptor Desc;
|
||||
|
||||
float s=coord.s,
|
||||
t=coord.t;
|
||||
|
||||
Far::PatchMap::Handle const * handle = context->GetPatchMap().FindPatch( coord.ptexIndex, s, t );
|
||||
if (not handle) {
|
||||
return 0; // no handle if there is a hole or 'coord' is incorrect
|
||||
}
|
||||
|
||||
VertexData const & vertexData = _currentBindState.vertexData;
|
||||
|
||||
if (vertexData.in) {
|
||||
|
||||
Far::PatchTables const & ptables = context->GetPatchTables();
|
||||
|
||||
Far::PatchParam pparam = ptables.GetPatchParam(*handle);
|
||||
|
||||
Far::ConstIndexArray cvs = ptables.GetPatchVertices(*handle);
|
||||
|
||||
Far::PatchDescriptor desc = ptables.GetPatchDescriptor(*handle);
|
||||
switch (desc.GetType()) {
|
||||
case Desc::REGULAR : evalBSpline( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
case Desc::BOUNDARY : evalBoundary( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
case Desc::CORNER : evalCorner( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
case Desc::GREGORY : evalGregory( pparam.bitField, t, s, cvs.begin(),
|
||||
&ptables.GetVertexValenceTable()[0],
|
||||
ptables.GetPatchQuadOffsets(*handle).begin(),
|
||||
ptables.GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
case Desc::GREGORY_BOUNDARY : evalGregoryBoundary( pparam.bitField, t, s, cvs.begin(),
|
||||
&ptables.GetVertexValenceTable()[0],
|
||||
ptables.GetPatchQuadOffsets(*handle).begin(),
|
||||
ptables.GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
case Desc::GREGORY_BASIS : {
|
||||
evalGregoryBasis( pparam.bitField, s, t,
|
||||
cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
} break;
|
||||
case Desc::QUADS : evalBilinear( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
outDesc,
|
||||
outQ, outDQU, outDQV );
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Vertex interpolation of samples at the limit
|
||||
int
|
||||
CpuEvalLimitController::_EvalLimitSample( LimitLocation const & coords,
|
||||
CpuEvalLimitContext * context,
|
||||
unsigned int index ) const {
|
||||
typedef Far::PatchDescriptor Desc;
|
||||
|
||||
float s=coords.s,
|
||||
t=coords.t;
|
||||
|
||||
Far::PatchMap::Handle const * handle = context->GetPatchMap().FindPatch( coords.ptexIndex, s, t );
|
||||
if (not handle) {
|
||||
return 0; // no handle if there is a hole or 'coord' is incorrect
|
||||
}
|
||||
|
||||
VertexData const & vertexData = _currentBindState.vertexData;
|
||||
|
||||
Far::PatchTables const & ptables = context->GetPatchTables();
|
||||
|
||||
Far::PatchParam pparam = ptables.GetPatchParam(*handle);
|
||||
|
||||
Far::PatchDescriptor desc = ptables.GetPatchDescriptor(*handle);
|
||||
|
||||
Far::ConstIndexArray cvs = ptables.GetPatchVertices(*handle);
|
||||
|
||||
if (vertexData.in) {
|
||||
|
||||
int offset = vertexData.outDesc.stride * index,
|
||||
doffset = vertexData.outDesc.length * index;
|
||||
|
||||
if (vertexData.out) {
|
||||
|
||||
// note : don't apply outDesc.offset here, it's done inside patch
|
||||
// evaluation
|
||||
float * out = vertexData.out+offset,
|
||||
* outDu = vertexData.outDu ? vertexData.outDu+doffset : 0,
|
||||
* outDv = vertexData.outDv ? vertexData.outDv+doffset : 0;
|
||||
|
||||
switch (desc.GetType()) {
|
||||
case Desc::REGULAR : evalBSpline( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
case Desc::BOUNDARY : evalBoundary( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
case Desc::CORNER : evalCorner( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
case Desc::GREGORY : evalGregory( pparam.bitField, t, s, cvs.begin(),
|
||||
&ptables.GetVertexValenceTable()[0],
|
||||
ptables.GetPatchQuadOffsets(*handle).begin(),
|
||||
ptables.GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
case Desc::GREGORY_BOUNDARY : evalGregoryBoundary( pparam.bitField, t, s, cvs.begin(),
|
||||
&ptables.GetVertexValenceTable()[0],
|
||||
ptables.GetPatchQuadOffsets(*handle).begin(),
|
||||
ptables.GetMaxValence(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
case Desc::GREGORY_BASIS : {
|
||||
evalGregoryBasis( pparam.bitField, s, t,
|
||||
cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
} break;
|
||||
case Desc::QUADS : evalBilinear( pparam.bitField, s, t, cvs.begin(),
|
||||
vertexData.inDesc,
|
||||
vertexData.in,
|
||||
vertexData.outDesc,
|
||||
out, outDu, outDv );
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VaryingData const & varyingData = _currentBindState.varyingData;
|
||||
|
||||
if (varyingData.in and varyingData.out) {
|
||||
|
||||
static int const zeroRings[6][4] = { {5, 6,10, 9}, // regular
|
||||
{1, 2, 6, 5}, // boundary / single-crease
|
||||
{1, 2, 5, 4}, // corner
|
||||
{0, 1, 2, 3}, // no permutation
|
||||
{0, 5, 10, 15} }; // gregory basis
|
||||
|
||||
int const * permute = 0;
|
||||
switch (desc.GetType()) {
|
||||
case Desc::REGULAR : permute = zeroRings[0]; break;
|
||||
case Desc::BOUNDARY : permute = zeroRings[1]; break;
|
||||
case Desc::CORNER : permute = zeroRings[2]; break;
|
||||
case Desc::GREGORY :
|
||||
case Desc::GREGORY_BOUNDARY : permute = zeroRings[3]; break;
|
||||
case Desc::GREGORY_BASIS : permute = zeroRings[4]; break;
|
||||
default:
|
||||
assert(0);
|
||||
};
|
||||
|
||||
int offset = varyingData.outDesc.stride * index;
|
||||
|
||||
Far::Index zeroRing[4] = { cvs[permute[0]],
|
||||
cvs[permute[1]],
|
||||
cvs[permute[2]],
|
||||
cvs[permute[3]] };
|
||||
|
||||
evalBilinear( pparam.bitField, s, t, zeroRing,
|
||||
varyingData.inDesc,
|
||||
varyingData.in,
|
||||
varyingData.outDesc,
|
||||
varyingData.out+offset, 0, 0);
|
||||
|
||||
}
|
||||
|
||||
// Note : currently we only support bilinear boundary interpolation rules
|
||||
// for limit face-varying data.
|
||||
|
||||
FacevaryingData const & facevaryingData = _currentBindState.facevaryingData;
|
||||
|
||||
if (facevaryingData.in and facevaryingData.out) {
|
||||
|
||||
int offset = facevaryingData.outDesc.stride * index;
|
||||
|
||||
static int const zeroRing[4] = {0,1,2,3};
|
||||
|
||||
// XXXX manuelk this assumes FVar data is ordered with 4 CVs / patch :
|
||||
// bi-cubic FVar interpolation will require proper topology
|
||||
// accessors in Far::PatchTables and this code will change
|
||||
evalBilinear( pparam.bitField, s, t, zeroRing,
|
||||
facevaryingData.inDesc,
|
||||
&facevaryingData.in[handle->patchIndex*4*facevaryingData.outDesc.stride],
|
||||
facevaryingData.outDesc,
|
||||
facevaryingData.out+offset, 0, 0);
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,298 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CPU_EVAL_LIMIT_CONTROLLER_H
|
||||
#define OSD_CPU_EVAL_LIMIT_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
struct LimitLocation;
|
||||
class CpuEvalLimitContext;
|
||||
|
||||
/// \brief CPU controler for limit surface evaluation.
|
||||
///
|
||||
/// A CPU-driven controller that can be called to evaluate samples on the limit
|
||||
/// surface for a given EvalContext.
|
||||
///
|
||||
/// Warning : this eval controller is re-entrant but it breaks the Osd API pattern
|
||||
/// by requiring client code to bind and unbind the data buffers to the
|
||||
/// Controller before calling evaluation methods.
|
||||
///
|
||||
/// Ex :
|
||||
/// \code
|
||||
/// evalCtroller->BindVertexBuffers( ... );
|
||||
/// evalCtroller->BindVaryingBuffers( ... );
|
||||
/// evalCtroller->BindFacevaryingBuffers( ... );
|
||||
///
|
||||
/// parallel_for( int index=0; i<nsamples; ++index ) {
|
||||
/// evalCtroller->EvalLimitSample( coord, evalCtxt, index );
|
||||
/// }
|
||||
///
|
||||
/// evalCtroller->Unbind();
|
||||
/// \endcode
|
||||
///
|
||||
class CpuEvalLimitController {
|
||||
|
||||
public:
|
||||
/// Constructor.
|
||||
CpuEvalLimitController();
|
||||
|
||||
/// Destructor.
|
||||
~CpuEvalLimitController();
|
||||
|
||||
/// \brief Binds control vertex data buffer
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input vertex data
|
||||
///
|
||||
/// @param oDesc data descriptor for the outQ data buffer
|
||||
/// -- derivative buffers do not have a descriptor and
|
||||
/// cannot be offset or padded with a stride (yet ?)
|
||||
///
|
||||
/// @param outQ output vertex data
|
||||
///
|
||||
/// @param outdQu output derivative along "u" of the vertex data (optional)
|
||||
///
|
||||
/// @param outdQv output derivative along "v" of the vertex data (optional)
|
||||
///
|
||||
template<class INPUT_BUFFER, class OUTPUT_BUFFER>
|
||||
void BindVertexBuffers( VertexBufferDescriptor const & iDesc, INPUT_BUFFER *inQ,
|
||||
VertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ,
|
||||
OUTPUT_BUFFER *outdQu=0,
|
||||
OUTPUT_BUFFER *outdQv=0 ) {
|
||||
_currentBindState.vertexData.inDesc = iDesc;
|
||||
_currentBindState.vertexData.in = inQ ? inQ->BindCpuBuffer() : 0;
|
||||
|
||||
_currentBindState.vertexData.outDesc = oDesc;
|
||||
_currentBindState.vertexData.out = outQ ? outQ->BindCpuBuffer() : 0;
|
||||
_currentBindState.vertexData.outDu = outdQu ? outdQu->BindCpuBuffer() : 0;
|
||||
_currentBindState.vertexData.outDv = outdQv ? outdQv->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
/// \brief Binds the varying-interpolated data streams
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input varying data
|
||||
///
|
||||
/// @param oDesc data descriptor for the outQ data buffer
|
||||
///
|
||||
/// @param outQ output varying data
|
||||
///
|
||||
template<class INPUT_BUFFER, class OUTPUT_BUFFER>
|
||||
void BindVaryingBuffers( VertexBufferDescriptor const & iDesc, INPUT_BUFFER *inQ,
|
||||
VertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ ) {
|
||||
_currentBindState.varyingData.inDesc = iDesc;
|
||||
_currentBindState.varyingData.in = inQ ? inQ->BindCpuBuffer() : 0;
|
||||
|
||||
_currentBindState.varyingData.outDesc = oDesc;
|
||||
_currentBindState.varyingData.out = outQ ? outQ->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
/// \brief Binds the face-varying-interpolated data streams
|
||||
///
|
||||
/// Note : currently we only support bilinear boundary interpolation rules
|
||||
/// for face-varying data. Although Hbr supports 3 addition smooth rule sets,
|
||||
/// the feature-adaptive patch interpolation code currently does not support
|
||||
/// them, and neither does this EvalContext
|
||||
///
|
||||
/// @param iDesc data descriptor shared by all input data buffers
|
||||
///
|
||||
/// @param inQ input face-varying data
|
||||
///
|
||||
/// @param oDesc data descriptor for the outQ data buffer
|
||||
///
|
||||
/// @param outQ output face-varying data
|
||||
///
|
||||
template<class INPUT_BUFFER, class OUTPUT_BUFFER>
|
||||
void BindFacevaryingBuffers( VertexBufferDescriptor const & iDesc, INPUT_BUFFER *inQ,
|
||||
VertexBufferDescriptor const & oDesc, OUTPUT_BUFFER *outQ ) {
|
||||
_currentBindState.facevaryingData.inDesc = iDesc;
|
||||
_currentBindState.facevaryingData.in = inQ ? inQ->BindCpuBuffer() : 0;
|
||||
|
||||
_currentBindState.facevaryingData.outDesc = oDesc;
|
||||
_currentBindState.facevaryingData.out = outQ ? outQ->BindCpuBuffer() : 0;
|
||||
}
|
||||
|
||||
/// \brief Vertex interpolation of a single sample at the limit
|
||||
///
|
||||
/// Evaluates "vertex" interpolation of a single sample on the surface limit.
|
||||
///
|
||||
/// This function is re-entrant but does not require binding the
|
||||
/// output vertex buffers. Pointers to memory where the data is
|
||||
/// output are explicitly passed to the function.
|
||||
///
|
||||
/// @param coord location on the limit surface to be evaluated
|
||||
///
|
||||
/// @param context the EvalLimitContext that the controller will evaluate
|
||||
///
|
||||
/// @param outDesc data descriptor for the outQ data buffer
|
||||
/// -- derivative buffers do not have a descriptor and
|
||||
/// cannot be offset or padded with a stride (yet ?)
|
||||
///
|
||||
/// @param outQ output vertex data
|
||||
///
|
||||
/// @param outDQU output derivative along "u" of the vertex data (optional)
|
||||
///
|
||||
/// @param outDQV output derivative along "v" of the vertex data (optional)
|
||||
///
|
||||
/// @return 1 if the sample was found
|
||||
///
|
||||
int EvalLimitSample( LimitLocation const & coord,
|
||||
CpuEvalLimitContext * context,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV ) const;
|
||||
|
||||
/// \brief Vertex interpolation of samples at the limit
|
||||
///
|
||||
/// Evaluates "vertex" interpolation of a sample on the surface limit.
|
||||
///
|
||||
/// @param coords location on the limit surface to be evaluated
|
||||
///
|
||||
/// @param context the EvalLimitContext that the controller will evaluate
|
||||
///
|
||||
/// @param index the index of the vertex in the output buffers bound to the
|
||||
/// context
|
||||
///
|
||||
/// @return the number of samples found (0 if the location was tagged as a hole
|
||||
/// or the coordinate was invalid)
|
||||
///
|
||||
int EvalLimitSample( LimitLocation const & coords,
|
||||
CpuEvalLimitContext * context,
|
||||
unsigned int index ) const {
|
||||
if (not context)
|
||||
return 0;
|
||||
|
||||
int n = _EvalLimitSample( coords, context, index );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void Unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
// Vertex interpolated streams
|
||||
struct VertexData {
|
||||
|
||||
VertexData() : in(0), out(0), outDu(0), outDv(0) { }
|
||||
|
||||
|
||||
void Reset() {
|
||||
in = out = outDu = outDv = NULL;
|
||||
inDesc.Reset();
|
||||
outDesc.Reset();
|
||||
}
|
||||
|
||||
VertexBufferDescriptor inDesc,
|
||||
outDesc;
|
||||
float * in,
|
||||
* out,
|
||||
* outDu,
|
||||
* outDv;
|
||||
};
|
||||
|
||||
// Varying interpolated streams
|
||||
struct VaryingData {
|
||||
|
||||
VaryingData() : in(0), out(0) { }
|
||||
|
||||
|
||||
void Reset() {
|
||||
in = out = NULL;
|
||||
inDesc.Reset();
|
||||
outDesc.Reset();
|
||||
}
|
||||
|
||||
VertexBufferDescriptor inDesc,
|
||||
outDesc;
|
||||
float * in,
|
||||
* out;
|
||||
};
|
||||
|
||||
// Facevarying interpolated streams
|
||||
struct FacevaryingData {
|
||||
|
||||
FacevaryingData() : in(0), out(0) { }
|
||||
|
||||
void Reset() {
|
||||
in = out = NULL;
|
||||
inDesc.Reset();
|
||||
outDesc.Reset();
|
||||
}
|
||||
|
||||
VertexBufferDescriptor inDesc,
|
||||
outDesc;
|
||||
float * in,
|
||||
* out;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int _EvalLimitSample( LimitLocation const & coords,
|
||||
CpuEvalLimitContext * context,
|
||||
unsigned int index ) const;
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() { }
|
||||
|
||||
void Reset() {
|
||||
vertexData.Reset();
|
||||
varyingData.Reset();
|
||||
facevaryingData.Reset();
|
||||
}
|
||||
|
||||
VertexData vertexData; // vertex interpolated data descriptor
|
||||
VaryingData varyingData; // varying interpolated data descriptor
|
||||
FacevaryingData facevaryingData; // face-varying interpolated data descriptor
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* OSD_CPU_EVAL_LIMIT_CONTROLLER_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,132 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CPU_EVAL_LIMIT_KERNEL_H
|
||||
#define OSD_CPU_EVAL_LIMIT_KERNEL_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
#include "../far/patchParam.h"
|
||||
|
||||
#include "../far/types.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
void
|
||||
evalBilinear(Far::PatchParam::BitField bits,
|
||||
float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV);
|
||||
|
||||
void
|
||||
evalBSpline(Far::PatchParam::BitField bits,
|
||||
float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
void
|
||||
evalBoundary(Far::PatchParam::BitField bits,
|
||||
float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
void
|
||||
evalCorner(Far::PatchParam::BitField bits,
|
||||
float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
void
|
||||
evalGregoryBasis(Far::PatchParam::BitField bits,
|
||||
float u, float v,
|
||||
Far::Index const *vertsIndices,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
void
|
||||
evalGregory(Far::PatchParam::BitField bits, float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
Far::Index const * vertexValenceBuffer,
|
||||
unsigned int const * quadOffsetBuffer,
|
||||
int maxValence,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
void
|
||||
evalGregoryBoundary(Far::PatchParam::BitField bits, float u, float v,
|
||||
Far::Index const * vertexIndices,
|
||||
Far::Index const * vertexValenceBuffer,
|
||||
unsigned int const * quadOffsetBuffer,
|
||||
int maxValence,
|
||||
VertexBufferDescriptor const & inDesc,
|
||||
float const * inQ,
|
||||
VertexBufferDescriptor const & outDesc,
|
||||
float * outQ,
|
||||
float * outDQU,
|
||||
float * outDQV );
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif /* OSD_CPU_EVAL_LIMIT_KERNEL_H */
|
@ -1,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
|
@ -1,74 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef FAR_CPU_EVALSTENCILS_CONTEXT_H
|
||||
#define FAR_CPU_EVALSTENCILS_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief CPU stencils evaluation context
|
||||
///
|
||||
///
|
||||
class CpuEvalStencilsContext : private NonCopyable<CpuEvalStencilsContext> {
|
||||
|
||||
public:
|
||||
/// \brief Creates an CpuEvalStencilsContext instance
|
||||
///
|
||||
/// @param stencils a pointer to the Far::StencilTables
|
||||
///
|
||||
static CpuEvalStencilsContext * Create(Far::LimitStencilTables const *stencils);
|
||||
|
||||
/// \brief Returns the Far::StencilTables applied
|
||||
Far::LimitStencilTables const * GetStencilTables() const {
|
||||
return _stencils;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
CpuEvalStencilsContext(Far::LimitStencilTables const *stencils);
|
||||
|
||||
private:
|
||||
|
||||
Far::LimitStencilTables const * _stencils;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // FAR_CPU_EVALSTENCILS_CONTEXT_H
|
@ -1,149 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cpuEvalStencilsController.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
CpuEvalStencilsController::CpuEvalStencilsController() {
|
||||
}
|
||||
|
||||
CpuEvalStencilsController::~CpuEvalStencilsController() {
|
||||
}
|
||||
|
||||
int
|
||||
CpuEvalStencilsController::_UpdateValues( CpuEvalStencilsContext * context ) {
|
||||
|
||||
int result=0;
|
||||
|
||||
Far::LimitStencilTables const * stencils = context->GetStencilTables();
|
||||
|
||||
int nstencils = stencils->GetNumStencils();
|
||||
if (not nstencils)
|
||||
return result;
|
||||
|
||||
VertexBufferDescriptor ctrlDesc = _currentBindState.controlDataDesc,
|
||||
outDesc = _currentBindState.outputDataDesc;
|
||||
|
||||
// make sure that we have control data to work with
|
||||
if (not ctrlDesc.CanEval(outDesc))
|
||||
return 0;
|
||||
|
||||
float const * ctrl = _currentBindState.controlData + ctrlDesc.offset;
|
||||
|
||||
float * out = _currentBindState.outputData + outDesc.offset;
|
||||
|
||||
if ((not ctrl) or (not out))
|
||||
return result;
|
||||
|
||||
unsigned char const * sizes = &stencils->GetSizes().at(0);
|
||||
Far::Index const * index = &stencils->GetControlIndices().at(0);
|
||||
|
||||
float const * weight = &stencils->GetWeights().at(0);
|
||||
|
||||
for (int i=0; i<nstencils; ++i) {
|
||||
|
||||
memset(out, 0, outDesc.length*sizeof(float));
|
||||
|
||||
for (int j=0; j<sizes[i]; ++j, ++index, ++weight) {
|
||||
|
||||
float const * cv = ctrl + (*index)*ctrlDesc.stride;
|
||||
|
||||
for (int k=0; k<outDesc.length; ++k) {
|
||||
out[k] += cv[k] * (*weight);
|
||||
}
|
||||
}
|
||||
out += outDesc.stride;
|
||||
}
|
||||
|
||||
return nstencils;
|
||||
}
|
||||
|
||||
int
|
||||
CpuEvalStencilsController::_UpdateDerivs( CpuEvalStencilsContext * context ) {
|
||||
|
||||
int result=0;
|
||||
|
||||
Far::LimitStencilTables const * stencils = context->GetStencilTables();
|
||||
|
||||
int nstencils = stencils->GetNumStencils();
|
||||
if (not nstencils)
|
||||
return result;
|
||||
|
||||
VertexBufferDescriptor ctrlDesc = _currentBindState.controlDataDesc,
|
||||
duDesc = _currentBindState.outputDuDesc,
|
||||
dvDesc = _currentBindState.outputDvDesc;
|
||||
|
||||
// make sure that we have control data to work with
|
||||
if (not (ctrlDesc.CanEval(duDesc) and ctrlDesc.CanEval(dvDesc)))
|
||||
return 0;
|
||||
|
||||
float const * ctrl = _currentBindState.controlData + ctrlDesc.offset;
|
||||
|
||||
float * du = _currentBindState.outputUDeriv + duDesc.offset,
|
||||
* dv = _currentBindState.outputVDeriv + dvDesc.offset;
|
||||
|
||||
if ((not ctrl) or (not du) or (not dv))
|
||||
return result;
|
||||
|
||||
unsigned char const * sizes = &stencils->GetSizes().at(0);
|
||||
Far::Index const * index = &stencils->GetControlIndices().at(0);
|
||||
|
||||
float const * duweight = &stencils->GetDuWeights().at(0),
|
||||
* dvweight = &stencils->GetDvWeights().at(0);
|
||||
|
||||
for (int i=0; i<nstencils; ++i) {
|
||||
|
||||
memset(du, 0, duDesc.length*sizeof(float));
|
||||
memset(dv, 0, dvDesc.length*sizeof(float));
|
||||
|
||||
for (int j=0; j<sizes[i]; ++j, ++index, ++duweight, ++dvweight) {
|
||||
|
||||
float const * cv = ctrl + (*index)*ctrlDesc.stride;
|
||||
|
||||
for (int k=0; k<duDesc.length; ++k) {
|
||||
du[k] += cv[k] * (*duweight);
|
||||
dv[k] += cv[k] * (*dvweight);
|
||||
}
|
||||
}
|
||||
du += duDesc.stride;
|
||||
dv += dvDesc.stride;
|
||||
}
|
||||
|
||||
return nstencils;
|
||||
}
|
||||
|
||||
void
|
||||
CpuEvalStencilsController::Synchronize() {
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,209 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef FAR_CPU_EVALSTENCILS_CONTROLLER_H
|
||||
#define FAR_CPU_EVALSTENCILS_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/cpuEvalStencilsContext.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief CPU stencils evaluation controller
|
||||
///
|
||||
/// CpuStencilsController is a compute controller class to launch
|
||||
/// single threaded CPU stencil evalution kernels.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class CpuEvalStencilsController {
|
||||
public:
|
||||
|
||||
/// Constructor.
|
||||
CpuEvalStencilsController();
|
||||
|
||||
/// Destructor.
|
||||
~CpuEvalStencilsController();
|
||||
|
||||
|
||||
/// \brief Applies stencil weights to the control vertex data
|
||||
///
|
||||
/// Applies the stencil weights to the control vertex data to evaluate the
|
||||
/// interpolated limit positions at the parametric locations of the stencils
|
||||
///
|
||||
/// @param context the CpuEvalStencilsContext with the stencil weights
|
||||
///
|
||||
/// @param controlDataDesc vertex buffer descriptor for the control vertex data
|
||||
///
|
||||
/// @param controlVertices vertex buffer with the control vertices data
|
||||
///
|
||||
/// @param outputDataDesc vertex buffer descriptor for the output vertex data
|
||||
///
|
||||
/// @param outputData vertex buffer where the vertex data will be output
|
||||
///
|
||||
template<class CONTROL_BUFFER, class OUTPUT_BUFFER>
|
||||
int UpdateValues( CpuEvalStencilsContext * context,
|
||||
VertexBufferDescriptor const & controlDataDesc, CONTROL_BUFFER *controlVertices,
|
||||
VertexBufferDescriptor const & outputDataDesc, OUTPUT_BUFFER *outputData ) {
|
||||
|
||||
if (not context->GetStencilTables()->GetNumStencils())
|
||||
return 0;
|
||||
|
||||
bindControlData( controlDataDesc, controlVertices );
|
||||
|
||||
bindOutputData( outputDataDesc, outputData );
|
||||
|
||||
int n = _UpdateValues( context );
|
||||
|
||||
unbind();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/// \brief Applies derivative stencil weights to the control vertex data
|
||||
///
|
||||
/// Computes the U and V derivative stencils to the control vertex data at
|
||||
/// the parametric locations contained in each stencil
|
||||
///
|
||||
/// @param context the CpuEvalStencilsContext with the stencil weights
|
||||
///
|
||||
/// @param controlDataDesc vertex buffer descriptor for the control vertex data
|
||||
///
|
||||
/// @param controlVertices vertex buffer with the control vertices data
|
||||
///
|
||||
/// @param outputDuDesc vertex buffer descriptor for the U derivative output data
|
||||
///
|
||||
/// @param outputDuData output vertex buffer for the U derivative data
|
||||
///
|
||||
/// @param outputDvDesc vertex buffer descriptor for the V deriv output data
|
||||
///
|
||||
/// @param outputDvData output vertex buffer for the V derivative data
|
||||
///
|
||||
template<class CONTROL_BUFFER, class OUTPUT_BUFFER>
|
||||
int UpdateDerivs( CpuEvalStencilsContext * context,
|
||||
VertexBufferDescriptor const & controlDataDesc, CONTROL_BUFFER *controlVertices,
|
||||
VertexBufferDescriptor const & outputDuDesc, OUTPUT_BUFFER *outputDuData,
|
||||
VertexBufferDescriptor const & outputDvDesc, OUTPUT_BUFFER *outputDvData ) {
|
||||
|
||||
if (not context->GetStencilTables()->GetNumStencils())
|
||||
return 0;
|
||||
|
||||
bindControlData( controlDataDesc, controlVertices );
|
||||
|
||||
bindOutputDerivData( outputDuDesc, outputDuData, outputDvDesc, outputDvData );
|
||||
|
||||
int n = _UpdateDerivs( context );
|
||||
|
||||
unbind();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
protected:
|
||||
|
||||
/// \brief Binds control vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindControlData(VertexBufferDescriptor const & controlDataDesc, VERTEX_BUFFER *controlData ) {
|
||||
|
||||
_currentBindState.controlData = controlData ? controlData->BindCpuBuffer() : 0;
|
||||
_currentBindState.controlDataDesc = controlDataDesc;
|
||||
|
||||
}
|
||||
|
||||
/// \brief Binds output vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindOutputData( VertexBufferDescriptor const & outputDataDesc, VERTEX_BUFFER *outputData ) {
|
||||
|
||||
_currentBindState.outputData = outputData ? outputData->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputDataDesc = outputDataDesc;
|
||||
}
|
||||
|
||||
/// \brief Binds output derivative vertex data buffer
|
||||
template<class VERTEX_BUFFER>
|
||||
void bindOutputDerivData( VertexBufferDescriptor const & outputDuDesc, VERTEX_BUFFER *outputDu,
|
||||
VertexBufferDescriptor const & outputDvDesc, VERTEX_BUFFER *outputDv ) {
|
||||
|
||||
_currentBindState.outputUDeriv = outputDu ? outputDu ->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputVDeriv = outputDv ? outputDv->BindCpuBuffer() : 0;
|
||||
_currentBindState.outputDuDesc = outputDuDesc;
|
||||
_currentBindState.outputDvDesc = outputDvDesc;
|
||||
}
|
||||
|
||||
/// \brief Unbinds any previously bound vertex and varying data buffers.
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int _UpdateValues( CpuEvalStencilsContext * context );
|
||||
int _UpdateDerivs( CpuEvalStencilsContext * context );
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : controlData(0), outputData(0), outputUDeriv(0), outputVDeriv(0) { }
|
||||
|
||||
void Reset() {
|
||||
controlData = outputData = outputUDeriv = outputVDeriv = NULL;
|
||||
controlDataDesc.Reset();
|
||||
outputDataDesc.Reset();
|
||||
outputDuDesc.Reset();
|
||||
outputDvDesc.Reset();
|
||||
}
|
||||
|
||||
// transient mesh data
|
||||
VertexBufferDescriptor controlDataDesc,
|
||||
outputDataDesc,
|
||||
outputDuDesc,
|
||||
outputDvDesc;
|
||||
|
||||
float * controlData,
|
||||
* outputData,
|
||||
* outputUDeriv,
|
||||
* outputVDeriv;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // FAR_CPU_EVALSTENCILS_CONTROLLER_H
|
148
opensubdiv/osd/cpuEvaluator.cpp
Normal file
148
opensubdiv/osd/cpuEvaluator.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cpuEvaluator.h"
|
||||
#include "../osd/cpuKernel.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CpuEvaluator::EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start, int end) {
|
||||
if (end <= start) return true;
|
||||
if (srcDesc.length != dstDesc.length) return false;
|
||||
|
||||
// XXX: we can probably expand cpuKernel.cpp to here.
|
||||
CpuEvalStencils(src, srcDesc, dst, dstDesc,
|
||||
sizes, offsets, indices, weights, start, end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CpuEvaluator::EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
float *dstDu,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
float *dstDv,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
const float * duWeights,
|
||||
const float * dvWeights,
|
||||
int start, int end) {
|
||||
if (end <= start) return true;
|
||||
if (srcDesc.length != dstDesc.length) return false;
|
||||
if (srcDesc.length != dstDuDesc.length) return false;
|
||||
if (srcDesc.length != dstDvDesc.length) return false;
|
||||
|
||||
CpuEvalStencils(src, srcDesc,
|
||||
dst, dstDesc,
|
||||
dstDu, dstDuDesc,
|
||||
dstDv, dstDvDesc,
|
||||
sizes, offsets, indices,
|
||||
weights, duWeights, dvWeights,
|
||||
start, end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct BufferAdapter {
|
||||
BufferAdapter(T *p, int length, int stride) :
|
||||
_p(p), _length(length), _stride(stride) { }
|
||||
void Clear() {
|
||||
for (int i = 0; i < _length; ++i) _p[i] = 0;
|
||||
}
|
||||
void AddWithWeight(T const *src, float w, float wu, float wv) {
|
||||
(void)wu;
|
||||
(void)wv;
|
||||
// TODO: derivatives.
|
||||
for (int i = 0; i < _length; ++i) {
|
||||
_p[i] += src[i] * w;
|
||||
}
|
||||
}
|
||||
const T *operator[] (int index) const {
|
||||
return _p + _stride * index;
|
||||
}
|
||||
BufferAdapter<T> & operator ++() {
|
||||
_p += _stride;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T *_p;
|
||||
int _length;
|
||||
int _stride;
|
||||
};
|
||||
|
||||
/* static */
|
||||
int
|
||||
CpuEvaluator::EvalPatches(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
PatchCoordArray const &patchCoords,
|
||||
Far::PatchTables const *patchTable) {
|
||||
src += srcDesc.offset;
|
||||
dst += dstDesc.offset;
|
||||
int count = 0;
|
||||
|
||||
// XXX: this implementaion is temporary.
|
||||
BufferAdapter<const float> srcT(src, srcDesc.length, srcDesc.stride);
|
||||
BufferAdapter<float> dstT(dst, dstDesc.length, dstDesc.stride);
|
||||
|
||||
for (size_t i = 0; i < patchCoords.size(); ++i) {
|
||||
PatchCoord const &coords = patchCoords[i];
|
||||
|
||||
patchTable->Evaluate(coords.handle, coords.s, coords.t,
|
||||
srcT, dstT);
|
||||
++count;
|
||||
++dstT;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
242
opensubdiv/osd/cpuEvaluator.h
Normal file
242
opensubdiv/osd/cpuEvaluator.h
Normal file
@ -0,0 +1,242 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_CPU_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_CPU_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
#include "../far/patchTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Coordinates set on a patch table
|
||||
/// XXX: this is a temporary structure, exists during Osd refactoring work.
|
||||
///
|
||||
struct PatchCoord {
|
||||
/// \brief Constructor
|
||||
///
|
||||
/// @param p patch handle
|
||||
///
|
||||
/// @param s parametric location on the patch
|
||||
///
|
||||
/// @param t parametric location on the patch
|
||||
///
|
||||
PatchCoord(Far::PatchTables::PatchHandle handle, float s, float t) :
|
||||
handle(handle), s(s), t(t) { }
|
||||
|
||||
Far::PatchTables::PatchHandle handle; ///< patch handle
|
||||
float s, t; ///< parametric location on patch
|
||||
};
|
||||
|
||||
typedef std::vector<PatchCoord> PatchCoordArray;
|
||||
|
||||
|
||||
class CpuEvaluator {
|
||||
public:
|
||||
/// \brief Generic static eval stencils function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently from OsdMesh template interface.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTable stencil table to be applied.
|
||||
///
|
||||
/// @param instance not used in the cpu kernel
|
||||
/// (declared as a typed pointer to prevent
|
||||
/// undesirable template resolution)
|
||||
///
|
||||
/// @param deviceContext not used in the cpu kernel
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(SRC_BUFFER *srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
const CpuEvaluator *instance = NULL,
|
||||
void * deviceContext = NULL) {
|
||||
(void)instance; // unused
|
||||
(void)deviceContext; // unused
|
||||
|
||||
return EvalStencils(srcBuffer->BindCpuBuffer(),
|
||||
srcDesc,
|
||||
dstBuffer->BindCpuBuffer(),
|
||||
dstDesc,
|
||||
&stencilTable->GetSizes()[0],
|
||||
&stencilTable->GetOffsets()[0],
|
||||
&stencilTable->GetControlIndices()[0],
|
||||
&stencilTable->GetWeights()[0],
|
||||
/*start = */ 0,
|
||||
/*end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
/// stencil evaluate function.
|
||||
static bool EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end);
|
||||
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(SRC_BUFFER *srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
DST_BUFFER *dstDuBuffer,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
DST_BUFFER *dstDvBuffer,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
const CpuEvaluator *evaluator = NULL,
|
||||
void * deviceContext = NULL) {
|
||||
(void)evaluator; // unused
|
||||
(void)deviceContext; // unused
|
||||
|
||||
return EvalStencils(srcBuffer->BindCpuBuffer(),
|
||||
srcDesc,
|
||||
dstBuffer->BindCpuBuffer(),
|
||||
dstDesc,
|
||||
dstDuBuffer->BindCpuBuffer(),
|
||||
dstDuDesc,
|
||||
dstDvBuffer->BindCpuBuffer(),
|
||||
dstDvDesc,
|
||||
&stencilTable->GetSizes()[0],
|
||||
&stencilTable->GetOffsets()[0],
|
||||
&stencilTable->GetControlIndices()[0],
|
||||
&stencilTable->GetWeights()[0],
|
||||
&stencilTable->GetDuWeights()[0],
|
||||
&stencilTable->GetDvWeights()[0],
|
||||
/*start = */ 0,
|
||||
/*end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
static bool EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
float *dstDu,
|
||||
VertexBufferDescriptor const &dstDuDesc,
|
||||
float *dstDv,
|
||||
VertexBufferDescriptor const &dstDvDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
const float * duWeights,
|
||||
const float * dvWeights,
|
||||
int start,
|
||||
int end);
|
||||
|
||||
/// \brief Generic limit eval function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently.
|
||||
///
|
||||
/// XXX: This interface is still work in progress. XXX
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCpuBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param patchCoord array of locations to be evaluated.
|
||||
///
|
||||
/// @param patchTable Far::PatchTable
|
||||
///
|
||||
/// @param instanced not used in the cpu evaluator
|
||||
///
|
||||
/// @param deviceContext not used in the cpu evaluator
|
||||
///
|
||||
template <typename SRC_BUFFER, typename DST_BUFFER>
|
||||
static int EvalPatches(SRC_BUFFER *srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
DST_BUFFER *dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
PatchCoordArray const &patchCoords,
|
||||
Far::PatchTables const *patchTable,
|
||||
CpuEvaluator const *instance,
|
||||
void * deviceContext = NULL) {
|
||||
(void)instance; // unused
|
||||
(void)deviceContext; // unused
|
||||
|
||||
return EvalPatches(srcBuffer->BindCpuBuffer(),
|
||||
srcDesc,
|
||||
dstBuffer->BindCpuBuffer(),
|
||||
dstDesc,
|
||||
patchCoords,
|
||||
patchTable);
|
||||
}
|
||||
|
||||
/// \brief limit eval function.
|
||||
static int EvalPatches(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
PatchCoordArray const &patchCoords,
|
||||
Far::PatchTables const *patchTable);
|
||||
|
||||
/// \brief synchronize all asynchronous computation invoked on this device.
|
||||
static void Synchronize(void * /*deviceContext = NULL*/) {
|
||||
// nothing.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_CPU_EVALUATOR_H
|
@ -70,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
|
||||
|
@ -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
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
#include "../osd/vertex.h"
|
||||
#include "../far/types.h"
|
||||
|
||||
#include <vector>
|
||||
|
@ -37,7 +37,7 @@ namespace Osd {
|
||||
/// \brief Concrete vertex buffer class for cpu subvision.
|
||||
///
|
||||
/// CpuVertexBuffer implements the VertexBufferInterface. An instance
|
||||
/// of this buffer class can be passed to CpuComputeController
|
||||
/// of this buffer class can be passed to CpuEvaluator
|
||||
///
|
||||
class CpuVertexBuffer {
|
||||
public:
|
||||
|
@ -1,227 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
#include "../osd/cudaComputeContext.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
template <class T> void *
|
||||
createCudaBuffer(std::vector<T> const & src) {
|
||||
|
||||
void * devicePtr = 0;
|
||||
|
||||
size_t size = src.size()*sizeof(T);
|
||||
|
||||
cudaError_t err = cudaMalloc(&devicePtr, size);
|
||||
if (err != cudaSuccess) {
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
err = cudaMemcpy(devicePtr, &src.at(0), size, cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess) {
|
||||
cudaFree(devicePtr);
|
||||
return 0;
|
||||
}
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class CudaComputeContext::CudaStencilTables {
|
||||
|
||||
public:
|
||||
explicit CudaStencilTables(Far::StencilTables const & stencilTables) {
|
||||
_numStencils = stencilTables.GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCudaBuffer(stencilTables.GetSizes());
|
||||
_offsets = createCudaBuffer(stencilTables.GetOffsets());
|
||||
_indices = createCudaBuffer(stencilTables.GetControlIndices());
|
||||
_weights = createCudaBuffer(stencilTables.GetWeights());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
~CudaStencilTables() {
|
||||
if (_sizes) { cudaFree(_sizes); }
|
||||
if (_offsets) { cudaFree(_offsets); }
|
||||
if (_indices) { cudaFree(_indices); }
|
||||
if (_weights) { cudaFree(_weights); }
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return _sizes and _offsets and _indices and _weights;
|
||||
}
|
||||
|
||||
void * GetSizes() const {
|
||||
return _sizes;
|
||||
}
|
||||
|
||||
void * GetOffsets() const {
|
||||
return _offsets;
|
||||
}
|
||||
|
||||
void * GetIndices() const {
|
||||
return _indices;
|
||||
}
|
||||
|
||||
void * GetWeights() const {
|
||||
return _weights;
|
||||
}
|
||||
|
||||
int GetNumStencils() const {
|
||||
return _numStencils;
|
||||
}
|
||||
|
||||
private:
|
||||
void * _sizes,
|
||||
* _offsets,
|
||||
* _indices,
|
||||
* _weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CudaComputeContext::CudaComputeContext(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables) :
|
||||
_vertexStencilTables(0), _varyingStencilTables(0),
|
||||
_numControlVertices(0) {
|
||||
|
||||
if (vertexStencilTables) {
|
||||
_vertexStencilTables = new CudaStencilTables(*vertexStencilTables);
|
||||
_numControlVertices = vertexStencilTables->GetNumControlVertices();
|
||||
}
|
||||
|
||||
if (varyingStencilTables) {
|
||||
_varyingStencilTables = new CudaStencilTables(*varyingStencilTables);
|
||||
|
||||
if (_numControlVertices) {
|
||||
assert(_numControlVertices ==
|
||||
varyingStencilTables->GetNumControlVertices());
|
||||
} else {
|
||||
_numControlVertices = varyingStencilTables->GetNumControlVertices();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CudaComputeContext::~CudaComputeContext() {
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
CudaComputeContext::HasVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
CudaComputeContext::HasVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
int
|
||||
CudaComputeContext::GetNumStencilsInVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
int
|
||||
CudaComputeContext::GetNumStencilsInVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVertexStencilTablesSizes() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetSizes() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVertexStencilTablesOffsets() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetOffsets() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVertexStencilTablesIndices() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetIndices() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVertexStencilTablesWeights() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetWeights() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVaryingStencilTablesSizes() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetSizes() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVaryingStencilTablesOffsets() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetOffsets() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVaryingStencilTablesIndices() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetIndices() : 0;
|
||||
}
|
||||
|
||||
void *
|
||||
CudaComputeContext::GetVaryingStencilTablesWeights() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetWeights() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CudaComputeContext *
|
||||
CudaComputeContext::Create(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void * /*deviceContext*/) {
|
||||
|
||||
CudaComputeContext *result =
|
||||
new CudaComputeContext(vertexStencilTables, varyingStencilTables);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,134 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_CUDA_COMPUTE_CONTEXT_H
|
||||
#define OSD_CUDA_COMPUTE_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far { class StencilTables; }
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief CUDA Refine Context
|
||||
///
|
||||
/// The CUDA implementation of the Refine module contextual functionality.
|
||||
///
|
||||
/// Contexts interface the serialized topological data pertaining to the
|
||||
/// geometric primitives with the capabilities of the selected discrete
|
||||
/// compute device.
|
||||
///
|
||||
class CudaComputeContext : public NonCopyable<CudaComputeContext> {
|
||||
|
||||
public:
|
||||
/// Creates an CudaComputeContext instance
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
/// @param deviceContext (not used)
|
||||
///
|
||||
static CudaComputeContext * Create(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
void *deviceContext = NULL);
|
||||
|
||||
/// Destructor
|
||||
virtual ~CudaComputeContext();
|
||||
|
||||
/// Returns true if the Context has a 'vertex' interpolation stencil table
|
||||
bool HasVertexStencilTables() const;
|
||||
|
||||
/// Returns true if the Context has a 'varying' interpolation stencil table
|
||||
bool HasVaryingStencilTables() const;
|
||||
|
||||
/// Returns the number of control vertices
|
||||
int GetNumControlVertices() const {
|
||||
return _numControlVertices;
|
||||
}
|
||||
|
||||
/// Returns the number of stencils in vertex stencil tables
|
||||
int GetNumStencilsInVertexStencilTables() const;
|
||||
|
||||
/// Returns the number of stencils in varying stencil tables
|
||||
int GetNumStencilsInVaryingStencilTables() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil sizes
|
||||
void * GetVertexStencilTablesSizes() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil offsets
|
||||
void * GetVertexStencilTablesOffsets() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil indices
|
||||
void * GetVertexStencilTablesIndices() const;
|
||||
|
||||
/// Returns the Cuda buffer containing vertex-stencil stencil weights
|
||||
void * GetVertexStencilTablesWeights() const;
|
||||
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil sizes
|
||||
void * GetVaryingStencilTablesSizes() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil offsets
|
||||
void * GetVaryingStencilTablesOffsets() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil indices
|
||||
void * GetVaryingStencilTablesIndices() const;
|
||||
|
||||
/// Returns the Cuda buffer containing Varying-stencil stencil weights
|
||||
void * GetVaryingStencilTablesWeights() const;
|
||||
|
||||
|
||||
protected:
|
||||
explicit CudaComputeContext(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables);
|
||||
|
||||
private:
|
||||
class CudaStencilTables;
|
||||
|
||||
CudaStencilTables * _vertexStencilTables,
|
||||
* _varyingStencilTables;
|
||||
|
||||
int _numControlVertices;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_CUDA_COMPUTE_CONTEXT_H
|
@ -1,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
|
@ -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
|
124
opensubdiv/osd/cudaEvaluator.cpp
Normal file
124
opensubdiv/osd/cudaEvaluator.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/cudaEvaluator.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include <vector>
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
extern "C" {
|
||||
void CudaEvalStencils(const float *src,
|
||||
float *dst,
|
||||
int length,
|
||||
int srcStride,
|
||||
int dstStride,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end);
|
||||
}
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
template <class T> void *
|
||||
createCudaBuffer(std::vector<T> const & src) {
|
||||
void * devicePtr = 0;
|
||||
|
||||
size_t size = src.size()*sizeof(T);
|
||||
|
||||
cudaError_t err = cudaMalloc(&devicePtr, size);
|
||||
if (err != cudaSuccess) {
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
err = cudaMemcpy(devicePtr, &src.at(0), size, cudaMemcpyHostToDevice);
|
||||
if (err != cudaSuccess) {
|
||||
cudaFree(devicePtr);
|
||||
return 0;
|
||||
}
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
CudaStencilTables::CudaStencilTables(Far::StencilTables const *stencilTables) {
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createCudaBuffer(stencilTables->GetSizes());
|
||||
_offsets = createCudaBuffer(stencilTables->GetOffsets());
|
||||
_indices = createCudaBuffer(stencilTables->GetControlIndices());
|
||||
_weights = createCudaBuffer(stencilTables->GetWeights());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CudaStencilTables::~CudaStencilTables() {
|
||||
if (_sizes) cudaFree(_sizes);
|
||||
if (_offsets) cudaFree(_offsets);
|
||||
if (_indices) cudaFree(_indices);
|
||||
if (_weights) cudaFree(_weights);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/* static */
|
||||
bool
|
||||
CudaEvaluator::EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end) {
|
||||
CudaEvalStencils(src + srcDesc.offset,
|
||||
dst + dstDesc.offset,
|
||||
srcDesc.length,
|
||||
srcDesc.stride,
|
||||
dstDesc.stride,
|
||||
sizes, offsets, indices, weights,
|
||||
start, end);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
CudaEvaluator::Synchronize(void * /*deviceContext*/) {
|
||||
cudaThreadSynchronize();
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
148
opensubdiv/osd/cudaEvaluator.h
Normal file
148
opensubdiv/osd/cudaEvaluator.h
Normal file
@ -0,0 +1,148 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_CUDA_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_CUDA_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include <vector>
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief CUDA stencil tables
|
||||
///
|
||||
/// This class is a cuda buffer representation of Far::StencilTables.
|
||||
///
|
||||
/// CudaComputeKernel consumes this table to apply stencils
|
||||
///
|
||||
///
|
||||
class CudaStencilTables {
|
||||
public:
|
||||
static CudaStencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
void *deviceContext = NULL) {
|
||||
(void)deviceContext; // unused
|
||||
return new CudaStencilTables(stencilTables);
|
||||
}
|
||||
|
||||
explicit CudaStencilTables(Far::StencilTables const *stencilTables);
|
||||
~CudaStencilTables();
|
||||
|
||||
// interfaces needed for CudaCompute
|
||||
void *GetSizesBuffer() const { return _sizes; }
|
||||
void *GetOffsetsBuffer() const { return _offsets; }
|
||||
void *GetIndicesBuffer() const { return _indices; }
|
||||
void *GetWeightsBuffer() const { return _weights; }
|
||||
int GetNumStencils() const { return _numStencils; }
|
||||
|
||||
private:
|
||||
void * _sizes,
|
||||
* _offsets,
|
||||
* _indices,
|
||||
* _weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class CudaEvaluator {
|
||||
public:
|
||||
/// \brief Generic static compute function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently from OsdMesh template interface.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindCudaBuffer() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindCudaBuffer() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTables stencil table to be applied. The table must have
|
||||
/// Cuda memory interfaces.
|
||||
///
|
||||
/// @param instance not used in the CudaEvaluator
|
||||
///
|
||||
/// @param deviceContext not used in the CudaEvaluator
|
||||
///
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
const void *instance = NULL,
|
||||
void * deviceContext = NULL) {
|
||||
|
||||
(void)instance; // unused
|
||||
(void)deviceContext; // unused
|
||||
return EvalStencils(srcVertexBuffer->BindCudaBuffer(),
|
||||
srcDesc,
|
||||
dstVertexBuffer->BindCudaBuffer(),
|
||||
dstDesc,
|
||||
(unsigned char const *)stencilTable->GetSizesBuffer(),
|
||||
(int const *)stencilTable->GetOffsetsBuffer(),
|
||||
(int const *)stencilTable->GetIndicesBuffer(),
|
||||
(float const *)stencilTable->GetWeightsBuffer(),
|
||||
/*start = */ 0,
|
||||
/*end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
static bool EvalStencils(const float *src,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
float *dst,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
const unsigned char * sizes,
|
||||
const int * offsets,
|
||||
const int * indices,
|
||||
const float * weights,
|
||||
int start,
|
||||
int end);
|
||||
|
||||
static void Synchronize(void *deviceContext = NULL);
|
||||
};
|
||||
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_CUDA_EVALUATOR_H
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace Osd {
|
||||
/// \brief Concrete vertex buffer class for Cuda subvision.
|
||||
///
|
||||
/// CudaVertexBuffer implements CudaVertexBufferInterface.
|
||||
/// An instance of this buffer class can be passed to CudaComputeController
|
||||
/// An instance of this buffer class can be passed to CudaEvaluator
|
||||
///
|
||||
class CudaVertexBuffer {
|
||||
|
||||
|
@ -1,284 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
#include "../osd/d3d11ComputeContext.h"
|
||||
#include "../far/error.h"
|
||||
|
||||
#include <D3D11.h>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct D3D11Table {
|
||||
|
||||
D3D11Table() : buffer(0), srv(0) { }
|
||||
|
||||
~D3D11Table() {
|
||||
SAFE_RELEASE(buffer);
|
||||
SAFE_RELEASE(srv);
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return (buffer and srv);
|
||||
}
|
||||
|
||||
template <class T> void initialize(std::vector<T> const & src,
|
||||
DXGI_FORMAT format, ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
size_t size = src.size()*sizeof(T);
|
||||
|
||||
if (size==0) {
|
||||
buffer = 0;
|
||||
srv = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ID3D11Device *device = 0;
|
||||
deviceContext->GetDevice(&device);
|
||||
assert(device);
|
||||
|
||||
D3D11_BUFFER_DESC bd;
|
||||
bd.ByteWidth = (unsigned int)size;
|
||||
bd.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
bd.CPUAccessFlags = 0;
|
||||
bd.MiscFlags = 0;
|
||||
bd.StructureByteStride = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
initData.pSysMem = &src.at(0);
|
||||
|
||||
HRESULT hr = device->CreateBuffer(&bd, &initData, &buffer);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Error creating compute table buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
|
||||
ZeroMemory(&srvd, sizeof(srvd));
|
||||
srvd.Format = format;
|
||||
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
srvd.Buffer.FirstElement = 0;
|
||||
srvd.Buffer.NumElements = (unsigned int)src.size();
|
||||
|
||||
hr = device->CreateShaderResourceView(buffer, &srvd, &srv);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Error creating compute table shader resource view\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11Buffer * buffer;
|
||||
ID3D11ShaderResourceView * srv;
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class D3D11ComputeContext::D3D11StencilTables {
|
||||
|
||||
public:
|
||||
|
||||
D3D11StencilTables(Far::StencilTables const & stencilTables,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
_numStencils = stencilTables.GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
// convert unsigned char sizes buffer to ints
|
||||
// (HLSL does not have uint8 type)
|
||||
std::vector<int> const sizes(stencilTables.GetSizes().begin(),
|
||||
stencilTables.GetSizes().end());
|
||||
|
||||
_sizes.initialize(sizes,
|
||||
DXGI_FORMAT_R32_SINT,
|
||||
deviceContext);
|
||||
_offsets.initialize(stencilTables.GetOffsets(),
|
||||
DXGI_FORMAT_R32_SINT,
|
||||
deviceContext);
|
||||
_indices.initialize(stencilTables.GetControlIndices(),
|
||||
DXGI_FORMAT_R32_SINT,
|
||||
deviceContext);
|
||||
_weights.initialize(stencilTables.GetWeights(),
|
||||
DXGI_FORMAT_R32_FLOAT,
|
||||
deviceContext);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return _sizes.IsValid() and _offsets.IsValid() and
|
||||
_indices.IsValid() and _weights.IsValid();
|
||||
}
|
||||
|
||||
D3D11Table const & GetSizes() const {
|
||||
return _sizes;
|
||||
}
|
||||
|
||||
D3D11Table const & GetOffsets() const {
|
||||
return _offsets;
|
||||
}
|
||||
|
||||
D3D11Table const & GetIndices() const {
|
||||
return _indices;
|
||||
}
|
||||
|
||||
D3D11Table const & GetWeights() const {
|
||||
return _weights;
|
||||
}
|
||||
|
||||
int GetNumStencils() const {
|
||||
return _numStencils;
|
||||
}
|
||||
|
||||
void Bind(ID3D11DeviceContext * deviceContext) const {
|
||||
ID3D11ShaderResourceView *SRViews[] = {
|
||||
_sizes.srv,
|
||||
_offsets.srv,
|
||||
_indices.srv,
|
||||
_weights.srv
|
||||
};
|
||||
deviceContext->CSSetShaderResources(1, 4, SRViews); // t1-t4
|
||||
}
|
||||
|
||||
static void Unbind(ID3D11DeviceContext * deviceContext) {
|
||||
ID3D11ShaderResourceView *SRViews[] = { 0, 0, 0, 0 };
|
||||
deviceContext->CSSetShaderResources(1, 4, SRViews);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
D3D11Table _sizes,
|
||||
_offsets,
|
||||
_indices,
|
||||
_weights;
|
||||
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
D3D11ComputeContext::D3D11ComputeContext(
|
||||
Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
ID3D11DeviceContext *deviceContext) :
|
||||
_vertexStencilTables(0), _varyingStencilTables(0),
|
||||
_numControlVertices(0) {
|
||||
|
||||
if (vertexStencilTables) {
|
||||
_vertexStencilTables =
|
||||
new D3D11StencilTables(*vertexStencilTables, deviceContext);
|
||||
_numControlVertices = vertexStencilTables->GetNumControlVertices();
|
||||
}
|
||||
|
||||
if (varyingStencilTables) {
|
||||
_varyingStencilTables =
|
||||
new D3D11StencilTables(*varyingStencilTables, deviceContext);
|
||||
|
||||
if (_numControlVertices) {
|
||||
assert(_numControlVertices==varyingStencilTables->GetNumControlVertices());
|
||||
} else {
|
||||
_numControlVertices = varyingStencilTables->GetNumControlVertices();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3D11ComputeContext::~D3D11ComputeContext() {
|
||||
delete _vertexStencilTables;
|
||||
delete _varyingStencilTables;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
D3D11ComputeContext::HasVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
D3D11ComputeContext::HasVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->IsValid() : false;
|
||||
}
|
||||
|
||||
int
|
||||
D3D11ComputeContext::GetNumStencilsInVertexStencilTables() const {
|
||||
return _vertexStencilTables ? _vertexStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
int
|
||||
D3D11ComputeContext::GetNumStencilsInVaryingStencilTables() const {
|
||||
return _varyingStencilTables ? _varyingStencilTables->GetNumStencils() : 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
D3D11ComputeContext::BindVertexStencilTables(ID3D11DeviceContext *deviceContext) const {
|
||||
if (_vertexStencilTables) {
|
||||
_vertexStencilTables->Bind(deviceContext);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
D3D11ComputeContext::BindVaryingStencilTables(ID3D11DeviceContext *deviceContext) const {
|
||||
if (_varyingStencilTables) {
|
||||
_varyingStencilTables->Bind(deviceContext);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
D3D11ComputeContext::UnbindStencilTables(ID3D11DeviceContext *deviceContext) const {
|
||||
D3D11StencilTables::Unbind(deviceContext);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
D3D11ComputeContext *
|
||||
D3D11ComputeContext::Create(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
D3D11ComputeContext *result =
|
||||
new D3D11ComputeContext(vertexStencilTables, varyingStencilTables,
|
||||
deviceContext);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,128 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_D3D11_COMPUTE_CONTEXT_H
|
||||
#define OSD_D3D11_COMPUTE_CONTEXT_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/nonCopyable.h"
|
||||
|
||||
struct ID3D11DeviceContext;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far{ class StencilTables; }
|
||||
|
||||
namespace Osd {
|
||||
|
||||
///
|
||||
/// \brief D3D Refine Context
|
||||
///
|
||||
/// The D3D implementation of the Refine module contextual functionality.
|
||||
///
|
||||
/// Contexts interface the serialized topological data pertaining to the
|
||||
/// geometric primitives with the capabilities of the selected discrete
|
||||
/// compute device.
|
||||
///
|
||||
class D3D11ComputeContext : public NonCopyable<D3D11ComputeContext> {
|
||||
public:
|
||||
|
||||
/// Creates an D3D11ComputeContext instance
|
||||
///
|
||||
/// @param vertexStencilTables The Far::StencilTables used for vertex
|
||||
/// interpolation
|
||||
///
|
||||
/// @param varyingStencilTables The Far::StencilTables used for varying
|
||||
/// interpolation
|
||||
///
|
||||
/// @param deviceContext The D3D device
|
||||
///
|
||||
static D3D11ComputeContext * Create(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Destructor
|
||||
virtual ~D3D11ComputeContext();
|
||||
|
||||
/// Returns true if the Context has a 'vertex' interpolation stencil table
|
||||
bool HasVertexStencilTables() const;
|
||||
|
||||
/// Returns true if the Context has a 'varying' interpolation stencil table
|
||||
bool HasVaryingStencilTables() const;
|
||||
|
||||
/// Returns the number of control vertices
|
||||
int GetNumControlVertices() const {
|
||||
return _numControlVertices;
|
||||
}
|
||||
|
||||
/// Returns the number of stencils in vertex stencil table
|
||||
int GetNumStencilsInVertexStencilTables() const;
|
||||
|
||||
/// Returns the number of stencils in varying stencil table
|
||||
int GetNumStencilsInVaryingStencilTables() const;
|
||||
|
||||
/// Binds D3D11 buffers containing stencils for 'vertex' interpolation
|
||||
///
|
||||
/// @param deviceContext The D3D device
|
||||
///
|
||||
void BindVertexStencilTables(ID3D11DeviceContext *deviceContext) const;
|
||||
|
||||
/// Binds D3D11 buffers containing stencils for 'varying' interpolation
|
||||
///
|
||||
/// @param deviceContext The D3D device
|
||||
///
|
||||
void BindVaryingStencilTables(ID3D11DeviceContext *deviceContext) const;
|
||||
|
||||
/// Unbinds D3D11 stencil buffers
|
||||
///
|
||||
/// @param deviceContext The D3D device
|
||||
///
|
||||
void UnbindStencilTables(ID3D11DeviceContext *deviceContext) const;
|
||||
|
||||
protected:
|
||||
|
||||
explicit D3D11ComputeContext(Far::StencilTables const * vertexStencilTables,
|
||||
Far::StencilTables const * varyingStencilTables,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
private:
|
||||
|
||||
class D3D11StencilTables;
|
||||
|
||||
D3D11StencilTables * _vertexStencilTables,
|
||||
* _varyingStencilTables;
|
||||
|
||||
int _numControlVertices;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_D3D11_COMPUTE_CONTEXT_H
|
@ -1,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
|
@ -1,213 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OSD_D3D11_COMPUTE_CONTROLLER_H
|
||||
#define OSD_D3D11_COMPUTE_CONTROLLER_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/d3d11ComputeContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct ID3D11DeviceContext;
|
||||
struct ID3D11Query;
|
||||
struct ID3D11UnorderedAccessView;
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Compute controller for launching D3D11 Compute subdivision kernels.
|
||||
///
|
||||
/// D3D11ComputeController is a compute controller class to launch
|
||||
/// D3D11Compute transfrom feedback subdivision kernels. It requires
|
||||
/// GLVertexBufferInterface as arguments of Refine function.
|
||||
///
|
||||
/// Controller entities execute requests from Context instances that they share
|
||||
/// common interfaces with. Controllers are attached to discrete compute devices
|
||||
/// and share the devices resources with Context entities.
|
||||
///
|
||||
class D3D11ComputeController {
|
||||
public:
|
||||
typedef D3D11ComputeContext ComputeContext;
|
||||
|
||||
/// Constructor.
|
||||
///
|
||||
/// @param deviceContext a valid instanciated D3D11 device context
|
||||
///
|
||||
D3D11ComputeController(ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Destructor.
|
||||
~D3D11ComputeController();
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The D3D11Context to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param vertexDesc The descriptor of vertex elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
/// @param varyingBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
/// @param varyingDesc The descriptor of varying elements to be refined.
|
||||
/// if it's null, all primvars in the vertex buffer
|
||||
/// will be refined.
|
||||
///
|
||||
template<class VERTEX_BUFFER, class VARYING_BUFFER>
|
||||
void Compute( D3D11ComputeContext const * context,
|
||||
VERTEX_BUFFER * vertexBuffer,
|
||||
VARYING_BUFFER * varyingBuffer,
|
||||
VertexBufferDescriptor const * vertexDesc=NULL,
|
||||
VertexBufferDescriptor const * varyingDesc=NULL ){
|
||||
|
||||
if (vertexBuffer) {
|
||||
bind(vertexBuffer, vertexDesc);
|
||||
|
||||
context->BindVertexStencilTables(_deviceContext);
|
||||
|
||||
ApplyStencilTableKernel(
|
||||
context, context->GetNumStencilsInVertexStencilTables());
|
||||
}
|
||||
|
||||
if (varyingBuffer) {
|
||||
bind(varyingBuffer, varyingDesc);
|
||||
|
||||
context->BindVaryingStencilTables(_deviceContext);
|
||||
|
||||
ApplyStencilTableKernel(
|
||||
context, context->GetNumStencilsInVaryingStencilTables());
|
||||
}
|
||||
|
||||
context->UnbindStencilTables(_deviceContext);
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
/// Execute subdivision kernels and apply to given vertex buffers.
|
||||
///
|
||||
/// @param context The D3D11Context to apply refinement operations to
|
||||
///
|
||||
/// @param vertexBuffer Vertex-interpolated data buffer
|
||||
///
|
||||
template<class VERTEX_BUFFER>
|
||||
void Compute(D3D11ComputeContext const * context,
|
||||
VERTEX_BUFFER *vertexBuffer) {
|
||||
|
||||
Compute<VERTEX_BUFFER>(context, vertexBuffer, (VERTEX_BUFFER*)0);
|
||||
}
|
||||
|
||||
/// Waits until all running subdivision kernels finish.
|
||||
void Synchronize();
|
||||
|
||||
protected:
|
||||
|
||||
void ApplyStencilTableKernel(ComputeContext const *context,
|
||||
int numStencils) const;
|
||||
|
||||
template<class BUFFER>
|
||||
void bind( BUFFER * buffer,
|
||||
VertexBufferDescriptor const * desc ) {
|
||||
|
||||
assert(buffer);
|
||||
|
||||
// if the vertex buffer descriptor is specified, use it
|
||||
// otherwise, assumes the data is tightly packed in the vertex buffer.
|
||||
if (desc) {
|
||||
_currentBindState.desc = *desc;
|
||||
} else {
|
||||
int numElements = buffer ? buffer->GetNumElements() : 0;
|
||||
_currentBindState.desc =
|
||||
VertexBufferDescriptor(0, numElements, numElements);
|
||||
}
|
||||
|
||||
_currentBindState.buffer = buffer->BindD3D11UAV(_deviceContext);
|
||||
|
||||
_currentBindState.kernelBundle = getKernel(_currentBindState.desc);
|
||||
|
||||
bindBuffer();
|
||||
}
|
||||
|
||||
|
||||
// Unbinds any previously bound vertex and varying data buffers.
|
||||
void unbind() {
|
||||
_currentBindState.Reset();
|
||||
unbindBuffer();
|
||||
}
|
||||
|
||||
// binds the primvar data buffer
|
||||
void bindBuffer();
|
||||
|
||||
// unbinds the primvar data buffer
|
||||
void unbindBuffer();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
ID3D11DeviceContext *_deviceContext;
|
||||
ID3D11Query *_query;
|
||||
|
||||
class KernelBundle;
|
||||
|
||||
// Bind state is a transitional state during refinement.
|
||||
// It doesn't take an ownership of the vertex buffers.
|
||||
struct BindState {
|
||||
|
||||
BindState() : buffer(0), kernelBundle(0) { }
|
||||
|
||||
void Reset() {
|
||||
buffer = 0;
|
||||
desc.Reset();
|
||||
kernelBundle = 0;
|
||||
}
|
||||
|
||||
ID3D11UnorderedAccessView * buffer;
|
||||
|
||||
VertexBufferDescriptor desc;
|
||||
|
||||
KernelBundle const * kernelBundle;
|
||||
};
|
||||
|
||||
BindState _currentBindState;
|
||||
|
||||
typedef std::vector<KernelBundle *> KernelRegistry;
|
||||
|
||||
KernelBundle const * getKernel(VertexBufferDescriptor const &desc);
|
||||
|
||||
KernelRegistry _kernelRegistry;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
#endif // OSD_D3D11_COMPUTE_CONTROLLER_H
|
375
opensubdiv/osd/d3d11ComputeEvaluator.cpp
Normal file
375
opensubdiv/osd/d3d11ComputeEvaluator.cpp
Normal file
@ -0,0 +1,375 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/d3d11ComputeEvaluator.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define INITGUID // for IID_ID3D11ShaderReflection
|
||||
#include <D3D11.h>
|
||||
#include <D3D11shader.h>
|
||||
#include <D3Dcompiler.h>
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
||||
|
||||
static const char *shaderSource =
|
||||
#include "../osd/hlslComputeKernel.gen.h"
|
||||
;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// must match constant buffer declaration in hlslComputeKernel.hlsl
|
||||
__declspec(align(16))
|
||||
|
||||
struct KernelUniformArgs {
|
||||
|
||||
int start; // batch
|
||||
int end;
|
||||
|
||||
int srcOffset;
|
||||
int dstOffset;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
static ID3D11Buffer *createBuffer(std::vector<T> const &src,
|
||||
ID3D11Device *device) {
|
||||
|
||||
size_t size = src.size()*sizeof(T);
|
||||
|
||||
ID3D11Buffer *buffer = NULL;
|
||||
D3D11_BUFFER_DESC bd;
|
||||
bd.ByteWidth = (unsigned int)size;
|
||||
bd.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
bd.CPUAccessFlags = 0;
|
||||
bd.MiscFlags = 0;
|
||||
bd.StructureByteStride = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
initData.pSysMem = &src.at(0);
|
||||
|
||||
HRESULT hr = device->CreateBuffer(&bd, &initData, &buffer);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Error creating compute table buffer\n");
|
||||
return NULL;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static ID3D11ShaderResourceView *createSRV(ID3D11Buffer *buffer,
|
||||
DXGI_FORMAT format,
|
||||
ID3D11Device *device,
|
||||
size_t size) {
|
||||
ID3D11ShaderResourceView *srv = NULL;
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
|
||||
ZeroMemory(&srvd, sizeof(srvd));
|
||||
srvd.Format = format;
|
||||
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
srvd.Buffer.FirstElement = 0;
|
||||
srvd.Buffer.NumElements = (unsigned int)size;
|
||||
|
||||
HRESULT hr = device->CreateShaderResourceView(buffer, &srvd, &srv);
|
||||
if (FAILED(hr)) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Error creating compute table shader resource view\n");
|
||||
return NULL;
|
||||
}
|
||||
return srv;
|
||||
}
|
||||
|
||||
D3D11StencilTables::D3D11StencilTables(Far::StencilTables const *stencilTables,
|
||||
ID3D11DeviceContext *deviceContext)
|
||||
{
|
||||
ID3D11Device *device = NULL;
|
||||
deviceContext->GetDevice(&device);
|
||||
assert(device);
|
||||
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
// convert unsigned char sizes buffer to ints
|
||||
// (HLSL does not have uint8 type)
|
||||
std::vector<int> const sizes(stencilTables->GetSizes().begin(),
|
||||
stencilTables->GetSizes().end());
|
||||
|
||||
_sizesBuffer = createBuffer(sizes, device);
|
||||
_offsetsBuffer = createBuffer(stencilTables->GetOffsets(), device);
|
||||
_indicesBuffer = createBuffer(stencilTables->GetControlIndices(), device);
|
||||
_weightsBuffer = createBuffer(stencilTables->GetWeights(), device);
|
||||
|
||||
_sizes = createSRV(_sizesBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTables->GetSizes().size());
|
||||
_offsets = createSRV(_offsetsBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTables->GetOffsets().size());
|
||||
_indices = createSRV(_indicesBuffer, DXGI_FORMAT_R32_SINT, device,
|
||||
stencilTables->GetControlIndices().size());
|
||||
_weights= createSRV(_weightsBuffer, DXGI_FORMAT_R32_FLOAT, device,
|
||||
stencilTables->GetWeights().size());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = NULL;
|
||||
_sizesBuffer = _offsetsBuffer = _indicesBuffer = _weightsBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11StencilTables::~D3D11StencilTables() {
|
||||
SAFE_RELEASE(_sizes);
|
||||
SAFE_RELEASE(_sizesBuffer);
|
||||
SAFE_RELEASE(_offsets);
|
||||
SAFE_RELEASE(_offsetsBuffer);
|
||||
SAFE_RELEASE(_indices);
|
||||
SAFE_RELEASE(_indicesBuffer);
|
||||
SAFE_RELEASE(_weights);
|
||||
SAFE_RELEASE(_weightsBuffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
D3D11ComputeEvaluator::D3D11ComputeEvaluator() :
|
||||
_computeShader(NULL),
|
||||
_classLinkage(NULL),
|
||||
_singleBufferKernel(NULL),
|
||||
_separateBufferKernel(NULL),
|
||||
_uniformArgs(NULL),
|
||||
_workGroupSize(64) {
|
||||
|
||||
}
|
||||
|
||||
D3D11ComputeEvaluator *
|
||||
D3D11ComputeEvaluator::Create(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
(void)deviceContext; // not used
|
||||
D3D11ComputeEvaluator *instance = new D3D11ComputeEvaluator();
|
||||
if (instance->Compile(srcDesc, dstDesc, deviceContext)) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
D3D11ComputeEvaluator::~D3D11ComputeEvaluator() {
|
||||
SAFE_RELEASE(_computeShader);
|
||||
SAFE_RELEASE(_classLinkage);
|
||||
SAFE_RELEASE(_singleBufferKernel);
|
||||
SAFE_RELEASE(_separateBufferKernel);
|
||||
SAFE_RELEASE(_uniformArgs);
|
||||
}
|
||||
|
||||
bool
|
||||
D3D11ComputeEvaluator::Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
|
||||
if (srcDesc.length > dstDesc.length) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"srcDesc length must be less than or equal to "
|
||||
"dstDesc length.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS
|
||||
| D3D10_SHADER_RESOURCES_MAY_ALIAS;
|
||||
#ifdef _DEBUG
|
||||
dwShaderFlags |= D3DCOMPILE_DEBUG;
|
||||
#endif
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << srcDesc.length; std::string lengthValue(ss.str()); ss.str("");
|
||||
ss << srcDesc.stride; std::string srcStrideValue(ss.str()); ss.str("");
|
||||
ss << dstDesc.stride; std::string dstStrideValue(ss.str()); ss.str("");
|
||||
ss << _workGroupSize; std::string workgroupSizeValue(ss.str()); ss.str("");
|
||||
|
||||
D3D_SHADER_MACRO defines[] =
|
||||
{ "LENGTH", lengthValue.c_str(),
|
||||
"SRC_STRIDE", srcStrideValue.c_str(),
|
||||
"DST_STRIDE", dstStrideValue.c_str(),
|
||||
"WORK_GROUP_SIZE", workgroupSizeValue.c_str(),
|
||||
0, 0 };
|
||||
|
||||
ID3DBlob * computeShaderBuffer = NULL;
|
||||
ID3DBlob * errorBuffer = NULL;
|
||||
|
||||
HRESULT hr = D3DCompile(shaderSource, strlen(shaderSource),
|
||||
NULL, &defines[0], NULL,
|
||||
"cs_main", "cs_5_0",
|
||||
dwShaderFlags, 0,
|
||||
&computeShaderBuffer, &errorBuffer);
|
||||
if (FAILED(hr)) {
|
||||
if (errorBuffer != NULL) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"Error compiling HLSL shader: %s\n",
|
||||
(CHAR*)errorBuffer->GetBufferPointer());
|
||||
errorBuffer->Release();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11Device *device = NULL;
|
||||
deviceContext->GetDevice(&device);
|
||||
assert(device);
|
||||
|
||||
device->CreateClassLinkage(&_classLinkage);
|
||||
assert(_classLinkage);
|
||||
|
||||
device->CreateComputeShader(computeShaderBuffer->GetBufferPointer(),
|
||||
computeShaderBuffer->GetBufferSize(),
|
||||
_classLinkage,
|
||||
&_computeShader);
|
||||
assert(_computeShader);
|
||||
|
||||
ID3D11ShaderReflection *reflector;
|
||||
D3DReflect(computeShaderBuffer->GetBufferPointer(),
|
||||
computeShaderBuffer->GetBufferSize(),
|
||||
IID_ID3D11ShaderReflection, (void**) &reflector);
|
||||
assert(reflector);
|
||||
|
||||
assert(reflector->GetNumInterfaceSlots() == 1);
|
||||
reflector->Release();
|
||||
|
||||
computeShaderBuffer->Release();
|
||||
|
||||
_classLinkage->GetClassInstance("singleBufferCompute", 0, &_singleBufferKernel);
|
||||
assert(_singleBufferKernel);
|
||||
_classLinkage->GetClassInstance("separateBufferCompute", 0, &_separateBufferKernel);
|
||||
assert(_separateBufferKernel);
|
||||
|
||||
D3D11_BUFFER_DESC cbDesc;
|
||||
ZeroMemory(&cbDesc, sizeof(cbDesc));
|
||||
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
cbDesc.MiscFlags = 0;
|
||||
cbDesc.ByteWidth = sizeof(KernelUniformArgs);
|
||||
device->CreateBuffer(&cbDesc, NULL, &_uniformArgs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
D3D11ComputeEvaluator::Synchronize(ID3D11DeviceContext *deviceContext) {
|
||||
// XXX: this is currently just for the performance measuring purpose.
|
||||
|
||||
// XXXFIXME!
|
||||
ID3D11Query *query = NULL;
|
||||
|
||||
ID3D11Device *device = NULL;
|
||||
deviceContext->GetDevice(&device);
|
||||
assert(device);
|
||||
|
||||
D3D11_QUERY_DESC desc;
|
||||
desc.Query = D3D11_QUERY_EVENT;
|
||||
desc.MiscFlags = 0;
|
||||
device->CreateQuery(&desc, &query);
|
||||
|
||||
deviceContext->Flush();
|
||||
deviceContext->End(query);
|
||||
while (S_OK != deviceContext->GetData(query, NULL, 0, 0));
|
||||
|
||||
SAFE_RELEASE(query);
|
||||
}
|
||||
|
||||
bool
|
||||
D3D11ComputeEvaluator::EvalStencils(ID3D11UnorderedAccessView *srcUAV,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
ID3D11UnorderedAccessView *dstUAV,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
ID3D11ShaderResourceView *sizesSRV,
|
||||
ID3D11ShaderResourceView *offsetsSRV,
|
||||
ID3D11ShaderResourceView *indicesSRV,
|
||||
ID3D11ShaderResourceView *weightsSRV,
|
||||
int start,
|
||||
int end,
|
||||
ID3D11DeviceContext *deviceContext) const {
|
||||
assert(deviceContext);
|
||||
|
||||
int count = end - start;
|
||||
if (count <= 0) return true;
|
||||
|
||||
KernelUniformArgs args;
|
||||
args.start = start;
|
||||
args.end = end;
|
||||
args.srcOffset = srcDesc.offset;
|
||||
args.dstOffset = dstDesc.offset;
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
deviceContext->Map(_uniformArgs, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
CopyMemory(mappedResource.pData, &args, sizeof(KernelUniformArgs));
|
||||
|
||||
deviceContext->Unmap(_uniformArgs, 0);
|
||||
deviceContext->CSSetConstantBuffers(0, 1, &_uniformArgs); // b0
|
||||
|
||||
// Unbind the vertexBuffer from the input assembler
|
||||
ID3D11Buffer *NULLBuffer = 0;
|
||||
UINT voffset = 0, vstride = 0;
|
||||
deviceContext->IASetVertexBuffers(0, 1, &NULLBuffer, &voffset, &vstride);
|
||||
ID3D11ShaderResourceView *NULLSRV = 0;
|
||||
deviceContext->VSSetShaderResources(0, 1, &NULLSRV);
|
||||
|
||||
// bind UAV
|
||||
ID3D11UnorderedAccessView *UAViews[] = { srcUAV, dstUAV };
|
||||
ID3D11ShaderResourceView *SRViews[] = {
|
||||
sizesSRV, offsetsSRV, indicesSRV, weightsSRV };
|
||||
|
||||
// bind source vertex and stencil tables
|
||||
deviceContext->CSSetShaderResources(1, 4, SRViews); // t1-t4
|
||||
|
||||
if (srcUAV == dstUAV) {
|
||||
deviceContext->CSSetUnorderedAccessViews(0, 1, UAViews, 0); // u0
|
||||
// Dispatch src == dst buffer
|
||||
deviceContext->CSSetShader(_computeShader, &_singleBufferKernel, 1);
|
||||
deviceContext->Dispatch((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
} else {
|
||||
deviceContext->CSSetUnorderedAccessViews(0, 2, UAViews, 0); // u0, u1
|
||||
// Dispatch src != dst buffer
|
||||
deviceContext->CSSetShader(_computeShader, &_separateBufferKernel, 1);
|
||||
deviceContext->Dispatch((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
}
|
||||
|
||||
// unbind stencil tables and vertexbuffers
|
||||
SRViews[0] = SRViews[1] = SRViews[2] = SRViews[3] = NULL;
|
||||
deviceContext->CSSetShaderResources(1, 4, SRViews);
|
||||
|
||||
UAViews[0] = UAViews[1] = NULL;
|
||||
deviceContext->CSSetUnorderedAccessViews(0, 2, UAViews, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
227
opensubdiv/osd/d3d11ComputeEvaluator.h
Normal file
227
opensubdiv/osd/d3d11ComputeEvaluator.h
Normal file
@ -0,0 +1,227 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_D3D11_COMPUTE_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_D3D11_COMPUTE_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
struct ID3D11DeviceContext;
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11ComputeShader;
|
||||
struct ID3D11ClassLinkage;
|
||||
struct ID3D11ClassInstance;
|
||||
struct ID3D11ShaderResourceView;
|
||||
struct ID3D11UnorderedAccessView;
|
||||
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief D3D11 stencil tables
|
||||
///
|
||||
/// This class is a D3D11 Shader Resource View representation of
|
||||
/// Far::StencilTables.
|
||||
///
|
||||
/// D3D11ComputeEvaluator consumes this table to apply stencils
|
||||
///
|
||||
class D3D11StencilTables {
|
||||
public:
|
||||
template <typename DEVICE_CONTEXT>
|
||||
static D3D11StencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
DEVICE_CONTEXT context) {
|
||||
return new D3D11StencilTables(stencilTables, context->GetDeviceContext());
|
||||
}
|
||||
|
||||
static D3D11StencilTables *Create(Far::StencilTables const *stencilTables,
|
||||
ID3D11DeviceContext *deviceContext) {
|
||||
return new D3D11StencilTables(stencilTables, deviceContext);
|
||||
}
|
||||
|
||||
D3D11StencilTables(Far::StencilTables const *stencilTables,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
~D3D11StencilTables();
|
||||
|
||||
// interfaces needed for D3D11ComputeEvaluator
|
||||
ID3D11ShaderResourceView *GetSizesSRV() const { return _sizes; }
|
||||
ID3D11ShaderResourceView *GetOffsetsSRV() const { return _offsets; }
|
||||
ID3D11ShaderResourceView *GetIndicesSRV() const { return _indices; }
|
||||
ID3D11ShaderResourceView *GetWeightsSRV() const { return _weights; }
|
||||
int GetNumStencils() const { return _numStencils; }
|
||||
|
||||
private:
|
||||
ID3D11ShaderResourceView *_sizes;
|
||||
ID3D11ShaderResourceView *_offsets;
|
||||
ID3D11ShaderResourceView *_indices;
|
||||
ID3D11ShaderResourceView *_weights;
|
||||
ID3D11Buffer *_sizesBuffer;
|
||||
ID3D11Buffer *_offsetsBuffer;
|
||||
ID3D11Buffer *_indicesBuffer;
|
||||
ID3D11Buffer *_weightsBuffer;
|
||||
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class D3D11ComputeEvaluator {
|
||||
public:
|
||||
typedef bool Instantiatable;
|
||||
static D3D11ComputeEvaluator * Create(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Constructor.
|
||||
D3D11ComputeEvaluator();
|
||||
|
||||
/// Destructor.
|
||||
~D3D11ComputeEvaluator();
|
||||
|
||||
/// \brief Generic static compute function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently from OsdMesh template interface.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBO() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTables stencil table to be applied. The table must have
|
||||
/// SSBO interfaces.
|
||||
///
|
||||
/// @param instance cached compiled instance. Clients are supposed to
|
||||
/// pre-compile an instance of this class and provide
|
||||
/// to this function. If it's null the kernel still
|
||||
/// compute by instantiating on-demand kernel although
|
||||
/// it may cause a performance problem.
|
||||
///
|
||||
/// @param deviceContext ID3D11DeviceContext.
|
||||
///
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
D3D11ComputeEvaluator const *instance,
|
||||
ID3D11DeviceContext * deviceContext) {
|
||||
if (instance) {
|
||||
return instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable,
|
||||
deviceContext);
|
||||
} else {
|
||||
// Create an instace on demand (slow)
|
||||
(void)deviceContext; // unused
|
||||
instance = Create(srcDesc, dstDesc, deviceContext);
|
||||
if (instance) {
|
||||
bool r = instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable,
|
||||
deviceContext);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatch the DX compute kernel on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
ID3D11DeviceContext *deviceContext) const {
|
||||
return EvalStencils(srcVertexBuffer->BindD3D11UAV(deviceContext),
|
||||
srcDesc,
|
||||
dstVertexBuffer->BindD3D11UAV(deviceContext),
|
||||
dstDesc,
|
||||
stencilTable->GetSizesSRV(),
|
||||
stencilTable->GetOffsetsSRV(),
|
||||
stencilTable->GetIndicesSRV(),
|
||||
stencilTable->GetWeightsSRV(),
|
||||
/* start = */ 0,
|
||||
/* end = */ stencilTable->GetNumStencils(),
|
||||
deviceContext);
|
||||
}
|
||||
|
||||
/// Dispatch the DX compute kernel on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
bool EvalStencils(ID3D11UnorderedAccessView *srcSRV,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
ID3D11UnorderedAccessView *dstUAV,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
ID3D11ShaderResourceView *sizesSRV,
|
||||
ID3D11ShaderResourceView *offsetsSRV,
|
||||
ID3D11ShaderResourceView *indicesSRV,
|
||||
ID3D11ShaderResourceView *weightsSRV,
|
||||
int start,
|
||||
int end,
|
||||
ID3D11DeviceContext *deviceContext) const;
|
||||
|
||||
/// Configure DX kernel. Returns false if it fails to compile the kernel.
|
||||
bool Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
ID3D11DeviceContext *deviceContext);
|
||||
|
||||
/// Wait the dispatched kernel finishes.
|
||||
static void Synchronize(ID3D11DeviceContext *deviceContext);
|
||||
|
||||
private:
|
||||
ID3D11ComputeShader * _computeShader;
|
||||
ID3D11ClassLinkage * _classLinkage;
|
||||
ID3D11ClassInstance * _singleBufferKernel;
|
||||
ID3D11ClassInstance * _separateBufferKernel;
|
||||
ID3D11Buffer * _uniformArgs; // uniform paramaeters for kernels
|
||||
|
||||
int _workGroupSize;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_D3D11_COMPUTE_EVALUATOR_H
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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
|
@ -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
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -1,44 +0,0 @@
|
||||
//
|
||||
// Copyright 2013 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/evalLimitContext.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
EvalLimitContext::EvalLimitContext(Far::PatchTables const & patchTables) {
|
||||
|
||||
_adaptive = patchTables.IsFeatureAdaptive();
|
||||
}
|
||||
|
||||
EvalLimitContext::~EvalLimitContext() {
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
@ -1,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 */
|
224
opensubdiv/osd/glComputeEvaluator.cpp
Normal file
224
opensubdiv/osd/glComputeEvaluator.cpp
Normal file
@ -0,0 +1,224 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#include "../osd/glComputeEvaluator.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../far/error.h"
|
||||
#include "../far/stencilTables.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
static const char *shaderSource =
|
||||
#include "../osd/glslComputeKernel.gen.h"
|
||||
;
|
||||
|
||||
template <class T> GLuint
|
||||
createSSBO(std::vector<T> const & src) {
|
||||
GLuint devicePtr = 0;
|
||||
glGenBuffers(1, &devicePtr);
|
||||
|
||||
#if defined(GL_EXT_direct_state_access)
|
||||
if (glNamedBufferDataEXT) {
|
||||
glNamedBufferDataEXT(devicePtr, src.size()*sizeof(T),
|
||||
&src.at(0), GL_STATIC_DRAW);
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
GLint prev = 0;
|
||||
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &prev);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, devicePtr);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, src.size()*sizeof(T),
|
||||
&src.at(0), GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, prev);
|
||||
}
|
||||
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
GLStencilTablesSSBO::GLStencilTablesSSBO(
|
||||
Far::StencilTables const *stencilTables) {
|
||||
_numStencils = stencilTables->GetNumStencils();
|
||||
if (_numStencils > 0) {
|
||||
_sizes = createSSBO(stencilTables->GetSizes());
|
||||
_offsets = createSSBO(stencilTables->GetOffsets());
|
||||
_indices = createSSBO(stencilTables->GetControlIndices());
|
||||
_weights = createSSBO(stencilTables->GetWeights());
|
||||
} else {
|
||||
_sizes = _offsets = _indices = _weights = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLStencilTablesSSBO::~GLStencilTablesSSBO() {
|
||||
if (_sizes) glDeleteBuffers(1, &_sizes);
|
||||
if (_offsets) glDeleteBuffers(1, &_offsets);
|
||||
if (_weights) glDeleteBuffers(1, &_weights);
|
||||
if (_indices) glDeleteBuffers(1, &_indices);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
GLComputeEvaluator::GLComputeEvaluator() :
|
||||
_program(0), _workGroupSize(64) {
|
||||
}
|
||||
|
||||
GLComputeEvaluator::~GLComputeEvaluator() {
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GLComputeEvaluator::Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc) {
|
||||
if (srcDesc.length > dstDesc.length) {
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR,
|
||||
"srcDesc length must be less than or equal to "
|
||||
"dstDesc length.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_program) {
|
||||
glDeleteProgram(_program);
|
||||
_program = 0;
|
||||
}
|
||||
_program = glCreateProgram();
|
||||
|
||||
GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
|
||||
|
||||
std::ostringstream defines;
|
||||
defines << "#define LENGTH " << srcDesc.length << "\n"
|
||||
<< "#define SRC_STRIDE " << srcDesc.stride << "\n"
|
||||
<< "#define DST_STRIDE " << dstDesc.stride << "\n"
|
||||
<< "#define WORK_GROUP_SIZE " << _workGroupSize << "\n";
|
||||
std::string defineStr = defines.str();
|
||||
|
||||
const char *shaderSources[3] = {"#version 430\n", 0, 0};
|
||||
shaderSources[1] = defineStr.c_str();
|
||||
shaderSources[2] = shaderSource;
|
||||
glShaderSource(shader, 3, shaderSources, NULL);
|
||||
glCompileShader(shader);
|
||||
glAttachShader(_program, shader);
|
||||
|
||||
GLint linked = 0;
|
||||
glLinkProgram(_program);
|
||||
glGetProgramiv(_program, GL_LINK_STATUS, &linked);
|
||||
|
||||
if (linked == GL_FALSE) {
|
||||
char buffer[1024];
|
||||
glGetShaderInfoLog(shader, 1024, NULL, buffer);
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, buffer);
|
||||
|
||||
glGetProgramInfoLog(_program, 1024, NULL, buffer);
|
||||
Far::Error(Far::FAR_RUNTIME_ERROR, buffer);
|
||||
|
||||
glDeleteProgram(_program);
|
||||
_program = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
// store uniform locations for the compute kernel program.
|
||||
_uniformSizes = glGetUniformLocation(_program, "stencilSizes");
|
||||
_uniformOffsets = glGetUniformLocation(_program, "stencilOffsets");
|
||||
_uniformIndices = glGetUniformLocation(_program, "stencilIndices");
|
||||
_uniformWeights = glGetUniformLocation(_program, "stencilIWeights");
|
||||
|
||||
_uniformStart = glGetUniformLocation(_program, "batchStart");
|
||||
_uniformEnd = glGetUniformLocation(_program, "batchEnd");
|
||||
|
||||
_uniformSrcOffset = glGetUniformLocation(_program, "srcOffset");
|
||||
_uniformDstOffset = glGetUniformLocation(_program, "dstOffset");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
GLComputeEvaluator::Synchronize(void * /*kernel*/) {
|
||||
// XXX: this is currently just for the performance measuring purpose.
|
||||
// need to be reimplemented by fence and sync.
|
||||
glFinish();
|
||||
}
|
||||
|
||||
bool
|
||||
GLComputeEvaluator::EvalStencils(GLuint srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
GLuint dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
GLuint sizesBuffer,
|
||||
GLuint offsetsBuffer,
|
||||
GLuint indicesBuffer,
|
||||
GLuint weightsBuffer,
|
||||
int start,
|
||||
int end) const {
|
||||
if (!_program) return false;
|
||||
int count = end - start;
|
||||
if (count <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, srcBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, dstBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, sizesBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, offsetsBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, indicesBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, weightsBuffer);
|
||||
|
||||
glUseProgram(_program);
|
||||
|
||||
glUniform1i(_uniformStart, start);
|
||||
glUniform1i(_uniformEnd, end);
|
||||
glUniform1i(_uniformSrcOffset, srcDesc.offset);
|
||||
glUniform1i(_uniformDstOffset, dstDesc.offset);
|
||||
|
||||
glDispatchCompute((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
||||
|
||||
glUseProgram(0);
|
||||
|
||||
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, 0);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
215
opensubdiv/osd/glComputeEvaluator.h
Normal file
215
opensubdiv/osd/glComputeEvaluator.h
Normal file
@ -0,0 +1,215 @@
|
||||
//
|
||||
// Copyright 2015 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
#ifndef OPENSUBDIV_OSD_GL_COMPUTE_EVALUATOR_H
|
||||
#define OPENSUBDIV_OSD_GL_COMPUTE_EVALUATOR_H
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
#include "../osd/opengl.h"
|
||||
#include "../osd/vertexDescriptor.h"
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Far {
|
||||
class StencilTables;
|
||||
}
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief GL stencil tables (Shader Storage buffer)
|
||||
///
|
||||
/// This class is a GLSL SSBO representation of Far::StencilTables.
|
||||
///
|
||||
/// GLSLComputeKernel consumes this table to apply stencils
|
||||
///
|
||||
class GLStencilTablesSSBO {
|
||||
public:
|
||||
static GLStencilTablesSSBO *Create(Far::StencilTables const *stencilTables,
|
||||
void *deviceContext = NULL) {
|
||||
(void)deviceContext; // unused
|
||||
return new GLStencilTablesSSBO(stencilTables);
|
||||
}
|
||||
|
||||
explicit GLStencilTablesSSBO(Far::StencilTables const *stencilTables);
|
||||
~GLStencilTablesSSBO();
|
||||
|
||||
// interfaces needed for GLSLComputeKernel
|
||||
GLuint GetSizesBuffer() const { return _sizes; }
|
||||
GLuint GetOffsetsBuffer() const { return _offsets; }
|
||||
GLuint GetIndicesBuffer() const { return _indices; }
|
||||
GLuint GetWeightsBuffer() const { return _weights; }
|
||||
int GetNumStencils() const { return _numStencils; }
|
||||
|
||||
private:
|
||||
GLuint _sizes;
|
||||
GLuint _offsets;
|
||||
GLuint _indices;
|
||||
GLuint _weights;
|
||||
int _numStencils;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class GLComputeEvaluator {
|
||||
public:
|
||||
typedef bool Instantiatable;
|
||||
static GLComputeEvaluator * Create(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
void * deviceContext = NULL) {
|
||||
(void)deviceContext; // not used
|
||||
GLComputeEvaluator *instance = new GLComputeEvaluator();
|
||||
if (instance->Compile(srcDesc, dstDesc)) return instance;
|
||||
delete instance;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
GLComputeEvaluator();
|
||||
|
||||
/// Destructor. note that the GL context must be made current.
|
||||
~GLComputeEvaluator();
|
||||
|
||||
/// \brief Generic static compute function. This function has a same
|
||||
/// signature as other device kernels have so that it can be called
|
||||
/// transparently from OsdMesh template interface.
|
||||
///
|
||||
/// @param srcBuffer Input primvar buffer.
|
||||
/// must have BindVBO() method returning a
|
||||
/// const float pointer for read
|
||||
///
|
||||
/// @param srcDesc vertex buffer descriptor for the input buffer
|
||||
///
|
||||
/// @param dstBuffer Output primvar buffer
|
||||
/// must have BindVBO() method returning a
|
||||
/// float pointer for write
|
||||
///
|
||||
/// @param dstDesc vertex buffer descriptor for the output buffer
|
||||
///
|
||||
/// @param stencilTable stencil table to be applied. The table must have
|
||||
/// SSBO interfaces.
|
||||
///
|
||||
/// @param evaluator cached compiled instance. Clients are supposed to
|
||||
/// pre-compile an instance of this class and provide
|
||||
/// to this function. If it's null the kernel still
|
||||
/// compute by instantiating on-demand kernel although
|
||||
/// it may cause a performance problem.
|
||||
///
|
||||
/// @param deviceContext not used in the GLSL kernel
|
||||
///
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
static bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable,
|
||||
GLComputeEvaluator const *instance,
|
||||
void * deviceContext = NULL) {
|
||||
if (instance) {
|
||||
return instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable);
|
||||
} else {
|
||||
// Create a kernel on demand (slow)
|
||||
(void)deviceContext; // unused
|
||||
instance = Create(srcDesc, dstDesc);
|
||||
if (instance) {
|
||||
bool r = instance->EvalStencils(srcVertexBuffer, srcDesc,
|
||||
dstVertexBuffer, dstDesc,
|
||||
stencilTable);
|
||||
delete instance;
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatch the GLSL compute kernel on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
template <typename VERTEX_BUFFER, typename STENCIL_TABLE>
|
||||
bool EvalStencils(VERTEX_BUFFER *srcVertexBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
VERTEX_BUFFER *dstVertexBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
STENCIL_TABLE const *stencilTable) const {
|
||||
return EvalStencils(srcVertexBuffer->BindVBO(),
|
||||
srcDesc,
|
||||
dstVertexBuffer->BindVBO(),
|
||||
dstDesc,
|
||||
stencilTable->GetSizesBuffer(),
|
||||
stencilTable->GetOffsetsBuffer(),
|
||||
stencilTable->GetIndicesBuffer(),
|
||||
stencilTable->GetWeightsBuffer(),
|
||||
/* start = */ 0,
|
||||
/* end = */ stencilTable->GetNumStencils());
|
||||
}
|
||||
|
||||
/// Dispatch the GLSL compute kernel on GPU asynchronously.
|
||||
/// returns false if the kernel hasn't been compiled yet.
|
||||
bool EvalStencils(GLuint srcBuffer,
|
||||
VertexBufferDescriptor const &srcDesc,
|
||||
GLuint dstBuffer,
|
||||
VertexBufferDescriptor const &dstDesc,
|
||||
GLuint sizesBuffer,
|
||||
GLuint offsetsBuffer,
|
||||
GLuint indicesBuffer,
|
||||
GLuint weightsBuffer,
|
||||
int start,
|
||||
int end) const;
|
||||
|
||||
/// Configure GLSL kernel. A valid GL context must be made current before
|
||||
/// calling this function. Returns false if it fails to compile the kernel.
|
||||
bool Compile(VertexBufferDescriptor const &srcDesc,
|
||||
VertexBufferDescriptor const &dstDesc);
|
||||
|
||||
/// Wait the dispatched kernel finishes.
|
||||
static void Synchronize(void *deviceContext);
|
||||
|
||||
private:
|
||||
GLuint _program;
|
||||
|
||||
GLuint _uniformSizes, // stencil tables
|
||||
_uniformOffsets,
|
||||
_uniformIndices,
|
||||
_uniformWeights,
|
||||
|
||||
_uniformStart, // range
|
||||
_uniformEnd,
|
||||
|
||||
_uniformSrcOffset, // src buffer offset (in elements)
|
||||
_uniformDstOffset; // dst buffer offset (in elements)
|
||||
|
||||
int _workGroupSize;
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
using namespace OPENSUBDIV_VERSION;
|
||||
|
||||
} // end namespace OpenSubdiv
|
||||
|
||||
|
||||
#endif // OPENSUBDIV_OSD_GL_COMPUTE_EVALUATOR_H
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user