mirror of
https://github.com/love2d/love.git
synced 2026-08-16 08:11:02 +02:00
vulkan: fix video rendering
This commit is contained in:
@@ -142,6 +142,9 @@ namespace love {
|
||||
}
|
||||
imagesInFlight[imageIndex] = inFlightFences[currentFrame];
|
||||
|
||||
// all data transfers should happen before any draw calls.
|
||||
std::vector<VkCommandBuffer> submitCommandbuffers = { dataTransferCommandBuffers.at(currentFrame), commandBuffers.at(imageIndex) };
|
||||
|
||||
VkSubmitInfo submitInfo{};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
|
||||
@@ -151,8 +154,8 @@ namespace love {
|
||||
submitInfo.pWaitSemaphores = waitSemaphores;
|
||||
submitInfo.pWaitDstStageMask = waitStages;
|
||||
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &commandBuffers[imageIndex];
|
||||
submitInfo.commandBufferCount = static_cast<uint32_t>(submitCommandbuffers.size());
|
||||
submitInfo.pCommandBuffers = submitCommandbuffers.data();
|
||||
|
||||
VkSemaphore signalSemaphores[] = { renderFinishedSemaphores.at(currentFrame) };
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
@@ -213,10 +216,10 @@ namespace love {
|
||||
initCapabilities();
|
||||
createSwapChain();
|
||||
createImageViews();
|
||||
createDefaultShaders();
|
||||
createCommandPool();
|
||||
createCommandBuffers();
|
||||
createDefaultTexture();
|
||||
createDefaultShaders();
|
||||
createQuadIndexBuffer();
|
||||
createSyncObjects();
|
||||
startRecordingGraphicsCommands();
|
||||
@@ -510,6 +513,9 @@ namespace love {
|
||||
if (vkBeginCommandBuffer(commandBuffers.at(imageIndex), &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);
|
||||
|
||||
@@ -519,8 +525,6 @@ namespace love {
|
||||
}
|
||||
|
||||
void Graphics::endRecordingGraphicsCommands() {
|
||||
const auto& commandBuffer = commandBuffers.at(imageIndex);
|
||||
|
||||
endRenderPass();
|
||||
|
||||
Vulkan::cmdTransitionImageLayout(commandBuffers.at(imageIndex), swapChainImages[imageIndex], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
@@ -528,6 +532,9 @@ namespace love {
|
||||
if (vkEndCommandBuffer(commandBuffers.at(imageIndex)) != VK_SUCCESS) {
|
||||
throw love::Exception("failed to record command buffer");
|
||||
}
|
||||
if (vkEndCommandBuffer(dataTransferCommandBuffers.at(currentFrame)) != VK_SUCCESS) {
|
||||
throw love::Exception("failed to record data transfer command buffer");
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::updatedBatchedDrawBuffers() {
|
||||
@@ -547,12 +554,16 @@ namespace love {
|
||||
return minUniformBufferOffsetAlignment;
|
||||
}
|
||||
|
||||
graphics::Texture* Graphics::getDefaultTexture() const {
|
||||
return dynamic_cast<graphics::Texture*>(standardTexture.get());
|
||||
}
|
||||
|
||||
const PFN_vkCmdPushDescriptorSetKHR Graphics::getVkCmdPushDescriptorSetKHRFunctionPointer() const {
|
||||
return vkCmdPushDescriptorSet;
|
||||
}
|
||||
|
||||
void Graphics::executeCommand(std::function<void(VkCommandBuffer)> command, std::function<void()> cleanUp) {
|
||||
command(commandBuffers.at(imageIndex));
|
||||
void Graphics::queueDatatransfer(std::function<void(VkCommandBuffer)> command, std::function<void()> cleanUp) {
|
||||
command(dataTransferCommandBuffers.at(currentFrame));
|
||||
cleanUpFunctions.at(currentFrame).push_back(std::move(cleanUp));
|
||||
}
|
||||
|
||||
@@ -1207,7 +1218,6 @@ namespace love {
|
||||
else {
|
||||
configuration.shader->setMainTex(texture);
|
||||
}
|
||||
configuration.shader->setVideoTextures(standardTexture.get(), standardTexture.get(), standardTexture.get());
|
||||
|
||||
ensureGraphicsPipelineConfiguration(configuration);
|
||||
|
||||
@@ -1416,6 +1426,7 @@ namespace love {
|
||||
|
||||
void Graphics::createCommandBuffers() {
|
||||
commandBuffers.resize(swapChainImages.size());
|
||||
dataTransferCommandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
||||
|
||||
VkCommandBufferAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
@@ -1426,6 +1437,16 @@ namespace love {
|
||||
if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
|
||||
throw love::Exception("failed to allocate command buffers");
|
||||
}
|
||||
|
||||
VkCommandBufferAllocateInfo dataTransferAllocInfo{};
|
||||
dataTransferAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
dataTransferAllocInfo.commandPool = commandPool;
|
||||
dataTransferAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
dataTransferAllocInfo.commandBufferCount = (uint32_t)MAX_FRAMES_IN_FLIGHT;
|
||||
|
||||
if (vkAllocateCommandBuffers(device, &dataTransferAllocInfo, dataTransferCommandBuffers.data()) != VK_SUCCESS) {
|
||||
throw love::Exception("failed to allocate data transfer command buffers");
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::createSyncObjects() {
|
||||
@@ -1565,6 +1586,7 @@ namespace love {
|
||||
void Graphics::cleanupSwapChain() {
|
||||
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
|
||||
vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());
|
||||
vkFreeCommandBuffers(device, commandPool, MAX_FRAMES_IN_FLIGHT, dataTransferCommandBuffers.data());
|
||||
for (auto const& p : graphicsPipelines) {
|
||||
vkDestroyPipeline(device, p.second, nullptr);
|
||||
}
|
||||
|
||||
@@ -114,8 +114,7 @@ namespace love {
|
||||
GraphicsReadback* newReadbackInternal(ReadbackMethod method, love::graphics::Buffer* buffer, size_t offset, size_t size, data::ByteData* dest, size_t destoffset) override { return nullptr; };
|
||||
GraphicsReadback* newReadbackInternal(ReadbackMethod method, love::graphics::Texture* texture, int slice, int mipmap, const Rect& rect, image::ImageData* dest, int destx, int desty) { return nullptr; }
|
||||
|
||||
// fixme: better naming for these two functions?
|
||||
void executeCommand(std::function<void(VkCommandBuffer)> command, std::function<void()> cleanUp);
|
||||
void queueDatatransfer(std::function<void(VkCommandBuffer)> command, std::function<void()> cleanUp);
|
||||
void queueCleanUp(std::function<void()> cleanUp);
|
||||
|
||||
VkCommandBuffer beginSingleTimeCommands();
|
||||
@@ -124,6 +123,7 @@ namespace love {
|
||||
uint32_t getNumImagesInFlight() const;
|
||||
const PFN_vkCmdPushDescriptorSetKHR getVkCmdPushDescriptorSetKHRFunctionPointer() const;
|
||||
const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
|
||||
graphics::Texture* getDefaultTexture() const;
|
||||
|
||||
protected:
|
||||
graphics::ShaderStage* newShaderStageInternal(ShaderStageType stage, const std::string& cachekey, const std::string& source, bool gles) override {
|
||||
@@ -190,6 +190,7 @@ namespace love {
|
||||
std::vector<std::pair<GraphicsPipelineConfiguration, VkPipeline>> graphicsPipelines; // FIXME improve performance by using a hash map
|
||||
VkCommandPool commandPool = VK_NULL_HANDLE;
|
||||
std::vector<VkCommandBuffer> commandBuffers;
|
||||
std::vector<VkCommandBuffer> dataTransferCommandBuffers;
|
||||
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
|
||||
std::vector<VkSemaphore> imageAvailableSemaphores;
|
||||
std::vector<VkSemaphore> renderFinishedSemaphores;
|
||||
|
||||
@@ -311,6 +311,11 @@ namespace love {
|
||||
auto vgfx = (Graphics*)gfx;
|
||||
device = vgfx->getDevice();
|
||||
|
||||
mainTex = vgfx->getDefaultTexture();
|
||||
ytexture = vgfx->getDefaultTexture();
|
||||
crtexture = vgfx->getDefaultTexture();
|
||||
cbtexture = vgfx->getDefaultTexture();
|
||||
|
||||
for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++) {
|
||||
if (!stages[i])
|
||||
continue;
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace love {
|
||||
if (vmaCreateImage(allocator, &imageInfo, &imageAllocationCreateInfo, &textureImage, &textureImageAllocation, nullptr) != VK_SUCCESS) {
|
||||
throw love::Exception("failed to create image");
|
||||
}
|
||||
// fixme: we should use VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL as the default image layout instead of VK_IMAGE_LAYOUT_GENERAL.
|
||||
transitionImageLayout(textureImage, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
|
||||
|
||||
if (data) {
|
||||
@@ -253,22 +254,25 @@ namespace love {
|
||||
static_cast<uint32_t>(r.h), 1
|
||||
};
|
||||
|
||||
// fixme: use VK_IMAGE_LAYOUT_DST_OPTIMAL
|
||||
Vulkan::cmdTransitionImageLayout(commandBuffer, image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
vkCmdCopyBufferToImage(
|
||||
commandBuffer,
|
||||
buffer,
|
||||
image,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1,
|
||||
®ion
|
||||
);
|
||||
|
||||
Vulkan::cmdTransitionImageLayout(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
|
||||
};
|
||||
|
||||
auto cleanUp = [allocator = allocator, stagingBuffer, vmaAllocation]() {
|
||||
vmaDestroyBuffer(allocator, stagingBuffer, vmaAllocation);
|
||||
};
|
||||
|
||||
vgfx->executeCommand(command, cleanUp);
|
||||
vgfx->queueDatatransfer(command, cleanUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,6 +491,13 @@ namespace love {
|
||||
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
}
|
||||
else if (oldLayout == VK_IMAGE_LAYOUT_GENERAL && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
|
||||
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
sourceStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
}
|
||||
else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_GENERAL) {
|
||||
barrier.srcAccessMask = 0;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
Reference in New Issue
Block a user