mirror of
https://github.com/love2d/love.git
synced 2026-08-19 20:19:42 +02:00
implement basic per frame uniform variables
This commit is contained in:
@@ -439,13 +439,15 @@ layout(location = 0) in vec2 inPosition;
|
|||||||
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
float windowWidth = 800;
|
layout(binding = 0) uniform LoveUniforms {
|
||||||
float windowHeight = 600;
|
float windowWidth;
|
||||||
|
float windowHeight;
|
||||||
|
} loveUniforms;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(
|
gl_Position = vec4(
|
||||||
2 * inPosition.x / windowWidth - 1,
|
2 * inPosition.x / loveUniforms.windowWidth - 1,
|
||||||
2 * inPosition.y / windowHeight - 1,
|
2 * inPosition.y / loveUniforms.windowHeight - 1,
|
||||||
0.0, 1.0);
|
0.0, 1.0);
|
||||||
fragColor = vec4(1, 1, 1, 1);
|
fragColor = vec4(1, 1, 1, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ enum BufferUsage
|
|||||||
BUFFERUSAGE_VERTEX = 0,
|
BUFFERUSAGE_VERTEX = 0,
|
||||||
BUFFERUSAGE_INDEX,
|
BUFFERUSAGE_INDEX,
|
||||||
BUFFERUSAGE_TEXEL,
|
BUFFERUSAGE_TEXEL,
|
||||||
|
BUFFERUSAGE_UNIFORM,
|
||||||
BUFFERUSAGE_SHADER_STORAGE,
|
BUFFERUSAGE_SHADER_STORAGE,
|
||||||
BUFFERUSAGE_MAX_ENUM
|
BUFFERUSAGE_MAX_ENUM
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -67,10 +67,14 @@ namespace love {
|
|||||||
createImageViews();
|
createImageViews();
|
||||||
createRenderPass();
|
createRenderPass();
|
||||||
createDefaultShaders();
|
createDefaultShaders();
|
||||||
|
createDescriptorSetLayout();
|
||||||
createGraphicsPipeline();
|
createGraphicsPipeline();
|
||||||
createFramebuffers();
|
createFramebuffers();
|
||||||
createCommandPool();
|
createCommandPool();
|
||||||
createCommandBuffers();
|
createCommandBuffers();
|
||||||
|
createUniformBuffers();
|
||||||
|
createDescriptorPool();
|
||||||
|
createDescriptorSets();
|
||||||
createSyncObjects();
|
createSyncObjects();
|
||||||
startRecordingGraphicsCommands();
|
startRecordingGraphicsCommands();
|
||||||
}
|
}
|
||||||
@@ -227,6 +231,9 @@ namespace love {
|
|||||||
buffers.push_back((VkBuffer)cmd.buffers->info[0].buffer->getHandle());
|
buffers.push_back((VkBuffer)cmd.buffers->info[0].buffer->getHandle());
|
||||||
offsets.push_back((VkDeviceSize) 0);
|
offsets.push_back((VkDeviceSize) 0);
|
||||||
|
|
||||||
|
prepareDraw(currentFrame);
|
||||||
|
|
||||||
|
vkCmdBindDescriptorSets(commandBuffers.at(imageIndex), VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets.at(currentFrame), 0, nullptr);
|
||||||
vkCmdBindVertexBuffers(commandBuffers.at(imageIndex), 0, 1, buffers.data(), offsets.data());
|
vkCmdBindVertexBuffers(commandBuffers.at(imageIndex), 0, 1, buffers.data(), offsets.data());
|
||||||
vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer) cmd.indexBuffer->getHandle(), 0, VK_INDEX_TYPE_UINT16);
|
vkCmdBindIndexBuffer(commandBuffers.at(imageIndex), (VkBuffer) cmd.indexBuffer->getHandle(), 0, VK_INDEX_TYPE_UINT16);
|
||||||
vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.indexCount), 1, 0, 0, 0);
|
vkCmdDrawIndexed(commandBuffers.at(imageIndex), static_cast<uint32_t>(cmd.indexCount), 1, 0, 0, 0);
|
||||||
@@ -239,6 +246,18 @@ namespace love {
|
|||||||
|
|
||||||
// END IMPLEMENTATION OVERRIDDEN FUNCTIONS
|
// END IMPLEMENTATION OVERRIDDEN FUNCTIONS
|
||||||
|
|
||||||
|
void Graphics::prepareDraw(uint32_t currentImage) {
|
||||||
|
auto& buffer = uniformBuffers.at(currentImage);
|
||||||
|
|
||||||
|
Shader::UniformBufferObject ubo{};
|
||||||
|
ubo.windowWidth = static_cast<float>(swapChainExtent.width);
|
||||||
|
ubo.windowHeight = static_cast<float>(swapChainExtent.height);
|
||||||
|
|
||||||
|
auto mappedInfo = buffer->map(0);
|
||||||
|
memcpy(mappedInfo.data, &ubo, sizeof(ubo));
|
||||||
|
buffer->unmap(0);
|
||||||
|
}
|
||||||
|
|
||||||
void Graphics::createVulkanInstance() {
|
void Graphics::createVulkanInstance() {
|
||||||
if (enableValidationLayers && !checkValidationSupport()) {
|
if (enableValidationLayers && !checkValidationSupport()) {
|
||||||
throw love::Exception("validation layers requested, but not available");
|
throw love::Exception("validation layers requested, but not available");
|
||||||
@@ -699,6 +718,79 @@ namespace love {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Graphics::createDescriptorSetLayout() {
|
||||||
|
VkDescriptorSetLayoutBinding uboLayoutBinding{};
|
||||||
|
uboLayoutBinding.binding = 0;
|
||||||
|
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
uboLayoutBinding.descriptorCount = 1;
|
||||||
|
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutCreateInfo layoutInfo{};
|
||||||
|
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||||
|
layoutInfo.bindingCount = 1;
|
||||||
|
layoutInfo.pBindings = &uboLayoutBinding;
|
||||||
|
|
||||||
|
if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
|
||||||
|
throw love::Exception("failed to create descriptor set layout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::createUniformBuffers() {
|
||||||
|
VkDeviceSize bufferSize = sizeof(Shader::UniformBufferObject);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
|
uniformBuffers.push_back(std::make_unique<StreamBuffer>(device, physicalDevice, BUFFERUSAGE_UNIFORM, bufferSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::createDescriptorPool() {
|
||||||
|
VkDescriptorPoolSize poolSize{};
|
||||||
|
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
poolSize.descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
|
VkDescriptorPoolCreateInfo poolInfo{};
|
||||||
|
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||||
|
poolInfo.poolSizeCount = 1;
|
||||||
|
poolInfo.pPoolSizes = &poolSize;
|
||||||
|
poolInfo.maxSets = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
|
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
|
||||||
|
throw love::Exception("failed to create descriptor pool");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::createDescriptorSets() {
|
||||||
|
std::vector<VkDescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT, descriptorSetLayout);
|
||||||
|
VkDescriptorSetAllocateInfo allocInfo{};
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||||
|
allocInfo.descriptorPool = descriptorPool;
|
||||||
|
allocInfo.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
allocInfo.pSetLayouts = layouts.data();
|
||||||
|
|
||||||
|
descriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
|
||||||
|
throw love::Exception("failed to allocate descriptor sets");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
|
VkDescriptorBufferInfo bufferInfo{};
|
||||||
|
bufferInfo.buffer = (VkBuffer) uniformBuffers.at(i)->getHandle();
|
||||||
|
bufferInfo.offset = 0;
|
||||||
|
bufferInfo.range = sizeof(Shader::UniformBufferObject);
|
||||||
|
|
||||||
|
VkWriteDescriptorSet descriptorWrite{};
|
||||||
|
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
|
descriptorWrite.dstSet = descriptorSets[i];
|
||||||
|
descriptorWrite.dstBinding = 0;
|
||||||
|
descriptorWrite.dstArrayElement = 0;
|
||||||
|
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
descriptorWrite.descriptorCount = 1;
|
||||||
|
descriptorWrite.pBufferInfo = &bufferInfo;
|
||||||
|
|
||||||
|
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Graphics::createGraphicsPipeline() {
|
void Graphics::createGraphicsPipeline() {
|
||||||
auto shader = reinterpret_cast<love::graphics::vulkan::Shader*>(love::graphics::vulkan::Shader::standardShaders[Shader::STANDARD_DEFAULT]);
|
auto shader = reinterpret_cast<love::graphics::vulkan::Shader*>(love::graphics::vulkan::Shader::standardShaders[Shader::STANDARD_DEFAULT]);
|
||||||
auto shaderStages = shader->getShaderStages();
|
auto shaderStages = shader->getShaderStages();
|
||||||
@@ -786,7 +878,8 @@ namespace love {
|
|||||||
|
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
||||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
pipelineLayoutInfo.setLayoutCount = 0;
|
pipelineLayoutInfo.setLayoutCount = 1;
|
||||||
|
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
|
||||||
pipelineLayoutInfo.pushConstantRangeCount = 0;
|
pipelineLayoutInfo.pushConstantRangeCount = 0;
|
||||||
|
|
||||||
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
|
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
|
||||||
@@ -892,6 +985,9 @@ namespace love {
|
|||||||
|
|
||||||
cleanupSwapChain();
|
cleanupSwapChain();
|
||||||
|
|
||||||
|
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
|
||||||
|
|
||||||
|
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
|
||||||
vkDestroyCommandPool(device, commandPool, nullptr);
|
vkDestroyCommandPool(device, commandPool, nullptr);
|
||||||
vkDestroyDevice(device, nullptr);
|
vkDestroyDevice(device, nullptr);
|
||||||
vkDestroySurfaceKHR(instance, surface, nullptr);
|
vkDestroySurfaceKHR(instance, surface, nullptr);
|
||||||
@@ -915,6 +1011,7 @@ namespace love {
|
|||||||
vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
|
vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
|
||||||
vkDestroyFence(device, inFlightFences[i], nullptr);
|
vkDestroyFence(device, inFlightFences[i], nullptr);
|
||||||
}
|
}
|
||||||
|
uniformBuffers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::recreateSwapChain() {
|
void Graphics::recreateSwapChain() {
|
||||||
@@ -927,6 +1024,9 @@ namespace love {
|
|||||||
createRenderPass();
|
createRenderPass();
|
||||||
createGraphicsPipeline();
|
createGraphicsPipeline();
|
||||||
createFramebuffers();
|
createFramebuffers();
|
||||||
|
createUniformBuffers();
|
||||||
|
createDescriptorPool();
|
||||||
|
createDescriptorSets();
|
||||||
createCommandBuffers();
|
createCommandBuffers();
|
||||||
createSyncObjects();
|
createSyncObjects();
|
||||||
startRecordingGraphicsCommands();
|
startRecordingGraphicsCommands();
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
namespace love {
|
namespace love {
|
||||||
@@ -117,6 +118,10 @@ namespace love {
|
|||||||
void createImageViews();
|
void createImageViews();
|
||||||
void createRenderPass();
|
void createRenderPass();
|
||||||
void createDefaultShaders();
|
void createDefaultShaders();
|
||||||
|
void createDescriptorSetLayout();
|
||||||
|
void createUniformBuffers();
|
||||||
|
void createDescriptorPool();
|
||||||
|
void createDescriptorSets();
|
||||||
void createGraphicsPipeline();
|
void createGraphicsPipeline();
|
||||||
void createFramebuffers();
|
void createFramebuffers();
|
||||||
void createCommandPool();
|
void createCommandPool();
|
||||||
@@ -128,6 +133,8 @@ namespace love {
|
|||||||
|
|
||||||
void startRecordingGraphicsCommands();
|
void startRecordingGraphicsCommands();
|
||||||
void endRecordingGraphicsCommands();
|
void endRecordingGraphicsCommands();
|
||||||
|
|
||||||
|
void prepareDraw(uint32_t currentImage);
|
||||||
|
|
||||||
VkInstance instance;
|
VkInstance instance;
|
||||||
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
||||||
@@ -140,6 +147,7 @@ namespace love {
|
|||||||
VkFormat swapChainImageFormat;
|
VkFormat swapChainImageFormat;
|
||||||
VkExtent2D swapChainExtent;
|
VkExtent2D swapChainExtent;
|
||||||
std::vector<VkImageView> swapChainImageViews;
|
std::vector<VkImageView> swapChainImageViews;
|
||||||
|
VkDescriptorSetLayout descriptorSetLayout;
|
||||||
VkPipelineLayout pipelineLayout;
|
VkPipelineLayout pipelineLayout;
|
||||||
VkRenderPass renderPass;
|
VkRenderPass renderPass;
|
||||||
VkPipeline graphicsPipeline;
|
VkPipeline graphicsPipeline;
|
||||||
@@ -147,7 +155,9 @@ namespace love {
|
|||||||
VkCommandPool commandPool;
|
VkCommandPool commandPool;
|
||||||
std::vector<VkCommandBuffer> commandBuffers;
|
std::vector<VkCommandBuffer> commandBuffers;
|
||||||
VkClearValue clearColor = { {{0.0f, 0.0f, 0.0f, 1.0f}} };
|
VkClearValue clearColor = { {{0.0f, 0.0f, 0.0f, 1.0f}} };
|
||||||
|
std::vector<std::unique_ptr<StreamBuffer>> uniformBuffers;
|
||||||
|
VkDescriptorPool descriptorPool;
|
||||||
|
std::vector<VkDescriptorSet> descriptorSets;
|
||||||
std::vector<VkSemaphore> imageAvailableSemaphores;
|
std::vector<VkSemaphore> imageAvailableSemaphores;
|
||||||
std::vector<VkSemaphore> renderFinishedSemaphores;
|
std::vector<VkSemaphore> renderFinishedSemaphores;
|
||||||
std::vector<VkFence> inFlightFences;
|
std::vector<VkFence> inFlightFences;
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ namespace love {
|
|||||||
|
|
||||||
void setVideoTextures(Texture* ytexture, Texture* cbtexture, Texture* crtexture) override {}
|
void setVideoTextures(Texture* ytexture, Texture* cbtexture, Texture* crtexture) override {}
|
||||||
|
|
||||||
|
struct UniformBufferObject {
|
||||||
|
float windowWidth;
|
||||||
|
float windowHeight;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Vec4 {
|
struct Vec4 {
|
||||||
float x, y, z, w;
|
float x, y, z, w;
|
||||||
@@ -64,6 +69,8 @@ namespace love {
|
|||||||
{ "love_VideoCrChannel", 3 },
|
{ "love_VideoCrChannel", 3 },
|
||||||
{ "MainTex", 4 }
|
{ "MainTex", 4 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace love {
|
|||||||
switch (mode) {
|
switch (mode) {
|
||||||
case BUFFERUSAGE_VERTEX: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
case BUFFERUSAGE_VERTEX: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||||
case BUFFERUSAGE_INDEX: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
case BUFFERUSAGE_INDEX: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||||
|
case BUFFERUSAGE_UNIFORM: return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||||
default:
|
default:
|
||||||
throw love::Exception("unsupported BufferUsage mode");
|
throw love::Exception("unsupported BufferUsage mode");
|
||||||
}
|
}
|
||||||
@@ -55,6 +56,11 @@ namespace love {
|
|||||||
vkBindBufferMemory(device, buffer, bufferMemory, 0);
|
vkBindBufferMemory(device, buffer, bufferMemory, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StreamBuffer::~StreamBuffer() {
|
||||||
|
//vkDestroyBuffer(device, buffer, nullptr);
|
||||||
|
//vkFreeMemory(device, bufferMemory, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
love::graphics::StreamBuffer::MapInfo StreamBuffer::map(size_t minsize) {
|
love::graphics::StreamBuffer::MapInfo StreamBuffer::map(size_t minsize) {
|
||||||
vkMapMemory(device, bufferMemory, 0, getSize(), 0, &mappedMemory);
|
vkMapMemory(device, bufferMemory, 0, getSize(), 0, &mappedMemory);
|
||||||
return love::graphics::StreamBuffer::MapInfo((uint8*) mappedMemory, getSize());
|
return love::graphics::StreamBuffer::MapInfo((uint8*) mappedMemory, getSize());
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace love {
|
|||||||
class StreamBuffer : public love::graphics::StreamBuffer {
|
class StreamBuffer : public love::graphics::StreamBuffer {
|
||||||
public:
|
public:
|
||||||
StreamBuffer(VkDevice device, VkPhysicalDevice physicalDevice, BufferUsage mode, size_t size);
|
StreamBuffer(VkDevice device, VkPhysicalDevice physicalDevice, BufferUsage mode, size_t size);
|
||||||
|
virtual ~StreamBuffer();
|
||||||
|
|
||||||
MapInfo map(size_t minsize) override;
|
MapInfo map(size_t minsize) override;
|
||||||
size_t unmap(size_t usedSize) override;
|
size_t unmap(size_t usedSize) override;
|
||||||
|
|||||||
Reference in New Issue
Block a user