mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-22 10:49:05 +02:00
Vulkan: Fix stencil-only clear for stencil upload.
Fixes stencil issues in Star Ocean.
This commit is contained in:
1 parent
22bf124631
commit
3eb6d38d75
9 files changed
+32
-23
No files matched your search
@@ -155,21 +155,22 @@ bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, bool skip
|
||||
// It's already zero, let's skip it.
|
||||
continue;
|
||||
}
|
||||
// These feel a little backwards : Mask is the bits that are going to be written, while value
|
||||
// is the "mask" that will be tested against.
|
||||
uint8_t mask = 0;
|
||||
|
||||
// These are the stencil bits that will be written. We discard when the bit doesn't match.
|
||||
uint8_t writeMask = 0;
|
||||
// This is the value to test the texture alpha against in the shader.
|
||||
uint32_t value = 0;
|
||||
if (dstBuffer->format == GE_FORMAT_4444) {
|
||||
mask = i | (i << 4);
|
||||
writeMask = i | (i << 4);
|
||||
value = i * 16;
|
||||
} else if (dstBuffer->format == GE_FORMAT_5551) {
|
||||
mask = 0xFF;
|
||||
writeMask = 0xFF;
|
||||
value = i * 128;
|
||||
} else {
|
||||
mask = i;
|
||||
writeMask = i;
|
||||
value = i;
|
||||
}
|
||||
renderManager->SetStencilParams(mask, 0xFF, 0xFF);
|
||||
renderManager->SetStencilParams(writeMask, 0xFF, 0xFF);
|
||||
// Need to specify both VERTEX and FRAGMENT bits here since that's what we set up in the pipeline layout, and we need
|
||||
// that for the post shaders. There's probably not really a cost to this.
|
||||
renderManager->PushConstants(vulkan2D_->GetPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, &value);
|
||||
|
||||
@@ -157,11 +157,11 @@ void GLRenderManager::StopThread() {
|
||||
}
|
||||
}
|
||||
|
||||
void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil) {
|
||||
void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, GLRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil) {
|
||||
assert(insideFrame_);
|
||||
// Eliminate dupes.
|
||||
if (steps_.size() && steps_.back()->render.framebuffer == fb && steps_.back()->stepType == GLRStepType::RENDER) {
|
||||
if (color != GLRRenderPassAction::CLEAR && depth != GLRRenderPassAction::CLEAR) {
|
||||
if (color != GLRRenderPassAction::CLEAR && depth != GLRRenderPassAction::CLEAR && stencil != GLRRenderPassAction::CLEAR) {
|
||||
// We don't move to a new step, this bind was unnecessary and we can safely skip it.
|
||||
return;
|
||||
}
|
||||
@@ -184,8 +184,11 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende
|
||||
data.clear.clearColor = clearColor;
|
||||
}
|
||||
if (depth == GLRRenderPassAction::CLEAR) {
|
||||
clearMask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
|
||||
clearMask |= GL_DEPTH_BUFFER_BIT;
|
||||
data.clear.clearZ = clearDepth;
|
||||
}
|
||||
if (stencil == GLRRenderPassAction::CLEAR) {
|
||||
clearMask |= GL_STENCIL_BUFFER_BIT;
|
||||
data.clear.clearStencil = clearStencil;
|
||||
}
|
||||
if (clearMask) {
|
||||
|
||||
@@ -310,7 +310,7 @@ public:
|
||||
deleter_.framebuffers.push_back(framebuffer);
|
||||
}
|
||||
|
||||
void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil);
|
||||
void BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRenderPassAction color, GLRRenderPassAction depth, GLRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil);
|
||||
void BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit, int attachment);
|
||||
bool CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride);
|
||||
void CopyImageToMemorySync(GLuint texture, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride);
|
||||
|
||||
@@ -391,7 +391,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
}
|
||||
|
||||
// Don't execute empty renderpasses.
|
||||
if (step.commands.empty() && step.render.color == VKRRenderPassAction::KEEP && step.render.depthStencil == VKRRenderPassAction::KEEP) {
|
||||
if (step.commands.empty() && step.render.color == VKRRenderPassAction::KEEP && step.render.depth == VKRRenderPassAction::KEEP && step.render.stencil == VKRRenderPassAction::KEEP) {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
@@ -610,12 +610,12 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
|
||||
fb->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
|
||||
renderPass = GetRenderPass(step.render.color, step.render.depthStencil, step.render.depthStencil);
|
||||
renderPass = GetRenderPass(step.render.color, step.render.depth, step.render.stencil);
|
||||
if (step.render.color == VKRRenderPassAction::CLEAR) {
|
||||
Uint8x4ToFloat4(clearVal[0].color.float32, step.render.clearColor);
|
||||
numClearVals = 1;
|
||||
}
|
||||
if (step.render.depthStencil == VKRRenderPassAction::CLEAR) {
|
||||
if (step.render.depth == VKRRenderPassAction::CLEAR || step.render.stencil == VKRRenderPassAction::CLEAR) {
|
||||
clearVal[1].depthStencil.depth = step.render.clearDepth;
|
||||
clearVal[1].depthStencil.stencil = step.render.clearStencil;
|
||||
numClearVals = 2;
|
||||
|
||||
@@ -108,7 +108,8 @@ struct VKRStep {
|
||||
struct {
|
||||
VKRFramebuffer *framebuffer;
|
||||
VKRRenderPassAction color;
|
||||
VKRRenderPassAction depthStencil;
|
||||
VKRRenderPassAction depth;
|
||||
VKRRenderPassAction stencil;
|
||||
uint32_t clearColor;
|
||||
float clearDepth;
|
||||
int clearStencil;
|
||||
|
||||
@@ -389,16 +389,16 @@ VkCommandBuffer VulkanRenderManager::GetInitCmd() {
|
||||
return frameData_[curFrame].initCmd;
|
||||
}
|
||||
|
||||
void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil) {
|
||||
void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, VKRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil) {
|
||||
assert(insideFrame_);
|
||||
// Eliminate dupes.
|
||||
if (steps_.size() && steps_.back()->render.framebuffer == fb && steps_.back()->stepType == VKRStepType::RENDER) {
|
||||
if (color != VKRRenderPassAction::CLEAR && depth != VKRRenderPassAction::CLEAR) {
|
||||
if (color != VKRRenderPassAction::CLEAR && depth != VKRRenderPassAction::CLEAR && stencil != VKRRenderPassAction::CLEAR) {
|
||||
// We don't move to a new step, this bind was unnecessary and we can safely skip it.
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (curRenderStep_ && curRenderStep_->commands.size() == 0 && curRenderStep_->render.color == VKRRenderPassAction::KEEP && curRenderStep_->render.depthStencil == VKRRenderPassAction::KEEP) {
|
||||
if (curRenderStep_ && curRenderStep_->commands.size() == 0 && curRenderStep_->render.color == VKRRenderPassAction::KEEP && curRenderStep_->render.depth == VKRRenderPassAction::KEEP && curRenderStep_->render.stencil == VKRRenderPassAction::KEEP) {
|
||||
// Can trivially kill the last empty render step.
|
||||
assert(steps_.back() == curRenderStep_);
|
||||
delete steps_.back();
|
||||
@@ -413,7 +413,8 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
|
||||
// This is what queues up new passes, and can end previous ones.
|
||||
step->render.framebuffer = fb;
|
||||
step->render.color = color;
|
||||
step->render.depthStencil = depth;
|
||||
step->render.depth= depth;
|
||||
step->render.stencil = stencil;
|
||||
step->render.clearColor = clearColor;
|
||||
step->render.clearDepth = clearDepth;
|
||||
step->render.clearStencil = clearStencil;
|
||||
@@ -617,7 +618,8 @@ void VulkanRenderManager::Clear(uint32_t clearColor, float clearZ, int clearSten
|
||||
curRenderStep_->render.clearDepth = clearZ;
|
||||
curRenderStep_->render.clearStencil = clearStencil;
|
||||
curRenderStep_->render.color = (clearMask & VK_IMAGE_ASPECT_COLOR_BIT) ? VKRRenderPassAction::CLEAR : VKRRenderPassAction::KEEP;
|
||||
curRenderStep_->render.depthStencil = (clearMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) ? VKRRenderPassAction::CLEAR : VKRRenderPassAction::KEEP;
|
||||
curRenderStep_->render.depth = (clearMask & VK_IMAGE_ASPECT_DEPTH_BIT) ? VKRRenderPassAction::CLEAR : VKRRenderPassAction::KEEP;
|
||||
curRenderStep_->render.stencil = (clearMask & VK_IMAGE_ASPECT_STENCIL_BIT) ? VKRRenderPassAction::CLEAR : VKRRenderPassAction::KEEP;
|
||||
} else {
|
||||
VkRenderData data{ VKRRenderCommand::CLEAR };
|
||||
data.clear.clearColor = clearColor;
|
||||
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
// Zaps queued up commands. Use if you know there's a risk you've queued up stuff that has already been deleted. Can happen during in-game shutdown.
|
||||
void Wipe();
|
||||
|
||||
void BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, uint32_t clearColor, float clearDepth, uint8_t clearStencil);
|
||||
void BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, VKRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil);
|
||||
VkImageView BindFramebufferAsTexture(VKRFramebuffer *fb, int binding, int aspectBit, int attachment);
|
||||
bool CopyFramebufferToMemorySync(VKRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride);
|
||||
void CopyImageToMemorySync(VkImage image, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride);
|
||||
|
||||
@@ -1090,8 +1090,9 @@ void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Render
|
||||
OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
|
||||
GLRRenderPassAction color = (GLRRenderPassAction)rp.color;
|
||||
GLRRenderPassAction depth = (GLRRenderPassAction)rp.depth;
|
||||
GLRRenderPassAction stencil = (GLRRenderPassAction)rp.stencil;
|
||||
|
||||
renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer : nullptr, color, depth, rp.clearColor, rp.clearDepth, rp.clearStencil);
|
||||
renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil);
|
||||
}
|
||||
|
||||
void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) {
|
||||
|
||||
@@ -1339,8 +1339,9 @@ void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPass
|
||||
VKFramebuffer *fb = (VKFramebuffer *)fbo;
|
||||
VKRRenderPassAction color = (VKRRenderPassAction)rp.color;
|
||||
VKRRenderPassAction depth = (VKRRenderPassAction)rp.depth;
|
||||
VKRRenderPassAction stencil = (VKRRenderPassAction)rp.stencil;
|
||||
|
||||
renderManager_.BindFramebufferAsRenderTarget(fb ? fb->GetFB() : nullptr, color, depth, rp.clearColor, rp.clearDepth, rp.clearStencil);
|
||||
renderManager_.BindFramebufferAsRenderTarget(fb ? fb->GetFB() : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil);
|
||||
curFramebuffer_ = fb;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user