Move clear handling to FramebufferVulkan, center the clear properly in non-buffered. more cleanup.

This commit is contained in:
Henrik Rydgard 2016-03-30 23:26:16 +02:00
parent c2b66a0882
commit 32f5930e15
5 changed files with 80 additions and 62 deletions

View File

@ -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_;

View File

@ -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);
}
}

View File

@ -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(&copyInfo, 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) {

View File

@ -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_;

View File

@ -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());