mirror of
https://github.com/love2d/love.git
synced 2026-08-12 16:40:57 +02:00
vulkan: fix uniform buffer descriptor
There was a bug where the count of used builtin uniform buffer objects was not advanced. This caused another problem since vulkan requires a certain alignment for the buffer. This commit fixes both of those things.
This commit is contained in:
@@ -26,7 +26,7 @@ namespace love {
|
||||
}
|
||||
|
||||
Buffer::Buffer(love::graphics::Graphics* gfx, const Settings& settings, const std::vector<DataDeclaration>& format, const void* data, size_t size, size_t arraylength)
|
||||
: love::graphics::Buffer(gfx, settings, format, size, arraylength), usageFlags(settings.usageFlags), allocator(allocator), gfx(gfx) {
|
||||
: love::graphics::Buffer(gfx, settings, format, size, arraylength), usageFlags(settings.usageFlags), gfx(gfx) {
|
||||
loadVolatile();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "graphics/Texture.h"
|
||||
#include "Vulkan.h"
|
||||
#include "common/version.h"
|
||||
#include "common/pixelformat.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
@@ -99,8 +100,8 @@ namespace love {
|
||||
|
||||
VkClearRect rect{};
|
||||
rect.layerCount = 1;
|
||||
rect.rect.extent.width = currentViewportWidth;
|
||||
rect.rect.extent.height = currentViewportHeight;
|
||||
rect.rect.extent.width = static_cast<uint32_t>(currentViewportWidth);
|
||||
rect.rect.extent.height = static_cast<uint32_t>(currentViewportHeight);
|
||||
|
||||
vkCmdClearAttachments(commandBuffers[imageIndex], 1, &attachment, 1, &rect);
|
||||
}
|
||||
@@ -121,8 +122,8 @@ namespace love {
|
||||
|
||||
VkClearRect rect{};
|
||||
rect.layerCount = 1;
|
||||
rect.rect.extent.width = currentViewportWidth;
|
||||
rect.rect.extent.height = currentViewportHeight;
|
||||
rect.rect.extent.width = static_cast<uint32_t>(currentViewportWidth);
|
||||
rect.rect.extent.height = static_cast<uint32_t>(currentViewportHeight);
|
||||
|
||||
vkCmdClearAttachments(commandBuffers[imageIndex], static_cast<uint32_t>(attachments.size()), attachments.data(), 1, &rect);
|
||||
}
|
||||
@@ -433,7 +434,7 @@ namespace love {
|
||||
|
||||
PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const {
|
||||
switch (format) {
|
||||
PIXELFORMAT_NORMAL:
|
||||
case PIXELFORMAT_NORMAL:
|
||||
if (isGammaCorrect()) {
|
||||
return PIXELFORMAT_RGBA8_UNORM_sRGB;
|
||||
}
|
||||
@@ -534,6 +535,10 @@ namespace love {
|
||||
return MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
const VkDeviceSize Graphics::getMinUniformBufferOffsetAlignment() const {
|
||||
return minUniformBufferOffsetAlignment;
|
||||
}
|
||||
|
||||
const PFN_vkCmdPushDescriptorSetKHR Graphics::getVkCmdPushDescriptorSetKHRFunctionPointer() const {
|
||||
return vkCmdPushDescriptorSet;
|
||||
}
|
||||
@@ -596,8 +601,8 @@ namespace love {
|
||||
// Same with point size.
|
||||
data.normalMatrix[1].w = getPointSize();
|
||||
|
||||
data.screenSizeParams.x = swapChainExtent.width;
|
||||
data.screenSizeParams.y = swapChainExtent.height;
|
||||
data.screenSizeParams.x = static_cast<float>(swapChainExtent.width);
|
||||
data.screenSizeParams.y = static_cast<float>(swapChainExtent.height);
|
||||
|
||||
data.screenSizeParams.z = 1.0f;
|
||||
data.screenSizeParams.w = 0.0f;
|
||||
@@ -711,6 +716,10 @@ namespace love {
|
||||
else {
|
||||
throw love::Exception("failed to find a suitable gpu");
|
||||
}
|
||||
|
||||
VkPhysicalDeviceProperties properties;
|
||||
vkGetPhysicalDeviceProperties(physicalDevice, &properties);
|
||||
minUniformBufferOffsetAlignment = properties.limits.minUniformBufferOffsetAlignment;
|
||||
}
|
||||
|
||||
bool Graphics::checkDeviceExtensionSupport(VkPhysicalDevice device) {
|
||||
@@ -1184,7 +1193,7 @@ namespace love {
|
||||
|
||||
ensureGraphicsPipelineConfiguration(configuration);
|
||||
|
||||
configuration.shader->cmdPushDescriptorSets(commandBuffers.at(imageIndex), currentFrame);
|
||||
configuration.shader->cmdPushDescriptorSets(commandBuffers.at(imageIndex), static_cast<uint32_t>(currentFrame));
|
||||
vkCmdBindVertexBuffers(commandBuffers.at(imageIndex), 0, static_cast<uint32_t>(bufferVector.size()), bufferVector.data(), offsets.data());
|
||||
}
|
||||
|
||||
@@ -1241,9 +1250,9 @@ namespace love {
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
||||
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
vertexInputInfo.vertexBindingDescriptionCount = configuration.vertexInputBindingDescriptions.size();
|
||||
vertexInputInfo.vertexBindingDescriptionCount = static_cast<uint32_t>(configuration.vertexInputBindingDescriptions.size());
|
||||
vertexInputInfo.pVertexBindingDescriptions = configuration.vertexInputBindingDescriptions.data();
|
||||
vertexInputInfo.vertexAttributeDescriptionCount = configuration.vertexInputAttributeDescriptions.size();
|
||||
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(configuration.vertexInputAttributeDescriptions.size());
|
||||
vertexInputInfo.pVertexAttributeDescriptions = configuration.vertexInputAttributeDescriptions.data();
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
|
||||
|
||||
@@ -118,6 +118,7 @@ namespace love {
|
||||
|
||||
uint32_t getNumImagesInFlight() const;
|
||||
const PFN_vkCmdPushDescriptorSetKHR getVkCmdPushDescriptorSetKHRFunctionPointer() const;
|
||||
const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
|
||||
|
||||
protected:
|
||||
graphics::ShaderStage* newShaderStageInternal(ShaderStageType stage, const std::string& cachekey, const std::string& source, bool gles) override {
|
||||
@@ -189,6 +190,7 @@ namespace love {
|
||||
std::vector<VkSemaphore> renderFinishedSemaphores;
|
||||
std::vector<VkFence> inFlightFences;
|
||||
std::vector<VkFence> imagesInFlight;
|
||||
VkDeviceSize minUniformBufferOffsetAlignment;
|
||||
PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSet;
|
||||
size_t currentFrame = 0;
|
||||
uint32_t imageIndex = 0;
|
||||
|
||||
@@ -150,6 +150,7 @@ namespace love {
|
||||
}
|
||||
|
||||
bool Shader::loadVolatile() {
|
||||
calculateUniformBufferSizeAligned();
|
||||
compileShaders();
|
||||
createDescriptorSetLayout();
|
||||
createPipelineLayout();
|
||||
@@ -211,15 +212,15 @@ namespace love {
|
||||
}
|
||||
}
|
||||
|
||||
auto mapInfo = streamBuffers[currentImage]->map(sizeof(BuiltinUniformData));
|
||||
memcpy(mapInfo.data, &uniformData, sizeof(BuiltinUniformData));
|
||||
streamBuffers[currentImage]->unmap(sizeof(BuiltinUniformData));
|
||||
streamBuffers[currentImage]->markUsed(sizeof(BuiltinUniformData));
|
||||
auto mapInfo = streamBuffers[currentImage]->map(uniformBufferSizeAligned);
|
||||
memcpy(mapInfo.data, &uniformData, uniformBufferSizeAligned);
|
||||
streamBuffers[currentImage]->unmap(uniformBufferSizeAligned);
|
||||
streamBuffers[currentImage]->markUsed(uniformBufferSizeAligned);
|
||||
|
||||
VkDescriptorBufferInfo bufferInfo{};
|
||||
bufferInfo.buffer = (VkBuffer)streamBuffers[currentImage]->getHandle();
|
||||
bufferInfo.offset = count * sizeof(BuiltinUniformData);
|
||||
bufferInfo.range = sizeof(graphics::Shader::BuiltinUniformData);
|
||||
bufferInfo.offset = count * uniformBufferSizeAligned;
|
||||
bufferInfo.range = sizeof(BuiltinUniformData);
|
||||
|
||||
auto mainTexImageInfo = createDescriptorImageInfo(mainTex);
|
||||
auto ytextureImageInfo = createDescriptorImageInfo(ytexture);
|
||||
@@ -268,6 +269,8 @@ namespace love {
|
||||
descriptorWrite[4].pImageInfo = &crtextureImageInfo;
|
||||
|
||||
vkCmdPushDescriptorSet(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, static_cast<uint32_t>(descriptorWrite.size()), descriptorWrite.data());
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
Shader::~Shader() {
|
||||
@@ -286,6 +289,19 @@ namespace love {
|
||||
return vertexAttributeIndices.at(name);
|
||||
}
|
||||
|
||||
void Shader::calculateUniformBufferSizeAligned() {
|
||||
gfx = Module::getInstance<Graphics>(Module::ModuleType::M_GRAPHICS);
|
||||
auto vgfx = (Graphics*)gfx;
|
||||
auto minAlignment = vgfx->getMinUniformBufferOffsetAlignment();
|
||||
uniformBufferSizeAligned =
|
||||
static_cast<VkDeviceSize>(
|
||||
std::ceil(
|
||||
static_cast<float>(sizeof(BuiltinUniformData)) / static_cast<float>(minAlignment)
|
||||
)
|
||||
)
|
||||
* minAlignment;
|
||||
}
|
||||
|
||||
void Shader::compileShaders() {
|
||||
using namespace glslang;
|
||||
using namespace spirv_cross;
|
||||
@@ -315,7 +331,7 @@ namespace love {
|
||||
|
||||
auto& glsl = stages[i]->getSource();
|
||||
const char* csrc = glsl.c_str();
|
||||
const int sourceLength = glsl.length();
|
||||
const int sourceLength = static_cast<int>(glsl.length());
|
||||
tshader->setStringsWithLengths(&csrc, &sourceLength, 1);
|
||||
|
||||
int defaultVersio = 450;
|
||||
@@ -451,7 +467,7 @@ namespace love {
|
||||
const auto numImagesInFlight = vgfx->getNumImagesInFlight();
|
||||
streamBuffers.resize(numImagesInFlight);
|
||||
for (uint32_t i = 0; i < numImagesInFlight; i++) {
|
||||
streamBuffers[i] = new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_SIZE * sizeof(BuiltinUniformData));
|
||||
streamBuffers[i] = new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_SIZE * uniformBufferSizeAligned);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,11 +52,13 @@ namespace love {
|
||||
void setMainTex(graphics::Texture* texture);
|
||||
|
||||
private:
|
||||
void calculateUniformBufferSizeAligned();
|
||||
void compileShaders();
|
||||
void createDescriptorSetLayout();
|
||||
void createPipelineLayout();
|
||||
void createStreamBuffers();
|
||||
|
||||
VkDeviceSize uniformBufferSizeAligned;
|
||||
PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSet;
|
||||
|
||||
VkDescriptorSetLayout descriptorSetLayout;
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace love {
|
||||
|
||||
VkImageSubresourceRange range{};
|
||||
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
range.layerCount = 1;
|
||||
range.layerCount = getMipmapCount();
|
||||
range.levelCount = 1;
|
||||
|
||||
vkCmdClearColorImage(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &range);
|
||||
|
||||
Reference in New Issue
Block a user