Vulkan fixes

This commit is contained in:
Karol Suprynowicz 2024-08-16 23:42:37 +02:00
parent 19861fe0cf
commit 1a2a401d3f
7 changed files with 91 additions and 53 deletions

View file

@ -100,12 +100,12 @@ public:
}
}
void setContext(gl::Context* context) {
void setContext(vks::Context* context) {
// Move the OpenGL context to the present thread
// Extra code because of the widget 'wrapper' context
_context = context;
_context->doneCurrent();
_context->moveToThread(this);
//_context->doneCurrent();
//_context->moveToThread(this);
}
virtual void run() override {
@ -119,16 +119,16 @@ public:
setPriority(QThread::HighPriority);
VulkanDisplayPlugin* currentPlugin{ nullptr };
Q_ASSERT(_context);
_context->makeCurrent();
CHECK_GL_ERROR();
//_context->makeCurrent();
//CHECK_GL_ERROR();
while (!_shutdown) {
if (_pendingOtherThreadOperation) {
PROFILE_RANGE(render, "MainThreadOp")
{
Lock lock(_mutex);
_context->doneCurrent();
//_context->doneCurrent();
// Move the context to the main thread
_context->moveToThread(_targetOperationThread);
//_context->moveToThread(_targetOperationThread);
_pendingOtherThreadOperation = false;
// Release the main thread to do it's action
_condition.notify_one();
@ -139,7 +139,7 @@ public:
Lock lock(_mutex);
_condition.wait(lock, [&] { return _finishedOtherThreadOperation; });
}
_context->makeCurrent();
//_context->makeCurrent();
}
// Check for a new display plugin
@ -152,9 +152,9 @@ public:
// Deactivate the old plugin
if (currentPlugin != nullptr) {
currentPlugin->uncustomizeContext();
CHECK_GL_ERROR();
//CHECK_GL_ERROR();
// Force completion of all pending GL commands
glFinish();
//glFinish();
}
if (newPlugin) {
@ -164,16 +164,16 @@ public:
#if defined(Q_OS_MAC)
newPlugin->swapBuffers();
#endif
gl::setSwapInterval(wantVsync ? 1 : 0);
//gl::setSwapInterval(wantVsync ? 1 : 0);
#if defined(Q_OS_MAC)
newPlugin->swapBuffers();
#endif
hasVsync = gl::getSwapInterval() != 0;
newPlugin->setVsyncEnabled(hasVsync);
newPlugin->customizeContext();
CHECK_GL_ERROR();
//hasVsync = gl::getSwapInterval() != 0;
//newPlugin->setVsyncEnabled(hasVsync);
//newPlugin->customizeContext();
//CHECK_GL_ERROR();
// Force completion of all pending GL commands
glFinish();
//glFinish();
}
currentPlugin = newPlugin;
}
@ -194,11 +194,11 @@ public:
#endif
// Execute the frame and present it to the display device.
{
PROFILE_RANGE(render, "PluginPresent")
gl::globalLock();
//PROFILE_RANGE(render, "PluginPresent")
//gl::globalLock();
currentPlugin->present(_refreshRateController);
gl::globalRelease(false);
CHECK_GL_ERROR();
//gl::globalRelease(false);
//CHECK_GL_ERROR();
}
#if defined(Q_OS_MAC)
_context->doneCurrent();
@ -207,9 +207,9 @@ public:
_refreshRateController->sleepThreadIfNeeded(this, currentPlugin->isHmd());
}
_context->doneCurrent();
//_context->doneCurrent();
Lock lock(_mutex);
_context->moveToThread(qApp->thread());
//_context->moveToThread(qApp->thread());
_shutdown = false;
_condition.notify_one();
}
@ -222,13 +222,13 @@ public:
_finishedOtherThreadOperation = false;
_condition.wait(lock, [&] { return !_pendingOtherThreadOperation; });
_context->makeCurrent();
//_context->makeCurrent();
f();
_context->doneCurrent();
//_context->doneCurrent();
_targetOperationThread = nullptr;
// Move the context back to the presentation thread
_context->moveToThread(this);
//_context->moveToThread(this);
// restore control of the context to the presentation thread and signal
// the end of the operation
@ -250,7 +250,7 @@ private:
bool _pendingOtherThreadOperation { false };
bool _finishedOtherThreadOperation { false };
std::queue<VulkanDisplayPlugin*> _newPluginQueue;
gl::Context* _context { nullptr };
vks::Context* _context { nullptr };
std::shared_ptr<RefreshRateController> _refreshRateController { nullptr };
};
@ -284,10 +284,10 @@ bool VulkanDisplayPlugin::activate() {
if (!widget->context()->makeCurrent()) {
throw std::runtime_error("Failed to make context current");
}
CHECK_GL_ERROR();
//CHECK_GL_ERROR();
widget->context()->doneCurrent();
presentThread->setContext(widget->context());
presentThread->setContext(&vks::Context::get());
connect(presentThread.data(), &QThread::started, [] { setThreadName("OpenGL Present Thread"); });
// Start execution
presentThread->start();
@ -496,6 +496,7 @@ ktx::StoragePointer textureToKtxVulkan(const gpu::Texture& texture) {
}
{
// TODO
auto gltexelformat = gpu::gl::GLTexelFormat::evalGLTexelFormat(texture.getStoredMipFormat());
header.glInternalFormat = gltexelformat.internalFormat;
header.glFormat = gltexelformat.format;
@ -707,8 +708,13 @@ void VulkanDisplayPlugin::present(const std::shared_ptr<RefreshRateController>&
if (_currentFrame) {
auto correction = getViewCorrection();
getBackend()->setCameraCorrection(correction, _prevRenderView);
auto vkBackend = std::dynamic_pointer_cast<gpu::vulkan::VKBackend>(getBackend());
Q_ASSERT(vkBackend);
vkBackend->setCameraCorrection(correction, _prevRenderView);
_prevRenderView = correction * _currentFrame->view;
uint32_t currentImageIndex = UINT32_MAX;
VK_CHECK_RESULT(_vkWindow->_swapchain.acquireNextImage(_vkWindow->_presentCompleteSemaphore, &currentImageIndex));
Q_ASSERT(currentImageIndex != UINT32_MAX);
{
withPresentThreadLock([&] {
_renderRate.increment();
@ -719,6 +725,8 @@ void VulkanDisplayPlugin::present(const std::shared_ptr<RefreshRateController>&
});
// Execute the frame rendering commands
PROFILE_RANGE_EX(render, "execute", 0xff00ff00, frameId)
vkBackend->setDrawCommandBuffer(_vkWindow->_drawCommandBuffers[currentImageIndex]);
_gpuContext->executeFrame(_currentFrame);
}
@ -747,6 +755,7 @@ void VulkanDisplayPlugin::present(const std::shared_ptr<RefreshRateController>&
PROFILE_RANGE_EX(render, "internalPresent", 0xff00ffff, frameId)
internalPresent();
}
_vkWindow->_swapchain.queuePresent(_vkWindow->_context.queue, currentImageIndex, _vkWindow->_renderCompleteSemaphore);
gpu::Backend::freeGPUMemSize.set(gpu::gl::getFreeDedicatedMemory());
} else if (alwaysPresent()) {

View file

@ -334,15 +334,16 @@ struct Cache {
std::vector<VkAttachmentDescription> attachments;
attachments.reserve(key.size());
std::vector<VkAttachmentReference> colorAttachmentReferences;
VkAttachmentReference depthReference;
VkAttachmentReference depthReference{};
for (const auto& format : key) {
VkAttachmentDescription attachment;
VkAttachmentDescription attachment{};
attachment.format = format;
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
if (isDepthStencilFormat(format)) {
attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depthReference.attachment = (uint32_t)(attachments.size());
@ -359,7 +360,7 @@ struct Cache {
std::vector<VkSubpassDescription> subpasses;
{
VkSubpassDescription subpass;
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
if (depthReference.layout != VK_IMAGE_LAYOUT_UNDEFINED) {
subpass.pDepthStencilAttachment = &depthReference;
@ -461,15 +462,17 @@ struct Cache {
// Shader modules
{
builder.shaderStages.resize(2);
builder.shaderStages.resize(2,{});
{
auto& shaderStage = builder.shaderStages[0];
shaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStage.stage = VK_SHADER_STAGE_VERTEX_BIT;
shaderStage.pName = "main";
shaderStage.module = getShaderModule(context, vertexShader);
}
{
auto& shaderStage = builder.shaderStages[1];
shaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStage.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shaderStage.pName = "main";
shaderStage.module = getShaderModule(context, fragmentShader);
@ -564,14 +567,11 @@ struct Cache {
Cache _cache;
// TODO: this is very cursed and will need to be changed in the future
VkCommandBuffer currentCommandBuffer;
void VKBackend::executeFrame(const FramePointer& frame) {
using namespace vks::debugutils;
{
PROFILE_RANGE(gpu_vk_detail, "Preprocess");
const auto& commandBuffer = currentCommandBuffer;
const auto& commandBuffer = _currentCommandBuffer;
for (const auto& batchPtr : frame->batches) {
const auto& batch = *batchPtr;
cmdBeginLabel(commandBuffer, "batch:" + batch.getName(), glm::vec4{ 1, 1, 0, 1 });
@ -706,6 +706,10 @@ void VKBackend::executeFrame(const FramePointer& frame) {
// _stereo._enable = savedStereo;
}
void VKBackend::setDrawCommandBuffer(VkCommandBuffer commandBuffer) {
_currentCommandBuffer = commandBuffer;
}
void VKBackend::trash(const VKBuffer& buffer) {
}
#if 0

View file

@ -49,6 +49,7 @@ public:
bool supportedTextureFormat(const gpu::Element& format) const override;
const std::string& getVersion() const override;
void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) final override {}
void setDrawCommandBuffer(VkCommandBuffer commandBuffer);
void trash(const VKBuffer& buffer);
@ -133,6 +134,7 @@ protected:
VkQueue _graphicsQueue; //TODO: initialize from device
VkQueue _transferQueue; //TODO: initialize from device
friend class VKBuffer;
VkCommandBuffer _currentCommandBuffer;
};
}} // namespace gpu::vulkan

View file

@ -144,21 +144,24 @@ namespace vks {
const VkDevice& device;
VkPipelineCache pipelineCache;
// TODO: is this initialized properly
VkRenderPass& renderPass { pipelineCreateInfo.renderPass };
VkPipelineLayout& layout { pipelineCreateInfo.layout };
PipelineInputAssemblyStateCreateInfo inputAssemblyState;
PipelineRasterizationStateCreateInfo rasterizationState;
VkPipelineMultisampleStateCreateInfo multisampleState;
PipelineDepthStencilStateCreateInfo depthStencilState;
PipelineViewportStateCreateInfo viewportState;
PipelineDynamicStateCreateInfo dynamicState;
PipelineColorBlendStateCreateInfo colorBlendState;
PipelineVertexInputStateCreateInfo vertexInputState;
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
// TODO: these need to be initialized
PipelineInputAssemblyStateCreateInfo inputAssemblyState {};
PipelineRasterizationStateCreateInfo rasterizationState {};
VkPipelineMultisampleStateCreateInfo multisampleState {};
PipelineDepthStencilStateCreateInfo depthStencilState {};
PipelineViewportStateCreateInfo viewportState {};
PipelineDynamicStateCreateInfo dynamicState {};
PipelineColorBlendStateCreateInfo colorBlendState {};
PipelineVertexInputStateCreateInfo vertexInputState {};
std::vector<VkPipelineShaderStageCreateInfo> shaderStages {};
VkGraphicsPipelineCreateInfo pipelineCreateInfo;
VkGraphicsPipelineCreateInfo pipelineCreateInfo{};
void update() {
pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineCreateInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
pipelineCreateInfo.pStages = shaderStages.data();
dynamicState.update();

View file

@ -5,6 +5,7 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// TODO: based on Vulkan Samples
#include <QtCore/QCoreApplication>
#include <QGuiApplication>
@ -57,11 +58,26 @@ void VKWindow::createSwapchain() {
}
_swapchain.create(&_extent.width, &_extent.height, false, false);
createCommandBuffers();
setupRenderPass();
setupDepthStencil();
setupFramebuffers();
}
void VKWindow::createCommandBuffers() {
VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo();
// Create a semaphore used to synchronize image presentation
// Ensures that the image is displayed before we start submitting new commands to the queue
VK_CHECK_RESULT(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &_presentCompleteSemaphore));
// Create a semaphore used to synchronize command submission
// Ensures that the image is not presented until all commands have been submitted and executed
VK_CHECK_RESULT(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &_renderCompleteSemaphore));
// Create one command buffer for each swap chain image
_drawCommandBuffers.resize(_swapchain.imageCount);
VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(_context.device->commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast<uint32_t>(_drawCommandBuffers.size()));
VK_CHECK_RESULT(vkAllocateCommandBuffers(_device, &cmdBufAllocateInfo, _drawCommandBuffers.data()));
}
void VKWindow::setupDepthStencil() {
auto &device = _context.device->logicalDevice;
if (_depthStencil.isAllocated) {
@ -252,6 +268,8 @@ void VKWindow::resizeFramebuffer() {
}
VKWindow::~VKWindow() {
vkDestroySemaphore(_device, _presentCompleteSemaphore, nullptr);
vkDestroySemaphore(_device, _renderCompleteSemaphore, nullptr);
_swapchain.cleanup();
}

View file

@ -48,14 +48,18 @@ protected:
void setupRenderPass();
void setupDepthStencil();
void setupFramebuffers();
void createCommandBuffers();
public:
vks::Context& _context{ vks::Context::get() };
const VkDevice& _device{ _context.device->logicalDevice };
//VkSurfaceKHR _surface;
VkRenderPass _renderPass;
VkRenderPass _renderPass{};
VkExtent2D _extent;
VulkanSwapChain _swapchain;
VkSemaphore _presentCompleteSemaphore{};
VkSemaphore _renderCompleteSemaphore{};
std::vector<VkCommandBuffer> _drawCommandBuffers;
struct : vks::Allocation {
bool isAllocated {false};
VkImage image;

View file

@ -131,10 +131,6 @@ void RenderThread::shutdown() {
_gpuContext.reset();
}
#ifndef USE_GL
extern VkCommandBuffer currentCommandBuffer;
#endif
void RenderThread::renderFrame(gpu::FramePointer& frame) {
#ifdef USE_GL
PROFILE_RANGE(render_gpu_gl, __FUNCTION__);
@ -178,7 +174,9 @@ void RenderThread::renderFrame(gpu::FramePointer& frame) {
uint32_t swapchainIndex;
VK_CHECK_RESULT(_swapchain.acquireNextImage(acquireComplete, &swapchainIndex));
auto framebuffer = _framebuffers[swapchainIndex];
const auto& commandBuffer = currentCommandBuffer = _vkcontext.createCommandBuffer();
const auto& commandBuffer = _vkcontext.createCommandBuffer();
//auto vkBackend = dynamic_pointer_cast<gpu::vulkan::VKBackend>(getBackend());
//Q_ASSERT(vkBackend);
auto rect = VkRect2D{ offset, _extent };
VkRenderPassBeginInfo beginInfo = vks::initializers::renderPassBeginInfo();