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 2 commits
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
2 changes: 2 additions & 0 deletions Common/Common.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@
<ClInclude Include="Vulkan\VulkanImage.h" />
<ClInclude Include="Vulkan\VulkanLoader.h" />
<ClInclude Include="Vulkan\VulkanMemory.h" />
<ClInclude Include="Vulkan\VulkanRenderManager.h" />
<ClInclude Include="x64Analyzer.h" />
<ClInclude Include="x64Emitter.h" />
</ItemGroup>
Expand Down Expand Up @@ -320,6 +321,7 @@
<ClCompile Include="Vulkan\VulkanImage.cpp" />
<ClCompile Include="Vulkan\VulkanLoader.cpp" />
<ClCompile Include="Vulkan\VulkanMemory.cpp" />
<ClCompile Include="Vulkan\VulkanRenderManager.cpp" />
<ClCompile Include="x64Analyzer.cpp" />
<ClCompile Include="x64Emitter.cpp" />
</ItemGroup>
Expand Down
4 changes: 3 additions & 1 deletion Common/Common.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
</ClInclude>
<ClInclude Include="OSVersion.h" />
<ClInclude Include="Hashmaps.h" />
<ClInclude Include="Vulkan\VulkanRenderManager.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp" />
Expand Down Expand Up @@ -138,6 +139,7 @@
<ClCompile Include="MemArenaAndroid.cpp" />
<ClCompile Include="MemArenaDarwin.cpp" />
<ClCompile Include="OSVersion.cpp" />
<ClCompile Include="Vulkan\VulkanRenderManager.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="Crypto">
Expand All @@ -153,4 +155,4 @@
<UniqueIdentifier>{c14d66ef-5f7c-4565-975a-72774e7ccfb9}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>
116 changes: 116 additions & 0 deletions Common/Vulkan/VulkanRenderManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include "base/logging.h"

#include "VulkanRenderManager.h"

void VulkanRenderManager::BeginFrameWrites() {
vulkan_->BeginFrame();
renderPasses_.push_back(new VKRRenderPass);
curRp_ = renderPasses_.back();
}

void VulkanRenderManager::EndFrame() {
vulkan_->EndFrame();
}


void VulkanRenderManager::Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask) {
// If this is the first drawing command, merge it into the pass.
if (curRp_->numDraws == 0) {
curRp_->clearColor = clearColor;
curRp_->clearZ = clearZ;
curRp_->clearStencil = clearStencil;
curRp_->clearMask = clearMask;
} else {
VkRenderData data{ VKR_CLEAR };
data.clear.clearColor = clearColor;
data.clear.clearZ = clearZ;
data.clear.clearStencil = clearStencil;
data.clear.clearMask = clearMask;
curRp_->commands.push_back(data);
}
}

void VulkanRenderManager::Flush(VkCommandBuffer cmdbuf) {
// Optimizes renderpasses, then sequences them.
for (int i = 0; i < renderPasses_.size(); i++) {
auto &commands = renderPasses_[i]->commands;
for (const auto &c : commands) {
switch (c.cmd) {
case VKR_VIEWPORT:
vkCmdSetViewport(cmdbuf, 0, 1, &c.viewport.vp);
break;

case VKR_SCISSOR:
vkCmdSetScissor(cmdbuf, 0, 1, &c.scissor.scissor);
break;

case VKR_DRAW_INDEXED:
vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, c.drawIndexed.pipeline);
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, c.drawIndexed.pipelineLayout, 0, 1, &c.drawIndexed.ds, c.drawIndexed.numUboOffsets, c.drawIndexed.uboOffsets);
vkCmdBindIndexBuffer(cmdbuf, c.drawIndexed.ibuffer, c.drawIndexed.ioffset, VK_INDEX_TYPE_UINT16);
vkCmdBindVertexBuffers(cmdbuf, 0, 1, &c.drawIndexed.vbuffer, &c.drawIndexed.voffset);
vkCmdDrawIndexed(cmdbuf, c.drawIndexed.count, c.drawIndexed.instances, 0, 0, 0);
break;

case VKR_DRAW:
vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, c.draw.pipeline);
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, c.draw.pipelineLayout, 0, 1, &c.draw.ds, c.draw.numUboOffsets, c.draw.uboOffsets);
vkCmdBindVertexBuffers(cmdbuf, 0, 1, &c.draw.vbuffer, &c.draw.voffset);
vkCmdDraw(cmdbuf, c.draw.count, 1, 0, 0);
break;

case VKR_STENCIL:
vkCmdSetStencilWriteMask(cmdbuf, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilWriteMask);
vkCmdSetStencilCompareMask(cmdbuf, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilCompareMask);
vkCmdSetStencilReference(cmdbuf, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilRef);
break;

case VKR_BLEND:
vkCmdSetBlendConstants(cmdbuf, c.blendColor.color);
break;

case VKR_CLEAR:
{
int numAttachments = 0;
VkClearRect rc{};
rc.baseArrayLayer = 0;
rc.layerCount = 1;
rc.rect.extent.width = curWidth_;
rc.rect.extent.height = curHeight_;
VkClearAttachment attachments[2];
if (c.clear.clearMask & VK_IMAGE_ASPECT_COLOR_BIT) {
VkClearAttachment &attachment = attachments[numAttachments++];
attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
attachment.colorAttachment = 0;
Uint8x4ToFloat4(attachment.clearValue.color.float32, c.clear.clearColor);
}
if (c.clear.clearMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
VkClearAttachment &attachment = attachments[numAttachments++];
attachment.aspectMask = 0;
if (c.clear.clearMask & VK_IMAGE_ASPECT_DEPTH_BIT) {
attachment.clearValue.depthStencil.depth = c.clear.clearZ;
attachment.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
}
if (c.clear.clearMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
attachment.clearValue.depthStencil.stencil = c.clear.clearStencil;
attachment.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
}
if (numAttachments) {
vkCmdClearAttachments(cmdbuf, numAttachments, attachments, 1, &rc);
}
break;
}
default:
ELOG("Unimpl queue command");
;
}
}
delete renderPasses_[i];
}
renderPasses_.clear();
}

void VulkanRenderManager::Sync(VkCommandBuffer cmd) {

}
168 changes: 168 additions & 0 deletions Common/Vulkan/VulkanRenderManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#pragma once

#include <cstdint>
#include <thread>

#include "Common/Vulkan/VulkanContext.h"
#include "math/dataconv.h"
#include "thin3d/thin3d.h"

// Takes the role that a GL driver does of sequencing and optimizing render passes.
// Only draws and binds are handled here, resource creation and allocations are handled as normal -
// that's the nice thing with Vulkan.

// The cool thing is that you can Flush on a different thread than you record the commands on!

enum VkRenderCmd : uint8_t {
VKR_STENCIL,
VKR_BLEND,
VKR_VIEWPORT,
VKR_SCISSOR,
VKR_CLEAR,
VKR_DRAW,
VKR_DRAW_INDEXED,
};

struct VkRenderData {
VkRenderCmd cmd;
union {
struct {
VkPipeline pipeline;
VkPipelineLayout pipelineLayout;
VkDescriptorSet ds;
int numUboOffsets;
uint32_t uboOffsets[3];
VkBuffer vbuffer;
VkDeviceSize voffset;
int count;
} draw;
struct {
VkPipeline pipeline;
VkPipelineLayout pipelineLayout;
VkDescriptorSet ds;
int numUboOffsets;
uint32_t uboOffsets[3];
VkBuffer vbuffer; // might need to increase at some point
VkDeviceSize voffset;
VkBuffer ibuffer;
VkDeviceSize ioffset;
int16_t count;
int16_t instances;
VkIndexType indexType;
} drawIndexed;
struct {
uint32_t clearColor;
float clearZ;
int clearStencil;
int clearMask; // VK_IMAGE_ASPECT_COLOR_BIT etc
} clear;

struct {
VkViewport vp;
} viewport;
struct {
VkRect2D scissor;
} scissor;
struct {
uint8_t stencilWriteMask;
uint8_t stencilCompareMask;
uint8_t stencilRef;
} stencil;
struct {
float color[4];
} blendColor;
struct {

} beginRp;
struct {

} endRp;
};
};

struct VKRRenderPass {
VkFramebuffer framebuffer;
uint32_t clearColor;
float clearZ;
int clearStencil;
int clearMask = 0; // VK_IMAGE_ASPECT_COLOR_BIT etc
int dontCareMask = 0;
int numDraws;
std::vector<VkRenderData> commands;
};

class VulkanRenderManager {
public:
VulkanRenderManager(VulkanContext *vulkan) : vulkan_(vulkan) {}

// Makes sure that the GPU has caught up enough that we can start writing buffers of this frame again.
void BeginFrameWrites();
void EndFrame();

void SetViewport(const VkViewport &vp) {
VkRenderData data{ VKR_VIEWPORT };
data.viewport.vp = vp;
curRp_->commands.push_back(data);
}

void SetScissor(const VkRect2D &rc) {
VkRenderData data{ VKR_SCISSOR };
data.scissor.scissor = rc;
curRp_->commands.push_back(data);
}

void SetBlendFactor(float color[4]) {
VkRenderData data{ VKR_BLEND };
CopyFloat4(data.blendColor.color, color);
curRp_->commands.push_back(data);
}

void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask);

void Draw(VkPipeline pipeline, VkPipelineLayout layout, VkDescriptorSet descSet, int numUboOffsets, uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, int count) {
VkRenderData data{ VKR_DRAW };
data.draw.count = count;
data.draw.pipeline = pipeline;
data.draw.pipelineLayout = layout;
data.draw.ds = descSet;
data.draw.vbuffer = vbuffer;
data.draw.voffset = voffset;
data.draw.numUboOffsets = numUboOffsets;
for (int i = 0; i < numUboOffsets; i++)
data.draw.uboOffsets[i] = uboOffsets[i];
curRp_->commands.push_back(data);
curRp_->numDraws++;
}

void DrawIndexed(VkPipeline pipeline, VkPipelineLayout layout, VkDescriptorSet descSet, int numUboOffsets, uint32_t *uboOffsets, VkBuffer vbuffer, int voffset, VkBuffer ibuffer, int ioffset, int count, VkIndexType indexType) {
VkRenderData data{ VKR_DRAW };
data.drawIndexed.count = count;
data.drawIndexed.pipeline = pipeline;
data.drawIndexed.pipelineLayout = layout;
data.drawIndexed.ds = descSet;
data.drawIndexed.vbuffer = vbuffer;
data.drawIndexed.voffset = voffset;
data.drawIndexed.ibuffer = ibuffer;
data.drawIndexed.ioffset = ioffset;
data.drawIndexed.numUboOffsets = numUboOffsets;
for (int i = 0; i < numUboOffsets; i++)
data.drawIndexed.uboOffsets[i] = uboOffsets[i];
data.drawIndexed.indexType = indexType;
curRp_->commands.push_back(data);
curRp_->numDraws++;
}

// Can run on a different thread! Just make sure to use BeginFrameWrites.
void Flush(VkCommandBuffer cmd);

// Bad for performance but sometimes necessary for synchronous CPU readbacks (screenshots and whatnot).
void Sync(VkCommandBuffer cmd);

std::vector<VKRRenderPass *> renderPasses_;
VKRRenderPass *curRp_;

private:
VulkanContext *vulkan_;
int curWidth_;
int curHeight_;
};
1 change: 1 addition & 0 deletions ext/native/thin3d/thin3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ enum class NativeObject {
CURRENT_RENDERPASS,
RENDERPASS_COMMANDBUFFER,
BOUND_TEXTURE_IMAGEVIEW,
RENDER_MANAGER,
};

enum FBColorDepth {
Expand Down
Loading