Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VulkanRenderManager - big refactoring of the Vulkan code #10033

Merged
merged 28 commits into from
Oct 26, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
84ed793
Initial work on render queue manager
hrydgard Aug 16, 2017
417b96a
Use RenderManager for thin3d stuff
hrydgard Aug 18, 2017
0a0494e
It builds! With some shortcuts, of course.
hrydgard Aug 19, 2017
833916a
A multitude of fixes. The UI now works correctly, though of course in…
hrydgard Aug 22, 2017
02f76ae
Rendering basics now works.
hrydgard Aug 22, 2017
1c5bd0f
Move the VulkanRenderManager stuff to thin3d, fits in better there.
hrydgard Aug 22, 2017
c788dc8
Synchronization is HARD. need a rethink, methinks.
hrydgard Aug 22, 2017
022657e
This makes a little more sense, but still hangs (frameAvailable = tru…
hrydgard Aug 22, 2017
48ac334
Vulkan: Don't forget to specify stencil load op in render passes
hrydgard Aug 28, 2017
d3672d9
Make sure not to begin and end the init command buffer on different t…
hrydgard Aug 22, 2017
72a41cd
Let's try a mutex. Doesn't completely solve the problem though..
hrydgard Aug 25, 2017
c403edf
Avoid re-binding pipelines.
hrydgard Aug 28, 2017
3e2b810
Improve synchronization, though there are very weird issues. Possibly…
hrydgard Aug 28, 2017
b5e06f3
VulkanRenderManager: BindPipeline should really be its own command. T…
hrydgard Oct 23, 2017
c4f0afc
Clean out some obsolete code
hrydgard Oct 9, 2017
d016bfe
Fix some resource leaks and excessive logging in VulkanRenderManager
hrydgard Oct 25, 2017
8639664
Warning fixes, CMakeLists.txt/Android.mk fixes
hrydgard Oct 25, 2017
9b183f1
Forgot to add the CMakeLists.txt change to the last commit.
hrydgard Oct 25, 2017
85cb604
Fix (some) crashes on blits. Validation issues remain.
hrydgard Oct 25, 2017
12f8580
Assorted fixes
hrydgard Oct 25, 2017
613cc46
Remove a bad check making us use the wrong way to copy depth buffers.…
hrydgard Oct 25, 2017
54e4eab
Warning fixes
hrydgard Oct 25, 2017
8644e85
Remove misguided hack.
hrydgard Oct 25, 2017
07e8b4f
Bump descriptor set limits, which became insufficient with the additi…
hrydgard Oct 25, 2017
ecad09d
32-bit android buildfix attempt
hrydgard Oct 25, 2017
7312576
More buildfixes, warning fix, memory leak fix
hrydgard Oct 26, 2017
5456194
Fix integer overflow affecting very large draw calls
hrydgard Oct 26, 2017
1e9984d
Another buildfix
hrydgard Oct 26, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
439 changes: 16 additions & 423 deletions Common/Vulkan/VulkanContext.cpp

Large diffs are not rendered by default.

99 changes: 24 additions & 75 deletions Common/Vulkan/VulkanContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,7 @@ class VulkanDeleteList {
std::vector<Callback> callbacks_;
};

// VulkanContext sets up the basics necessary for rendering to a window, including framebuffers etc.
// Optionally, it can create a depth buffer for you as well.
// VulkanContext manages the device and swapchain, and deferred deletion of objects.
class VulkanContext {
public:
VulkanContext();
Expand Down Expand Up @@ -227,19 +226,12 @@ class VulkanContext {
void ReinitSurfaceAndroid(int width, int height);
#endif
void InitQueue();
bool InitObjects(bool depthPresent);
bool InitSwapchain(VkCommandBuffer cmd);
void InitSurfaceRenderPass(bool include_depth, bool clear);
void InitFramebuffers(bool include_depth);
void InitDepthStencilBuffer(VkCommandBuffer cmd);
bool InitObjects();
bool InitSwapchain();

// Also destroys the surface.
void DestroyObjects();

void DestroySurfaceRenderPass();
void DestroyFramebuffers();
void DestroySwapChain();
void DestroyDepthStencilBuffer();
void DestroyDevice();

void WaitUntilQueueIdle();
Expand All @@ -248,41 +240,17 @@ class VulkanContext {
VkFence CreateFence(bool presignalled);
bool CreateShaderModule(const std::vector<uint32_t> &spirv, VkShaderModule *shaderModule);

void WaitAndResetFence(VkFence fence);
int GetBackbufferWidth() { return width_; }
int GetBackbufferHeight() { return height_; }

int GetWidth() { return width_; }
int GetHeight() { return height_; }

VkCommandBuffer GetInitCommandBuffer();

VkFramebuffer GetSurfaceFramebuffer() {
return framebuffers_[current_buffer];
}
// This must only be accessed between BeginSurfaceRenderPass and EndSurfaceRenderPass.
VkCommandBuffer GetSurfaceCommandBuffer() {
return frame_[curFrame_].cmdBuf;
}

VkCommandBuffer BeginFrame();
// The surface render pass is special because it has to acquire the backbuffer, and may thus "block".
// Use the returned command buffer to enqueue commands that render to the backbuffer.
// To render to other buffers first, you can submit additional commandbuffers using QueueBeforeSurfaceRender(cmd).
VkCommandBuffer BeginSurfaceRenderPass(VkClearValue clear_values[2]);
// May eventually need the ability to break and resume the backbuffer render pass in a few rare cases.
void EndSurfaceRenderPass();
void BeginFrame();
void EndFrame();

void QueueBeforeSurfaceRender(VkCommandBuffer cmd);

bool MemoryTypeFromProperties(uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex);

VkResult InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFunc, int bits, void *userdata = nullptr);
void DestroyDebugMsgCallback();

VkRenderPass GetSurfaceRenderPass() const {
return surface_render_pass_;
}

VkPhysicalDevice GetPhysicalDevice(int n = 0) const {
return physical_devices_[n];
}
Expand Down Expand Up @@ -327,8 +295,19 @@ class VulkanContext {
return inflightFrames_;
}

int GetCurFrame() const {
return curFrame_;
}

VkSwapchainKHR GetSwapchain() const {
return swapchain_;
}
VkFormat GetSwapchainFormat() const {
return swapchainFormat_;
}

enum {
MAX_INFLIGHT_FRAMES = 2,
MAX_INFLIGHT_FRAMES = 3,
};

private:
Expand All @@ -340,9 +319,6 @@ class VulkanContext {

bool CheckLayers(const std::vector<LayerProperties> &layer_props, const std::vector<const char *> &layer_names) const;

VkSemaphore acquireSemaphore_;
VkSemaphore renderingCompleteSemaphore_;

#ifdef _WIN32
HINSTANCE connection = nullptr; // hInstance - Windows Instance
HWND window = nullptr; // hWnd - window handle
Expand Down Expand Up @@ -380,36 +356,15 @@ class VulkanContext {
// Custom collection of things that are good to know
VulkanPhysicalDeviceInfo deviceInfo_;

struct swap_chain_buffer {
VkImage image;
VkImageView view;
};

// Swap chain
int width_ = 0;
int height_ = 0;
int flags_ = 0;
VkFormat swapchain_format = VK_FORMAT_UNDEFINED;
std::vector<VkFramebuffer> framebuffers_;
uint32_t swapchainImageCount = 0;
VkSwapchainKHR swap_chain_ = VK_NULL_HANDLE;
std::vector<swap_chain_buffer> swapChainBuffers;

int inflightFrames_ = MAX_INFLIGHT_FRAMES;

// Manages flipping command buffers for the backbuffer render pass.
// It is recommended to do the same for other rendering passes.
struct FrameData {
FrameData() : hasInitCommands(false), cmdInit(nullptr), cmdBuf(nullptr) {}

VkFence fence;
bool hasInitCommands;

// TODO: Move to frame data
VkCommandPool cmdPool;
VkCommandBuffer cmdInit;
VkCommandBuffer cmdBuf;

FrameData() {}
VulkanDeleteList deleteList;
};
FrameData frame_[MAX_INFLIGHT_FRAMES];
Expand All @@ -421,15 +376,9 @@ class VulkanContext {

std::vector<VkDebugReportCallbackEXT> msg_callbacks;

struct {
VkFormat format;
VkImage image = VK_NULL_HANDLE;
VkDeviceMemory mem = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
} depth;
VkSwapchainKHR swapchain_;
VkFormat swapchainFormat_;

VkRenderPass surface_render_pass_ = VK_NULL_HANDLE;
uint32_t current_buffer = 0;
uint32_t queue_count = 0;

VkPhysicalDeviceFeatures featuresAvailable_;
Expand All @@ -438,15 +387,15 @@ class VulkanContext {
std::vector<VkCommandBuffer> cmdQueue_;
};

// Stand-alone utility functions
void VulkanBeginCommandBuffer(VkCommandBuffer cmd);

// Detailed control.
void TransitionImageLayout2(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask,
VkImageLayout oldImageLayout, VkImageLayout newImageLayout,
VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask);

void TransitionFromPresent(VkCommandBuffer cmd, VkImage image);
void TransitionToPresent(VkCommandBuffer cmd, VkImage image);

// GLSL compiler
void init_glslang();
void finalize_glslang();
Expand Down
17 changes: 5 additions & 12 deletions Common/Vulkan/VulkanImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,9 @@ uint8_t *VulkanTexture::Lock(int level, int *rowPitch) {
return (uint8_t *)data;
}

void VulkanTexture::Unlock() {
void VulkanTexture::Unlock(VkCommandBuffer cmd) {
vkUnmapMemory(vulkan_->GetDevice(), mappableMemory);

VkCommandBuffer cmd = vulkan_->GetInitCommandBuffer();

// if we already have an image, queue it for destruction and forget it.
Wipe();

Expand Down Expand Up @@ -227,11 +225,9 @@ static bool IsDepthStencilFormat(VkFormat format) {
}
}

bool VulkanTexture::CreateDirect(int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage, const VkComponentMapping *mapping) {
bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage, const VkComponentMapping *mapping) {
Wipe();

VkCommandBuffer cmd = vulkan_->GetInitCommandBuffer();

tex_width = w;
tex_height = h;
numMips_ = numMips;
Expand Down Expand Up @@ -336,7 +332,7 @@ bool VulkanTexture::CreateDirect(int w, int h, int numMips, VkFormat format, VkI
return true;
}

void VulkanTexture::UploadMip(int mip, int mipWidth, int mipHeight, VkBuffer buffer, uint32_t offset, size_t rowLength) {
void VulkanTexture::UploadMip(VkCommandBuffer cmd, int mip, int mipWidth, int mipHeight, VkBuffer buffer, uint32_t offset, size_t rowLength) {
VkBufferImageCopy copy_region = {};
copy_region.bufferOffset = offset;
copy_region.bufferRowLength = (uint32_t)rowLength;
Expand All @@ -349,21 +345,18 @@ void VulkanTexture::UploadMip(int mip, int mipWidth, int mipHeight, VkBuffer buf
copy_region.imageSubresource.baseArrayLayer = 0;
copy_region.imageSubresource.layerCount = 1;

VkCommandBuffer cmd = vulkan_->GetInitCommandBuffer();
vkCmdCopyBufferToImage(cmd, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy_region);
}

void VulkanTexture::EndCreate() {
VkCommandBuffer cmd = vulkan_->GetInitCommandBuffer();
void VulkanTexture::EndCreate(VkCommandBuffer cmd) {
TransitionImageLayout2(cmd, image,
VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
}

void VulkanTexture::TransitionForUpload() {
VkCommandBuffer cmd = vulkan_->GetInitCommandBuffer();
void VulkanTexture::TransitionForUpload(VkCommandBuffer cmd) {
TransitionImageLayout2(cmd, image,
VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
Expand Down
10 changes: 5 additions & 5 deletions Common/Vulkan/VulkanImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ class VulkanTexture {
// been called.
VkResult Create(int w, int h, VkFormat format);
uint8_t *Lock(int level, int *rowPitch);
void Unlock();
void Unlock(VkCommandBuffer cmd);

// Fast uploads from buffer. Mipmaps supported.
// Usage must at least include VK_IMAGE_USAGE_TRANSFER_DST_BIT in order to use UploadMip.
// When using UploadMip, initialLayout should be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
bool CreateDirect(int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, const VkComponentMapping *mapping = nullptr);
void UploadMip(int mip, int mipWidth, int mipHeight, VkBuffer buffer, uint32_t offset, size_t rowLength); // rowLength is in pixels
void EndCreate();
bool CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, const VkComponentMapping *mapping = nullptr);
void UploadMip(VkCommandBuffer cmd, int mip, int mipWidth, int mipHeight, VkBuffer buffer, uint32_t offset, size_t rowLength); // rowLength is in pixels
void EndCreate(VkCommandBuffer cmd);

void TransitionForUpload();
void TransitionForUpload(VkCommandBuffer cmd);

int GetNumMips() const { return numMips_; }
void Destroy();
Expand Down
Loading