mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-05 04:56:31 +00:00
Move clear handling to FramebufferVulkan, center the clear properly in non-buffered. more cleanup.
This commit is contained in:
parent
c2b66a0882
commit
32f5930e15
@ -74,6 +74,7 @@ public:
|
||||
void QueueDeleteImageView(VkImageView imageView) { imageViews_.push_back(imageView); }
|
||||
void QueueDeleteDeviceMemory(VkDeviceMemory deviceMemory) { deviceMemory_.push_back(deviceMemory); }
|
||||
void QueueDeleteSampler(VkSampler sampler) { samplers_.push_back(sampler); }
|
||||
void QueueDeletePipeline(VkPipeline pipeline) { pipelines_.push_back(pipeline); }
|
||||
void QueueDeletePipelineCache(VkPipelineCache pipelineCache) { pipelineCaches_.push_back(pipelineCache); }
|
||||
void QueueDeleteRenderPass(VkRenderPass renderPass) { renderPasses_.push_back(renderPass); }
|
||||
void QueueDeleteFramebuffer(VkFramebuffer framebuffer) { framebuffers_.push_back(framebuffer); }
|
||||
@ -88,6 +89,7 @@ public:
|
||||
assert(imageViews_.size() == 0);
|
||||
assert(deviceMemory_.size() == 0);
|
||||
assert(samplers_.size() == 0);
|
||||
assert(pipelines_.size() == 0);
|
||||
assert(pipelineCaches_.size() == 0);
|
||||
assert(renderPasses_.size() == 0);
|
||||
assert(framebuffers_.size() == 0);
|
||||
@ -100,6 +102,7 @@ public:
|
||||
imageViews_ = std::move(del.imageViews_);
|
||||
deviceMemory_ = std::move(del.deviceMemory_);
|
||||
samplers_ = std::move(del.samplers_);
|
||||
pipelines_ = std::move(del.pipelines_);
|
||||
pipelineCaches_ = std::move(del.pipelineCaches_);
|
||||
renderPasses_ = std::move(del.renderPasses_);
|
||||
framebuffers_ = std::move(del.framebuffers_);
|
||||
@ -139,6 +142,10 @@ public:
|
||||
vkDestroySampler(device, sampler, nullptr);
|
||||
}
|
||||
samplers_.clear();
|
||||
for (auto &pipeline : pipelines_) {
|
||||
vkDestroyPipeline(device, pipeline, nullptr);
|
||||
}
|
||||
pipelines_.clear();
|
||||
for (auto &pcache : pipelineCaches_) {
|
||||
vkDestroyPipelineCache(device, pcache, nullptr);
|
||||
}
|
||||
@ -166,6 +173,7 @@ private:
|
||||
std::vector<VkImageView> imageViews_;
|
||||
std::vector<VkDeviceMemory> deviceMemory_;
|
||||
std::vector<VkSampler> samplers_;
|
||||
std::vector<VkPipeline> pipelines_;
|
||||
std::vector<VkPipelineCache> pipelineCaches_;
|
||||
std::vector<VkRenderPass> renderPasses_;
|
||||
std::vector<VkFramebuffer> framebuffers_;
|
||||
|
@ -800,51 +800,9 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
|
||||
}
|
||||
} else if (result.action == SW_CLEAR) {
|
||||
// Note: we won't get here if the clear is alpha but not color, or color but not alpha.
|
||||
// A rectangle will be used instead.
|
||||
// TODO: If this is the first clear in a frame, translate to a cleared attachment load instead.
|
||||
|
||||
int mask = gstate.isClearModeColorMask() ? 1 : 0;
|
||||
if (gstate.isClearModeAlphaMask()) mask |= 2;
|
||||
if (gstate.isClearModeDepthMask()) mask |= 4;
|
||||
|
||||
VkClearValue colorValue, depthValue;
|
||||
colorValue.color.float32[0] = (result.color & 0xFF) * (1.0f / 255.0f);
|
||||
colorValue.color.float32[1] = ((result.color >> 8) & 0xFF) * (1.0f / 255.0f);
|
||||
colorValue.color.float32[2] = ((result.color >> 16) & 0xFF) * (1.0f / 255.0f);
|
||||
colorValue.color.float32[3] = ((result.color >> 24) & 0xFF) * (1.0f / 255.0f);
|
||||
depthValue.depthStencil.depth = result.depth;
|
||||
depthValue.depthStencil.stencil = (result.color >> 24) & 0xFF;
|
||||
|
||||
VkClearRect rect;
|
||||
rect.baseArrayLayer = 0;
|
||||
rect.layerCount = 1;
|
||||
rect.rect.offset.x = 0;
|
||||
rect.rect.offset.y = 0;
|
||||
rect.rect.extent.width = gstate_c.curRTRenderWidth;
|
||||
rect.rect.extent.height = gstate_c.curRTRenderHeight;
|
||||
|
||||
int count = 0;
|
||||
VkClearAttachment attach[2];
|
||||
if (mask & 3) {
|
||||
attach[count].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
attach[count].clearValue = colorValue;
|
||||
attach[count].colorAttachment = 0;
|
||||
count++;
|
||||
}
|
||||
if (mask & 4) {
|
||||
attach[count].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
attach[count].clearValue = depthValue;
|
||||
attach[count].colorAttachment = 0;
|
||||
count++;
|
||||
}
|
||||
vkCmdClearAttachments(cmd_, count, attach, 1, &rect);
|
||||
|
||||
if (mask & 1) {
|
||||
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
|
||||
}
|
||||
if (mask & 4) {
|
||||
framebufferManager_->SetDepthUpdated();
|
||||
}
|
||||
// We let the framebuffer manager handle the clear. It can use renderpasses to optimize on tilers.
|
||||
framebufferManager_->NotifyClear(gstate.isClearModeColorMask(), gstate.isClearModeAlphaMask(), gstate.isClearModeDepthMask(), result.color, result.depth);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,8 @@ FramebufferManagerVulkan::FramebufferManagerVulkan(VulkanContext *vulkan) :
|
||||
pixelBufObj_(nullptr),
|
||||
currentPBO_(0),
|
||||
curFrame_(0),
|
||||
pipelineBasicTex_(VK_NULL_HANDLE),
|
||||
pipelinePostShader_(VK_NULL_HANDLE),
|
||||
vulkan2D_(vulkan) {
|
||||
|
||||
// Create a bunch of render pass objects, for normal rendering with a depth buffer,
|
||||
@ -175,6 +177,7 @@ FramebufferManagerVulkan::FramebufferManagerVulkan(VulkanContext *vulkan) :
|
||||
vsBasicTex_ = CompileShaderModule(vulkan_, VK_SHADER_STAGE_VERTEX_BIT, tex_vs, &vs_errors);
|
||||
assert(fsBasicTex_ != VK_NULL_HANDLE);
|
||||
assert(vsBasicTex_ != VK_NULL_HANDLE);
|
||||
|
||||
pipelineBasicTex_ = vulkan2D_.GetPipeline(pipelineCache2D_, rpClearColorClearDepth_, vsBasicTex_, fsBasicTex_);
|
||||
|
||||
VkSamplerCreateInfo samp = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
|
||||
@ -212,12 +215,59 @@ FramebufferManagerVulkan::~FramebufferManagerVulkan() {
|
||||
|
||||
vulkan_->Delete().QueueDeleteSampler(linearSampler_);
|
||||
vulkan_->Delete().QueueDeleteSampler(nearestSampler_);
|
||||
|
||||
vulkan_->Delete().QueueDeletePipeline(pipelineBasicTex_);
|
||||
if (pipelinePostShader_ != VK_NULL_HANDLE)
|
||||
vulkan_->Delete().QueueDeletePipeline(pipelinePostShader_);
|
||||
vulkan_->Delete().QueueDeletePipelineCache(pipelineCache2D_);
|
||||
}
|
||||
|
||||
void FramebufferManagerVulkan::NotifyClear(bool clearColor, bool clearDepth, uint32_t color, float depth) {
|
||||
void FramebufferManagerVulkan::NotifyClear(bool clearColor, bool clearAlpha, bool clearDepth, uint32_t color, float depth) {
|
||||
if (!this->useBufferedRendering_) {
|
||||
float x, y, w, h;
|
||||
CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)pixelWidth_, (float)pixelHeight_, ROTATION_LOCKED_HORIZONTAL);
|
||||
|
||||
VkClearValue colorValue, depthValue;
|
||||
colorValue.color.float32[0] = (color & 0xFF) * (1.0f / 255.0f);
|
||||
colorValue.color.float32[1] = ((color >> 8) & 0xFF) * (1.0f / 255.0f);
|
||||
colorValue.color.float32[2] = ((color >> 16) & 0xFF) * (1.0f / 255.0f);
|
||||
colorValue.color.float32[3] = ((color >> 24) & 0xFF) * (1.0f / 255.0f);
|
||||
depthValue.depthStencil.depth = depth;
|
||||
depthValue.depthStencil.stencil = (color >> 24) & 0xFF;
|
||||
|
||||
VkClearRect rect;
|
||||
rect.baseArrayLayer = 0;
|
||||
rect.layerCount = 1;
|
||||
rect.rect.offset.x = x;
|
||||
rect.rect.offset.y = y;
|
||||
rect.rect.extent.width = w;
|
||||
rect.rect.extent.height = h;
|
||||
|
||||
int count = 0;
|
||||
VkClearAttachment attach[2];
|
||||
// TODO: Should change to a rectangle draw with color mask if both aren't set.
|
||||
if (clearColor || clearAlpha) {
|
||||
attach[count].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
attach[count].clearValue = colorValue;
|
||||
attach[count].colorAttachment = 0;
|
||||
count++;
|
||||
}
|
||||
if (clearDepth) {
|
||||
attach[count].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
attach[count].clearValue = depthValue;
|
||||
attach[count].colorAttachment = 0;
|
||||
count++;
|
||||
}
|
||||
vkCmdClearAttachments(curCmd_, count, attach, 1, &rect);
|
||||
|
||||
if (clearColor) {
|
||||
SetColorUpdated(gstate_c.skipDrawReason);
|
||||
}
|
||||
if (clearAlpha) {
|
||||
SetDepthUpdated();
|
||||
}
|
||||
} else {
|
||||
// TODO: Clever render pass magic.
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerVulkan::DoNotifyDraw() {
|
||||
@ -328,8 +378,6 @@ void FramebufferManagerVulkan::DrawPixels(VirtualFramebuffer *vfb, int dstX, int
|
||||
vp.minDepth = 0.0;
|
||||
vp.maxDepth = 1.0;
|
||||
if (useBufferedRendering_ && vfb && vfb->fbo_vk) {
|
||||
// fbo_bind_as_render_target(vfb->fbo_vk);
|
||||
// glViewport(0, 0, vfb->renderWidth, vfb->renderHeight);
|
||||
vp.x = 0;
|
||||
vp.y = 0;
|
||||
vp.width = vfb->renderWidth;
|
||||
@ -699,17 +747,16 @@ void FramebufferManagerVulkan::BlitFramebufferDepth(VirtualFramebuffer *src, Vir
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerVulkan::BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags) {
|
||||
VulkanTexture *FramebufferManagerVulkan::GetFramebufferColor(u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags) {
|
||||
if (framebuffer == NULL) {
|
||||
framebuffer = currentRenderVfb_;
|
||||
}
|
||||
|
||||
if (!framebuffer->fbo_vk || !useBufferedRendering_) {
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE;
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
// currentRenderVfb_ will always be set when this is called, except from the GE debugger.
|
||||
// Let's just not bother with the copy in that case.
|
||||
bool skipCopy = (flags & BINDFBCOLOR_MAY_COPY) == 0;
|
||||
@ -717,8 +764,11 @@ void FramebufferManagerVulkan::BindFramebufferColor(int stage, u32 fbRawAddress,
|
||||
skipCopy = true;
|
||||
}
|
||||
if (!skipCopy && currentRenderVfb_ && framebuffer->fb_address == fbRawAddress) {
|
||||
// TODO: Enable the below code
|
||||
return framebuffer->fbo_vk->GetColor();
|
||||
/*
|
||||
// TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size.
|
||||
fbo_vk *renderCopy = GetTempFBO(framebuffer->renderWidth, framebuffer->renderHeight, (FBOColorDepth)framebuffer->colorDepth);
|
||||
VulkanFBO *renderCopy = GetTempFBO(framebuffer->renderWidth, framebuffer->renderHeight, (FBOColorDepth)framebuffer->colorDepth);
|
||||
if (renderCopy) {
|
||||
VirtualFramebuffer copyInfo = *framebuffer;
|
||||
copyInfo.fbo_vk = renderCopy;
|
||||
@ -745,18 +795,14 @@ void FramebufferManagerVulkan::BindFramebufferColor(int stage, u32 fbRawAddress,
|
||||
|
||||
BlitFramebuffer(©Info, x, y, framebuffer, x, y, w, h, 0);
|
||||
|
||||
fbo_bind_color_as_texture(renderCopy, 0);
|
||||
return nullptr; // fbo_bind_color_as_texture(renderCopy, 0);
|
||||
} else {
|
||||
fbo_bind_color_as_texture(framebuffer->fbo_vk, 0);
|
||||
return framebuffer->fbo_vk->GetColor();
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
fbo_bind_color_as_texture(framebuffer->fbo_vk, 0);
|
||||
return framebuffer->fbo_vk->GetColor();
|
||||
}
|
||||
|
||||
if (stage != GL_TEXTURE0) {
|
||||
glActiveTexture(stage);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
struct CardboardSettings * FramebufferManagerVulkan::GetCardboardSettings(struct CardboardSettings * cardboardSettings) {
|
||||
|
@ -111,7 +111,7 @@ public:
|
||||
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst);
|
||||
|
||||
// For use when texturing from a framebuffer. May create a duplicate if target.
|
||||
void BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags);
|
||||
VulkanTexture *GetFramebufferColor(u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags);
|
||||
|
||||
// Reads a rectangular subregion of a framebuffer to the right position in its backing memory.
|
||||
void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) override;
|
||||
@ -141,7 +141,7 @@ public:
|
||||
|
||||
// If within a render pass, this will just issue a regular clear. If beginning a new render pass,
|
||||
// do that.
|
||||
void NotifyClear(bool clearColor, bool clearDepth, uint32_t color, float depth);
|
||||
void NotifyClear(bool clearColor, bool clearAlpha, bool clearDepth, uint32_t color, float depth);
|
||||
void NotifyDraw() {
|
||||
DoNotifyDraw();
|
||||
}
|
||||
@ -228,6 +228,9 @@ private:
|
||||
VkShaderModule vsBasicTex_;
|
||||
VkPipeline pipelineBasicTex_;
|
||||
|
||||
// Postprocessing
|
||||
VkPipeline pipelinePostShader_;
|
||||
|
||||
VkSampler linearSampler_;
|
||||
VkSampler nearestSampler_;
|
||||
|
||||
|
@ -128,6 +128,9 @@ static VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugRep
|
||||
// https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/issues/121
|
||||
if (msgCode == 6 && (!memcmp(pMsg, "Cannot map", 10) || !memcmp(pMsg, "Cannot sub", 10)))
|
||||
return false;
|
||||
// And for dynamic offsets.
|
||||
if (msgCode == 62 && (!memcmp(pMsg, "VkDesc", 6)))
|
||||
return false;
|
||||
|
||||
#ifdef _WIN32
|
||||
OutputDebugStringA(message.str().c_str());
|
||||
|
Loading…
x
Reference in New Issue
Block a user