mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +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)
|
if (!color.hasValue && !stencil.hasValue && !depth.hasValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
flushBatchedDraws();
|
std::vector<OptionalColorD> colors;
|
||||||
|
|
||||||
if (renderPassState.active)
|
if (color.hasValue)
|
||||||
{
|
colors.resize(std::max(1, (int)states.back().renderTargets.colors.size()), color);
|
||||||
VkClearAttachment attachment{};
|
|
||||||
|
|
||||||
if (color.hasValue)
|
clear(colors, stencil, depth);
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt stencil, OptionalDouble 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();
|
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)
|
if (renderPassState.active)
|
||||||
{
|
{
|
||||||
std::vector<VkClearAttachment> attachments;
|
std::vector<VkClearAttachment> attachments;
|
||||||
for (const auto &color : colors)
|
for (size_t i = 0; i < ncolors; i++)
|
||||||
{
|
{
|
||||||
|
const OptionalColorD &color = colors[i];
|
||||||
VkClearAttachment attachment{};
|
VkClearAttachment attachment{};
|
||||||
if (color.hasValue)
|
if (color.hasValue)
|
||||||
{
|
{
|
||||||
Colorf cf((float)color.value.r, (float)color.value.g, (float)color.value.b, (float)color.value.a);
|
auto texture = i < rts.size() ? rts[i].texture.get() : nullptr;
|
||||||
gammaCorrectColor(cf);
|
|
||||||
|
|
||||||
attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
attachment.clearValue.color.float32[0] = static_cast<float>(cf.r);
|
attachment.clearValue.color = Texture::getClearColor(texture, color.value);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
attachments.push_back(attachment);
|
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);
|
depthStencilAttachment.clearValue.depthStencil.depth = static_cast<float>(depth.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
attachments.push_back(depthStencilAttachment);
|
if (stencil.hasValue || depth.hasValue)
|
||||||
|
attachments.push_back(depthStencilAttachment);
|
||||||
|
|
||||||
VkClearRect rect{};
|
VkClearRect rect{};
|
||||||
rect.layerCount = 1;
|
rect.layerCount = 1;
|
||||||
@@ -324,36 +248,38 @@ void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt sten
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < colors.size(); i++)
|
for (size_t i = 0; i < ncolors; i++)
|
||||||
{
|
{
|
||||||
if (colors[i].hasValue)
|
if (colors[i].hasValue)
|
||||||
{
|
{
|
||||||
renderPassState.renderPassConfiguration.colorAttachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
renderPassState.renderPassConfiguration.colorAttachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
|
|
||||||
auto &color = colors[i];
|
auto texture = i < rts.size() ? rts[i].texture.get() : nullptr;
|
||||||
Colorf cf((float)color.value.r, (float)color.value.g, (float)color.value.b, (float)color.value.a);
|
renderPassState.clearColors[i].color = Texture::getClearColor(texture, colors[i].value);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth.hasValue)
|
if (depth.hasValue)
|
||||||
{
|
{
|
||||||
renderPassState.renderPassConfiguration.staticData.depthStencilAttachment.depthLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
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)
|
if (stencil.hasValue)
|
||||||
{
|
{
|
||||||
renderPassState.renderPassConfiguration.staticData.depthStencilAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
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,
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS);
|
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);
|
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)
|
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);
|
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{};
|
VkClearColorValue c{};
|
||||||
switch (vulkanFormat.internalFormatRepresentation)
|
|
||||||
|
switch (formattype)
|
||||||
{
|
{
|
||||||
case FORMATREPRESENTATION_FLOAT:
|
case PIXELFORMATTYPE_SINT:
|
||||||
clearColor.float32[0] = 0.0f;
|
c.int32[0] = (int32)color.r;
|
||||||
clearColor.float32[1] = 0.0f;
|
c.int32[1] = (int32)color.g;
|
||||||
clearColor.float32[2] = 0.0f;
|
c.int32[2] = (int32)color.b;
|
||||||
clearColor.float32[3] = 0.0f;
|
c.int32[3] = (int32)color.a;
|
||||||
break;
|
break;
|
||||||
case FORMATREPRESENTATION_SINT:
|
case PIXELFORMATTYPE_UINT:
|
||||||
clearColor.int32[0] = 0;
|
c.uint32[0] = (uint32)color.r;
|
||||||
clearColor.int32[1] = 0;
|
c.uint32[1] = (uint32)color.g;
|
||||||
clearColor.int32[2] = 0;
|
c.uint32[2] = (uint32)color.b;
|
||||||
clearColor.int32[3] = 0;
|
c.uint32[3] = (uint32)color.a;
|
||||||
break;
|
break;
|
||||||
case FORMATREPRESENTATION_UINT:
|
default:
|
||||||
clearColor.uint32[0] = 0;
|
{
|
||||||
clearColor.uint32[1] = 0;
|
Colorf cf((float)color.r, (float)color.g, (float)color.b, (float)color.a);
|
||||||
clearColor.uint32[2] = 0;
|
gammaCorrectColor(cf);
|
||||||
clearColor.uint32[3] = 0;
|
c.float32[0] = cf.r;
|
||||||
|
c.float32[1] = cf.g;
|
||||||
|
c.float32[2] = cf.b;
|
||||||
|
c.float32[3] = cf.a;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return clearColor;
|
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::generateMipmapsInternal()
|
void Texture::generateMipmapsInternal()
|
||||||
|
|||||||
@@ -68,12 +68,12 @@ public:
|
|||||||
int getMSAA() const override;
|
int getMSAA() const override;
|
||||||
ptrdiff_t getHandle() const override;
|
ptrdiff_t getHandle() const override;
|
||||||
|
|
||||||
|
static VkClearColorValue getClearColor(love::graphics::Texture *texture, const ColorD &color);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createTextureImageView();
|
void createTextureImageView();
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
VkClearColorValue getClearValue();
|
|
||||||
|
|
||||||
Graphics *vgfx = nullptr;
|
Graphics *vgfx = nullptr;
|
||||||
VkDevice device = VK_NULL_HANDLE;
|
VkDevice device = VK_NULL_HANDLE;
|
||||||
VkImageAspectFlags imageAspect;
|
VkImageAspectFlags imageAspect;
|
||||||
|
|||||||
Reference in New Issue
Block a user