mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
ColorTable can provide vtkm::exec::Colortable to a specific device
Previously it wasn't possible to get a color table transfered to a specific device.
This commit is contained in:
parent
abfc946f84
commit
6dc06423d8
@ -0,0 +1,21 @@
|
||||
# VTK-m VirtualObjectHandle can transfer to a device using runtime `DeviceAdapterId` value
|
||||
|
||||
Previously `VirtualObjectHandle` required the caller to know a compile time device adapter tag to
|
||||
transfer data. This was problematic since in parts of VTK-m you would only have the runtime
|
||||
`vtkm::cont::DeviceAdapterId` value of the desired device. To than transfer the
|
||||
`VirtualObjectHandle` you would have to call `FindDeviceAdapterTagAndCall`. All this extra
|
||||
work was unneeded as `VirtualObjectHandle` internally was immediately converting from
|
||||
a compile time type to a runtime value.
|
||||
|
||||
|
||||
Here is an example of how you can now transfer a `VirtualObjectHandle` to a device using
|
||||
a runtime value:
|
||||
```cpp
|
||||
|
||||
template<typename BaseType>
|
||||
const BaseType* moveToDevice(VirtualObjectHandle<BaseType>& handle,
|
||||
vtkm::cont::vtkm::cont::DeviceAdapterId deviceId)
|
||||
{
|
||||
return handle.PrepareForExecution(deviceId);
|
||||
}
|
||||
```
|
@ -155,6 +155,7 @@ void ColorTable::SetColorSpace(ColorSpace space)
|
||||
{
|
||||
if (this->Impl->CSpace != space || this->Impl->HostSideCache.get() == nullptr)
|
||||
{
|
||||
this->Impl->HostSideCacheChanged = true;
|
||||
this->Impl->CSpace = space;
|
||||
//Remove any existing host and execution data
|
||||
|
||||
@ -841,8 +842,8 @@ bool ColorTable::Sample(vtkm::Int32 numSamples,
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
vtkm::cont::VirtualObjectHandle<vtkm::exec::ColorTableBase>* ColorTable::GetHandleForExecution()
|
||||
const
|
||||
const vtkm::exec::ColorTableBase* ColorTable::PrepareForExecution(
|
||||
vtkm::cont::DeviceAdapterId deviceId) const
|
||||
{
|
||||
//Only rebuild the array handles that have changed since the last time
|
||||
//we have modified or color / opacity information
|
||||
@ -859,17 +860,20 @@ vtkm::cont::VirtualObjectHandle<vtkm::exec::ColorTableBase>* ColorTable::GetHand
|
||||
this->Impl->OpacityMidSharpHandle = vtkm::cont::make_ArrayHandle(this->Impl->OpacityMidSharp);
|
||||
}
|
||||
|
||||
if (this->Impl->ColorArraysChanged || this->Impl->OpacityArraysChanged)
|
||||
if (this->Impl->ColorArraysChanged || this->Impl->OpacityArraysChanged ||
|
||||
this->Impl->HostSideCacheChanged)
|
||||
{
|
||||
vtkm::cont::TryExecute(
|
||||
detail::transfer_color_table_to_device{}, this->Impl->HostSideCache.get(), this->Impl.get());
|
||||
|
||||
this->Impl->HostSideCache->Modified();
|
||||
vtkm::cont::internal::FindDeviceAdapterTagAndCall(deviceId,
|
||||
VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG(),
|
||||
detail::transfer_color_table_to_device{},
|
||||
this->Impl->HostSideCache.get(),
|
||||
this->Impl.get());
|
||||
}
|
||||
|
||||
this->Impl->ColorArraysChanged = false;
|
||||
this->Impl->OpacityArraysChanged = false;
|
||||
return this->Impl->ExecHandle.get();
|
||||
this->Impl->HostSideCacheChanged = false;
|
||||
return this->Impl->ExecHandle->PrepareForExecution(deviceId);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -661,10 +661,20 @@ public:
|
||||
double tolerance = 0.002) const;
|
||||
|
||||
|
||||
/// \brief returns a virtual object handle of the exec color table
|
||||
/// \brief returns a virtual object pointer of the exec color table
|
||||
///
|
||||
/// This object is only valid as long as the ColorTable is unmodified
|
||||
vtkm::cont::VirtualObjectHandle<vtkm::exec::ColorTableBase>* GetHandleForExecution() const;
|
||||
/// This pointer is only valid as long as the ColorTable is unmodified
|
||||
const vtkm::exec::ColorTableBase* PrepareForExecution(vtkm::cont::DeviceAdapterId deviceId) const;
|
||||
|
||||
/// \brief returns a virtual object pointer of the exec color table
|
||||
///
|
||||
/// This pointer is only valid as long as the ColorTable is unmodified
|
||||
template <typename DeviceAdapter>
|
||||
const vtkm::exec::ColorTableBase* PrepareForExecution(DeviceAdapter) const
|
||||
{
|
||||
auto deviceId = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId();
|
||||
return this->PrepareForExecution(deviceId);
|
||||
}
|
||||
|
||||
|
||||
/// \brief returns the modified count for the virtual object handle of the exec color table
|
||||
|
@ -83,7 +83,7 @@ struct transfer_color_table_to_device
|
||||
template <typename DeviceAdapter, typename ColorTableInternals>
|
||||
bool operator()(DeviceAdapter device,
|
||||
vtkm::exec::ColorTableBase* portal,
|
||||
ColorTableInternals* internals)
|
||||
ColorTableInternals* internals) const
|
||||
{
|
||||
auto p1 = internals->ColorPosHandle.PrepareForInput(device);
|
||||
auto p2 = internals->ColorRGBHandle.PrepareForInput(device);
|
||||
@ -102,6 +102,7 @@ struct transfer_color_table_to_device
|
||||
portal->ONodes = detail::get_ptr(vtkm::cont::ArrayPortalToIteratorBegin(p3));
|
||||
portal->Alpha = detail::get_ptr(vtkm::cont::ArrayPortalToIteratorBegin(p4));
|
||||
portal->MidSharp = detail::get_ptr(vtkm::cont::ArrayPortalToIteratorBegin(p5));
|
||||
portal->Modified();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -184,16 +185,14 @@ template <typename T, typename S>
|
||||
bool ColorTable::Map(const vtkm::cont::ArrayHandle<T, S>& values,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::UInt8, 4>>& rgbaOut) const
|
||||
{
|
||||
return vtkm::cont::TryExecute(
|
||||
detail::map_color_table{}, this->GetHandleForExecution(), values, rgbaOut);
|
||||
return vtkm::cont::TryExecute(detail::map_color_table{}, this, values, rgbaOut);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
template <typename T, typename S>
|
||||
bool ColorTable::Map(const vtkm::cont::ArrayHandle<T, S>& values,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::UInt8, 3>>& rgbOut) const
|
||||
{
|
||||
return vtkm::cont::TryExecute(
|
||||
detail::map_color_table{}, this->GetHandleForExecution(), values, rgbOut);
|
||||
return vtkm::cont::TryExecute(detail::map_color_table{}, this, values, rgbOut);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
template <typename T, int N, typename S>
|
||||
|
@ -47,7 +47,7 @@ struct ColorTableInternals
|
||||
// BelowRangeColor
|
||||
// AboveRangeColor
|
||||
//Note the pointers inside the host side portal are not valid, as they
|
||||
//are execution
|
||||
//are execution pointers
|
||||
std::unique_ptr<vtkm::exec::ColorTableBase> HostSideCache;
|
||||
//Execution side version of the ColorTableBase.
|
||||
std::unique_ptr<vtkm::cont::VirtualObjectHandle<vtkm::exec::ColorTableBase>> ExecHandle;
|
||||
@ -66,6 +66,7 @@ struct ColorTableInternals
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<float, 2>> OpacityMidSharpHandle;
|
||||
bool ColorArraysChanged = true;
|
||||
bool OpacityArraysChanged = true;
|
||||
bool HostSideCacheChanged = true;
|
||||
|
||||
void RecalculateRange()
|
||||
{
|
||||
|
@ -114,29 +114,26 @@ public:
|
||||
/// Release all the execution side resources
|
||||
VTKM_CONT void ReleaseExecutionResources() { this->Internals->ReleaseExecutionResources(); }
|
||||
|
||||
/// Get a valid \c VirtualBaseType* with the current control side state for \c DeviceAdapter.
|
||||
|
||||
/// Get a valid \c VirtualBaseType* with the current control side state for \c deviceId.
|
||||
/// VirtualObjectHandle and the returned pointer are analogous to ArrayHandle and Portal
|
||||
/// The returned pointer will be invalidated if:
|
||||
/// 1. A new pointer is requested for a different DeviceAdapter
|
||||
/// 1. A new pointer is requested for a different deviceId
|
||||
/// 2. VirtualObjectHandle is destroyed
|
||||
/// 3. Reset or ReleaseResources is called
|
||||
///
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT const VirtualBaseType* PrepareForExecution(DeviceAdapter) const
|
||||
VTKM_CONT const VirtualBaseType* PrepareForExecution(vtkm::cont::DeviceAdapterId deviceId) const
|
||||
{
|
||||
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
|
||||
|
||||
if (!this->GetValid())
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("No target object bound");
|
||||
}
|
||||
|
||||
vtkm::cont::DeviceAdapterId deviceId = DeviceInfo::GetId();
|
||||
if (deviceId < 0 || deviceId >= VTKM_MAX_DEVICE_ADAPTER_ID)
|
||||
{
|
||||
std::string msg = "Device '" + DeviceInfo::GetName() + "' has invalid ID of " +
|
||||
std::to_string(deviceId) + "(VTKM_MAX_DEVICE_ADAPTER_ID = " +
|
||||
std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
|
||||
std::string msg = "An invalid device adapter ID of " + std::to_string(deviceId) +
|
||||
"was used when trying to construct a virtual object. The valid range is between " +
|
||||
"0 and " + std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
|
||||
throw vtkm::cont::ErrorBadType(msg);
|
||||
}
|
||||
|
||||
@ -144,7 +141,9 @@ public:
|
||||
{
|
||||
if (!this->Internals->Transfers[static_cast<std::size_t>(deviceId)])
|
||||
{
|
||||
std::string msg = DeviceInfo::GetName() + " was not in the list specified in Bind";
|
||||
std::string msg = "The device adapter ID of " + std::to_string(deviceId) +
|
||||
" was not part of the set of valid adapters when this virtual object was constructed " +
|
||||
"or last binded to a set of device adapters.";
|
||||
throw vtkm::cont::ErrorBadType(msg);
|
||||
}
|
||||
|
||||
@ -159,6 +158,20 @@ public:
|
||||
return this->Internals->Current->PrepareForExecution();
|
||||
}
|
||||
|
||||
/// Get a valid \c VirtualBaseType* with the current control side state for \c DeviceAdapter.
|
||||
/// VirtualObjectHandle and the returned pointer are analogous to ArrayHandle and Portal
|
||||
/// The returned pointer will be invalidated if:
|
||||
/// 1. A new pointer is requested for a different DeviceAdapter
|
||||
/// 2. VirtualObjectHandle is destroyed
|
||||
/// 3. Reset or ReleaseResources is called
|
||||
///
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT const VirtualBaseType* PrepareForExecution(DeviceAdapter) const
|
||||
{
|
||||
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
|
||||
return this->PrepareForExecution(DeviceInfo::GetId());
|
||||
}
|
||||
|
||||
private:
|
||||
class TransferInterface
|
||||
{
|
||||
|
@ -381,6 +381,21 @@ public:
|
||||
VTKM_TEST_ASSERT(result == correct_hsv_values[i],
|
||||
"incorrect value when interpolating between values");
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::UInt8, 3>> colors_rgb;
|
||||
table.SetColorSpace(vtkm::cont::ColorSpace::RGB);
|
||||
table.Map(field, colors_rgb);
|
||||
|
||||
const vtkm::Vec<vtkm::UInt8, 3> correct_rgb_values[nvals] = { { 0, 0, 255 }, { 51, 0, 204 },
|
||||
{ 102, 0, 153 }, { 153, 0, 102 },
|
||||
{ 204, 0, 51 }, { 255, 0, 0 } };
|
||||
auto rgb_portal = colors_rgb.GetPortalConstControl();
|
||||
for (std::size_t i = 0; i < nvals; ++i)
|
||||
{
|
||||
auto result = rgb_portal.Get(static_cast<vtkm::Id>(i));
|
||||
VTKM_TEST_ASSERT(result == correct_rgb_values[i],
|
||||
"incorrect value when interpolating between values");
|
||||
}
|
||||
}
|
||||
|
||||
static void TestOpacityOnlyPoints()
|
||||
@ -430,6 +445,38 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void TestWorkletTransport()
|
||||
{
|
||||
using namespace vtkm::worklet::colorconversion;
|
||||
|
||||
vtkm::cont::ColorTable table(vtkm::cont::ColorTable::Preset::LINEAR_GREEN);
|
||||
VTKM_TEST_ASSERT((table.GetRange() == vtkm::Range{ 0.0, 1.0 }),
|
||||
"loading linear green table failed with wrong range");
|
||||
VTKM_TEST_ASSERT((table.GetNumberOfPoints() == 21),
|
||||
"loading linear green table failed with number of control points");
|
||||
|
||||
constexpr vtkm::Id nvals = 3;
|
||||
constexpr double data[3] = { 0.0f, 0.5f, 1.0f };
|
||||
auto samples = vtkm::cont::make_ArrayHandle(data, nvals);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::UInt8, 4>> colors;
|
||||
TransferFunction transfer(table.PrepareForExecution(DeviceAdapterTag{}));
|
||||
vtkm::worklet::DispatcherMapField<TransferFunction, DeviceAdapterTag> dispatcher(transfer);
|
||||
dispatcher.Invoke(samples, colors);
|
||||
|
||||
const vtkm::Vec<vtkm::UInt8, 4> correct_sampling_points[nvals] = { { 14, 28, 31, 255 },
|
||||
{ 21, 150, 21, 255 },
|
||||
{ 255, 251, 230, 255 } };
|
||||
|
||||
auto portal = colors.GetPortalConstControl();
|
||||
for (std::size_t i = 0; i < nvals; ++i)
|
||||
{
|
||||
auto result = portal.Get(static_cast<vtkm::Id>(i));
|
||||
VTKM_TEST_ASSERT(result == correct_sampling_points[i],
|
||||
"incorrect value when interpolating in linear green preset");
|
||||
}
|
||||
}
|
||||
|
||||
static void TestSampling()
|
||||
{
|
||||
|
||||
@ -498,7 +545,7 @@ public:
|
||||
{
|
||||
TestConstructors();
|
||||
TestLoadPresets();
|
||||
TestClamping(); //this needs to also verify default opacity
|
||||
TestClamping();
|
||||
TestRangeColors();
|
||||
|
||||
TestRescaleRange(); //uses Lab
|
||||
@ -508,6 +555,7 @@ public:
|
||||
|
||||
TestOpacityOnlyPoints();
|
||||
|
||||
TestWorkletTransport();
|
||||
TestSampling();
|
||||
TestLookupTable();
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ class VTKM_ALWAYS_EXPORT ColorTableRGB final : public ColorTableBase
|
||||
public:
|
||||
inline VTKM_EXEC vtkm::Vec<float, 3> MapThroughColorSpace(const vtkm::Vec<float, 3>& rgb1,
|
||||
const vtkm::Vec<float, 3>& rgb2,
|
||||
float weight) const final;
|
||||
float weight) const;
|
||||
};
|
||||
|
||||
class VTKM_ALWAYS_EXPORT ColorTableHSV final : public ColorTableBase
|
||||
@ -76,7 +76,7 @@ class VTKM_ALWAYS_EXPORT ColorTableHSV final : public ColorTableBase
|
||||
public:
|
||||
inline VTKM_EXEC vtkm::Vec<float, 3> MapThroughColorSpace(const vtkm::Vec<float, 3>& rgb1,
|
||||
const vtkm::Vec<float, 3>& rgb2,
|
||||
float weight) const final;
|
||||
float weight) const;
|
||||
};
|
||||
|
||||
class VTKM_ALWAYS_EXPORT ColorTableHSVWrap final : public ColorTableBase
|
||||
@ -84,7 +84,7 @@ class VTKM_ALWAYS_EXPORT ColorTableHSVWrap final : public ColorTableBase
|
||||
public:
|
||||
inline VTKM_EXEC vtkm::Vec<float, 3> MapThroughColorSpace(const vtkm::Vec<float, 3>& rgb1,
|
||||
const vtkm::Vec<float, 3>& rgb2,
|
||||
float weight) const final;
|
||||
float weight) const;
|
||||
};
|
||||
|
||||
class VTKM_ALWAYS_EXPORT ColorTableLab final : public ColorTableBase
|
||||
@ -92,7 +92,7 @@ class VTKM_ALWAYS_EXPORT ColorTableLab final : public ColorTableBase
|
||||
public:
|
||||
inline VTKM_EXEC vtkm::Vec<float, 3> MapThroughColorSpace(const vtkm::Vec<float, 3>& rgb1,
|
||||
const vtkm::Vec<float, 3>& rgb2,
|
||||
float weight) const final;
|
||||
float weight) const;
|
||||
};
|
||||
|
||||
class VTKM_ALWAYS_EXPORT ColorTableDiverging final : public ColorTableBase
|
||||
@ -100,7 +100,7 @@ class VTKM_ALWAYS_EXPORT ColorTableDiverging final : public ColorTableBase
|
||||
public:
|
||||
inline VTKM_EXEC vtkm::Vec<float, 3> MapThroughColorSpace(const vtkm::Vec<float, 3>& rgb1,
|
||||
const vtkm::Vec<float, 3>& rgb2,
|
||||
float weight) const final;
|
||||
float weight) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user