Cycles: Add support for uchar4 attributes.

* Added support for uchar4 attributes to Cycles' attribute system.
* This is used for Vertex Colors now, which saves some memory (4 unsigned characters, instead of 4 floats).
* GPU Texture Limit on sm_20 and sm_21 decreased from 95 to 94, because we need a new texture for the uchar4 attributes. This is no problem for sm_30 or newer.

Part of my GSoC 2014.
This commit is contained in:
Thomas Dinges
2014-06-13 23:40:39 +02:00
parent 7e20583688
commit 0ce3a755f8
12 changed files with 91 additions and 33 deletions

View File

@@ -42,7 +42,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData);
void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam); void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam);
void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution); void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution);
void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata); void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata);
void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *fdata); void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata);
ParticleCurveData::ParticleCurveData() ParticleCurveData::ParticleCurveData()
{ {
@@ -726,9 +726,9 @@ void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset
} }
} }
void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *fdata) void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata)
{ {
if(fdata == NULL) if(cdata == NULL)
return; return;
int vertexindex = vert_offset; int vertexindex = vert_offset;
@@ -740,17 +740,17 @@ void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offs
for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) { for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
for(int section = 0; section < resol; section++) { for(int section = 0; section < resol; section++) {
fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++; vertexindex++;
fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++; vertexindex++;
fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++; vertexindex++;
fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++; vertexindex++;
fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++; vertexindex++;
fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve]));
vertexindex++; vertexindex++;
} }
} }
@@ -923,13 +923,12 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num); ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num);
if(primitive == CURVE_TRIANGLES) { if(primitive == CURVE_TRIANGLES) {
Attribute *attr_vcol = mesh->attributes.add( Attribute *attr_vcol = mesh->attributes.add(
ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER); ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
float3 *fdata = attr_vcol->data_float3(); uchar4 *cdata = attr_vcol->data_uchar4();
ExportCurveTriangleVcol(mesh, &CData, tri_num * 3, used_res, fdata); ExportCurveTriangleVcol(mesh, &CData, tri_num * 3, used_res, cdata);
} }
else { else {
Attribute *attr_vcol = mesh->curve_attributes.add( Attribute *attr_vcol = mesh->curve_attributes.add(

View File

@@ -347,25 +347,25 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
continue; continue;
Attribute *attr = mesh->attributes.add( Attribute *attr = mesh->attributes.add(
ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER); ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
BL::MeshColorLayer::data_iterator c; BL::MeshColorLayer::data_iterator c;
float3 *fdata = attr->data_float3(); uchar4 *cdata = attr->data_uchar4();
size_t i = 0; size_t i = 0;
for(l->data.begin(c); c != l->data.end(); ++c, ++i) { for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
fdata[0] = color_srgb_to_scene_linear(get_float3(c->color1())); cdata[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
fdata[1] = color_srgb_to_scene_linear(get_float3(c->color2())); cdata[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
fdata[2] = color_srgb_to_scene_linear(get_float3(c->color3())); cdata[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
if(nverts[i] == 4) { if(nverts[i] == 4) {
fdata[3] = fdata[0]; cdata[3] = cdata[0];
fdata[4] = fdata[2]; cdata[4] = cdata[2];
fdata[5] = color_srgb_to_scene_linear(get_float3(c->color4())); cdata[5] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
fdata += 6; cdata += 6;
} }
else else
fdata += 3; cdata += 3;
} }
} }
} }

View File

@@ -259,11 +259,20 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData
return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
} }
else if(elem == ATTR_ELEMENT_CORNER) { else if(elem == ATTR_ELEMENT_CORNER || elem == ATTR_ELEMENT_CORNER_BYTE) {
int tri = offset + sd->prim*3; int tri = offset + sd->prim*3;
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0)); float3 f0, f1, f2;
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2)); if(elem == ATTR_ELEMENT_CORNER) {
f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
}
else {
f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 0));
f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 1));
f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 2));
}
#ifdef __RAY_DIFFERENTIALS__ #ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;

View File

@@ -49,6 +49,7 @@ KERNEL_TEX(float4, texture_float4, __curve_keys)
KERNEL_TEX(uint4, texture_uint4, __attributes_map) KERNEL_TEX(uint4, texture_uint4, __attributes_map)
KERNEL_TEX(float, texture_float, __attributes_float) KERNEL_TEX(float, texture_float, __attributes_float)
KERNEL_TEX(float4, texture_float4, __attributes_float3) KERNEL_TEX(float4, texture_float4, __attributes_float3)
KERNEL_TEX(uchar4, texture_uchar4, __attributes_uchar4)
/* lights */ /* lights */
KERNEL_TEX(float4, texture_float4, __light_distribution) KERNEL_TEX(float4, texture_float4, __light_distribution)

View File

@@ -478,6 +478,7 @@ typedef enum AttributeElement {
ATTR_ELEMENT_VERTEX, ATTR_ELEMENT_VERTEX,
ATTR_ELEMENT_VERTEX_MOTION, ATTR_ELEMENT_VERTEX_MOTION,
ATTR_ELEMENT_CORNER, ATTR_ELEMENT_CORNER,
ATTR_ELEMENT_CORNER_BYTE,
ATTR_ELEMENT_CURVE, ATTR_ELEMENT_CURVE,
ATTR_ELEMENT_CURVE_KEY, ATTR_ELEMENT_CURVE_KEY,
ATTR_ELEMENT_CURVE_KEY_MOTION, ATTR_ELEMENT_CURVE_KEY_MOTION,

View File

@@ -252,9 +252,9 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
case 96: r = kernel_tex_image_interp(__tex_image_096, x, y); break; case 96: r = kernel_tex_image_interp(__tex_image_096, x, y); break;
case 97: r = kernel_tex_image_interp(__tex_image_097, x, y); break; case 97: r = kernel_tex_image_interp(__tex_image_097, x, y); break;
case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break; case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break;
case 99: r = kernel_tex_image_interp(__tex_image_099, x, y); break;
#if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 300) #if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 300)
case 99: r = kernel_tex_image_interp(__tex_image_099, x, y); break;
case 100: r = kernel_tex_image_interp(__tex_image_100, x, y); break; case 100: r = kernel_tex_image_interp(__tex_image_100, x, y); break;
case 101: r = kernel_tex_image_interp(__tex_image_101, x, y); break; case 101: r = kernel_tex_image_interp(__tex_image_101, x, y); break;
case 102: r = kernel_tex_image_interp(__tex_image_102, x, y); break; case 102: r = kernel_tex_image_interp(__tex_image_102, x, y); break;

View File

@@ -69,6 +69,15 @@ void Attribute::add(const float& f)
buffer.push_back(data[i]); buffer.push_back(data[i]);
} }
void Attribute::add(const uchar4& f)
{
char *data = (char*)&f;
size_t size = sizeof(f);
for(size_t i = 0; i < size; i++)
buffer.push_back(data[i]);
}
void Attribute::add(const float3& f) void Attribute::add(const float3& f)
{ {
char *data = (char*)&f; char *data = (char*)&f;
@@ -136,6 +145,7 @@ size_t Attribute::element_size(int numverts, int numtris, int numsteps, int numc
size = numtris; size = numtris;
break; break;
case ATTR_ELEMENT_CORNER: case ATTR_ELEMENT_CORNER:
case ATTR_ELEMENT_CORNER_BYTE:
size = numtris*3; size = numtris*3;
break; break;
case ATTR_ELEMENT_CURVE: case ATTR_ELEMENT_CURVE:

View File

@@ -68,6 +68,7 @@ public:
float3 *data_float3() { return (float3*)data(); } float3 *data_float3() { return (float3*)data(); }
float4 *data_float4() { return (float4*)data(); } float4 *data_float4() { return (float4*)data(); }
float *data_float() { return (float*)data(); } float *data_float() { return (float*)data(); }
uchar4 *data_uchar4() { return (uchar4*)data(); }
Transform *data_transform() { return (Transform*)data(); } Transform *data_transform() { return (Transform*)data(); }
VoxelAttribute *data_voxel() { return ( VoxelAttribute*)data(); } VoxelAttribute *data_voxel() { return ( VoxelAttribute*)data(); }
@@ -80,6 +81,7 @@ public:
void add(const float& f); void add(const float& f);
void add(const float3& f); void add(const float3& f);
void add(const uchar4& f);
void add(const Transform& f); void add(const Transform& f);
void add(const VoxelAttribute& f); void add(const VoxelAttribute& f);
void add(const char *data); void add(const char *data);

View File

@@ -29,7 +29,7 @@
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
/* generic */ /* generic */
#define TEX_NUM_IMAGES 95 #define TEX_NUM_IMAGES 94
#define TEX_IMAGE_BYTE_START TEX_NUM_FLOAT_IMAGES #define TEX_IMAGE_BYTE_START TEX_NUM_FLOAT_IMAGES
/* extended gpu */ /* extended gpu */

View File

@@ -745,7 +745,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
device->tex_alloc("__attributes_map", dscene->attributes_map); device->tex_alloc("__attributes_map", dscene->attributes_map);
} }
static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_float, vector<float4>& attr_float3, static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_float, vector<float4>& attr_float3, vector<uchar4>& attr_uchar4,
Attribute *mattr, TypeDesc& type, int& offset, AttributeElement& element) Attribute *mattr, TypeDesc& type, int& offset, AttributeElement& element)
{ {
if(mattr) { if(mattr) {
@@ -766,6 +766,15 @@ static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_floa
VoxelAttribute *voxel_data = mattr->data_voxel(); VoxelAttribute *voxel_data = mattr->data_voxel();
offset = voxel_data->slot; offset = voxel_data->slot;
} }
if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
uchar4 *data = mattr->data_uchar4();
offset = attr_uchar4.size();
attr_uchar4.resize(attr_uchar4.size() + size);
for(size_t k = 0; k < size; k++)
attr_uchar4[offset+k] = data[k];
}
else if(mattr->type == TypeDesc::TypeFloat) { else if(mattr->type == TypeDesc::TypeFloat) {
float *data = mattr->data_float(); float *data = mattr->data_float();
offset = attr_float.size(); offset = attr_float.size();
@@ -802,7 +811,7 @@ static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_floa
offset -= mesh->vert_offset; offset -= mesh->vert_offset;
else if(element == ATTR_ELEMENT_FACE) else if(element == ATTR_ELEMENT_FACE)
offset -= mesh->tri_offset; offset -= mesh->tri_offset;
else if(element == ATTR_ELEMENT_CORNER) else if(element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE)
offset -= 3*mesh->tri_offset; offset -= 3*mesh->tri_offset;
else if(element == ATTR_ELEMENT_CURVE) else if(element == ATTR_ELEMENT_CURVE)
offset -= mesh->curve_offset; offset -= mesh->curve_offset;
@@ -843,6 +852,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
* maps next */ * maps next */
vector<float> attr_float; vector<float> attr_float;
vector<float4> attr_float3; vector<float4> attr_float3;
vector<uchar4> attr_uchar4;
for(size_t i = 0; i < scene->meshes.size(); i++) { for(size_t i = 0; i < scene->meshes.size(); i++) {
Mesh *mesh = scene->meshes[i]; Mesh *mesh = scene->meshes[i];
@@ -863,10 +873,10 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
memcpy(triangle_mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size()); memcpy(triangle_mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size());
} }
update_attribute_element_offset(mesh, attr_float, attr_float3, triangle_mattr, update_attribute_element_offset(mesh, attr_float, attr_float3, attr_uchar4, triangle_mattr,
req.triangle_type, req.triangle_offset, req.triangle_element); req.triangle_type, req.triangle_offset, req.triangle_element);
update_attribute_element_offset(mesh, attr_float, attr_float3, curve_mattr, update_attribute_element_offset(mesh, attr_float, attr_float3, attr_uchar4, curve_mattr,
req.curve_type, req.curve_offset, req.curve_element); req.curve_type, req.curve_offset, req.curve_element);
if(progress.get_cancel()) return; if(progress.get_cancel()) return;
@@ -892,6 +902,10 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
dscene->attributes_float3.copy(&attr_float3[0], attr_float3.size()); dscene->attributes_float3.copy(&attr_float3[0], attr_float3.size());
device->tex_alloc("__attributes_float3", dscene->attributes_float3); device->tex_alloc("__attributes_float3", dscene->attributes_float3);
} }
if(attr_uchar4.size()) {
dscene->attributes_uchar4.copy(&attr_uchar4[0], attr_uchar4.size());
device->tex_alloc("__attributes_uchar4", dscene->attributes_uchar4);
}
} }
void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)

View File

@@ -85,6 +85,7 @@ public:
device_vector<uint4> attributes_map; device_vector<uint4> attributes_map;
device_vector<float> attributes_float; device_vector<float> attributes_float;
device_vector<float4> attributes_float3; device_vector<float4> attributes_float3;
device_vector<uchar4> attributes_uchar4;
/* lights */ /* lights */
device_vector<float4> light_distribution; device_vector<float4> light_distribution;

View File

@@ -26,6 +26,27 @@
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
ccl_device uchar float_to_byte(float val)
{
return ((val <= 0.0f) ? 0 : (((val) > (1.0f - 0.5f / 255.0f)) ? 255 : ((255.0f * (val)) + 0.5f)));
}
ccl_device uchar4 color_float_to_byte(float3 c)
{
uchar r, g, b;
r = float_to_byte(c.x);
g = float_to_byte(c.y);
b = float_to_byte(c.z);
return make_uchar4(r, g, b, 0);
}
ccl_device_inline float3 color_byte_to_float(uchar4 c)
{
return make_float3(c.x*(1.0f/255.0f), c.y*(1.0f/255.0f), c.z*(1.0f/255.0f));
}
ccl_device float color_srgb_to_scene_linear(float c) ccl_device float color_srgb_to_scene_linear(float c)
{ {
if(c < 0.04045f) if(c < 0.04045f)