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:
niki
2022-07-29 21:04:35 +02:00
parent 6d7bd645fc
commit 7a3e9ed71e
6 changed files with 49 additions and 20 deletions
+1 -1
View File
@@ -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();
}
+19 -10
View File
@@ -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{};
+2
View File
@@ -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;
+24 -8
View File
@@ -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);
}
}
+2
View File
@@ -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;
+1 -1
View File
@@ -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);