diff --git a/display/lava-extras/display/DisplayOutput.cc b/display/lava-extras/display/DisplayOutput.cc index 205f4d52b15c57229d3cf3872beefc5bee3021e5..b94ec6dec41ad35f3f99e21fa2f531b5dcdec8ea 100644 --- a/display/lava-extras/display/DisplayOutput.cc +++ b/display/lava-extras/display/DisplayOutput.cc @@ -29,15 +29,9 @@ DisplayOutput::instanceExtensions(const std::vector<const char *> &available) { return result; } -void DisplayOutput::onInstanceCreated(Instance *instance) {} - std::vector<const char *> DisplayOutput::deviceExtensions() { return {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; } -void DisplayOutput::onPhysicalDeviceSelected(vk::PhysicalDevice phy) {} - -void DisplayOutput::onLogicalDeviceCreated(const SharedDevice &device) {} - } // namespace display } // namespace lava diff --git a/display/lava-extras/display/DisplayOutput.hh b/display/lava-extras/display/DisplayOutput.hh index 1949c642f9679e29b8608eab151dcf3bfe21e5cf..401e04c638abe5735a246bd10d120f3635098706 100644 --- a/display/lava-extras/display/DisplayOutput.hh +++ b/display/lava-extras/display/DisplayOutput.hh @@ -18,19 +18,8 @@ class DisplayOutput : public lava::features::IFeature { uint32_t index); /* IFeature overrides */ - std::vector<const char *> instanceExtensions(std::vector<const char *> const& available) override; - - void onInstanceCreated(Instance *instance) override; - std::vector<const char *> deviceExtensions() override; - void onPhysicalDeviceSelected(vk::PhysicalDevice phy) override; - void onLogicalDeviceCreated(SharedDevice const &device) override; - - protected: - lava::Instance *mInstance; - lava::Device *mDevice; - vk::PhysicalDevice mPhysicalDevice; }; } // namespace display } // namespace lava diff --git a/display/lava-extras/display/TiledDisplay.cc b/display/lava-extras/display/TiledDisplay.cc new file mode 100644 index 0000000000000000000000000000000000000000..88d17bb6f6341fbf3ed92959e13fc00120ecd54f --- /dev/null +++ b/display/lava-extras/display/TiledDisplay.cc @@ -0,0 +1,98 @@ +#include "TiledDisplay.hh" +#include "DisplayOutput.hh" +#include "DisplayWindow.hh" +#include <lava/createinfos/Images.hh> +#include <lava/objects/Device.hh> +#include <lava/objects/Image.hh> +#include <lava/objects/MemoryChunk.hh> + +namespace lava { + +namespace display { + +lava::display::TiledDisplay::TiledDisplay( + const std::vector<lava::SharedDevice> &devices, + const lava::display::TiledDisplay::Config &config) + : mConfig(config), mDevices(devices) { + + auto output = devices[0]->get<DisplayOutput>(); + if (!output) + throw std::logic_error("TiledDisplay: all devices need to have the " + "DisplayOutput feature."); + + for (auto const &c : config.tiles) { + mWindows.push_back(output->openWindow(mDevices[c.device], c.display)); + } + + auto ci = lava::ImageCreateInfo() + .setTiling(vk::ImageTiling::eLinear) + .setCombinedType(vk::ImageViewType::e2D) + .setSize(config.sourceWidth, config.sourceHeight) + .setFormat(config.sourceFormat) + .setMipLevels(1); + + for (auto const &d : devices) { + auto img = ci.create(d); + img->realizeRAM(); + img->changeLayout(vk::ImageLayout::eGeneral); + mHostImages.push_back(img); + } +} + +void TiledDisplay::submit(const SharedImage &image) { + auto master_idx = + std::find(begin(mDevices), end(mDevices), image->device()) - + begin(mDevices); + if (master_idx == mDevices.size()) + throw std::logic_error( + "For now you should present to the original device, too"); + + image->blitTo(mHostImages[master_idx]); + auto master_map = mHostImages[master_idx]->memoryChunk()->map(); + + for (size_t i = 0; i < mHostImages.size(); i++) { + if (i == master_idx) + continue; + auto map = mHostImages[i]->memoryChunk()->map(); + memcpy(map.data(), master_map.data(), + mHostImages[master_idx]->levelBytes(0)); + } + + for (size_t i = 0; i < mConfig.tiles.size(); i++) { + auto const &tile = mConfig.tiles[i]; + auto const &window = mWindows[i]; + auto frame = window->startFrame(); + { + auto cmd = + mDevices[tile.device]->graphicsQueue().beginCommandBuffer(); + + auto sub = vk::ImageSubresourceLayers() + .setAspectMask(vk::ImageAspectFlagBits::eColor) + .setLayerCount(1); + + auto src = + (tile.device == master_idx) ? image : mHostImages[tile.device]; + + src->blitTo( + frame.image(), cmd, + vk::ImageBlit() + .setSrcOffsets( + {{vk::Offset3D{tile.srcRect.offset.x, + tile.srcRect.offset.y, 0}, + vk::Offset3D(tile.srcRect.offset.x + + tile.srcRect.extent.width, + tile.srcRect.offset.y + + tile.srcRect.extent.height, + 1)}}) + .setDstOffsets( + {{vk::Offset3D{0, 0, 0}, + vk::Offset3D(window->width(), window->height(), 1)}}) + + .setSrcSubresource(sub) + .setDstSubresource(sub)); + } + } +} + +} // namespace display +} // namespace lava diff --git a/display/lava-extras/display/TiledDisplay.hh b/display/lava-extras/display/TiledDisplay.hh new file mode 100644 index 0000000000000000000000000000000000000000..f10a68996b285abfa8e8884afdcc6791e42037cf --- /dev/null +++ b/display/lava-extras/display/TiledDisplay.hh @@ -0,0 +1,39 @@ +#pragma once +#include <vector> + +#include <lava/fwd.hh> +#include <lava/common/vulkan.hh> +#include "fwd.hh" + +namespace lava { +namespace display { + +class TiledDisplay { + public: + struct TileConfig { + int device; + int display; + + vk::Rect2D srcRect; + }; + + struct Config { + int sourceHeight, sourceWidth; + vk::Format sourceFormat; + std::vector<TileConfig> tiles; + }; + + TiledDisplay(std::vector<SharedDevice> const& devices, Config const &config); + + void submit(SharedImage const &image); + + protected: + Config mConfig; + std::vector<SharedDisplayWindow> mWindows; + std::vector<SharedDevice> mDevices; + std::vector<char> mBuffer; + std::vector<SharedImage> mHostImages; +}; + +} // namespace display +} // namespace lava diff --git a/display/lava-extras/display/fwd.hh b/display/lava-extras/display/fwd.hh new file mode 100644 index 0000000000000000000000000000000000000000..57b01c68dc0f4c5000570673183540d420539a64 --- /dev/null +++ b/display/lava-extras/display/fwd.hh @@ -0,0 +1,18 @@ +#pragma once +#include <memory> + +#define LAVA_FORWARD_DECLARE_CLASS(T) \ + class T; \ + using Shared ## T = std::shared_ptr<T>; \ + using Weak ## T = std::weak_ptr<T>; \ + using Unique ## T = std::unique_ptr<T> + +namespace lava { +namespace display { + LAVA_FORWARD_DECLARE_CLASS(DisplayOutput); + LAVA_FORWARD_DECLARE_CLASS(DisplayWindow); + LAVA_FORWARD_DECLARE_CLASS(TiledDisplay); +} +} + +#undef LAVA_FORWARD_DECLARE_CLASS