mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +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.width = static_cast<uint32_t>(currentViewportWidth);
|
||||||
rect.rect.extent.height = static_cast<uint32_t>(currentViewportHeight);
|
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) {
|
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.width = static_cast<uint32_t>(currentViewportWidth);
|
||||||
rect.rect.extent.height = static_cast<uint32_t>(currentViewportHeight);
|
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) {
|
void Graphics::present(void* screenshotCallbackdata) {
|
||||||
@@ -143,7 +143,7 @@ void Graphics::present(void* screenshotCallbackdata) {
|
|||||||
imagesInFlight[imageIndex] = inFlightFences[currentFrame];
|
imagesInFlight[imageIndex] = inFlightFences[currentFrame];
|
||||||
|
|
||||||
// all data transfers should happen before any draw calls.
|
// 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{};
|
VkSubmitInfo submitInfo{};
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
@@ -374,14 +374,14 @@ Graphics::RendererInfo Graphics::getRendererInfo() const {
|
|||||||
void Graphics::draw(const DrawCommand& cmd) {
|
void Graphics::draw(const DrawCommand& cmd) {
|
||||||
prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType, cmd.cullMode);
|
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) {
|
void Graphics::draw(const DrawIndexedCommand& cmd) {
|
||||||
prepareDraw(*cmd.attributes, *cmd.buffers, cmd.texture, cmd.primitiveType, cmd.cullMode);
|
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));
|
vkCmdBindIndexBuffer(commandBuffers.at(currentFrame), (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);
|
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) {
|
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);
|
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;
|
int baseVertex = start * 4;
|
||||||
|
|
||||||
for (int quadindex = 0; quadindex < count; quadindex += MAX_QUADS_PER_DRAW) {
|
for (int quadindex = 0; quadindex < count; quadindex += MAX_QUADS_PER_DRAW) {
|
||||||
int quadcount = std::min(MAX_QUADS_PER_DRAW, count - quadindex);
|
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;
|
baseVertex += quadcount * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -503,14 +503,14 @@ void Graphics::startRecordingGraphicsCommands() {
|
|||||||
beginInfo.flags = 0;
|
beginInfo.flags = 0;
|
||||||
beginInfo.pInheritanceInfo = nullptr;
|
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");
|
throw love::Exception("failed to begin recording command buffer");
|
||||||
}
|
}
|
||||||
if (vkBeginCommandBuffer(dataTransferCommandBuffers.at(currentFrame), &beginInfo) != VK_SUCCESS) {
|
if (vkBeginCommandBuffer(dataTransferCommandBuffers.at(currentFrame), &beginInfo) != VK_SUCCESS) {
|
||||||
throw love::Exception("failed to begin recording data transfer command buffer");
|
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);
|
startRenderPass(nullptr, swapChainExtent.width, swapChainExtent.height);
|
||||||
|
|
||||||
@@ -520,9 +520,9 @@ void Graphics::startRecordingGraphicsCommands() {
|
|||||||
void Graphics::endRecordingGraphicsCommands() {
|
void Graphics::endRecordingGraphicsCommands() {
|
||||||
endRenderPass();
|
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");
|
throw love::Exception("failed to record command buffer");
|
||||||
}
|
}
|
||||||
if (vkEndCommandBuffer(dataTransferCommandBuffers.at(currentFrame)) != VK_SUCCESS) {
|
if (vkEndCommandBuffer(dataTransferCommandBuffers.at(currentFrame)) != VK_SUCCESS) {
|
||||||
@@ -1175,8 +1175,8 @@ void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindi
|
|||||||
|
|
||||||
ensureGraphicsPipelineConfiguration(configuration);
|
ensureGraphicsPipelineConfiguration(configuration);
|
||||||
|
|
||||||
configuration.shader->cmdPushDescriptorSets(commandBuffers.at(imageIndex), static_cast<uint32_t>(currentFrame));
|
configuration.shader->cmdPushDescriptorSets(commandBuffers.at(currentFrame), static_cast<uint32_t>(currentFrame));
|
||||||
vkCmdBindVertexBuffers(commandBuffers.at(imageIndex), 0, static_cast<uint32_t>(bufferVector.size()), bufferVector.data(), offsets.data());
|
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) {
|
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;
|
currentViewportHeight = (float)h;
|
||||||
|
|
||||||
if (renderTargetTexture) {
|
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;
|
currentGraphicsPipeline = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::endRenderPass() {
|
void Graphics::endRenderPass() {
|
||||||
vkCmdEndRendering(commandBuffers.at(imageIndex));
|
vkCmdEndRendering(commandBuffers.at(currentFrame));
|
||||||
|
|
||||||
if (renderTargetTexture) {
|
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;
|
renderTargetTexture = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1239,7 +1239,7 @@ VkSampler Graphics::createSampler(const SamplerState& samplerState) {
|
|||||||
samplerInfo.addressModeV = Vulkan::getWrapMode(samplerState.wrapV);
|
samplerInfo.addressModeV = Vulkan::getWrapMode(samplerState.wrapV);
|
||||||
samplerInfo.addressModeW = Vulkan::getWrapMode(samplerState.wrapW);
|
samplerInfo.addressModeW = Vulkan::getWrapMode(samplerState.wrapW);
|
||||||
samplerInfo.anisotropyEnable = VK_TRUE;
|
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.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||||
samplerInfo.unnormalizedCoordinates = VK_FALSE;
|
samplerInfo.unnormalizedCoordinates = VK_FALSE;
|
||||||
if (samplerState.depthSampleMode.hasValue) {
|
if (samplerState.depthSampleMode.hasValue) {
|
||||||
@@ -1399,13 +1399,13 @@ void Graphics::ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration
|
|||||||
auto it = graphicsPipelines.find(configuration);
|
auto it = graphicsPipelines.find(configuration);
|
||||||
if (it != graphicsPipelines.end()) {
|
if (it != graphicsPipelines.end()) {
|
||||||
if (it->second != currentGraphicsPipeline) {
|
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;
|
currentGraphicsPipeline = it->second;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VkPipeline pipeline = createGraphicsPipeline(configuration);
|
VkPipeline pipeline = createGraphicsPipeline(configuration);
|
||||||
graphicsPipelines.insert({configuration, pipeline});
|
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;
|
currentGraphicsPipeline = pipeline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1424,14 +1424,14 @@ void Graphics::createCommandPool() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::createCommandBuffers() {
|
void Graphics::createCommandBuffers() {
|
||||||
commandBuffers.resize(swapChainImages.size());
|
commandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
dataTransferCommandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
dataTransferCommandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo allocInfo{};
|
VkCommandBufferAllocateInfo allocInfo{};
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
allocInfo.commandPool = commandPool;
|
allocInfo.commandPool = commandPool;
|
||||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
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) {
|
if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
|
||||||
throw love::Exception("failed to allocate command buffers");
|
throw love::Exception("failed to allocate command buffers");
|
||||||
@@ -1498,7 +1498,7 @@ void Graphics::cleanup() {
|
|||||||
vkDestroyFence(device, inFlightFences[i], nullptr);
|
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());
|
vkFreeCommandBuffers(device, commandPool, MAX_FRAMES_IN_FLIGHT, dataTransferCommandBuffers.data());
|
||||||
|
|
||||||
for (auto const& p : samplers) {
|
for (auto const& p : samplers) {
|
||||||
|
|||||||
Reference in New Issue
Block a user