vtk-m/vtkm/rendering/raytracing/ChannelBuffer.cxx
2017-06-17 14:28:45 -07:00

467 lines
13 KiB
C++

//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2015 Sandia Corporation.
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/TryExecute.h>
#include <vtkm/rendering/raytracing/ChannelBuffer.h>
#include <vtkm/rendering/raytracing/ChannelBufferOperations.h>
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
#include <vtkm/rendering/vtkm_rendering_export.h>
#include <vtkm/worklet/DispatcherMapField.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
template <typename Precision>
ChannelBuffer<Precision>::ChannelBuffer()
{
this->NumChannels = 4;
this->Size = 0;
this->Name = "default";
}
template <typename Precision>
ChannelBuffer<Precision>::ChannelBuffer(const vtkm::Int32 numChannels, const vtkm::Id size)
{
if (size < 1)
throw vtkm::cont::ErrorBadValue("ChannelBuffer: Size must be greater that 0");
if (numChannels < 1)
throw vtkm::cont::ErrorBadValue("ChannelBuffer: NumChannels must be greater that 0");
this->NumChannels = numChannels;
this->Size = size;
Buffer.Allocate(this->Size * this->NumChannels);
}
template <typename Precision>
vtkm::Int32 ChannelBuffer<Precision>::GetNumChannels() const
{
return this->NumChannels;
}
template <typename Precision>
vtkm::Id ChannelBuffer<Precision>::GetSize() const
{
return this->Size;
}
template <typename Precision>
vtkm::Id ChannelBuffer<Precision>::GetBufferLength() const
{
return this->Size * static_cast<vtkm::Id>(this->NumChannels);
}
template <typename Precision>
void ChannelBuffer<Precision>::SetName(const std::string name)
{
this->Name = name;
}
template <typename Precision>
std::string ChannelBuffer<Precision>::GetName() const
{
return this->Name;
}
template <typename Precision>
void ChannelBuffer<Precision>::Resize(const vtkm::Id newSize)
{
if (newSize < 0)
throw vtkm::cont::ErrorBadValue("ChannelBuffer resize: Size must be greater than -1");
this->Size = newSize;
this->Buffer.Allocate(this->Size * static_cast<vtkm::Id>(NumChannels));
}
class ExtractChannel : public vtkm::worklet::WorkletMapField
{
protected:
vtkm::Id NumChannels; // the nnumber of channels in the buffer
vtkm::Id ChannelNum; // the channel to extract
public:
VTKM_CONT
ExtractChannel(const vtkm::Int32 numChannels, const vtkm::Int32 channel)
: NumChannels(numChannels)
, ChannelNum(channel)
{
}
typedef void ControlSignature(FieldOut<>, WholeArrayIn<>);
typedef void ExecutionSignature(_1, _2, WorkIndex);
template <typename T, typename BufferPortalType>
VTKM_EXEC void operator()(T& outValue,
const BufferPortalType& inBuffer,
const vtkm::Id& index) const
{
vtkm::Id valueIndex = index * NumChannels + ChannelNum;
BOUNDS_CHECK(inBuffer, valueIndex);
outValue = inBuffer.Get(valueIndex);
}
}; //class Extract Channel
template <typename Precision>
struct ExtractChannelFunctor
{
ChannelBuffer<Precision>* Self;
vtkm::cont::ArrayHandle<Precision> Output;
vtkm::Int32 Channel;
ExtractChannelFunctor(ChannelBuffer<Precision>* self,
vtkm::cont::ArrayHandle<Precision> output,
const vtkm::Int32 channel)
: Self(self)
, Output(output)
, Channel(channel)
{
}
template <typename Device>
bool operator()(Device device)
{
Output.PrepareForOutput(Self->GetSize(), device);
vtkm::worklet::DispatcherMapField<ExtractChannel, Device>(
ExtractChannel(Self->GetNumChannels(), Channel))
.Invoke(Output, Self->Buffer);
return true;
}
};
template <typename Precision>
ChannelBuffer<Precision> ChannelBuffer<Precision>::GetChannel(const vtkm::Int32 channel)
{
if (channel < 0 || channel >= this->NumChannels)
throw vtkm::cont::ErrorBadValue("ChannelBuffer: invalid channel to extract");
ChannelBuffer<Precision> output(1, this->Size);
output.SetName(this->Name);
ExtractChannelFunctor<Precision> functor(this, output.Buffer, channel);
vtkm::cont::TryExecute(functor);
return output;
}
//static
class Expand : public vtkm::worklet::WorkletMapField
{
protected:
vtkm::Int32 NumChannels;
public:
VTKM_CONT
Expand(const vtkm::Int32 numChannels)
: NumChannels(numChannels)
{
}
typedef void ControlSignature(FieldIn<>, WholeArrayIn<>, WholeArrayOut<>);
typedef void ExecutionSignature(_1, _2, _3, WorkIndex);
template <typename T, typename IndexPortalType, typename BufferPortalType>
VTKM_EXEC void operator()(const T& inValue,
const IndexPortalType& sparseIndexes,
BufferPortalType& outBuffer,
const vtkm::Id& index) const
{
vtkm::Id sparse = index / NumChannels;
BOUNDS_CHECK(sparseIndexes, sparse);
vtkm::Id sparseIndex = sparseIndexes.Get(sparse) * NumChannels;
vtkm::Id outIndex = sparseIndex + index % NumChannels;
BOUNDS_CHECK(outBuffer, outIndex);
outBuffer.Set(outIndex, inValue);
}
}; //class Expand
template <typename Precision>
struct ExpandFunctorSignature
{
vtkm::cont::ArrayHandle<Precision> Input;
vtkm::cont::ArrayHandle<vtkm::Id> SparseIndexes;
ChannelBuffer<Precision>* Output;
vtkm::cont::ArrayHandle<Precision> Signature;
vtkm::Id OutputLength;
vtkm::Int32 NumChannels;
ExpandFunctorSignature(vtkm::cont::ArrayHandle<Precision> input,
vtkm::cont::ArrayHandle<vtkm::Id> sparseIndexes,
ChannelBuffer<Precision>* outChannelBuffer,
vtkm::Id outputLength,
vtkm::Int32 numChannels,
vtkm::cont::ArrayHandle<Precision> signature)
: Input(input)
, SparseIndexes(sparseIndexes)
, Output(outChannelBuffer)
, Signature(signature)
, OutputLength(outputLength)
, NumChannels(numChannels)
{
}
template <typename Device>
bool operator()(Device device)
{
vtkm::Id totalSize = OutputLength * static_cast<vtkm::Id>(NumChannels);
Output->Buffer.PrepareForOutput(totalSize, device);
ChannelBufferOperations::InitChannels(*Output, Signature, device);
vtkm::worklet::DispatcherMapField<Expand, Device>(Expand(NumChannels))
.Invoke(Input, SparseIndexes, Output->Buffer);
return true;
}
};
template <typename Precision>
struct ExpandFunctor
{
vtkm::cont::ArrayHandle<Precision> Input;
vtkm::cont::ArrayHandle<vtkm::Id> SparseIndexes;
ChannelBuffer<Precision>* Output;
vtkm::Id OutputLength;
vtkm::Int32 NumChannels;
Precision InitVal;
ExpandFunctor(vtkm::cont::ArrayHandle<Precision> input,
vtkm::cont::ArrayHandle<vtkm::Id> sparseIndexes,
ChannelBuffer<Precision>* outChannelBuffer,
vtkm::Id outputLength,
vtkm::Int32 numChannels,
Precision initVal)
: Input(input)
, SparseIndexes(sparseIndexes)
, Output(outChannelBuffer)
, OutputLength(outputLength)
, NumChannels(numChannels)
, InitVal(initVal)
{
}
template <typename Device>
bool operator()(Device device)
{
vtkm::Id totalSize = OutputLength * static_cast<vtkm::Id>(NumChannels);
Output->Buffer.PrepareForOutput(totalSize, device);
ChannelBufferOperations::InitConst(*Output, InitVal, device);
vtkm::worklet::DispatcherMapField<Expand, Device>(Expand(NumChannels))
.Invoke(Input, SparseIndexes, Output->Buffer);
return true;
}
};
template <typename Precision>
class NormalizeBuffer : public vtkm::worklet::WorkletMapField
{
protected:
Precision MinScalar;
Precision InvDeltaScalar;
bool Invert;
public:
VTKM_CONT
NormalizeBuffer(const Precision minScalar, const Precision maxScalar, bool invert)
: MinScalar(minScalar)
, Invert(invert)
{
if (maxScalar - minScalar == 0.)
{
InvDeltaScalar = MinScalar;
}
else
{
InvDeltaScalar = 1.f / (maxScalar - minScalar);
}
//std::cout<<"Min scalar "<<minScalar<<" max "<<maxScalar<<std::endl;
}
typedef void ControlSignature(FieldInOut<>);
typedef void ExecutionSignature(_1);
VTKM_EXEC
void operator()(Precision& value) const
{
value = (value - MinScalar) * InvDeltaScalar;
if (Invert)
value = 1.f - value;
}
}; //class normalize buffer
template <typename Precision>
struct NormalizeFunctor
{
vtkm::cont::ArrayHandle<Precision> Input;
bool Invert;
NormalizeFunctor(vtkm::cont::ArrayHandle<Precision> input, bool invert)
: Input(input)
, Invert(invert)
{
}
template <typename Device>
bool operator()(Device vtkmNotUsed(device))
{
vtkm::cont::Field asField("name meaningless", vtkm::cont::Field::ASSOC_POINTS, Input);
vtkm::Range range;
asField.GetRange(&range);
Precision minScalar = static_cast<Precision>(range.Min);
Precision maxScalar = static_cast<Precision>(range.Max);
vtkm::worklet::DispatcherMapField<NormalizeBuffer<Precision>, Device>(
NormalizeBuffer<Precision>(minScalar, maxScalar, Invert))
.Invoke(Input);
return true;
}
};
template <typename Precision>
ChannelBuffer<Precision> ChannelBuffer<Precision>::ExpandBuffer(
vtkm::cont::ArrayHandle<vtkm::Id> sparseIndexes,
const vtkm::Id outputSize,
vtkm::cont::ArrayHandle<Precision> signature)
{
VTKM_ASSERT(this->NumChannels == signature.GetPortalConstControl().GetNumberOfValues());
ChannelBuffer<Precision> output(this->NumChannels, outputSize);
output.SetName(this->Name);
ExpandFunctorSignature<Precision> functor(
this->Buffer, sparseIndexes, &output, outputSize, this->NumChannels, signature);
vtkm::cont::TryExecute(functor);
return output;
}
template <typename Precision>
ChannelBuffer<Precision> ChannelBuffer<Precision>::ExpandBuffer(
vtkm::cont::ArrayHandle<vtkm::Id> sparseIndexes,
const vtkm::Id outputSize,
Precision initValue)
{
ChannelBuffer<Precision> output(this->NumChannels, outputSize);
output.SetName(this->Name);
ExpandFunctor<Precision> functor(
this->Buffer, sparseIndexes, &output, outputSize, this->NumChannels, initValue);
vtkm::cont::TryExecute(functor);
return output;
}
template <typename Precision>
void ChannelBuffer<Precision>::Normalize(bool invert)
{
NormalizeFunctor<Precision> functor(this->Buffer, invert);
vtkm::cont::TryExecute(functor);
}
template <typename Precision>
struct ResizeChannelFunctor
{
ChannelBuffer<Precision>* Self;
vtkm::Int32 NumChannels;
ResizeChannelFunctor(ChannelBuffer<Precision>* self, vtkm::Int32 numChannels)
: Self(self)
, NumChannels(numChannels)
{
}
template <typename Device>
bool operator()(Device device)
{
Self->SetNumChannels(NumChannels, device);
return true;
}
};
template <typename Precision>
struct InitConstFunctor
{
ChannelBuffer<Precision>* Self;
Precision Value;
InitConstFunctor(ChannelBuffer<Precision>* self, Precision value)
: Self(self)
, Value(value)
{
}
template <typename Device>
bool operator()(Device device)
{
ChannelBufferOperations::InitConst(*Self, Value, device);
return true;
}
};
template <typename Precision>
void ChannelBuffer<Precision>::InitConst(const Precision value)
{
InitConstFunctor<Precision> functor(this, value);
vtkm::cont::TryExecute(functor);
}
template <typename Precision>
struct InitChannelFunctor
{
ChannelBuffer<Precision>* Self;
const vtkm::cont::ArrayHandle<Precision>& Signature;
InitChannelFunctor(ChannelBuffer<Precision>* self,
const vtkm::cont::ArrayHandle<Precision>& signature)
: Self(self)
, Signature(signature)
{
}
template <typename Device>
bool operator()(Device device)
{
ChannelBufferOperations::InitChannels(*Self, Signature, device);
return true;
}
};
template <typename Precision>
void ChannelBuffer<Precision>::InitChannels(const vtkm::cont::ArrayHandle<Precision>& signature)
{
InitChannelFunctor<Precision> functor(this, signature);
vtkm::cont::TryExecute(functor);
}
template <typename Precision>
void ChannelBuffer<Precision>::SetNumChannels(const vtkm::Int32 numChannels)
{
ResizeChannelFunctor<Precision> functor(this, numChannels);
vtkm::cont::TryExecute(functor);
}
// Instantiate supported types
template class ChannelBuffer<vtkm::Float32>;
template class ChannelBuffer<vtkm::Float64>;
}
}
} // namespace vtkm::rendering::raytracing