mirror of
https://github.com/love2d/love.git
synced 2026-08-15 15:51:12 +02:00
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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user