mirror of
https://github.com/love2d/love.git
synced 2026-08-16 16:20:42 +02:00
vulkan: cut down on number of cmd buffers
Until now we've used a command buffer for every swap chain image, however it makes more sense to just have a command buffer for every frame in flight, since we won't be ever recording more than that. This makes it more in line with the data transfer command buffers, which are also just created per frame in flight. This should make more sense.
This commit is contained in:
@@ -103,7 +103,7 @@ void Graphics::clear(OptionalColorD color, OptionalInt stencil, OptionalDouble d
|
||||
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);
|
||||
vkCmdClearAttachments(commandBuffers[currentFrame], 1, &attachment, 1, &rect);
|
||||
}
|
||||
|
||||
void Graphics::clear(const std::vector<OptionalColorD>& colors, OptionalInt stencil, OptionalDouble depth) {
|
||||
@@ -125,7 +125,7 @@ void Graphics::clear(const std::vector<OptionalColorD>& colors, OptionalInt sten
|
||||
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);
|
||||
vkCmdClearAttachments(commandBuffers[currentFrame], static_cast<uint32_t>(attachments.size()), attachments.data(), 1, &rect);
|
||||
}
|
||||
|
||||
void Graphics::present(void* screenshotCallbackdata) {
|
||||
@@ -143,7 +143,7 @@ void Graphics::present(void* screenshotCallbackdata) {
|
||||
imagesInFlight[imageIndex] = inFlightFences[currentFrame];
|
||||
|
||||
// all data transfers should happen before any draw calls.
|
||||
std::vector<VkCommandBuffer> submitCommandbuffers = { dataTransferCommandBuffers.at(currentFrame), commandBuffers.at(imageIndex) };
|
||||
std::vector<VkCommandBuffer> submitCommandbuffers = { dataTransferCommandBuffers.at(currentFrame), commandBuffers.at(currentFrame) };
|
||||
|
||||
VkSubmitInfo submitInfo{};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
@@ -374,14 +374,14 @@ Graphics::RendererInfo Graphics::getRendererInfo() const {
|
||||
void Graphics::draw(const DrawCommand& cmd) {
|
||||
prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType, cmd.cullMode);
|
||||
|
||||
vkCmdDraw(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.vertexCount), static_cast<uint32_t>(cmd.instanceCount), static_cast<uint32_t>(cmd.vertexStart), 0);
|
||||
vkCmdDraw(commandBuffers.at(currentFrame), static_cast<uint32_t>(cmd.vertexCount), static_cast<uint32_t>(cmd.instanceCount), static_cast<uint32_t>(cmd.vertexStart), 0);
|
||||
}
|
||||
|
||||
void Graphics::draw(const DrawIndexedCommand& cmd) {
|
||||
prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType, cmd.cullMode);
|
||||
|
||||
vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer)cmd.indexBuffer->getHandle(), static_cast<VkDeviceSize>(cmd.indexBufferOffset), getVulkanIndexBufferType(cmd.indexType));
|
||||
vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.indexCount), static_cast<uint32_t>(cmd.instanceCount), 0, 0, 0);
|
||||
vkCmdBindIndexBuffer(commandBuffers.at(currentFrame), (VkBuffer)cmd.indexBuffer->getHandle(), static_cast<VkDeviceSize>(cmd.indexBufferOffset), getVulkanIndexBufferType(cmd.indexType));
|
||||
vkCmdDrawIndexed(commandBuffers.at(currentFrame), static_cast<uint32_t>(cmd.indexCount), static_cast<uint32_t>(cmd.instanceCount), 0, 0, 0);
|
||||
}
|
||||
|
||||
void Graphics::drawQuads(int start, int count, const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture) {
|
||||
@@ -390,14 +390,14 @@ void Graphics::drawQuads(int start, int count, const VertexAttributes& attribute
|
||||
|
||||
prepareDraw(attributes, buffers, texture, PRIMITIVE_TRIANGLES, CULL_BACK);
|
||||
|
||||
vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer)quadIndexBuffer->getHandle(), 0, getVulkanIndexBufferType(INDEX_UINT16));
|
||||
vkCmdBindIndexBuffer(commandBuffers.at(currentFrame), (VkBuffer)quadIndexBuffer->getHandle(), 0, getVulkanIndexBufferType(INDEX_UINT16));
|
||||
|
||||
int baseVertex = start * 4;
|
||||
|
||||
for (int quadindex = 0; quadindex < count; quadindex += MAX_QUADS_PER_DRAW) {
|
||||
int quadcount = std::min(MAX_QUADS_PER_DRAW, count - quadindex);
|
||||
|
||||
vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast<uint32_t>(quadcount * 6), 1, 0, baseVertex, 0);
|
||||
vkCmdDrawIndexed(commandBuffers.at(currentFrame), static_cast<uint32_t>(quadcount * 6), 1, 0, baseVertex, 0);
|
||||
baseVertex += quadcount * 4;
|
||||
}
|
||||
}
|
||||
@@ -503,14 +503,14 @@ void Graphics::startRecordingGraphicsCommands() {
|
||||
beginInfo.flags = 0;
|
||||
beginInfo.pInheritanceInfo = nullptr;
|
||||
|
||||
if (vkBeginCommandBuffer(commandBuffers.at(imageIndex), &beginInfo) != VK_SUCCESS) {
|
||||
if (vkBeginCommandBuffer(commandBuffers.at(currentFrame), &beginInfo) != VK_SUCCESS) {
|
||||
throw love::Exception("failed to begin recording command buffer");
|
||||
}
|
||||
if (vkBeginCommandBuffer(dataTransferCommandBuffers.at(currentFrame), &beginInfo) != VK_SUCCESS) {
|
||||
throw love::Exception("failed to begin recording data transfer command buffer");
|
||||
}
|
||||
|
||||
Vulkan::cmdTransitionImageLayout(commandBuffers.at(imageIndex), swapChainImages[imageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), swapChainImages[imageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
startRenderPass(nullptr, swapChainExtent.width, swapChainExtent.height);
|
||||
|
||||
@@ -520,9 +520,9 @@ void Graphics::startRecordingGraphicsCommands() {
|
||||
void Graphics::endRecordingGraphicsCommands() {
|
||||
endRenderPass();
|
||||
|
||||
Vulkan::cmdTransitionImageLayout(commandBuffers.at(imageIndex), swapChainImages[imageIndex], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), swapChainImages[imageIndex], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
|
||||
if (vkEndCommandBuffer(commandBuffers.at(imageIndex)) != VK_SUCCESS) {
|
||||
if (vkEndCommandBuffer(commandBuffers.at(currentFrame)) != VK_SUCCESS) {
|
||||
throw love::Exception("failed to record command buffer");
|
||||
}
|
||||
if (vkEndCommandBuffer(dataTransferCommandBuffers.at(currentFrame)) != VK_SUCCESS) {
|
||||
@@ -1175,8 +1175,8 @@ void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindi
|
||||
|
||||
ensureGraphicsPipelineConfiguration(configuration);
|
||||
|
||||
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());
|
||||
configuration.shader->cmdPushDescriptorSets(commandBuffers.at(currentFrame), static_cast<uint32_t>(currentFrame));
|
||||
vkCmdBindVertexBuffers(commandBuffers.at(currentFrame), 0, static_cast<uint32_t>(bufferVector.size()), bufferVector.data(), offsets.data());
|
||||
}
|
||||
|
||||
void Graphics::startRenderPass(Texture* texture, uint32_t w, uint32_t h) {
|
||||
@@ -1210,19 +1210,19 @@ void Graphics::startRenderPass(Texture* texture, uint32_t w, uint32_t h) {
|
||||
currentViewportHeight = (float)h;
|
||||
|
||||
if (renderTargetTexture) {
|
||||
Vulkan::cmdTransitionImageLayout(commandBuffers.at(imageIndex), (VkImage)texture->getHandle(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), (VkImage)texture->getHandle(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
vkCmdBeginRendering(commandBuffers.at(imageIndex), &renderingInfo);
|
||||
vkCmdBeginRendering(commandBuffers.at(currentFrame), &renderingInfo);
|
||||
|
||||
currentGraphicsPipeline = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void Graphics::endRenderPass() {
|
||||
vkCmdEndRendering(commandBuffers.at(imageIndex));
|
||||
vkCmdEndRendering(commandBuffers.at(currentFrame));
|
||||
|
||||
if (renderTargetTexture) {
|
||||
Vulkan::cmdTransitionImageLayout(commandBuffers.at(imageIndex), (VkImage)renderTargetTexture->getHandle(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), (VkImage)renderTargetTexture->getHandle(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
renderTargetTexture = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1239,7 +1239,7 @@ VkSampler Graphics::createSampler(const SamplerState& samplerState) {
|
||||
samplerInfo.addressModeV = Vulkan::getWrapMode(samplerState.wrapV);
|
||||
samplerInfo.addressModeW = Vulkan::getWrapMode(samplerState.wrapW);
|
||||
samplerInfo.anisotropyEnable = VK_TRUE;
|
||||
samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy; // fixme: samplerState.maxAnisotropy
|
||||
samplerInfo.maxAnisotropy = static_cast<float>(samplerState.maxAnisotropy);
|
||||
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||
samplerInfo.unnormalizedCoordinates = VK_FALSE;
|
||||
if (samplerState.depthSampleMode.hasValue) {
|
||||
@@ -1399,13 +1399,13 @@ void Graphics::ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration
|
||||
auto it = graphicsPipelines.find(configuration);
|
||||
if (it != graphicsPipelines.end()) {
|
||||
if (it->second != currentGraphicsPipeline) {
|
||||
vkCmdBindPipeline(commandBuffers.at(imageIndex), VK_PIPELINE_BIND_POINT_GRAPHICS, it->second);
|
||||
vkCmdBindPipeline(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_GRAPHICS, it->second);
|
||||
currentGraphicsPipeline = it->second;
|
||||
}
|
||||
} else {
|
||||
VkPipeline pipeline = createGraphicsPipeline(configuration);
|
||||
graphicsPipelines.insert({configuration, pipeline});
|
||||
vkCmdBindPipeline(commandBuffers.at(imageIndex), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
vkCmdBindPipeline(commandBuffers.at(currentFrame), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
currentGraphicsPipeline = pipeline;
|
||||
}
|
||||
}
|
||||
@@ -1424,14 +1424,14 @@ void Graphics::createCommandPool() {
|
||||
}
|
||||
|
||||
void Graphics::createCommandBuffers() {
|
||||
commandBuffers.resize(swapChainImages.size());
|
||||
commandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
||||
dataTransferCommandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
||||
|
||||
VkCommandBufferAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
allocInfo.commandPool = commandPool;
|
||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
allocInfo.commandBufferCount = (uint32_t)commandBuffers.size();
|
||||
allocInfo.commandBufferCount = (uint32_t)MAX_FRAMES_IN_FLIGHT;
|
||||
|
||||
if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
|
||||
throw love::Exception("failed to allocate command buffers");
|
||||
@@ -1498,7 +1498,7 @@ void Graphics::cleanup() {
|
||||
vkDestroyFence(device, inFlightFences[i], nullptr);
|
||||
}
|
||||
|
||||
vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());
|
||||
vkFreeCommandBuffers(device, commandPool, MAX_FRAMES_IN_FLIGHT, commandBuffers.data());
|
||||
vkFreeCommandBuffers(device, commandPool, MAX_FRAMES_IN_FLIGHT, dataTransferCommandBuffers.data());
|
||||
|
||||
for (auto const& p : samplers) {
|
||||
|
||||
Reference in New Issue
Block a user