//============================================================================ // 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. //============================================================================ #include #include #include #include #include #include #include #include #include #include #include #include #include namespace vtkm { namespace rendering { namespace raytracing { class BufferAddition : public vtkm::worklet::WorkletMapField { public: VTKM_CONT BufferAddition() {} using ControlSignature = void(FieldIn, FieldInOut); using ExecutionSignature = void(_1, _2); template VTKM_EXEC void operator()(const ValueType& value1, ValueType& value2) const { value2 += value1; } }; //class BufferAddition class BufferMultiply : public vtkm::worklet::WorkletMapField { public: VTKM_CONT BufferMultiply() {} using ControlSignature = void(FieldIn, FieldInOut); using ExecutionSignature = void(_1, _2); template VTKM_EXEC void operator()(const ValueType& value1, ValueType& value2) const { value2 *= value1; } }; //class BufferMultiply template ChannelBuffer::ChannelBuffer() { this->NumChannels = 4; this->Size = 0; this->Name = "default"; } template ChannelBuffer::ChannelBuffer(const vtkm::Int32 numChannels, const vtkm::Id size) { if (size < 0) throw vtkm::cont::ErrorBadValue("ChannelBuffer: Size must be greater that -1"); if (numChannels < 0) throw vtkm::cont::ErrorBadValue("ChannelBuffer: NumChannels must be greater that -1"); this->NumChannels = numChannels; this->Size = size; Buffer.Allocate(this->Size * this->NumChannels); } template vtkm::Int32 ChannelBuffer::GetNumChannels() const { return this->NumChannels; } template vtkm::Id ChannelBuffer::GetSize() const { return this->Size; } template vtkm::Id ChannelBuffer::GetBufferLength() const { return this->Size * static_cast(this->NumChannels); } template void ChannelBuffer::SetName(const std::string name) { this->Name = name; } template std::string ChannelBuffer::GetName() const { return this->Name; } template void ChannelBuffer::AddBuffer(const ChannelBuffer& other) { if (this->NumChannels != other.GetNumChannels()) throw vtkm::cont::ErrorBadValue("ChannelBuffer add: number of channels must be equal"); if (this->Size != other.GetSize()) throw vtkm::cont::ErrorBadValue("ChannelBuffer add: size must be equal"); vtkm::worklet::DispatcherMapField().Invoke(other.Buffer, this->Buffer); } template void ChannelBuffer::MultiplyBuffer(const ChannelBuffer& other) { if (this->NumChannels != other.GetNumChannels()) throw vtkm::cont::ErrorBadValue("ChannelBuffer add: number of channels must be equal"); if (this->Size != other.GetSize()) throw vtkm::cont::ErrorBadValue("ChannelBuffer add: size must be equal"); vtkm::worklet::DispatcherMapField().Invoke(other.Buffer, this->Buffer); } template void ChannelBuffer::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(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) { } using ControlSignature = void(FieldOut, WholeArrayIn, FieldIn); using ExecutionSignature = void(_1, _2, _3); template 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 ChannelBuffer ChannelBuffer::GetChannel(const vtkm::Int32 channel) { if (channel < 0 || channel >= this->NumChannels) throw vtkm::cont::ErrorBadValue("ChannelBuffer: invalid channel to extract"); ChannelBuffer output(1, this->Size); output.SetName(this->Name); if (this->Size == 0) { return output; } vtkm::cont::Invoker invoke; invoke(ExtractChannel(this->GetNumChannels(), channel), output.Buffer, this->Buffer, vtkm::cont::ArrayHandleIndex(this->GetSize())); return output; } //static class Expand : public vtkm::worklet::WorkletMapField { protected: vtkm::Int32 NumChannels; public: VTKM_CONT Expand(const vtkm::Int32 numChannels) : NumChannels(numChannels) { } using ControlSignature = void(FieldIn, WholeArrayIn, WholeArrayOut); using ExecutionSignature = void(_1, _2, _3, WorkIndex); template 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 struct ExpandFunctorSignature { vtkm::cont::ArrayHandle Input; vtkm::cont::ArrayHandle SparseIndexes; ChannelBuffer* Output; vtkm::cont::ArrayHandle Signature; vtkm::Id OutputLength; vtkm::Int32 NumChannels; ExpandFunctorSignature(vtkm::cont::ArrayHandle input, vtkm::cont::ArrayHandle sparseIndexes, ChannelBuffer* outChannelBuffer, vtkm::Id outputLength, vtkm::Int32 numChannels, vtkm::cont::ArrayHandle signature) : Input(input) , SparseIndexes(sparseIndexes) , Output(outChannelBuffer) , Signature(signature) , OutputLength(outputLength) , NumChannels(numChannels) { } template bool operator()(Device device) { vtkm::Id totalSize = this->OutputLength * static_cast(this->NumChannels); { vtkm::cont::Token token; this->Output->Buffer.PrepareForOutput(totalSize, device, token); } ChannelBufferOperations::InitChannels(*this->Output, this->Signature, device); vtkm::worklet::DispatcherMapField dispatcher((Expand(this->NumChannels))); dispatcher.SetDevice(Device()); dispatcher.Invoke(this->Input, this->SparseIndexes, this->Output->Buffer); return true; } }; template struct ExpandFunctor { vtkm::cont::ArrayHandle Input; vtkm::cont::ArrayHandle SparseIndexes; ChannelBuffer* Output; vtkm::Id OutputLength; vtkm::Int32 NumChannels; Precision InitVal; ExpandFunctor(vtkm::cont::ArrayHandle input, vtkm::cont::ArrayHandle sparseIndexes, ChannelBuffer* outChannelBuffer, vtkm::Id outputLength, vtkm::Int32 numChannels, Precision initVal) : Input(input) , SparseIndexes(sparseIndexes) , Output(outChannelBuffer) , OutputLength(outputLength) , NumChannels(numChannels) , InitVal(initVal) { } template bool operator()(Device device) { vtkm::Id totalSize = this->OutputLength * static_cast(this->NumChannels); { vtkm::cont::Token token; this->Output->Buffer.PrepareForOutput(totalSize, device, token); } ChannelBufferOperations::InitConst(*this->Output, this->InitVal, device); vtkm::worklet::DispatcherMapField dispatcher((Expand(this->NumChannels))); dispatcher.SetDevice(Device()); dispatcher.Invoke(this->Input, this->SparseIndexes, this->Output->Buffer); return true; } }; template 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); } } using ControlSignature = void(FieldInOut); using ExecutionSignature = void(_1); VTKM_EXEC void operator()(Precision& value) const { value = (value - MinScalar) * InvDeltaScalar; if (Invert) value = 1.f - value; } }; //class normalize buffer template struct NormalizeFunctor { vtkm::cont::ArrayHandle Input; bool Invert; NormalizeFunctor(vtkm::cont::ArrayHandle input, bool invert) : Input(input) , Invert(invert) { } template bool operator()(Device vtkmNotUsed(device)) { auto asField = vtkm::cont::make_FieldPoint("name meaningless", this->Input); vtkm::Range range; asField.GetRange(&range); Precision minScalar = static_cast(range.Min); Precision maxScalar = static_cast(range.Max); vtkm::worklet::DispatcherMapField> dispatcher( NormalizeBuffer(minScalar, maxScalar, Invert)); dispatcher.SetDevice(Device()); dispatcher.Invoke(Input); return true; } }; template ChannelBuffer ChannelBuffer::ExpandBuffer( vtkm::cont::ArrayHandle sparseIndexes, const vtkm::Id outputSize, vtkm::cont::ArrayHandle signature) { VTKM_ASSERT(this->NumChannels == signature.ReadPortal().GetNumberOfValues()); ChannelBuffer output(this->NumChannels, outputSize); output.SetName(this->Name); ExpandFunctorSignature functor( this->Buffer, sparseIndexes, &output, outputSize, this->NumChannels, signature); vtkm::cont::TryExecute(functor); return output; } template ChannelBuffer ChannelBuffer::ExpandBuffer( vtkm::cont::ArrayHandle sparseIndexes, const vtkm::Id outputSize, Precision initValue) { ChannelBuffer output(this->NumChannels, outputSize); output.SetName(this->Name); ExpandFunctor functor( this->Buffer, sparseIndexes, &output, outputSize, this->NumChannels, initValue); vtkm::cont::TryExecute(functor); return output; } template void ChannelBuffer::Normalize(bool invert) { auto asField = vtkm::cont::make_FieldPoint("name meaningless", this->Buffer); vtkm::Range range; asField.GetRange(&range); Precision minScalar = static_cast(range.Min); Precision maxScalar = static_cast(range.Max); vtkm::worklet::DispatcherMapField> dispatcher( NormalizeBuffer(minScalar, maxScalar, invert)); dispatcher.Invoke(this->Buffer); } template struct ResizeChannelFunctor { ChannelBuffer* Self; vtkm::Int32 NumChannels; ResizeChannelFunctor(ChannelBuffer* self, vtkm::Int32 numChannels) : Self(self) , NumChannels(numChannels) { } template bool operator()(Device device) { Self->SetNumChannels(NumChannels, device); return true; } }; template void ChannelBuffer::InitConst(const Precision value) { vtkm::cont::ArrayHandleConstant valueHandle(value, this->GetBufferLength()); vtkm::cont::Algorithm::Copy(valueHandle, this->Buffer); } template struct InitChannelFunctor { ChannelBuffer* Self; const vtkm::cont::ArrayHandle& Signature; InitChannelFunctor(ChannelBuffer* self, const vtkm::cont::ArrayHandle& signature) : Self(self) , Signature(signature) { } template bool operator()(Device device) { ChannelBufferOperations::InitChannels(*Self, Signature, device); return true; } }; template void ChannelBuffer::InitChannels(const vtkm::cont::ArrayHandle& signature) { InitChannelFunctor functor(this, signature); vtkm::cont::TryExecute(functor); } template void ChannelBuffer::SetNumChannels(const vtkm::Int32 numChannels) { ResizeChannelFunctor functor(this, numChannels); vtkm::cont::TryExecute(functor); } template ChannelBuffer ChannelBuffer::Copy() { ChannelBuffer res(NumChannels, Size); vtkm::cont::Algorithm::Copy(this->Buffer, res.Buffer); return res; } // Instantiate supported types template class ChannelBuffer; template class ChannelBuffer; } } } // namespace vtkm::rendering::raytracing