mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
@@ -42,7 +42,7 @@ class Buffer final
|
||||
, public Volatile
|
||||
{
|
||||
public:
|
||||
Buffer(love::graphics::Graphics *gfx, const Settings& settings, const std::vector<DataDeclaration> &format, const void *data, size_t size, size_t arraylength);
|
||||
Buffer(love::graphics::Graphics *gfx, const Settings &settings, const std::vector<DataDeclaration> &format, const void *data, size_t size, size_t arraylength);
|
||||
virtual ~Buffer();
|
||||
|
||||
virtual bool loadVolatile() override;
|
||||
|
||||
@@ -81,8 +81,6 @@ Graphics::Graphics()
|
||||
throw love::Exception("could not find vulkan");
|
||||
|
||||
volkInitializeCustom((PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr());
|
||||
|
||||
instanceVersion = volkGetInstanceVersion();
|
||||
}
|
||||
|
||||
Graphics::~Graphics()
|
||||
@@ -360,7 +358,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
|
||||
}
|
||||
}
|
||||
|
||||
endRecordingGraphicsCommands(present);
|
||||
endRecordingGraphicsCommands();
|
||||
|
||||
if (imagesInFlight[imageIndex] != VK_NULL_HANDLE)
|
||||
vkWaitForFences(device, 1, &imagesInFlight.at(imageIndex), VK_TRUE, UINT64_MAX);
|
||||
@@ -412,7 +410,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
|
||||
callbacks.clear();
|
||||
}
|
||||
|
||||
startRecordingGraphicsCommands(false);
|
||||
startRecordingGraphicsCommands();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,9 +436,9 @@ void Graphics::present(void *screenshotCallbackdata)
|
||||
|
||||
VkResult result = vkQueuePresentKHR(presentQueue, &presentInfo);
|
||||
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized)
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || swapChainRecreationRequested)
|
||||
{
|
||||
framebufferResized = false;
|
||||
swapChainRecreationRequested = false;
|
||||
recreateSwapChain();
|
||||
}
|
||||
else if (result != VK_SUCCESS)
|
||||
@@ -465,6 +463,9 @@ void Graphics::present(void *screenshotCallbackdata)
|
||||
|
||||
void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight)
|
||||
{
|
||||
if (swapChain != VK_NULL_HANDLE && (pixelWidth != this->pixelWidth || pixelHeight != this->pixelHeight || width != this->width || height != this->height))
|
||||
requestSwapchainRecreation();
|
||||
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->pixelWidth = pixelwidth;
|
||||
@@ -601,7 +602,7 @@ void Graphics::unSetMode()
|
||||
renderPassUsages.clear();
|
||||
framebufferUsages.clear();
|
||||
pipelineUsages.clear();
|
||||
|
||||
|
||||
created = false;
|
||||
vkDeviceWaitIdle(device);
|
||||
Volatile::unloadAll();
|
||||
@@ -675,34 +676,7 @@ Graphics::RendererInfo Graphics::getRendererInfo() const
|
||||
|
||||
Graphics::RendererInfo info;
|
||||
|
||||
if (isDebugEnabled())
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Vulkan( ";
|
||||
ss << renderPasses.size() << " ";
|
||||
ss << framebuffers.size() << " ";
|
||||
ss << graphicsPipelines.size() << " ";
|
||||
if (optionalDeviceFeatures.extendedDynamicState)
|
||||
ss << "eds ";
|
||||
if (optionalDeviceFeatures.memoryRequirements2)
|
||||
ss << "mr2 ";
|
||||
if (optionalDeviceFeatures.dedicatedAllocation)
|
||||
ss << "da ";
|
||||
if (optionalDeviceFeatures.bufferDeviceAddress)
|
||||
ss << "bda ";
|
||||
if (optionalDeviceFeatures.memoryBudget)
|
||||
ss << "mb ";
|
||||
if (optionalDeviceFeatures.shaderFloatControls)
|
||||
ss << "sfc ";
|
||||
if (optionalDeviceFeatures.spirv14)
|
||||
ss << "spv14 ";
|
||||
ss << ")";
|
||||
|
||||
info.name = ss.str();
|
||||
}
|
||||
else
|
||||
info.name = "Vulkan";
|
||||
|
||||
info.name = "Vulkan";
|
||||
info.device = deviceProperties.deviceName;
|
||||
info.vendor = Vulkan::getVendorName(deviceProperties.vendorID);
|
||||
info.version = Vulkan::getVulkanApiVersion(deviceProperties.apiVersion);
|
||||
@@ -832,11 +806,7 @@ void Graphics::setScissor(const Rect &rect)
|
||||
{
|
||||
flushBatchedDraws();
|
||||
|
||||
VkRect2D scissor = computeScissor(rect,
|
||||
static_cast<double>(swapChainExtent.width),
|
||||
static_cast<double>(swapChainExtent.height),
|
||||
getCurrentDPIScale(),
|
||||
preTransform);
|
||||
VkRect2D scissor = computeScissor(rect, static_cast<double>(swapChainExtent.width), static_cast<double>(swapChainExtent.height), getCurrentDPIScale(), preTransform);
|
||||
vkCmdSetScissor(commandBuffers.at(currentFrame), 0, 1, &scissor);
|
||||
|
||||
states.back().scissor = true;
|
||||
@@ -1133,7 +1103,7 @@ void Graphics::beginFrame()
|
||||
cleanUpFn();
|
||||
cleanUpFunctions.at(currentFrame).clear();
|
||||
|
||||
startRecordingGraphicsCommands(true);
|
||||
startRecordingGraphicsCommands();
|
||||
|
||||
Vulkan::cmdTransitionImageLayout(
|
||||
commandBuffers.at(currentFrame),
|
||||
@@ -1164,7 +1134,7 @@ void Graphics::beginFrame()
|
||||
usedShadersInFrame.clear();
|
||||
}
|
||||
|
||||
void Graphics::startRecordingGraphicsCommands(bool newFrame)
|
||||
void Graphics::startRecordingGraphicsCommands()
|
||||
{
|
||||
VkCommandBufferBeginInfo beginInfo{};
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
@@ -1179,7 +1149,7 @@ void Graphics::startRecordingGraphicsCommands(bool newFrame)
|
||||
setDefaultRenderPass();
|
||||
}
|
||||
|
||||
void Graphics::endRecordingGraphicsCommands(bool present) {
|
||||
void Graphics::endRecordingGraphicsCommands() {
|
||||
if (renderPassState.active)
|
||||
endRenderPass();
|
||||
|
||||
@@ -1187,16 +1157,6 @@ void Graphics::endRecordingGraphicsCommands(bool present) {
|
||||
throw love::Exception("failed to record command buffer");
|
||||
}
|
||||
|
||||
uint32_t Graphics::getNumImagesInFlight() const
|
||||
{
|
||||
return MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
uint32_t Graphics::getFrameIndex() const
|
||||
{
|
||||
return static_cast<uint32_t>(currentFrame);
|
||||
}
|
||||
|
||||
const VkDeviceSize Graphics::getMinUniformBufferOffsetAlignment() const
|
||||
{
|
||||
return minUniformBufferOffsetAlignment;
|
||||
@@ -1297,7 +1257,7 @@ void Graphics::createVulkanInstance()
|
||||
appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0); // get this version from somewhere else?
|
||||
appInfo.pEngineName = "LOVE Game Framework";
|
||||
appInfo.engineVersion = VK_MAKE_API_VERSION(0, VERSION_MAJOR, VERSION_MINOR, VERSION_REV);
|
||||
appInfo.apiVersion = instanceVersion;
|
||||
appInfo.apiVersion = VK_API_VERSION_1_3;
|
||||
|
||||
VkInstanceCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
@@ -1351,7 +1311,7 @@ bool Graphics::checkValidationSupport()
|
||||
{
|
||||
bool layerFound = false;
|
||||
|
||||
for (const auto& layerProperties : availableLayers)
|
||||
for (const auto &layerProperties : availableLayers)
|
||||
{
|
||||
if (strcmp(layerName, layerProperties.layerName) == 0)
|
||||
{
|
||||
@@ -1546,8 +1506,8 @@ void Graphics::createLogicalDevice()
|
||||
|
||||
// sanity check for dependencies.
|
||||
|
||||
if (optionalDeviceFeatures.extendedDynamicState && !optionalInstanceExtensions.physicalDeviceProperties2)
|
||||
optionalDeviceFeatures.extendedDynamicState = false;
|
||||
if (optionalDeviceFeatures.extendedDynamicState && !optionalInstanceExtensions.physicalDeviceProperties2)
|
||||
optionalDeviceFeatures.extendedDynamicState = false;
|
||||
if (optionalDeviceFeatures.dedicatedAllocation && !optionalDeviceFeatures.memoryRequirements2)
|
||||
optionalDeviceFeatures.dedicatedAllocation = false;
|
||||
if (optionalDeviceFeatures.bufferDeviceAddress && !optionalInstanceExtensions.physicalDeviceProperties2)
|
||||
@@ -1606,7 +1566,7 @@ void Graphics::createLogicalDevice()
|
||||
if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS)
|
||||
throw love::Exception("failed to create logical device");
|
||||
|
||||
volkLoadDevice(device);
|
||||
volkLoadDevice(device);
|
||||
|
||||
vkGetDeviceQueue(device, indices.graphicsFamily.value, 0, &graphicsQueue);
|
||||
vkGetDeviceQueue(device, indices.presentFamily.value, 0, &presentQueue);
|
||||
@@ -1705,15 +1665,15 @@ void Graphics::createSwapChain()
|
||||
VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
|
||||
VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);
|
||||
|
||||
if ((swapChainSupport.capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) ||
|
||||
(swapChainSupport.capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR))
|
||||
if ((swapChainSupport.capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) ||
|
||||
(swapChainSupport.capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR))
|
||||
{
|
||||
uint32_t width, height;
|
||||
width = extent.width;
|
||||
height = extent.height;
|
||||
extent.width = height;
|
||||
extent.height = width;
|
||||
}
|
||||
uint32_t width, height;
|
||||
width = extent.width;
|
||||
height = extent.height;
|
||||
extent.width = height;
|
||||
extent.height = width;
|
||||
}
|
||||
|
||||
auto currentTransform = swapChainSupport.capabilities.currentTransform;
|
||||
constexpr float PI = 3.14159265358979323846f;
|
||||
@@ -1789,7 +1749,7 @@ VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurface
|
||||
// TODO: turn off GammaCorrect if a sRGB format can't be found?
|
||||
if (isGammaCorrect())
|
||||
{
|
||||
for (const auto& availableFormat : availableFormats)
|
||||
for (const auto &availableFormat : availableFormats)
|
||||
// fixme: what if this format and colorspace is not available?
|
||||
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||
return availableFormat;
|
||||
@@ -1805,8 +1765,6 @@ VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurface
|
||||
|
||||
VkPresentModeKHR Graphics::chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes)
|
||||
{
|
||||
int vsync = Vulkan::getVsync();
|
||||
|
||||
const auto begin = availablePresentModes.begin();
|
||||
const auto end = availablePresentModes.end();
|
||||
|
||||
@@ -1871,12 +1829,12 @@ VkCompositeAlphaFlagBitsKHR Graphics::chooseCompositeAlpha(const VkSurfaceCapabi
|
||||
return VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
|
||||
return VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
|
||||
else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
|
||||
return VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
|
||||
else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
|
||||
return VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
|
||||
else
|
||||
throw love::Exception("failed to find composite alpha");
|
||||
else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
|
||||
return VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
|
||||
else if (capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
|
||||
return VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
|
||||
else
|
||||
throw love::Exception("failed to find composite alpha");
|
||||
}
|
||||
|
||||
void Graphics::createImageViews()
|
||||
@@ -2002,7 +1960,7 @@ VkFramebuffer Graphics::createFramebuffer(FramebufferConfiguration &configuratio
|
||||
{
|
||||
std::vector<VkImageView> attachments;
|
||||
|
||||
for (const auto& colorView : configuration.colorViews)
|
||||
for (const auto &colorView : configuration.colorViews)
|
||||
attachments.push_back(colorView);
|
||||
|
||||
if (configuration.staticData.depthView)
|
||||
@@ -2062,8 +2020,8 @@ void Graphics::createDefaultShaders()
|
||||
|
||||
VkRenderPass Graphics::createRenderPass(RenderPassConfiguration &configuration)
|
||||
{
|
||||
VkSubpassDescription subPass{};
|
||||
subPass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
VkSubpassDescription subPass{};
|
||||
subPass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
|
||||
std::vector<VkAttachmentDescription> attachments;
|
||||
std::vector<VkAttachmentReference> colorAttachmentRefs;
|
||||
@@ -2091,8 +2049,8 @@ VkRenderPass Graphics::createRenderPass(RenderPassConfiguration &configuration)
|
||||
attachments.push_back(colorDescription);
|
||||
}
|
||||
|
||||
subPass.colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
|
||||
subPass.pColorAttachments = colorAttachmentRefs.data();
|
||||
subPass.colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
|
||||
subPass.pColorAttachments = colorAttachmentRefs.data();
|
||||
|
||||
VkAttachmentReference depthStencilAttachmentRef{};
|
||||
if (configuration.staticData.depthAttachment.format != VK_FORMAT_UNDEFINED)
|
||||
@@ -2156,20 +2114,20 @@ VkRenderPass Graphics::createRenderPass(RenderPassConfiguration &configuration)
|
||||
|
||||
std::array<VkSubpassDependency, 2> dependencies = { dependency, readbackDependency };
|
||||
|
||||
VkRenderPassCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
createInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
|
||||
createInfo.pAttachments = attachments.data();
|
||||
createInfo.subpassCount = 1;
|
||||
createInfo.pSubpasses = &subPass;
|
||||
VkRenderPassCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
createInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
|
||||
createInfo.pAttachments = attachments.data();
|
||||
createInfo.subpassCount = 1;
|
||||
createInfo.pSubpasses = &subPass;
|
||||
createInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
|
||||
createInfo.pDependencies = dependencies.data();
|
||||
|
||||
VkRenderPass renderPass;
|
||||
if (vkCreateRenderPass(device, &createInfo, nullptr, &renderPass) != VK_SUCCESS)
|
||||
throw love::Exception("failed to create render pass");
|
||||
VkRenderPass renderPass;
|
||||
if (vkCreateRenderPass(device, &createInfo, nullptr, &renderPass) != VK_SUCCESS)
|
||||
throw love::Exception("failed to create render pass");
|
||||
|
||||
return renderPass;
|
||||
return renderPass;
|
||||
}
|
||||
|
||||
bool Graphics::usesConstantVertexColor(const VertexAttributes &vertexAttributes)
|
||||
@@ -2261,7 +2219,7 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi
|
||||
|
||||
GraphicsPipelineConfiguration configuration{};
|
||||
|
||||
configuration.renderPass = renderPassState.beginInfo.renderPass;
|
||||
configuration.renderPass = renderPassState.beginInfo.renderPass;
|
||||
configuration.vertexAttributes = attributes;
|
||||
configuration.shader = (Shader*)Shader::current;
|
||||
configuration.wireFrame = states.back().wireframe;
|
||||
@@ -2295,7 +2253,7 @@ void Graphics::prepareDraw(const VertexAttributes &attributes, const BufferBindi
|
||||
}
|
||||
}
|
||||
|
||||
if (usesConstantVertexColor(attributes))
|
||||
if (!usesConstantVertexColor(attributes))
|
||||
{
|
||||
bufferVector.push_back((VkBuffer)defaultConstantColor->getHandle());
|
||||
offsets.push_back((VkDeviceSize)0);
|
||||
@@ -2328,35 +2286,15 @@ void Graphics::setDefaultRenderPass()
|
||||
renderPassState.msaa = msaaSamples;
|
||||
renderPassState.numColorAttachments = 1;
|
||||
renderPassState.transitionImages.clear();
|
||||
|
||||
VkViewport viewport{};
|
||||
viewport.x = 0.0f;
|
||||
viewport.y = 0.0f;
|
||||
viewport.width = renderPassState.width;
|
||||
viewport.height = renderPassState.height;
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
|
||||
vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
|
||||
}
|
||||
|
||||
void Graphics::setRenderPass(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture)
|
||||
{
|
||||
VkViewport viewport{};
|
||||
viewport.x = 0.0f;
|
||||
viewport.y = 0.0f;
|
||||
viewport.width = static_cast<float>(pixelw);
|
||||
viewport.height = static_cast<float>(pixelh);
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
|
||||
vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
|
||||
|
||||
auto currentCommandBuffer = commandBuffers.at(currentFrame);
|
||||
|
||||
// fixme: hasSRGBtexture
|
||||
RenderPassConfiguration renderPassConfiguration{};
|
||||
for (const auto& color : rts.colors)
|
||||
for (const auto &color : rts.colors)
|
||||
renderPassConfiguration.colorAttachments.push_back({
|
||||
Vulkan::getTextureFormat(color.texture->getPixelFormat(), isPixelFormatSRGB(color.texture->getPixelFormat())).internalFormat,
|
||||
false,
|
||||
@@ -2406,6 +2344,16 @@ void Graphics::startRenderPass()
|
||||
{
|
||||
renderPassState.active = true;
|
||||
|
||||
VkViewport viewport{};
|
||||
viewport.x = 0.0f;
|
||||
viewport.y = 0.0f;
|
||||
viewport.width = renderPassState.width;
|
||||
viewport.height = renderPassState.height;
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
|
||||
vkCmdSetViewport(commandBuffers.at(currentFrame), 0, 1, &viewport);
|
||||
|
||||
if (renderPassState.useConfigurations)
|
||||
{
|
||||
auto &renderPassConfiguration = renderPassState.renderPassConfiguration;
|
||||
@@ -2518,6 +2466,14 @@ void Graphics::cleanupUnusedObjects()
|
||||
eraseUnusedObjects(graphicsPipelines, pipelineUsages, vkDestroyPipeline, device);
|
||||
}
|
||||
|
||||
void Graphics::requestSwapchainRecreation()
|
||||
{
|
||||
if (swapChain != VK_NULL_HANDLE)
|
||||
{
|
||||
swapChainRecreationRequested = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::setComputeShader(Shader *shader)
|
||||
{
|
||||
computeShader = shader;
|
||||
@@ -2688,7 +2644,7 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration &confi
|
||||
pipelineInfo.subpass = 0;
|
||||
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||
pipelineInfo.basePipelineIndex = -1;
|
||||
pipelineInfo.renderPass = configuration.renderPass;
|
||||
pipelineInfo.renderPass = configuration.renderPass;
|
||||
|
||||
VkPipeline graphicsPipeline;
|
||||
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS)
|
||||
@@ -2740,6 +2696,26 @@ VkSampleCountFlagBits Graphics::getMsaaCount(int requestedMsaa) const
|
||||
return VK_SAMPLE_COUNT_1_BIT;
|
||||
}
|
||||
|
||||
void Graphics::setVsync(int vsync)
|
||||
{
|
||||
if (vsync != this->vsync)
|
||||
{
|
||||
this->vsync = vsync;
|
||||
|
||||
// With the extension VK_EXT_swapchain_maintenance1 a swapchain recreation might not be needed
|
||||
// https://github.com/KhronosGroup/Vulkan-Docs/blob/main/proposals/VK_EXT_swapchain_maintenance1.adoc
|
||||
// However, there are not any drivers that support it, yet.
|
||||
// Reevaluate again in the future.
|
||||
|
||||
requestSwapchainRecreation();
|
||||
}
|
||||
}
|
||||
|
||||
int Graphics::getVsync() const
|
||||
{
|
||||
return vsync;
|
||||
}
|
||||
|
||||
void Graphics::createColorResources()
|
||||
{
|
||||
if (msaaSamples & VK_SAMPLE_COUNT_1_BIT)
|
||||
@@ -2770,7 +2746,8 @@ void Graphics::createColorResources()
|
||||
allocationInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
||||
allocationInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
|
||||
|
||||
vmaCreateImage(vmaAllocator, &imageInfo, &allocationInfo, &colorImage, &colorImageAllocation, nullptr);
|
||||
if (vmaCreateImage(vmaAllocator, &imageInfo, &allocationInfo, &colorImage, &colorImageAllocation, nullptr))
|
||||
throw love::Exception("failed to create color image");
|
||||
|
||||
VkImageViewCreateInfo imageViewInfo{};
|
||||
imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
@@ -2787,7 +2764,8 @@ void Graphics::createColorResources()
|
||||
imageViewInfo.subresourceRange.baseArrayLayer = 0;
|
||||
imageViewInfo.subresourceRange.layerCount = 1;
|
||||
|
||||
vkCreateImageView(device, &imageViewInfo, nullptr, &colorImageView);
|
||||
if (vkCreateImageView(device, &imageViewInfo, nullptr, &colorImageView) != VK_SUCCESS)
|
||||
throw love::Exception("failed to create color image view");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2838,7 +2816,8 @@ void Graphics::createDepthResources()
|
||||
allocationInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
||||
allocationInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
|
||||
|
||||
vmaCreateImage(vmaAllocator, &imageInfo, &allocationInfo, &depthImage, &depthImageAllocation, nullptr);
|
||||
if (vmaCreateImage(vmaAllocator, &imageInfo, &allocationInfo, &depthImage, &depthImageAllocation, nullptr) != VK_SUCCESS)
|
||||
throw love::Exception("failed to create depth image");
|
||||
|
||||
VkImageViewCreateInfo imageViewInfo{};
|
||||
imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
@@ -2857,7 +2836,8 @@ void Graphics::createDepthResources()
|
||||
imageViewInfo.subresourceRange.baseArrayLayer = 0;
|
||||
imageViewInfo.subresourceRange.layerCount = 1;
|
||||
|
||||
vkCreateImageView(device, &imageViewInfo, nullptr, &depthImageView);
|
||||
if (vkCreateImageView(device, &imageViewInfo, nullptr, &depthImageView) != VK_SUCCESS)
|
||||
throw love::Exception("failed to create depth image view");
|
||||
}
|
||||
|
||||
void Graphics::createCommandPool()
|
||||
@@ -2972,10 +2952,12 @@ void Graphics::cleanupSwapChain()
|
||||
vmaDestroyImage(vmaAllocator, colorImage, colorImageAllocation);
|
||||
vkDestroyImageView(device, depthImageView, nullptr);
|
||||
vmaDestroyImage(vmaAllocator, depthImage, depthImageAllocation);
|
||||
for (const auto &swapChainImageView : swapChainImageViews)
|
||||
vkDestroyImageView(device, swapChainImageView, nullptr);
|
||||
swapChainImageViews.clear();
|
||||
for (const auto &swapChainImageView : swapChainImageViews)
|
||||
vkDestroyImageView(device, swapChainImageView, nullptr);
|
||||
swapChainImageViews.clear();
|
||||
vkDestroySwapchainKHR(device, swapChain, nullptr);
|
||||
|
||||
swapChain = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void Graphics::recreateSwapChain()
|
||||
|
||||
@@ -70,23 +70,23 @@ struct RenderPassConfiguration
|
||||
bool resolve = false;
|
||||
} staticData;
|
||||
|
||||
bool operator==(const RenderPassConfiguration &conf) const
|
||||
bool operator==(const RenderPassConfiguration &conf) const
|
||||
{
|
||||
return colorAttachments == conf.colorAttachments &&
|
||||
(memcmp(&staticData, &conf.staticData, sizeof(StaticRenderPassConfiguration)) == 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct RenderPassConfigurationHasher
|
||||
{
|
||||
size_t operator()(const RenderPassConfiguration &configuration) const
|
||||
size_t operator()(const RenderPassConfiguration &configuration) const
|
||||
{
|
||||
size_t hashes[] = {
|
||||
XXH32(configuration.colorAttachments.data(), configuration.colorAttachments.size() * sizeof(VkFormat), 0),
|
||||
XXH32(&configuration.staticData, sizeof(configuration.staticData), 0),
|
||||
};
|
||||
return XXH32(hashes, sizeof(hashes), 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FramebufferConfiguration
|
||||
@@ -126,7 +126,8 @@ struct FramebufferConfigurationHasher
|
||||
|
||||
struct OptionalInstanceExtensions
|
||||
{
|
||||
bool physicalDeviceProperties2 = false;
|
||||
// VK_KHR_get_physical_device_properties2
|
||||
bool physicalDeviceProperties2 = false;
|
||||
};
|
||||
|
||||
struct OptionalDeviceFeatures
|
||||
@@ -155,7 +156,7 @@ struct OptionalDeviceFeatures
|
||||
|
||||
struct GraphicsPipelineConfiguration
|
||||
{
|
||||
VkRenderPass renderPass;
|
||||
VkRenderPass renderPass;
|
||||
VertexAttributes vertexAttributes;
|
||||
Shader *shader = nullptr;
|
||||
bool wireFrame;
|
||||
@@ -288,8 +289,6 @@ public:
|
||||
void queueCleanUp(std::function<void()> cleanUp);
|
||||
void addReadbackCallback(std::function<void()> callback);
|
||||
void submitGpuCommands(bool present, void *screenshotCallbackData = nullptr);
|
||||
uint32_t getNumImagesInFlight() const;
|
||||
uint32_t getFrameIndex() const;
|
||||
const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
|
||||
graphics::Texture *getDefaultTexture() const;
|
||||
VkSampler getCachedSampler(const SamplerState &sampler);
|
||||
@@ -298,6 +297,8 @@ public:
|
||||
graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData();
|
||||
const OptionalDeviceFeatures &getEnabledOptionalDeviceExtensions() const;
|
||||
VkSampleCountFlagBits getMsaaCount(int requestedMsaa) const;
|
||||
void setVsync(int vsync);
|
||||
int getVsync() const;
|
||||
|
||||
protected:
|
||||
graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
|
||||
@@ -328,10 +329,10 @@ private:
|
||||
void createScreenshotCallbackBuffers();
|
||||
void createDefaultRenderPass();
|
||||
void createDefaultFramebuffers();
|
||||
VkFramebuffer createFramebuffer(FramebufferConfiguration &configuration);
|
||||
VkFramebuffer getFramebuffer(FramebufferConfiguration &configuration);
|
||||
VkFramebuffer createFramebuffer(FramebufferConfiguration &configuration);
|
||||
VkFramebuffer getFramebuffer(FramebufferConfiguration &configuration);
|
||||
void createDefaultShaders();
|
||||
VkRenderPass createRenderPass(RenderPassConfiguration &configuration);
|
||||
VkRenderPass createRenderPass(RenderPassConfiguration &configuration);
|
||||
VkPipeline createGraphicsPipeline(GraphicsPipelineConfiguration &configuration);
|
||||
void createColorResources();
|
||||
VkFormat findSupportedFormat(const std::vector<VkFormat> &candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
|
||||
@@ -346,8 +347,8 @@ private:
|
||||
void recreateSwapChain();
|
||||
void initDynamicState();
|
||||
void beginFrame();
|
||||
void startRecordingGraphicsCommands(bool newFrame);
|
||||
void endRecordingGraphicsCommands(bool present);
|
||||
void startRecordingGraphicsCommands();
|
||||
void endRecordingGraphicsCommands();
|
||||
void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration &configuration);
|
||||
bool usesConstantVertexColor(const VertexAttributes &attribs);
|
||||
void createVulkanVertexFormat(
|
||||
@@ -364,8 +365,8 @@ private:
|
||||
void endRenderPass();
|
||||
VkSampler createSampler(const SamplerState &sampler);
|
||||
void cleanupUnusedObjects();
|
||||
void requestSwapchainRecreation();
|
||||
|
||||
uint32_t instanceVersion = VK_API_VERSION_1_0;
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
||||
uint32_t deviceApiVersion = VK_API_VERSION_1_0;
|
||||
@@ -377,7 +378,7 @@ private:
|
||||
VkQueue graphicsQueue = VK_NULL_HANDLE;
|
||||
VkQueue presentQueue = VK_NULL_HANDLE;
|
||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
|
||||
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
|
||||
VkSurfaceTransformFlagBitsKHR preTransform = {};
|
||||
Matrix4 displayRotation;
|
||||
std::vector<VkImage> swapChainImages;
|
||||
@@ -393,7 +394,7 @@ private:
|
||||
VmaAllocation depthImageAllocation = VK_NULL_HANDLE;
|
||||
VkRenderPass defaultRenderPass = VK_NULL_HANDLE;
|
||||
std::vector<VkFramebuffer> defaultFramebuffers;
|
||||
std::unordered_map<RenderPassConfiguration, VkRenderPass, RenderPassConfigurationHasher> renderPasses;
|
||||
std::unordered_map<RenderPassConfiguration, VkRenderPass, RenderPassConfigurationHasher> renderPasses;
|
||||
std::unordered_map<FramebufferConfiguration, VkFramebuffer, FramebufferConfigurationHasher> framebuffers;
|
||||
std::unordered_map<GraphicsPipelineConfiguration, VkPipeline, GraphicsPipelineConfigurationHasher> graphicsPipelines;
|
||||
std::unordered_map<VkRenderPass, bool> renderPassUsages;
|
||||
@@ -402,17 +403,18 @@ private:
|
||||
std::unordered_map<uint64, VkSampler> samplers;
|
||||
VkCommandPool commandPool = VK_NULL_HANDLE;
|
||||
std::vector<VkCommandBuffer> commandBuffers;
|
||||
Shader* computeShader = nullptr;
|
||||
Shader *computeShader = nullptr;
|
||||
std::vector<VkSemaphore> imageAvailableSemaphores;
|
||||
std::vector<VkSemaphore> renderFinishedSemaphores;
|
||||
std::vector<VkFence> inFlightFences;
|
||||
std::vector<VkFence> imagesInFlight;
|
||||
int vsync = 1;
|
||||
VkDeviceSize minUniformBufferOffsetAlignment = 0;
|
||||
bool imageRequested = false;
|
||||
uint32_t frameCounter = 0;
|
||||
size_t currentFrame = 0;
|
||||
uint32_t imageIndex = 0;
|
||||
bool framebufferResized = false;
|
||||
bool swapChainRecreationRequested = false;
|
||||
bool transitionColorDepthLayouts = false;
|
||||
VmaAllocator vmaAllocator = VK_NULL_HANDLE;
|
||||
StrongRef<love::graphics::Texture> defaultTexture;
|
||||
|
||||
@@ -196,7 +196,7 @@ bool Shader::loadVolatile()
|
||||
createPipelineLayout();
|
||||
createDescriptorPoolSizes();
|
||||
createStreamBuffers();
|
||||
descriptorSetsVector.resize(vgfx->getNumImagesInFlight());
|
||||
descriptorSetsVector.resize(MAX_FRAMES_IN_FLIGHT);
|
||||
currentFrame = 0;
|
||||
currentUsedUniformStreamBuffersCount = 0;
|
||||
currentUsedDescriptorSetsCount = 0;
|
||||
@@ -234,8 +234,7 @@ void Shader::unloadVolatile()
|
||||
}
|
||||
}
|
||||
|
||||
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
|
||||
gfx->queueCleanUp([shaderModules = std::move(shaderModules), device = device, descriptorSetLayout = descriptorSetLayout, pipelineLayout = pipelineLayout, descriptorPools = descriptorPools, computePipeline = computePipeline](){
|
||||
vgfx->queueCleanUp([shaderModules = std::move(shaderModules), device = device, descriptorSetLayout = descriptorSetLayout, pipelineLayout = pipelineLayout, descriptorPools = descriptorPools, computePipeline = computePipeline](){
|
||||
for (const auto pool : descriptorPools)
|
||||
vkDestroyDescriptorPool(device, pool, nullptr);
|
||||
for (const auto shaderModule : shaderModules)
|
||||
@@ -274,10 +273,11 @@ VkPipeline Shader::getComputePipeline() const
|
||||
return computePipeline;
|
||||
}
|
||||
|
||||
void Shader::newFrame(uint32_t frameIndex)
|
||||
void Shader::newFrame()
|
||||
{
|
||||
currentFrame = frameIndex;
|
||||
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
|
||||
updatedUniforms.clear();
|
||||
currentUsedUniformStreamBuffersCount = 0;
|
||||
currentUsedDescriptorSetsCount = 0;
|
||||
|
||||
@@ -295,12 +295,10 @@ void Shader::newFrame(uint32_t frameIndex)
|
||||
else
|
||||
streamBuffers.at(0)->nextFrame();
|
||||
|
||||
if (currentUsedDescriptorSetsCount >= static_cast<uint32_t>(descriptorSetsVector.at(currentFrame).size()))
|
||||
if (descriptorSetsVector.at(currentFrame).size() == 0)
|
||||
descriptorSetsVector.at(currentFrame).push_back(allocateDescriptorSet());
|
||||
|
||||
currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount);
|
||||
|
||||
initDescriptorSet();
|
||||
currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(0);
|
||||
}
|
||||
|
||||
void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint bindPoint)
|
||||
@@ -336,15 +334,17 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind
|
||||
VkWriteDescriptorSet uniformWrite{};
|
||||
uniformWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
uniformWrite.dstSet = currentDescriptorSet;
|
||||
uniformWrite.dstBinding = uniformLocation;
|
||||
uniformWrite.dstBinding = localUniformLocation;
|
||||
uniformWrite.dstArrayElement = 0;
|
||||
uniformWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
uniformWrite.descriptorCount = 1;
|
||||
uniformWrite.pBufferInfo = &bufferInfo;
|
||||
uniformWrite.pBufferInfo = &bufferInfo;
|
||||
|
||||
vkUpdateDescriptorSets(device, 1, &uniformWrite, 0, nullptr);
|
||||
|
||||
currentUsedUniformStreamBuffersCount++;
|
||||
|
||||
updatedUniforms.insert(localUniformLocation);
|
||||
}
|
||||
|
||||
static const std::vector<BuiltinUniform> builtinUniformTextures = {
|
||||
@@ -365,18 +365,28 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind
|
||||
imageInfo.imageView = (VkImageView)texture->getRenderTargetHandle();
|
||||
imageInfo.sampler = (VkSampler)texture->getSamplerHandle();
|
||||
|
||||
auto location = builtinUniformInfo[builtin]->location;
|
||||
|
||||
VkWriteDescriptorSet textureWrite{};
|
||||
textureWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
textureWrite.dstSet = currentDescriptorSet;
|
||||
textureWrite.dstBinding = builtinUniformInfo[builtin]->location;
|
||||
textureWrite.dstBinding = location;
|
||||
textureWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
textureWrite.descriptorCount = 1;
|
||||
textureWrite.pImageInfo = &imageInfo;
|
||||
|
||||
vkUpdateDescriptorSets(device, 1, &textureWrite, 0, nullptr);
|
||||
|
||||
updatedUniforms.insert(location);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &u : uniformInfos)
|
||||
{
|
||||
if (updatedUniforms.find(u.second.location) == updatedUniforms.end())
|
||||
updateUniform(&u.second, u.second.count);
|
||||
}
|
||||
|
||||
vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, ¤tDescriptorSet, 0, nullptr);
|
||||
|
||||
currentUsedDescriptorSetsCount++;
|
||||
@@ -386,7 +396,7 @@ void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBind
|
||||
|
||||
currentDescriptorSet = descriptorSetsVector.at(currentFrame).at(currentUsedDescriptorSetsCount);
|
||||
|
||||
initDescriptorSet();
|
||||
updatedUniforms.clear();
|
||||
}
|
||||
|
||||
Shader::~Shader()
|
||||
@@ -399,7 +409,7 @@ void Shader::attach()
|
||||
auto &usedShadersInFrame = vgfx->getUsedShadersInFrame();
|
||||
if (usedShadersInFrame.find(this) == usedShadersInFrame.end())
|
||||
{
|
||||
newFrame(vgfx->getFrameIndex());
|
||||
newFrame();
|
||||
usedShadersInFrame.insert(this);
|
||||
}
|
||||
|
||||
@@ -463,6 +473,9 @@ void Shader::updateUniform(const UniformInfo* info, int count, bool internal)
|
||||
{
|
||||
auto vkTexture = dynamic_cast<Texture*>(info->textures[i]);
|
||||
|
||||
if (vkTexture == nullptr)
|
||||
throw love::Exception("uniform variable %s is not set.", info->name.c_str());
|
||||
|
||||
VkDescriptorImageInfo imageInfo{};
|
||||
|
||||
imageInfo.imageLayout = vkTexture->getImageLayout();
|
||||
@@ -501,6 +514,9 @@ void Shader::updateUniform(const UniformInfo* info, int count, bool internal)
|
||||
|
||||
for (int i = 0; i < info->count; i++)
|
||||
{
|
||||
if (info->buffers[i] == nullptr)
|
||||
throw love::Exception("uniform variable %s is not set.", info->name.c_str());
|
||||
|
||||
VkDescriptorBufferInfo bufferInfo{};
|
||||
bufferInfo.buffer = (VkBuffer)info->buffers[i]->getHandle();;
|
||||
bufferInfo.offset = 0;
|
||||
@@ -526,12 +542,19 @@ void Shader::updateUniform(const UniformInfo* info, int count, bool internal)
|
||||
std::vector<VkBufferView> bufferViews;
|
||||
|
||||
for (int i = 0; i < info->count; i++)
|
||||
{
|
||||
if (info->buffers[i] == nullptr)
|
||||
throw love::Exception("uniform variable %s is not set.", info->name.c_str());
|
||||
|
||||
bufferViews.push_back((VkBufferView)info->buffers[i]->getTexelBufferHandle());
|
||||
}
|
||||
|
||||
write.pTexelBufferView = bufferViews.data();
|
||||
|
||||
vkUpdateDescriptorSets(device, 1, &write, 0, nullptr);
|
||||
}
|
||||
|
||||
updatedUniforms.insert(info->location);
|
||||
}
|
||||
|
||||
void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures, int count)
|
||||
@@ -544,6 +567,8 @@ void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures,
|
||||
if (oldTexture)
|
||||
oldTexture->release();
|
||||
}
|
||||
|
||||
updateUniform(info, count);
|
||||
}
|
||||
|
||||
void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count)
|
||||
@@ -556,6 +581,8 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe
|
||||
if (oldBuffer)
|
||||
oldBuffer->release();
|
||||
}
|
||||
|
||||
updateUniform(info, count);
|
||||
}
|
||||
|
||||
void Shader::calculateUniformBufferSizeAligned()
|
||||
@@ -568,13 +595,6 @@ void Shader::calculateUniformBufferSizeAligned()
|
||||
uniformBufferSizeAligned = factor * minAlignment;
|
||||
}
|
||||
|
||||
void Shader::initDescriptorSet()
|
||||
{
|
||||
for (const auto &entry : uniformInfos)
|
||||
if (Vulkan::getDescriptorType(entry.second.baseType) != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
|
||||
updateUniform(&entry.second, entry.second.count, true);
|
||||
}
|
||||
|
||||
void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::SPIRType &type, size_t baseoff, const std::string &basename)
|
||||
{
|
||||
using namespace spirv_cross;
|
||||
@@ -776,7 +796,7 @@ void Shader::compileShaders()
|
||||
auto defaultUniformBlockSize = comp.get_declared_struct_size(type);
|
||||
localUniformStagingData.resize(defaultUniformBlockSize);
|
||||
localUniformData.resize(defaultUniformBlockSize);
|
||||
uniformLocation = comp.get_decoration(resource.id, spv::DecorationBinding);
|
||||
localUniformLocation = comp.get_decoration(resource.id, spv::DecorationBinding);
|
||||
|
||||
memset(localUniformStagingData.data(), 0, defaultUniformBlockSize);
|
||||
memset(localUniformData.data(), 0, defaultUniformBlockSize);
|
||||
@@ -956,7 +976,7 @@ void Shader::createDescriptorSetLayout()
|
||||
if (!localUniformStagingData.empty())
|
||||
{
|
||||
VkDescriptorSetLayoutBinding uniformBinding{};
|
||||
uniformBinding.binding = uniformLocation;
|
||||
uniformBinding.binding = localUniformLocation;
|
||||
uniformBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
uniformBinding.descriptorCount = 1;
|
||||
uniformBinding.stageFlags = stageFlags;
|
||||
@@ -1023,7 +1043,9 @@ void Shader::createDescriptorPoolSizes()
|
||||
|
||||
void Shader::createStreamBuffers()
|
||||
{
|
||||
streamBuffers.push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned));
|
||||
size_t size = STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned;
|
||||
if (size > 0)
|
||||
streamBuffers.push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, size));
|
||||
}
|
||||
|
||||
void Shader::setVideoTextures(graphics::Texture *ytexture, graphics::Texture *cbtexture, graphics::Texture *crtexture)
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
|
||||
|
||||
namespace love
|
||||
@@ -63,7 +64,7 @@ public:
|
||||
|
||||
const VkPipelineLayout getGraphicsPipelineLayout() const;
|
||||
|
||||
void newFrame(uint32_t frameIndex);
|
||||
void newFrame();
|
||||
|
||||
void cmdPushDescriptorSets(VkCommandBuffer, VkPipelineBindPoint);
|
||||
|
||||
@@ -101,8 +102,7 @@ private:
|
||||
const spirv_cross::SPIRType &type,
|
||||
size_t baseoff,
|
||||
const std::string &basename);
|
||||
void initDescriptorSet();
|
||||
void updateUniform(const UniformInfo* info, int count, bool internal);
|
||||
void updateUniform(const UniformInfo *info, int count, bool internal);
|
||||
|
||||
VkDescriptorSet allocateDescriptorSet();
|
||||
|
||||
@@ -121,6 +121,8 @@ private:
|
||||
std::queue<VkDescriptorSet> freeDescriptorSets;
|
||||
std::vector<std::vector<VkDescriptorSet>> descriptorSetsVector;
|
||||
|
||||
std::set<uint32_t> updatedUniforms;
|
||||
|
||||
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
||||
std::vector<VkShaderModule> shaderModules;
|
||||
|
||||
@@ -135,7 +137,7 @@ private:
|
||||
std::unique_ptr<StreamBuffer> uniformBufferObjectBuffer;
|
||||
std::vector<uint8> localUniformData;
|
||||
std::vector<uint8> localUniformStagingData;
|
||||
uint32_t uniformLocation;
|
||||
uint32_t localUniformLocation;
|
||||
OptionalInt builtinUniformDataOffset;
|
||||
|
||||
std::unordered_map<std::string, int> attributes;
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace vulkan
|
||||
{
|
||||
|
||||
static uint32_t numShaderSwitches;
|
||||
static int vsync = 1;
|
||||
|
||||
void Vulkan::shaderSwitch()
|
||||
{
|
||||
@@ -48,16 +47,6 @@ void Vulkan::resetShaderSwitches()
|
||||
numShaderSwitches = 0;
|
||||
}
|
||||
|
||||
void Vulkan::setVsync(int value)
|
||||
{
|
||||
vsync = value;
|
||||
}
|
||||
|
||||
int Vulkan::getVsync()
|
||||
{
|
||||
return vsync;
|
||||
}
|
||||
|
||||
VkFormat Vulkan::getVulkanVertexFormat(DataFormat format)
|
||||
{
|
||||
switch (format)
|
||||
|
||||
@@ -58,9 +58,6 @@ public:
|
||||
static uint32_t getNumShaderSwitches();
|
||||
static void resetShaderSwitches();
|
||||
|
||||
static void setVsync(int vsync);
|
||||
static int getVsync();
|
||||
|
||||
static VkFormat getVulkanVertexFormat(DataFormat format);
|
||||
static TextureFormat getTextureFormat(PixelFormat, bool sRGB);
|
||||
static std::string getVendorName(uint32_t vendorId);
|
||||
|
||||
@@ -1100,8 +1100,11 @@ void Window::setVSync(int vsync)
|
||||
}
|
||||
|
||||
#ifdef LOVE_GRAPHICS_VULKAN
|
||||
// TODO: this doesn't update the swap-chain, but it should.
|
||||
love::graphics::vulkan::Vulkan::setVsync(vsync);
|
||||
if (windowRenderer == love::graphics::RENDERER_VULKAN)
|
||||
{
|
||||
auto vgfx = dynamic_cast<love::graphics::vulkan::Graphics*>(graphics.get());
|
||||
vgfx->setVsync(vsync);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LOVE_GRAPHICS_METAL) && defined(LOVE_MACOS)
|
||||
@@ -1132,7 +1135,10 @@ int Window::getVSync() const
|
||||
|
||||
#ifdef LOVE_GRAPHICS_VULKAN
|
||||
if (windowRenderer == love::graphics::RENDERER_VULKAN)
|
||||
return love::graphics::vulkan::Vulkan::getVsync();
|
||||
{
|
||||
auto vgfx = dynamic_cast<love::graphics::vulkan::Graphics*>(graphics.get());
|
||||
return vgfx->getVsync();
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user