mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Use RenderManager for thin3d stuff
This commit is contained in:
parent
84ed793adf
commit
417b96a1b0
3 changed files with 123 additions and 68 deletions
|
@ -1,5 +1,18 @@
|
|||
#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) {
|
||||
|
@ -32,6 +45,7 @@ void VulkanRenderManager::Flush(VkCommandBuffer cmdbuf) {
|
|||
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);
|
||||
|
@ -39,9 +53,10 @@ void VulkanRenderManager::Flush(VkCommandBuffer cmdbuf) {
|
|||
break;
|
||||
|
||||
case VKR_DRAW:
|
||||
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, c.drawIndexed.pipelineLayout, 0, 1, &c.draw.ds, c.draw.numUboOffsets, c.draw.uboOffsets);
|
||||
vkCmdBindVertexBuffers(cmdbuf, 0, 1, &c.drawIndexed.vbuffer, &c.drawIndexed.voffset);
|
||||
vkCmdDraw(cmdbuf, c.drawIndexed.count, c.drawIndexed.instances, 0, 0);
|
||||
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:
|
||||
|
@ -55,11 +70,45 @@ void VulkanRenderManager::Flush(VkCommandBuffer cmdbuf) {
|
|||
break;
|
||||
|
||||
case VKR_CLEAR:
|
||||
// vkCmdClearAttachments
|
||||
{
|
||||
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) {
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
#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.
|
||||
// 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,
|
||||
|
@ -29,7 +33,7 @@ struct VkRenderData {
|
|||
int numUboOffsets;
|
||||
uint32_t uboOffsets[3];
|
||||
VkBuffer vbuffer;
|
||||
int offset;
|
||||
VkDeviceSize voffset;
|
||||
int count;
|
||||
} draw;
|
||||
struct {
|
||||
|
@ -44,6 +48,7 @@ struct VkRenderData {
|
|||
VkDeviceSize ioffset;
|
||||
int16_t count;
|
||||
int16_t instances;
|
||||
VkIndexType indexType;
|
||||
} drawIndexed;
|
||||
struct {
|
||||
uint32_t clearColor;
|
||||
|
@ -88,44 +93,76 @@ struct VKRRenderPass {
|
|||
|
||||
class VulkanRenderManager {
|
||||
public:
|
||||
void SetViewport(VkViewport vp) {
|
||||
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(VkRect2D rc) {
|
||||
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, VkBuffer vbuffer, int offset, int count) {
|
||||
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.offset = offset;
|
||||
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, VkBuffer vbuffer, int voffset, VkBuffer ibuffer, int ioffset, int count) {
|
||||
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 synchonous CPU readbacks (screenshots and whatnot).
|
||||
// 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_;
|
||||
};
|
|
@ -135,6 +135,7 @@ static const VkStencilOp stencilOpToVK[8] = {
|
|||
VK_STENCIL_OP_DECREMENT_AND_WRAP,
|
||||
};
|
||||
|
||||
// TODO: Replace with the one from dataconv
|
||||
static inline void Uint8x4ToFloat4(uint32_t u, float f[4]) {
|
||||
f[0] = ((u >> 0) & 0xFF) * (1.0f / 255.0f);
|
||||
f[1] = ((u >> 8) & 0xFF) * (1.0f / 255.0f);
|
||||
|
@ -475,7 +476,7 @@ public:
|
|||
return (uintptr_t)boundImageView_[0];
|
||||
|
||||
case NativeObject::RENDER_MANAGER:
|
||||
return renderManager_;
|
||||
return (uintptr_t)&renderManager_;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -701,7 +702,7 @@ bool VKTexture::Create(const TextureDesc &desc) {
|
|||
}
|
||||
|
||||
VKContext::VKContext(VulkanContext *vulkan)
|
||||
: viewportDirty_(false), scissorDirty_(false), vulkan_(vulkan), frameNum_(0), caps_{} {
|
||||
: viewportDirty_(false), scissorDirty_(false), vulkan_(vulkan), frameNum_(0), caps_{}, renderManager_(vulkan) {
|
||||
caps_.anisoSupported = vulkan->GetFeaturesAvailable().samplerAnisotropy != 0;
|
||||
caps_.geometryShaderSupported = vulkan->GetFeaturesAvailable().geometryShader != 0;
|
||||
caps_.tesselationShaderSupported = vulkan->GetFeaturesAvailable().tessellationShader != 0;
|
||||
|
@ -892,7 +893,7 @@ VkCommandBuffer VKContext::AllocCmdBuf() {
|
|||
}
|
||||
|
||||
void VKContext::BeginFrame() {
|
||||
vulkan_->BeginFrame();
|
||||
renderManager_.BeginFrameWrites();
|
||||
|
||||
FrameData &frame = frame_[frameNum_];
|
||||
frame.startCmdBufs_ = 0;
|
||||
|
@ -920,6 +921,7 @@ void VKContext::WaitRenderCompletion(Framebuffer *fbo) {
|
|||
|
||||
void VKContext::EndFrame() {
|
||||
EndCurrentRenderpass();
|
||||
renderManager_.Flush(cmd_);
|
||||
|
||||
if (cmd_)
|
||||
Crash();
|
||||
|
@ -934,7 +936,8 @@ void VKContext::EndFrame() {
|
|||
|
||||
// Stop collecting data in the frame's data pushbuffer.
|
||||
push_->End();
|
||||
vulkan_->EndFrame();
|
||||
|
||||
renderManager_.EndFrame();
|
||||
|
||||
frameNum_++;
|
||||
if (frameNum_ >= vulkan_->GetInflightFrames())
|
||||
|
@ -1109,16 +1112,16 @@ void VKContext::SetViewports(int count, Viewport *viewports) {
|
|||
}
|
||||
|
||||
void VKContext::SetBlendFactor(float color[4]) {
|
||||
vkCmdSetBlendConstants(cmd_, color);
|
||||
renderManager_.SetBlendFactor(color);
|
||||
}
|
||||
|
||||
void VKContext::ApplyDynamicState() {
|
||||
if (scissorDirty_) {
|
||||
vkCmdSetScissor(cmd_, 0, 1, &scissor_);
|
||||
renderManager_.SetScissor(scissor_);
|
||||
scissorDirty_ = false;
|
||||
}
|
||||
if (viewportDirty_) {
|
||||
vkCmdSetViewport(cmd_, 0, 1, &viewport_);
|
||||
renderManager_.SetViewport(viewport_);
|
||||
viewportDirty_ = false;
|
||||
}
|
||||
}
|
||||
|
@ -1303,13 +1306,9 @@ void VKContext::Draw(int vertexCount, int offset) {
|
|||
uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf);
|
||||
size_t vbBindOffset = push_->Push(vbuf->GetData(), vbuf->GetSize(), &vulkanVbuf);
|
||||
|
||||
vkCmdBindPipeline(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, curPipeline_->vkpipeline);
|
||||
VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf);
|
||||
vkCmdBindDescriptorSets(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &descSet, 1, &ubo_offset);
|
||||
VkBuffer buffers[1] = { vulkanVbuf };
|
||||
VkDeviceSize offsets[1] = { vbBindOffset };
|
||||
vkCmdBindVertexBuffers(cmd_, 0, 1, buffers, offsets);
|
||||
vkCmdDraw(cmd_, vertexCount, 1, offset, 0);
|
||||
|
||||
renderManager_.Draw(curPipeline_->vkpipeline, pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset, vertexCount);
|
||||
}
|
||||
|
||||
void VKContext::DrawIndexed(int vertexCount, int offset) {
|
||||
|
@ -1323,17 +1322,9 @@ void VKContext::DrawIndexed(int vertexCount, int offset) {
|
|||
size_t vbBindOffset = push_->Push(vbuf->GetData(), vbuf->GetSize(), &vulkanVbuf);
|
||||
size_t ibBindOffset = push_->Push(ibuf->GetData(), ibuf->GetSize(), &vulkanIbuf);
|
||||
|
||||
vkCmdBindPipeline(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, curPipeline_->vkpipeline);
|
||||
|
||||
VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf);
|
||||
vkCmdBindDescriptorSets(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &descSet, 1, &ubo_offset);
|
||||
|
||||
VkBuffer buffers[1] = { vulkanVbuf };
|
||||
VkDeviceSize offsets[1] = { vbBindOffset };
|
||||
vkCmdBindVertexBuffers(cmd_, 0, 1, buffers, offsets);
|
||||
|
||||
vkCmdBindIndexBuffer(cmd_, vulkanIbuf, ibBindOffset, VK_INDEX_TYPE_UINT32);
|
||||
vkCmdDrawIndexed(cmd_, vertexCount, 1, 0, offset, 0);
|
||||
renderManager_.DrawIndexed(curPipeline_->vkpipeline, pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset, vulkanIbuf, (int)ibBindOffset, vertexCount, VK_INDEX_TYPE_UINT32);
|
||||
}
|
||||
|
||||
void VKContext::DrawUP(const void *vdata, int vertexCount) {
|
||||
|
@ -1343,52 +1334,30 @@ void VKContext::DrawUP(const void *vdata, int vertexCount) {
|
|||
size_t vbBindOffset = push_->Push(vdata, vertexCount * curPipeline_->stride[0], &vulkanVbuf);
|
||||
uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf);
|
||||
|
||||
vkCmdBindPipeline(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, curPipeline_->vkpipeline);
|
||||
|
||||
VkBuffer buffers[1] = { vulkanVbuf };
|
||||
VkDeviceSize offsets[1] = { vbBindOffset };
|
||||
vkCmdBindVertexBuffers(cmd_, 0, 1, buffers, offsets);
|
||||
|
||||
VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf);
|
||||
vkCmdBindDescriptorSets(cmd_, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &descSet, 1, &ubo_offset);
|
||||
vkCmdDraw(cmd_, vertexCount, 1, 0, 0);
|
||||
|
||||
renderManager_.Draw(curPipeline_->vkpipeline, pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, vbBindOffset, vertexCount);
|
||||
}
|
||||
|
||||
// TODO: We should avoid this function as much as possible, instead use renderpass on-load clearing.
|
||||
void VKContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) {
|
||||
void VKContext::Clear(int clearMask, uint32_t colorval, float depthVal, int stencilVal) {
|
||||
if (!curRenderPass_) {
|
||||
ELOG("Clear: Need an active render pass");
|
||||
return;
|
||||
}
|
||||
|
||||
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 (mask & FBChannel::FB_COLOR_BIT) {
|
||||
VkClearAttachment &attachment = attachments[numAttachments++];
|
||||
attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
attachment.colorAttachment = 0;
|
||||
Uint8x4ToFloat4(colorval, attachment.clearValue.color.float32);
|
||||
}
|
||||
if (mask & (FBChannel::FB_DEPTH_BIT | FBChannel::FB_STENCIL_BIT)) {
|
||||
VkClearAttachment &attachment = attachments[numAttachments++];
|
||||
attachment.aspectMask = 0;
|
||||
if (mask & FBChannel::FB_DEPTH_BIT) {
|
||||
attachment.clearValue.depthStencil.depth = depthVal;
|
||||
attachment.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
}
|
||||
if (mask & FBChannel::FB_STENCIL_BIT) {
|
||||
attachment.clearValue.depthStencil.stencil = stencilVal;
|
||||
attachment.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
}
|
||||
if (numAttachments) {
|
||||
vkCmdClearAttachments(cmd_, numAttachments, attachments, 1, &rc);
|
||||
}
|
||||
int mask = 0;
|
||||
if (clearMask & FBChannel::FB_COLOR_BIT)
|
||||
mask |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
if (clearMask & FBChannel::FB_DEPTH_BIT)
|
||||
mask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (clearMask & FBChannel::FB_STENCIL_BIT)
|
||||
mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
renderManager_.Clear(colorval, depthVal, stencilVal, mask);
|
||||
}
|
||||
|
||||
DrawContext *T3DCreateVulkanContext(VulkanContext *vulkan) {
|
||||
|
|
Loading…
Add table
Reference in a new issue