Vulkan/opengl transfer test

This commit is contained in:
Brad Davis 2019-07-01 08:50:03 -07:00 committed by Karol Suprynowicz
parent b7efed9461
commit c9130d9da1
3 changed files with 253 additions and 21 deletions

View file

@ -74,6 +74,14 @@ void PlayerWindow::keyPressEvent(QKeyEvent* event) {
loadFrame();
return;
case Qt::Key_F3:
_renderThread.testGlTransfer();
return;
case Qt::Key_F4:
_renderThread.testVkTransfer();
return;
case Qt::Key_W:
_renderThread.move(vec3{ 0, 0, -0.1f } * moveScale);
return;
@ -114,7 +122,7 @@ static const QString DEFAULT_TRACING_RULES =
void PlayerWindow::loadFrame(const QString& path) {
DependencyManager::get<tracing::Tracer>()->startTracing();
QLoggingCategory::setFilterRules(DEFAULT_TRACING_RULES);
QTimer::singleShot(8000, [] {
QTimer::singleShot(10 * 1000, [] {
DependencyManager::get<tracing::Tracer>()->stopTracing();
DependencyManager::get<tracing::Tracer>()->serialize("D:/frames/trace-{DATE}_{TIME}.json.gz");
});

View file

@ -8,7 +8,8 @@
#include "RenderThread.h"
#include <QtGui/QWindow>
#include <QtCore/QThreadPool>
#include <gl/OffscreenGLCanvas.h>
#ifdef USE_GL
#include <gl/QOpenGLContextWrapper.h>
#endif
@ -34,7 +35,13 @@ void RenderThread::initialize(QWindow* window) {
Parent::initialize();
_window = window;
_vkcontext.setValidationEnabled(true);
#ifdef USE_GL
_vkcontext.createInstance();
_vkcontext.createDevice();
_vkstagingBuffer = _vkcontext.createStagingBuffer(1024 * 1024 * 512, nullptr);
_window->setFormat(getDefaultOpenGLSurfaceFormat());
_context.setWindow(window);
_context.create();
@ -64,15 +71,14 @@ void RenderThread::initialize(QWindow* window) {
auto size = window->size();
_extent = vk::Extent2D{ (uint32_t)size.width(), (uint32_t)size.height() };
_context.setValidationEnabled(true);
_context.requireExtensions({
_vkcontext.requireExtensions({
std::string{ VK_KHR_SURFACE_EXTENSION_NAME },
std::string{ VK_KHR_WIN32_SURFACE_EXTENSION_NAME },
});
_context.requireDeviceExtensions({ VK_KHR_SWAPCHAIN_EXTENSION_NAME });
_context.createInstance();
_surface = _context.instance.createWin32SurfaceKHR({ {}, GetModuleHandle(NULL), (HWND)window->winId() });
_context.createDevice(_surface);
_vkcontext.requireDeviceExtensions({ VK_KHR_SWAPCHAIN_EXTENSION_NAME });
_vkcontext.createInstance();
_surface = _vkcontext.instance.createWin32SurfaceKHR({ {}, GetModuleHandle(NULL), (HWND)window->winId() });
_vkcontext.createDevice(_surface);
_swapchain.setSurface(_surface);
_swapchain.create(_extent, true);
@ -124,11 +130,11 @@ void RenderThread::renderFrame(gpu::FramePointer& frame) {
_context.makeCurrent();
#endif
if (_correction != glm::mat4()) {
std::unique_lock<std::mutex> lock(_frameLock);
if (_correction != glm::mat4()) {
_backend->setCameraCorrection(_correction, _activeFrame->view, true);
//_prevRenderView = _correction * _activeFrame->view;
}
std::unique_lock<std::mutex> lock(_frameLock);
if (_correction != glm::mat4()) {
_backend->setCameraCorrection(_correction, _activeFrame->view, true);
//_prevRenderView = _correction * _activeFrame->view;
}
}
_backend->recycle();
_backend->syncCache();
@ -196,10 +202,9 @@ void RenderThread::renderFrame(gpu::FramePointer& frame) {
//glClear(GL_COLOR_BUFFER_BIT);
/* glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(
0, 0, fboSize.x, fboSize.y,
0, 0, windowSize.width(), windowSize.height(),
GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBlitFramebuffer(0, 0, fboSize.x, fboSize.y, 0, 0, windowSize.width(), windowSize.height(), GL_COLOR_BUFFER_BIT,
GL_NEAREST);
*/
(void)CHECK_GL_ERROR();
_context.swapBuffers();
@ -232,7 +237,7 @@ bool RenderThread::process() {
pendingFrames.swap(_pendingFrames);
pendingSize.swap(_pendingSize);
}
while (!pendingFrames.empty()) {
_activeFrame = pendingFrames.front();
pendingFrames.pop();
@ -318,3 +323,216 @@ void RenderThread::setupRenderPass() {
_renderPass = _device.createRenderPass(renderPassInfo);
}
#endif
class QLambdaRunnable : public QRunnable {
public:
QLambdaRunnable(const std::function<void()>& f) : _f(f) {}
void run() override { _f(); }
private:
std::function<void()> _f;
};
struct VkBufferTransferItem {
using Vector = std::vector<VkBufferTransferItem>;
vk::DeviceSize offset{ 0 };
gpu::BufferPointer gpuBuffer;
vks::Buffer deviceBuffer;
void allocateDeviceBuffer(const vks::Context& context) {
static const vk::BufferUsageFlags flags = vk::BufferUsageFlagBits::eVertexBuffer |
vk::BufferUsageFlagBits::eUniformBuffer |
vk::BufferUsageFlagBits::eTransferDst;
deviceBuffer = context.createDeviceBuffer(flags, gpuBuffer->getSize());
}
static void populateStagingBuffer(vks::Buffer& stagingBuffer, Vector& vector) {
vk::DeviceSize totalSize = 0;
for (auto& item : vector) {
item.offset = totalSize;
totalSize += item.gpuBuffer->getSize();
}
stagingBuffer.map();
for (auto& item : vector) {
const auto& gpuBuffer = item.gpuBuffer;
auto itemSize = gpuBuffer->getSize();
item.offset = totalSize;
if ((itemSize + item.offset) >= stagingBuffer.size) {
qDebug() << "Bad copy";
}
stagingBuffer.copy(itemSize, gpuBuffer->getData(), item.offset);
totalSize += itemSize;
}
stagingBuffer.unmap();
}
static void transferBuffers(const vks::Context& context, vks::Buffer& stagingBuffer, Vector& vector) {
vk::CommandPool commandPool;
{
vk::CommandPoolCreateInfo createInfo{ vk::CommandPoolCreateFlagBits::eTransient, context.queueIndices.transfer };
commandPool = context.device.createCommandPool(createInfo);
}
vk::CommandBuffer commandBuffer;
{
vk::CommandBufferAllocateInfo allocInfo{ commandPool, vk::CommandBufferLevel::ePrimary, 1 };
commandBuffer = context.device.allocateCommandBuffers(allocInfo)[0];
}
commandBuffer.begin(vk::CommandBufferBeginInfo{ vk::CommandBufferUsageFlagBits::eOneTimeSubmit });
for (auto& item : vector) {
vk::BufferCopy region{ item.offset, 0, item.gpuBuffer->getSize() };
commandBuffer.copyBuffer(stagingBuffer.buffer, item.deviceBuffer.buffer, region);
}
commandBuffer.end();
{
PROFILE_RANGE(render_gpu_gl, "vk_submitTranferCommandBuffer");
auto transferQueue = context.device.getQueue(context.queueIndices.transfer, 0);
auto fence = context.device.createFence({});
{
vk::SubmitInfo submitInfo{};
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
transferQueue.submit(submitInfo, fence);
}
{
PROFILE_RANGE(render_gpu_gl, "vk_submitTranferCommandBufferWait");
transferQueue.waitIdle();
while (vk::Result::eSuccess != context.device.waitForFences(fence, VK_TRUE, UINT64_MAX)) {
QThread::msleep(1);
}
}
}
}
};
void RenderThread::testVkTransfer() {
static std::atomic<bool> running{ false };
if (running) {
return;
}
running = true;
QThreadPool::globalInstance()->start(new QLambdaRunnable([this] {
PROFILE_RANGE(render_gpu_gl, "vk_bufferCopyTest");
VkBufferTransferItem::Vector bufferTransfers;
{
std::unordered_set<gpu::BufferPointer> allBuffers;
for (const auto& batch : _activeFrame->batches) {
for (const auto& buffer : batch->_buffers._items) {
if (buffer._data && 0 != buffer._data->getSize()) {
allBuffers.insert(buffer._data);
}
}
}
{
PROFILE_RANGE(render_gpu_gl, "vk_populateStagingBuffers");
bufferTransfers.resize(allBuffers.size());
size_t i = 0;
for (const auto& buffer : allBuffers) {
auto& item = bufferTransfers[i++];
item.gpuBuffer = buffer;
}
VkBufferTransferItem::populateStagingBuffer(_vkstagingBuffer, bufferTransfers);
}
}
//{
// PROFILE_RANGE(render_gpu_gl, "vk_defragStagingBuffers");
// VkBufferTransferItem::defragStagingBuffers(_vkcontext, bufferTransfers);
//}
{
PROFILE_RANGE(render_gpu_gl, "vk_allocateDeviceBuffers");
for (auto& item : bufferTransfers) {
item.allocateDeviceBuffer(_vkcontext);
}
}
{
PROFILE_RANGE(render_gpu_gl, "vk_transferBuffers");
VkBufferTransferItem::transferBuffers(_vkcontext, _vkstagingBuffer, bufferTransfers);
}
{
PROFILE_RANGE(render_gpu_gl, "vk_destroyTransferDeviceBuffers");
for (auto& item : bufferTransfers) {
item.deviceBuffer.destroy();
}
}
running = false;
}));
}
struct GlBufferTransferItem {
using Vector = std::vector<GlBufferTransferItem>;
gpu::BufferPointer gpuBuffer;
GLuint glbuffer;
void allocateDeviceBuffer() {
glCreateBuffers(1, &glbuffer);
glNamedBufferStorage(glbuffer, gpuBuffer->getSize(), gpuBuffer->getData(), 0);
}
void destroyDeviceBuffer() { glDeleteBuffers(1, &glbuffer); }
};
void RenderThread::testGlTransfer() {
static std::atomic<bool> running{ false };
if (running) {
return;
}
running = true;
QThreadPool::globalInstance()->start(new QLambdaRunnable([this] {
static std::once_flag once;
static OffscreenGLCanvas glcanvas;
std::call_once(once, [] {
glcanvas.create();
glcanvas.makeCurrent();
});
PROFILE_RANGE(render_gpu_gl, "gl_bufferTransferTest");
GlBufferTransferItem::Vector bufferTransfers;
{
std::unordered_set<gpu::BufferPointer> allBuffers;
for (const auto& batch : _activeFrame->batches) {
for (const auto& buffer : batch->_buffers._items) {
if (buffer._data && 0 != buffer._data->getSize()) {
allBuffers.insert(buffer._data);
}
}
}
{
PROFILE_RANGE(render_gpu_gl, "gl_initBuffers");
bufferTransfers.resize(allBuffers.size());
size_t i = 0;
for (const auto& buffer : allBuffers) {
auto& item = bufferTransfers[i++];
item.gpuBuffer = buffer;
}
}
}
{
PROFILE_RANGE(render_gpu_gl, "gl_allocateDeviceBuffers");
for (auto& item : bufferTransfers) {
item.allocateDeviceBuffer();
}
}
{
PROFILE_RANGE(render_gpu_gl, "gl_destroyDeviceBuffers");
for (auto& item : bufferTransfers) {
item.destroyDeviceBuffer();
}
}
running = false;
}));
}

View file

@ -13,12 +13,14 @@
#include <GenericThread.h>
#include <shared/RateCounter.h>
#include <vk/Config.h>
#include <vk/Context.h>
#ifdef USE_GL
#include <gl/Config.h>
#include <gl/Context.h>
#include <gpu/gl/GLBackend.h>
#else
#include <vk/VKWindow.h>
#include <gpu/vk/VKBackend.h>
#endif
@ -27,11 +29,13 @@ class RenderThread : public GenericThread {
public:
QWindow* _window{ nullptr };
vks::Context& _vkcontext{ vks::Context::get() };
const vk::Device& _vkdevice{ _vkcontext.device };
vks::Buffer _vkstagingBuffer;
#ifdef USE_GL
gl::Context _context;
#else
vks::Context& _context{ vks::Context::get() };
const vk::Device& _device{ _context.device };
vk::SurfaceKHR _surface;
vk::RenderPass _renderPass;
@ -63,6 +67,8 @@ public:
void setup() override;
bool process() override;
void shutdown() override;
void testVkTransfer();
void testGlTransfer();
void submitFrame(const gpu::FramePointer& frame);
void initialize(QWindow* window);