TCU_THROW(NotSupportedError, "WSI not supported");
}
+bool Platform::hasDisplay (wsi::Type) const
+{
+ return false;
+}
+
void Platform::describePlatform (std::ostream& dst) const
{
dst << "vk::Platform::describePlatform() not implemented";
virtual Library* createLibrary (void) const = 0;
virtual wsi::Display* createWsiDisplay (wsi::Type wsiType) const;
+ virtual bool hasDisplay (wsi::Type wsiType) const;
virtual void getMemoryLimits (PlatformMemoryLimits& limits) const = 0;
virtual void describePlatform (std::ostream& dst) const;
ACCESS_LAST
};
+Access accessFlagToAccess (vk::VkAccessFlagBits flag)
+{
+ switch (flag)
+ {
+ case vk::VK_ACCESS_INDIRECT_COMMAND_READ_BIT: return ACCESS_INDIRECT_COMMAND_READ_BIT;
+ case vk::VK_ACCESS_INDEX_READ_BIT: return ACCESS_INDEX_READ_BIT;
+ case vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: return ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
+ case vk::VK_ACCESS_UNIFORM_READ_BIT: return ACCESS_UNIFORM_READ_BIT;
+ case vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: return ACCESS_INPUT_ATTACHMENT_READ_BIT;
+ case vk::VK_ACCESS_SHADER_READ_BIT: return ACCESS_SHADER_READ_BIT;
+ case vk::VK_ACCESS_SHADER_WRITE_BIT: return ACCESS_SHADER_WRITE_BIT;
+ case vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: return ACCESS_COLOR_ATTACHMENT_READ_BIT;
+ case vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: return ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ case vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: return ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
+ case vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: return ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+ case vk::VK_ACCESS_TRANSFER_READ_BIT: return ACCESS_TRANSFER_READ_BIT;
+ case vk::VK_ACCESS_TRANSFER_WRITE_BIT: return ACCESS_TRANSFER_WRITE_BIT;
+ case vk::VK_ACCESS_HOST_READ_BIT: return ACCESS_HOST_READ_BIT;
+ case vk::VK_ACCESS_HOST_WRITE_BIT: return ACCESS_HOST_WRITE_BIT;
+ case vk::VK_ACCESS_MEMORY_READ_BIT: return ACCESS_MEMORY_READ_BIT;
+ case vk::VK_ACCESS_MEMORY_WRITE_BIT: return ACCESS_MEMORY_WRITE_BIT;
+
+ default:
+ DE_FATAL("Unknown access flags");
+ return ACCESS_LAST;
+ }
+}
+
// Sequential stage enums
enum PipelineStage
{
PIPELINESTAGE_LAST
};
-PipelineStage pipelineStageFlagToPipelineStage (vk::VkPipelineStageFlagBits flags)
+PipelineStage pipelineStageFlagToPipelineStage (vk::VkPipelineStageFlagBits flag)
{
- switch (flags)
+ switch (flag)
{
case vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT: return PIPELINESTAGE_TOP_OF_PIPE_BIT;
case vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT: return PIPELINESTAGE_BOTTOM_OF_PIPE_BIT;
const vk::VkPipelineStageFlags m_allowedStages;
const vk::VkAccessFlags m_allowedAccesses;
- // [dstStage][srcStage] = srcAccesses
- // In stage dstStage write srcAccesses from srcStage are not yet available
- vk::VkAccessFlags m_unavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
+ // [dstStage][srcStage][dstAccess] = srcAccesses
+ // In stage dstStage write srcAccesses from srcStage are not yet available for dstAccess
+ vk::VkAccessFlags m_unavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST][ACCESS_LAST];
// Latest pipeline transition is not available in stage
bool m_unavailableLayoutTransition[PIPELINESTAGE_LAST];
// [dstStage] = dstAccesses
// There are no write operations that are not yet available
// initially.
- m_unavailableWriteOperations[dstStage][srcStage] = 0;
+ for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
+ {
+ const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+ if ((dstAccess_ & m_allowedAccesses) == 0)
+ continue;
+
+ m_unavailableWriteOperations[dstStage][srcStage][dstAccess] = 0;
+ }
}
}
}
// Mark all accesses from all stages invisible
m_invisibleOperations[dstStage] |= m_allowedAccesses;
- // Mark write access from srcStage unavailable to all stages
- m_unavailableWriteOperations[dstStage][srcStage] |= access;
+ // Mark write access from srcStage unavailable to all stages for all accesses
+ for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
+ {
+ const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+ if ((dstAccess_ & m_allowedAccesses) == 0)
+ continue;
+
+ m_unavailableWriteOperations[dstStage][srcStage][dstAccess] |= access;
+ }
}
}
}
dstAccesses |= m_invisibleOperations[dstStage];
}
- // Make sure all write operations fro mall stages are available
+ // Make sure all write operations from all stages are available
for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
{
const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
if ((srcStage_ & m_allowedStages) == 0)
continue;
- if (m_unavailableWriteOperations[dstStage][srcStage])
+ for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
{
- dstStages |= dstStage_;
- srcStages |= dstStage_;
- srcAccesses |= m_unavailableWriteOperations[dstStage][srcStage];
+ const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+ if ((dstAccess_ & m_allowedAccesses) == 0)
+ continue;
+
+ if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess])
+ {
+ dstStages |= dstStage_;
+ srcStages |= dstStage_;
+ srcAccesses |= m_unavailableWriteOperations[dstStage][srcStage][dstAccess];
+ }
}
if (m_unavailableLayoutTransition[dstStage] && !m_unavailableLayoutTransition[srcStage])
}
void CacheState::checkImageLayoutBarrier (vk::VkPipelineStageFlags srcStages,
- vk::VkAccessFlags srcAccesses,
- vk::VkPipelineStageFlags dstStages,
- vk::VkAccessFlags dstAccesses)
+ vk::VkAccessFlags srcAccesses,
+ vk::VkPipelineStageFlags dstStages,
+ vk::VkAccessFlags dstAccesses)
{
DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
if ((srcStage_ & m_allowedStages) == 0)
continue;
- if (m_unavailableWriteOperations[dstStage][srcStage] != (getWriteAccessFlags() & m_allowedAccesses))
+ for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
{
- anyWriteAvailable = true;
- break;
+ const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+ if ((dstAccess_ & m_allowedAccesses) == 0)
+ continue;
+
+ if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess] != (getWriteAccessFlags() & m_allowedAccesses))
+ {
+ anyWriteAvailable = true;
+ break;
+ }
}
}
}
continue;
// All write operations are available after layout transition
- m_unavailableWriteOperations[dstStage][srcStage] = 0;
+ for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
+ {
+ const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+ if ((dstAccess_ & m_allowedAccesses) == 0)
+ continue;
+
+ m_unavailableWriteOperations[dstStage][srcStage][dstAccess] = 0;
+ }
}
}
}
// Transitivity
{
vk::VkPipelineStageFlags oldIncompleteOperations[PIPELINESTAGE_LAST];
- vk::VkAccessFlags oldUnavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
+ vk::VkAccessFlags oldUnavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST][ACCESS_LAST];
bool oldUnavailableLayoutTransition[PIPELINESTAGE_LAST];
deMemcpy(oldIncompleteOperations, m_incompleteOperations, sizeof(oldIncompleteOperations));
continue;
// Writes that are available in srcStage are also available in dstStage
- m_unavailableWriteOperations[dstStage][sharedStage] &= oldUnavailableWriteOperations[srcStage][sharedStage];
+ for (vk::VkAccessFlags sharedAccess_ = 1; sharedAccess_ <= m_allowedAccesses; sharedAccess_ <<= 1)
+ {
+ const Access sharedAccess = accessFlagToAccess((vk::VkAccessFlagBits)sharedAccess_);
+
+ if ((sharedAccess_ & m_allowedAccesses) == 0)
+ continue;
+
+ m_unavailableWriteOperations[dstStage][sharedStage][sharedAccess] &= oldUnavailableWriteOperations[srcStage][sharedStage][sharedAccess];
+ }
}
}
}
if ((srcStage_ & m_allowedStages) == 0)
continue;
- // Make srcAccesses from srcStage available in dstStage
- if ((srcStage_ & srcStages) != 0)
- m_unavailableWriteOperations[dstStage][srcStage] &= ~srcAccesses;
+ // Make srcAccesses from srcStage available in dstStage for dstAccess
+ for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
+ {
+ const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+ if ((dstAccess_ & m_allowedAccesses) == 0)
+ continue;
- if (m_unavailableWriteOperations[dstStage][srcStage] != 0)
- allWritesAvailable = false;
+ if (((srcStage_ & srcStages) != 0) && ((dstAccess_ & dstAccesses) != 0))
+ m_unavailableWriteOperations[dstStage][srcStage][dstAccess] &= ~srcAccesses;
+
+ if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess] != 0)
+ allWritesAvailable = false;
+ }
}
// If all writes are available in dstStage make dstAccesses also visible
if ((srcStage_ & m_allowedStages) == 0)
continue;
- // Some write operations are not available yet
- if (m_unavailableWriteOperations[dstStage][srcStage] != 0)
- return false;
+ for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
+ {
+ const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+ if ((dstAccess_ & m_allowedAccesses) == 0)
+ continue;
+
+ // Some write operations are not available yet
+ if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess] != 0)
+ return false;
+ }
}
}
{
ops.push_back(OP_PIPELINE_BARRIER_GLOBAL);
- if (state.hasImage)
+ if (state.hasImage && (state.imageLayout != vk::VK_IMAGE_LAYOUT_UNDEFINED))
ops.push_back(OP_PIPELINE_BARRIER_IMAGE);
if (state.hasBuffer)
}
catch (const tcu::NotSupportedError& e)
{
- if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))))
+ if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))) &&
+ platform.hasDisplay(wsiType))
{
// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
// must support creating native display & window for that WSI type.
}
catch (const tcu::NotSupportedError& e)
{
- if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))))
+ if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
+ platform.hasDisplay(wsiType))
{
// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
// must support creating native display & window for that WSI type.
}
catch (const tcu::NotSupportedError& e)
{
- if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))))
+ if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))) &&
+ platform.hasDisplay(wsiType))
{
// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
// must support creating native display & window for that WSI type.
}
catch (const tcu::NotSupportedError& e)
{
- if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))))
+ if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))) &&
+ platform.hasDisplay(wsiType))
{
// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
// must support creating native display & window for that WSI type.
}
catch (const tcu::NotSupportedError& e)
{
- if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))))
+ if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))) &&
+ platform.hasDisplay(wsiType))
{
// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
// must support creating native display & window for that WSI type.
}
catch (const tcu::NotSupportedError& e)
{
- if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))))
+ if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
+ platform.hasDisplay(wsiType))
{
// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
// must support creating native display & window for that WSI type.
}
catch (const tcu::NotSupportedError& e)
{
- if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))))
+ if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
+ platform.hasDisplay(wsiType))
{
// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
// must support creating native display & window for that WSI type.
TCU_THROW(NotSupportedError, "WSI type not supported on Android");
}
+bool Platform::hasDisplay (vk::wsi::Type wsiType) const
+{
+ if (wsiType == vk::wsi::TYPE_ANDROID)
+ return true;
+
+ return false;
+}
+
} // Android
} // tcu
void describePlatform (std::ostream& dst) const;
void getMemoryLimits (vk::PlatformMemoryLimits& limits) const;
vk::wsi::Display* createWsiDisplay (vk::wsi::Type wsiType) const;
+ bool hasDisplay (vk::wsi::Type wsiType) const;
private:
NativeActivity& m_activity;
{
}
+XlibDisplay::DisplayState XlibDisplay::s_displayState = XlibDisplay::DISPLAY_STATE_UNKNOWN;
+
+bool XlibDisplay::hasDisplay (const char* name)
+{
+ if (s_displayState == DISPLAY_STATE_UNKNOWN)
+ {
+ XInitThreads();
+ Display *display = XOpenDisplay((char*)name);
+ if (display)
+ {
+ s_displayState = DISPLAY_STATE_AVAILABLE;
+ XCloseDisplay(display);
+ } else
+ s_displayState = DISPLAY_STATE_UNAVAILABLE;
+ }
+ return s_displayState == DISPLAY_STATE_AVAILABLE ? true : false;
+}
+
XlibDisplay::XlibDisplay (EventState& eventState, const char* name)
: DisplayBase (eventState)
{
virtual ~DisplayBase (void);
virtual void processEvents (void) = 0;
+ enum DisplayState
+ {
+ DISPLAY_STATE_UNKNOWN = -1,
+ DISPLAY_STATE_UNAVAILABLE,
+ DISPLAY_STATE_AVAILABLE
+ };
+
protected:
EventState& m_eventState;
bool getVisualInfo (VisualID visualID, XVisualInfo& dst);
void processEvents (void);
void processEvent (XEvent& event);
+ static bool hasDisplay (const char* name);
+
+ static DisplayState s_displayState;
protected:
::Display* m_display;
namespace x11
{
+XcbDisplay::DisplayState XcbDisplay::s_displayState = XcbDisplay::DISPLAY_STATE_UNKNOWN;
+
+bool XcbDisplay::hasDisplay (const char* name)
+{
+ if (s_displayState == DISPLAY_STATE_UNKNOWN)
+ {
+ xcb_connection_t *connection = xcb_connect(name, NULL);
+ if (connection)
+ {
+ s_displayState = DISPLAY_STATE_AVAILABLE;
+ xcb_disconnect(connection);
+ } else
+ s_displayState = DISPLAY_STATE_UNAVAILABLE;
+ }
+ return s_displayState == DISPLAY_STATE_AVAILABLE ? true : false;
+}
+
XcbDisplay::XcbDisplay (EventState& platform, const char* name)
: DisplayBase (platform)
{
xcb_connection_t* getConnection (void) { return m_connection; }
void processEvents (void);
+ static bool hasDisplay (const char* name);
+ static DisplayState s_displayState;
protected:
xcb_screen_t* m_screen;
xcb_connection_t* m_connection;
# if defined (DEQP_SUPPORT_XCB)
# include "tcuLnxX11Xcb.hpp"
# endif // DEQP_SUPPORT_XCB
+# define X11_DISPLAY ""
#endif // DEQP_SUPPORT_X11
#if defined (DEQP_SUPPORT_WAYLAND)
# include "tcuLnxWayland.hpp"
+# define WAYLAND_DISPLAY DE_NULL
#endif // DEQP_SUPPORT_WAYLAND
namespace tcu
{
#if defined (DEQP_SUPPORT_X11)
case vk::wsi::TYPE_XLIB:
- return new VulkanDisplayXlib(MovePtr<x11::DisplayBase>(new x11::XlibDisplay(m_eventState,"")));
+ return new VulkanDisplayXlib(MovePtr<x11::DisplayBase>(new x11::XlibDisplay(m_eventState,X11_DISPLAY)));
break;
#endif // DEQP_SUPPORT_X11
#if defined (DEQP_SUPPORT_XCB)
case vk::wsi::TYPE_XCB:
- return new VulkanDisplayXcb(MovePtr<x11::DisplayBase>(new x11::XcbDisplay(m_eventState,"")));
+ return new VulkanDisplayXcb(MovePtr<x11::DisplayBase>(new x11::XcbDisplay(m_eventState,X11_DISPLAY)));
break;
#endif // DEQP_SUPPORT_XCB
#if defined (DEQP_SUPPORT_WAYLAND)
case vk::wsi::TYPE_WAYLAND:
- return new VulkanDisplayWayland(MovePtr<wayland::Display>(new wayland::Display(m_eventState, DE_NULL)));
+ return new VulkanDisplayWayland(MovePtr<wayland::Display>(new wayland::Display(m_eventState, WAYLAND_DISPLAY)));
break;
#endif // DEQP_SUPPORT_WAYLAND
};
}
+bool VulkanPlatform::hasDisplay (vk::wsi::Type wsiType) const
+{
+ switch(wsiType)
+ {
+#if defined (DEQP_SUPPORT_X11)
+ case vk::wsi::TYPE_XLIB:
+ return x11::XlibDisplay::hasDisplay(X11_DISPLAY);
+#endif // DEQP_SUPPORT_X11
+#if defined (DEQP_SUPPORT_XCB)
+ case vk::wsi::TYPE_XCB:
+ return x11::XcbDisplay::hasDisplay(X11_DISPLAY);
+#endif // DEQP_SUPPORT_XCB
+#if defined (DEQP_SUPPORT_WAYLAND)
+ case vk::wsi::TYPE_WAYLAND:
+ return wayland::Display::hasDisplay(WAYLAND_DISPLAY);
+#endif // DEQP_SUPPORT_WAYLAND
+ default:
+ return false;
+ };
+}
vk::Library* VulkanPlatform::createLibrary (void) const
{
return new VulkanLibrary();
VulkanPlatform (EventState& eventState);
vk::wsi::Display* createWsiDisplay (vk::wsi::Type wsiType) const;
vk::Library* createLibrary (void) const;
+ bool hasDisplay (vk::wsi::Type wsiType) const;
void describePlatform (std::ostream& dst) const;
void getMemoryLimits (vk::PlatformMemoryLimits& limits) const;
Display::handleGlobalRemove
};
+Display::DisplayState Display::s_displayState = Display::DISPLAY_STATE_UNKNOWN;
+
const struct wl_shell_surface_listener Window::s_shellSurfaceListener =
{
Window::handlePing,
DE_UNREF(name);
}
+bool Display::hasDisplay (const char* name)
+{
+ if (s_displayState == DISPLAY_STATE_UNKNOWN)
+ {
+ struct wl_display *display = wl_display_connect(name);
+ if (display)
+ {
+ s_displayState = DISPLAY_STATE_AVAILABLE;
+ wl_display_disconnect(display);
+ } else
+ s_displayState = DISPLAY_STATE_UNAVAILABLE;
+ }
+ return s_displayState == DISPLAY_STATE_AVAILABLE ? true : false;
+}
+
Display::Display (EventState& eventState, const char* name)
: m_eventState (eventState)
, m_display (DE_NULL)
struct wl_shell* getShell (void) { return m_shell; }
void processEvents (void);
+ static bool hasDisplay (const char* name);
+
+ enum DisplayState
+ {
+ DISPLAY_STATE_UNKNOWN = -1,
+ DISPLAY_STATE_UNAVAILABLE,
+ DISPLAY_STATE_AVAILABLE
+ };
+ static DisplayState s_displayState;
protected:
EventState& m_eventState;
return new VulkanDisplay();
}
+bool VulkanPlatform::hasDisplay (vk::wsi::Type wsiType) const
+{
+ if (wsiType != vk::wsi::TYPE_MACOS)
+ return false;
+
+ return true;
+}
vk::Library* VulkanPlatform::createLibrary (void) const
{
return new VulkanLibrary();
VulkanPlatform ();
vk::wsi::Display* createWsiDisplay (vk::wsi::Type wsiType) const;
vk::Library* createLibrary (void) const;
+ bool hasDisplay (vk::wsi::Type wsiType) const;
void describePlatform (std::ostream& dst) const;
void getMemoryLimits (vk::PlatformMemoryLimits& limits) const;
};
return new VulkanDisplay(m_instance);
}
+bool VulkanPlatform::hasDisplay (vk::wsi::Type wsiType) const
+{
+ if (wsiType != vk::wsi::TYPE_WIN32)
+ return false;
+
+ return true;
+}
+
} // win32
} // tcu
vk::Library* createLibrary (void) const;
vk::wsi::Display* createWsiDisplay (vk::wsi::Type wsiType) const;
+ bool hasDisplay (vk::wsi::Type wsiType) const;
void getMemoryLimits (vk::PlatformMemoryLimits& limits) const;
void describePlatform (std::ostream& dst) const;