vulkan: love.graphics.clear fixes.

- Fix love.graphics.clear(color) when multiple canvases are active.
- Fix love.graphics.clear when an integer-format canvas is active.
This commit is contained in:
Sasha Szpakowski
2024-03-28 19:00:29 -03:00
parent d82922f774
commit b33afc4371
3 changed files with 60 additions and 126 deletions
+28 -102
View File
@@ -185,89 +185,12 @@ void Graphics::clear(OptionalColorD color, OptionalInt stencil, OptionalDouble d
if (!color.hasValue && !stencil.hasValue && !depth.hasValue)
return;
flushBatchedDraws();
std::vector<OptionalColorD> colors;
if (renderPassState.active)
{
VkClearAttachment attachment{};
if (color.hasValue)
colors.resize(std::max(1, (int)states.back().renderTargets.colors.size()), color);
if (color.hasValue)
{
Colorf cf((float)color.value.r, (float)color.value.g, (float)color.value.b, (float)color.value.a);
gammaCorrectColor(cf);
attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
attachment.clearValue.color.float32[0] = static_cast<float>(cf.r);
attachment.clearValue.color.float32[1] = static_cast<float>(cf.g);
attachment.clearValue.color.float32[2] = static_cast<float>(cf.b);
attachment.clearValue.color.float32[3] = static_cast<float>(cf.a);
}
VkClearAttachment depthStencilAttachment{};
if (stencil.hasValue)
{
depthStencilAttachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
depthStencilAttachment.clearValue.depthStencil.stencil = static_cast<uint32_t>(stencil.value);
}
if (depth.hasValue)
{
depthStencilAttachment.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
depthStencilAttachment.clearValue.depthStencil.depth = static_cast<float>(depth.value);
}
std::array<VkClearAttachment, 2> attachments = {
attachment,
depthStencilAttachment
};
VkClearRect rect{};
rect.layerCount = 1;
rect.rect.extent.width = static_cast<uint32_t>(renderPassState.width);
rect.rect.extent.height = static_cast<uint32_t>(renderPassState.height);
vkCmdClearAttachments(
commandBuffers[currentFrame],
static_cast<uint32_t>(attachments.size()), attachments.data(),
1, &rect);
}
else
{
if (color.hasValue)
{
renderPassState.renderPassConfiguration.colorAttachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
Colorf cf((float)color.value.r, (float)color.value.g, (float)color.value.b, (float)color.value.a);
gammaCorrectColor(cf);
renderPassState.clearColors[0].color.float32[0] = static_cast<float>(cf.r);
renderPassState.clearColors[0].color.float32[1] = static_cast<float>(cf.g);
renderPassState.clearColors[0].color.float32[2] = static_cast<float>(cf.b);
renderPassState.clearColors[0].color.float32[3] = static_cast<float>(cf.a);
}
if (depth.hasValue)
{
renderPassState.renderPassConfiguration.staticData.depthStencilAttachment.depthLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
renderPassState.clearColors[1].depthStencil.depth = static_cast<float>(depth.value);
}
if (stencil.hasValue)
{
renderPassState.renderPassConfiguration.staticData.depthStencilAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
renderPassState.clearColors[1].depthStencil.stencil = static_cast<uint32_t>(stencil.value);
}
if (renderPassState.isWindow)
{
renderPassState.windowClearRequested = true;
renderPassState.mainWindowClearColorValue = color;
renderPassState.mainWindowClearDepthValue = depth;
renderPassState.mainWindowClearStencilValue = stencil;
}
else
startRenderPass();
}
clear(colors, stencil, depth);
}
void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt stencil, OptionalDouble depth)
@@ -277,22 +200,22 @@ void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt sten
flushBatchedDraws();
const auto &rts = states.back().renderTargets.colors;
size_t ncolorbuffers = isRenderTargetActive() ? rts.size() : 1;
size_t ncolors = std::min(ncolorbuffers, colors.size());
if (renderPassState.active)
{
std::vector<VkClearAttachment> attachments;
for (const auto &color : colors)
for (size_t i = 0; i < ncolors; i++)
{
const OptionalColorD &color = colors[i];
VkClearAttachment attachment{};
if (color.hasValue)
{
Colorf cf((float)color.value.r, (float)color.value.g, (float)color.value.b, (float)color.value.a);
gammaCorrectColor(cf);
auto texture = i < rts.size() ? rts[i].texture.get() : nullptr;
attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
attachment.clearValue.color.float32[0] = static_cast<float>(cf.r);
attachment.clearValue.color.float32[1] = static_cast<float>(cf.g);
attachment.clearValue.color.float32[2] = static_cast<float>(cf.b);
attachment.clearValue.color.float32[3] = static_cast<float>(cf.a);
attachment.clearValue.color = Texture::getClearColor(texture, color.value);
}
attachments.push_back(attachment);
}
@@ -310,7 +233,8 @@ void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt sten
depthStencilAttachment.clearValue.depthStencil.depth = static_cast<float>(depth.value);
}
attachments.push_back(depthStencilAttachment);
if (stencil.hasValue || depth.hasValue)
attachments.push_back(depthStencilAttachment);
VkClearRect rect{};
rect.layerCount = 1;
@@ -324,36 +248,38 @@ void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt sten
}
else
{
for (size_t i = 0; i < colors.size(); i++)
for (size_t i = 0; i < ncolors; i++)
{
if (colors[i].hasValue)
{
renderPassState.renderPassConfiguration.colorAttachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
auto &color = colors[i];
Colorf cf((float)color.value.r, (float)color.value.g, (float)color.value.b, (float)color.value.a);
gammaCorrectColor(cf);
renderPassState.clearColors[i].color.float32[0] = static_cast<float>(cf.r);
renderPassState.clearColors[i].color.float32[1] = static_cast<float>(cf.g);
renderPassState.clearColors[i].color.float32[2] = static_cast<float>(cf.b);
renderPassState.clearColors[i].color.float32[3] = static_cast<float>(cf.a);
auto texture = i < rts.size() ? rts[i].texture.get() : nullptr;
renderPassState.clearColors[i].color = Texture::getClearColor(texture, colors[i].value);
}
}
if (depth.hasValue)
{
renderPassState.renderPassConfiguration.staticData.depthStencilAttachment.depthLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
renderPassState.clearColors[colors.size()].depthStencil.depth = static_cast<float>(depth.value);
renderPassState.clearColors[ncolorbuffers].depthStencil.depth = static_cast<float>(depth.value);
}
if (stencil.hasValue)
{
renderPassState.renderPassConfiguration.staticData.depthStencilAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
renderPassState.clearColors[colors.size()].depthStencil.stencil = static_cast<uint32_t>(stencil.value);
renderPassState.clearColors[ncolorbuffers].depthStencil.stencil = static_cast<uint32_t>(stencil.value);
}
startRenderPass();
if (renderPassState.isWindow)
{
renderPassState.windowClearRequested = true;
renderPassState.mainWindowClearColorValue = colors.empty() ? OptionalColorD() : colors[0];
renderPassState.mainWindowClearDepthValue = depth;
renderPassState.mainWindowClearStencilValue = stencil;
}
else
startRenderPass();
}
}
+30 -22
View File
@@ -383,7 +383,7 @@ void Texture::clear()
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS);
auto clearColor = getClearValue();
auto clearColor = getClearColor(this, ColorD(0, 0, 0, 0));
vkCmdClearColorImage(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range);
@@ -393,7 +393,7 @@ void Texture::clear()
}
else if (imageLayout == VK_IMAGE_LAYOUT_GENERAL)
{
auto clearColor = getClearValue();
auto clearColor = getClearColor(this, ColorD(0, 0, 0, 0));
vkCmdClearColorImage(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &range);
}
@@ -415,33 +415,41 @@ void Texture::clear()
}
}
VkClearColorValue Texture::getClearValue()
VkClearColorValue Texture::getClearColor(love::graphics::Texture *texture, const ColorD &color)
{
auto vulkanFormat = Vulkan::getTextureFormat(format);
PixelFormatType formattype = PIXELFORMATTYPE_SFLOAT;
if (texture != nullptr)
formattype = getPixelFormatInfo(texture->getPixelFormat()).dataType;
VkClearColorValue clearColor{};
switch (vulkanFormat.internalFormatRepresentation)
VkClearColorValue c{};
switch (formattype)
{
case FORMATREPRESENTATION_FLOAT:
clearColor.float32[0] = 0.0f;
clearColor.float32[1] = 0.0f;
clearColor.float32[2] = 0.0f;
clearColor.float32[3] = 0.0f;
case PIXELFORMATTYPE_SINT:
c.int32[0] = (int32)color.r;
c.int32[1] = (int32)color.g;
c.int32[2] = (int32)color.b;
c.int32[3] = (int32)color.a;
break;
case FORMATREPRESENTATION_SINT:
clearColor.int32[0] = 0;
clearColor.int32[1] = 0;
clearColor.int32[2] = 0;
clearColor.int32[3] = 0;
case PIXELFORMATTYPE_UINT:
c.uint32[0] = (uint32)color.r;
c.uint32[1] = (uint32)color.g;
c.uint32[2] = (uint32)color.b;
c.uint32[3] = (uint32)color.a;
break;
case FORMATREPRESENTATION_UINT:
clearColor.uint32[0] = 0;
clearColor.uint32[1] = 0;
clearColor.uint32[2] = 0;
clearColor.uint32[3] = 0;
default:
{
Colorf cf((float)color.r, (float)color.g, (float)color.b, (float)color.a);
gammaCorrectColor(cf);
c.float32[0] = cf.r;
c.float32[1] = cf.g;
c.float32[2] = cf.b;
c.float32[3] = cf.a;
}
break;
}
return clearColor;
return c;
}
void Texture::generateMipmapsInternal()
+2 -2
View File
@@ -68,12 +68,12 @@ public:
int getMSAA() const override;
ptrdiff_t getHandle() const override;
static VkClearColorValue getClearColor(love::graphics::Texture *texture, const ColorD &color);
private:
void createTextureImageView();
void clear();
VkClearColorValue getClearValue();
Graphics *vgfx = nullptr;
VkDevice device = VK_NULL_HANDLE;
VkImageAspectFlags imageAspect;