mirror of
https://github.com/love2d/love.git
synced 2026-08-19 12:14:20 +02:00
vulkan: dynamically increase size of available memory for uniforms
This commit is contained in:
@@ -117,7 +117,7 @@ static const TBuiltInResource defaultTBuiltInResource = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t STREAMBUFFER_SIZE = 1024;
|
static const uint32_t STREAMBUFFER_DEFAULT_SIZE = 16;
|
||||||
|
|
||||||
static VkShaderStageFlagBits getStageBit(ShaderStageType type) {
|
static VkShaderStageFlagBits getStageBit(ShaderStageType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -174,8 +174,10 @@ void Shader::unloadVolatile() {
|
|||||||
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
|
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
|
||||||
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
||||||
});
|
});
|
||||||
for (const auto streamBuffer : streamBuffers) {
|
for (const auto streamBufferVector : streamBuffers) {
|
||||||
delete streamBuffer;
|
for (const auto streamBuffer : streamBufferVector) {
|
||||||
|
delete streamBuffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
shaderModules.clear();
|
shaderModules.clear();
|
||||||
shaderStages.clear();
|
shaderStages.clear();
|
||||||
@@ -200,24 +202,46 @@ static VkDescriptorImageInfo createDescriptorImageInfo(graphics::Texture* textur
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
|
void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
|
||||||
|
// detect wether a new frame has begun
|
||||||
if (currentImage != imageIndex) {
|
if (currentImage != imageIndex) {
|
||||||
currentImage = imageIndex;
|
currentImage = imageIndex;
|
||||||
count = 0;
|
count = 0;
|
||||||
streamBuffers[currentImage]->nextFrame();
|
|
||||||
|
// we needed more memory last frame, let's collapse all buffers into a single one.
|
||||||
|
if (streamBuffers.at(currentImage).size() > 1) {
|
||||||
|
size_t newSize = 0;
|
||||||
|
for (auto streamBuffer : streamBuffers.at(currentImage)) {
|
||||||
|
newSize += streamBuffer->getSize();
|
||||||
|
delete streamBuffer;
|
||||||
|
}
|
||||||
|
streamBuffers.at(currentImage).clear();
|
||||||
|
streamBuffers.at(currentImage).push_back(new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, newSize));
|
||||||
|
}
|
||||||
|
// no collapse necessary, can just call nextFrame to reset the current (only) streambuffer
|
||||||
|
else {
|
||||||
|
streamBuffers.at(currentImage).at(0)->nextFrame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// still the same frame
|
||||||
else {
|
else {
|
||||||
if (count >= STREAMBUFFER_SIZE) {
|
auto usedStreamBufferMemory = count * uniformBufferSizeAligned;
|
||||||
throw love::Exception("uniform stream buffer: out of memory (fixme: resize)");
|
if (usedStreamBufferMemory >= streamBuffers.at(currentImage).back()->getSize()) {
|
||||||
|
// we ran out of memory in the current frame, need to allocate more.
|
||||||
|
streamBuffers.at(currentImage).push_back(new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned));
|
||||||
|
count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mapInfo = streamBuffers[currentImage]->map(uniformBufferSizeAligned);
|
// additional data is always added onto the last stream buffer in the current frame
|
||||||
|
auto currentStreamBuffer = streamBuffers.at(currentImage).back();
|
||||||
|
|
||||||
|
auto mapInfo = currentStreamBuffer->map(uniformBufferSizeAligned);
|
||||||
memcpy(mapInfo.data, &uniformData, uniformBufferSizeAligned);
|
memcpy(mapInfo.data, &uniformData, uniformBufferSizeAligned);
|
||||||
streamBuffers[currentImage]->unmap(uniformBufferSizeAligned);
|
currentStreamBuffer->unmap(uniformBufferSizeAligned);
|
||||||
streamBuffers[currentImage]->markUsed(uniformBufferSizeAligned);
|
currentStreamBuffer->markUsed(uniformBufferSizeAligned);
|
||||||
|
|
||||||
VkDescriptorBufferInfo bufferInfo{};
|
VkDescriptorBufferInfo bufferInfo{};
|
||||||
bufferInfo.buffer = (VkBuffer)streamBuffers[currentImage]->getHandle();
|
bufferInfo.buffer = (VkBuffer)currentStreamBuffer->getHandle();
|
||||||
bufferInfo.offset = count * uniformBufferSizeAligned;
|
bufferInfo.offset = count * uniformBufferSizeAligned;
|
||||||
bufferInfo.range = sizeof(BuiltinUniformData);
|
bufferInfo.range = sizeof(BuiltinUniformData);
|
||||||
|
|
||||||
@@ -471,7 +495,7 @@ void Shader::createStreamBuffers() {
|
|||||||
const auto numImagesInFlight = vgfx->getNumImagesInFlight();
|
const auto numImagesInFlight = vgfx->getNumImagesInFlight();
|
||||||
streamBuffers.resize(numImagesInFlight);
|
streamBuffers.resize(numImagesInFlight);
|
||||||
for (uint32_t i = 0; i < numImagesInFlight; i++) {
|
for (uint32_t i = 0; i < numImagesInFlight; i++) {
|
||||||
streamBuffers[i] = new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_SIZE * uniformBufferSizeAligned);
|
streamBuffers[i].push_back(new StreamBuffer(gfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,10 @@ private:
|
|||||||
VkDescriptorSetLayout descriptorSetLayout;
|
VkDescriptorSetLayout descriptorSetLayout;
|
||||||
VkPipelineLayout pipelineLayout;
|
VkPipelineLayout pipelineLayout;
|
||||||
|
|
||||||
std::vector<StreamBuffer*> streamBuffers;
|
// we don't know how much memory we need per frame for the uniform buffer descriptors
|
||||||
|
// we keep a vector of stream buffers per frame in flight
|
||||||
|
// that gets dynamically increased if more memory is needed
|
||||||
|
std::vector<std::vector<StreamBuffer*>> streamBuffers;
|
||||||
|
|
||||||
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
||||||
std::vector<VkShaderModule> shaderModules;
|
std::vector<VkShaderModule> shaderModules;
|
||||||
@@ -92,6 +95,7 @@ private:
|
|||||||
graphics::Texture* crtexture;
|
graphics::Texture* crtexture;
|
||||||
|
|
||||||
uint32_t currentImage;
|
uint32_t currentImage;
|
||||||
|
// todo: give this variable a better name
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user