Browse Source

vulkan: implement getRendererInfo

niki 3 years ago
parent
commit
ef08282f0d

+ 44 - 18
src/modules/graphics/vulkan/Graphics.cpp

@@ -48,7 +48,16 @@ namespace love {
 				return "love.graphics.vulkan";
 			}
 
-			Graphics::Graphics() {
+			const VkDevice Graphics::getDevice() const {
+				return device;
+			}
+
+			const VkPhysicalDevice Graphics::getPhysicalDevice() const {
+				return physicalDevice;
+			}
+
+			const VmaAllocator Graphics::getVmaAllocator() const {
+				return vmaAllocator;
 			}
 
 			Graphics::~Graphics() {
@@ -294,6 +303,19 @@ namespace love {
 				created = false;
 				cleanup();
 			}
+			
+			Graphics::RendererInfo Graphics::getRendererInfo() const {
+				VkPhysicalDeviceProperties deviceProperties;
+				vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
+
+				Graphics::RendererInfo info;
+				info.device = deviceProperties.deviceName;
+				info.vendor = Vulkan::getVendorName(deviceProperties.vendorID);
+				info.version = Vulkan::getVulkanApiVersion(deviceProperties.apiVersion);
+				info.name = "Vulkan";
+
+				return info;
+			}
 
 			void Graphics::draw(const DrawIndexedCommand& cmd) {
 				std::cout << "drawIndexed ";
@@ -356,12 +378,8 @@ namespace love {
 
 			bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) { 
 				std::cout << "isPixelFormatSupported ";
-				switch (format) {
-				case PIXELFORMAT_LA8_UNORM:
-					return false;
-				default:
-					return true;
-				}
+
+				return true;
 			}
 
 			void Graphics::drawQuads(int start, int count, const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture) {
@@ -431,6 +449,10 @@ namespace love {
 
 			// END IMPLEMENTATION OVERRIDDEN FUNCTIONS
 
+			void Graphics::setTexture(graphics::Texture* texture) {
+				currentTexture = texture;
+			}
+
 			void Graphics::updatedBatchedDrawBuffers() {
 				batchedDrawState.vb[0] = batchedDrawBuffers[currentFrame].vertexBuffer1;
 				batchedDrawState.vb[0]->nextFrame();
@@ -456,7 +478,7 @@ namespace love {
 
 			graphics::StreamBuffer* Graphics::getUniformBuffer() {
 				auto data = getCurrentBuiltinUniformData();
-				for (auto it : uniformBufferMap) {
+				for (auto &it : uniformBufferMap) {
 					if (it.first == data) {
 						return it.second;
 					}
@@ -556,7 +578,7 @@ namespace love {
 				appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);	//todo, get this version from somewhere else?
 				appInfo.pEngineName = "LOVE Engine";
 				appInfo.engineVersion = VK_MAKE_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_REV);
-				appInfo.apiVersion = VK_API_VERSION_1_0;
+				appInfo.apiVersion = VK_API_VERSION_1_3;
 
 				VkInstanceCreateInfo createInfo{};
 				createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
@@ -682,6 +704,12 @@ namespace love {
 				if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
 					score += 1000;
 				}
+				if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
+					score += 100;
+				}
+				if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
+					score += 10;
+				}
 
 				// definitely needed
 
@@ -710,7 +738,7 @@ namespace love {
 				return score;
 			}
 
-			Graphics::QueueFamilyIndices Graphics::findQueueFamilies(VkPhysicalDevice device) {
+			QueueFamilyIndices Graphics::findQueueFamilies(VkPhysicalDevice device) {
 				QueueFamilyIndices indices;
 
 				uint32_t queueFamilyCount = 0;
@@ -761,16 +789,12 @@ namespace love {
 				VkPhysicalDeviceFeatures deviceFeatures{};
 				deviceFeatures.samplerAnisotropy = VK_TRUE;
 
-				VkPhysicalDeviceFeatures2 deviceFeatures2{};
-				deviceFeatures2.features.robustBufferAccess = VK_TRUE;
-				deviceFeatures2.pNext = nullptr;
-
 				VkDeviceCreateInfo createInfo{};
 				createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
 				createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
 				createInfo.pQueueCreateInfos = queueCreateInfos.data();
 				createInfo.pEnabledFeatures = &deviceFeatures;
-				createInfo.pNext = &deviceFeatures2;
+				createInfo.pNext = nullptr;
 
 				createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
 				createInfo.ppEnabledExtensionNames = deviceExtensions.data();
@@ -804,7 +828,9 @@ namespace love {
 				allocatorCreateInfo.instance = instance;
 				allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions;
 
-				vmaCreateAllocator(&allocatorCreateInfo, &vmaAllocator);
+				if (vmaCreateAllocator(&allocatorCreateInfo, &vmaAllocator) != VK_SUCCESS) {
+					throw love::Exception("failed to create vma allocator");
+				}
 			}
 
 			void Graphics::createSurface() {
@@ -815,7 +841,7 @@ namespace love {
 				}
 			}
 
-			Graphics::SwapChainSupportDetails Graphics::querySwapChainSupport(VkPhysicalDevice device) {
+			SwapChainSupportDetails Graphics::querySwapChainSupport(VkPhysicalDevice device) {
 				SwapChainSupportDetails details;
 
 				vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
@@ -1416,7 +1442,7 @@ namespace love {
 				quadIndexBuffer->unmap(size);
 			}
 
-			bool operator==(const Graphics::GraphicsPipelineConfiguration& first, const Graphics::GraphicsPipelineConfiguration& other) {
+			bool operator==(const GraphicsPipelineConfiguration& first, const GraphicsPipelineConfiguration& other) {
 				if (first.vertexInputAttributeDescriptions.size() != other.vertexInputAttributeDescriptions.size()) {
 					return false;
 				}

+ 76 - 96
src/modules/graphics/vulkan/Graphics.h

@@ -19,25 +19,61 @@
 namespace love {
 	namespace graphics {
 		namespace vulkan {
-			class Graphics final : public love::graphics::Graphics {
-			public:
-				Graphics();
+			struct GraphicsPipelineConfiguration {
+				std::vector<VkVertexInputBindingDescription> vertexInputBindingDescriptions;
+				std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions;
 
-				virtual ~Graphics();
+				friend static bool operator==(const GraphicsPipelineConfiguration& first, const GraphicsPipelineConfiguration& other);
+			};
 
-				const char* getName() const override;
+			struct DecriptorSetConfiguration {
+				graphics::Texture* texture;
+				graphics::StreamBuffer* buffer;
 
-				const VkDevice getDevice() const {
-					return device;
+				bool operator==(const DecriptorSetConfiguration& conf2) {
+					return this->texture == conf2.texture && this->buffer == conf2.buffer;
 				}
+			};
 
-				const VkPhysicalDevice getPhysicalDevice() const {
-					return physicalDevice;
+			struct BatchedDrawBuffers {
+				StreamBuffer* vertexBuffer1;
+				StreamBuffer* vertexBuffer2;
+				StreamBuffer* indexBuffer;
+				StreamBuffer* constantColorBuffer;
+
+				~BatchedDrawBuffers() {
+					delete vertexBuffer1;
+					delete vertexBuffer2;
+					delete indexBuffer;
+					delete constantColorBuffer;
 				}
+			};
 
-				const VmaAllocator getVmaAllocator() const {
-					return vmaAllocator;
+			struct QueueFamilyIndices {
+				std::optional<uint32_t> graphicsFamily;
+				std::optional<uint32_t> presentFamily;
+
+				bool isComplete() {
+					return graphicsFamily.has_value() && presentFamily.has_value();
 				}
+			};
+
+			struct SwapChainSupportDetails {
+				VkSurfaceCapabilitiesKHR capabilities;
+				std::vector<VkSurfaceFormatKHR> formats;
+				std::vector<VkPresentModeKHR> presentModes;
+			};
+
+			class Graphics final : public love::graphics::Graphics {
+			public:
+				Graphics() = default;
+
+				virtual ~Graphics();
+
+				const char* getName() const override;
+				const VkDevice getDevice() const;
+				const VkPhysicalDevice getPhysicalDevice() const;
+				const VmaAllocator getVmaAllocator() const;
 
 				// implementation for virtual functions
 				love::graphics::Texture* newTexture(const love::graphics::Texture::Settings& settings, const love::graphics::Texture::Slices* data = nullptr) override { 
@@ -69,7 +105,7 @@ namespace love {
 				bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) override;
 				Renderer getRenderer() const override { std::cout << "getRenderer "; return RENDERER_VULKAN; }
 				bool usesGLSLES() const override { std::cout << "usesGLSES "; return false; }
-				RendererInfo getRendererInfo() const override { std::cout << "getRendererInfo "; return {}; }
+				RendererInfo getRendererInfo() const override;
 				void draw(const DrawCommand& cmd) override { std::cout << "draw "; }
 				void draw(const DrawIndexedCommand& cmd) override;
 				void drawQuads(int start, int count, const VertexAttributes& attributes, const BufferBindings& buffers, graphics::Texture* texture) override;
@@ -80,22 +116,6 @@ namespace love {
 				VkCommandBuffer beginSingleTimeCommands();
 				void endSingleTimeCommands(VkCommandBuffer);
 
-				struct GraphicsPipelineConfiguration {
-					std::vector<VkVertexInputBindingDescription> vertexInputBindingDescriptions;
-					std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions;
-
-					friend static bool operator==(const GraphicsPipelineConfiguration& first, const GraphicsPipelineConfiguration& other);
-				};
-
-				struct DecriptorSetConfiguration {
-					graphics::Texture* texture;
-					graphics::StreamBuffer* buffer;
-
-					bool operator==(const DecriptorSetConfiguration& conf2) {
-						return this->texture == conf2.texture && this->buffer == conf2.buffer;
-					}
-				};
-
 				void setShader(Shader*);
 
 			protected:
@@ -114,58 +134,6 @@ namespace love {
 				void setRenderTargetsInternal(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture) override { std::cout << "setRenderTargetsInternal "; }
 
 			private:
-				graphics::Texture* currentTexture;
-
-				void setTexture(graphics::Texture* texture) {
-					currentTexture = texture;
-				}
-
-				VkDescriptorSet* getDescriptorSet(int currentFrame);
-				graphics::StreamBuffer* getUniformBuffer();
-
-				std::vector<std::pair<graphics::Shader::BuiltinUniformData, graphics::StreamBuffer*>> uniformBufferMap;
-				std::vector<std::pair<DecriptorSetConfiguration, std::vector<VkDescriptorSet>>> descriptorSetsMap;
-
-				struct BatchedDrawBuffers {
-					StreamBuffer* vertexBuffer1;
-					StreamBuffer* vertexBuffer2;
-					StreamBuffer* indexBuffer;
-					StreamBuffer* constantColorBuffer;
-
-					~BatchedDrawBuffers() {
-						delete vertexBuffer1;
-						delete vertexBuffer2;
-						delete indexBuffer;
-						delete constantColorBuffer;
-					}
-				};
-
-				// we need an array of draw buffers, since the frames are being rendered asynchronously
-				// and we can't (or shouldn't) update the contents of the buffers while they're still in flight / being rendered.
-				std::vector<BatchedDrawBuffers> batchedDrawBuffers;
-				void updatedBatchedDrawBuffers();
-
-				void createVulkanVertexFormat(VertexAttributes vertexAttributes, bool& useConstantVertexColor, GraphicsPipelineConfiguration& configuration);
-
-				StreamBuffer* quadIndexBuffer = nullptr;
-
-				// vulkan specific member functions and variables
-
-				struct QueueFamilyIndices {
-					std::optional<uint32_t> graphicsFamily;
-					std::optional<uint32_t> presentFamily;
-
-					bool isComplete() {
-						return graphicsFamily.has_value() && presentFamily.has_value();
-					}
-				};
-
-				struct SwapChainSupportDetails {
-					VkSurfaceCapabilitiesKHR capabilities;
-					std::vector<VkSurfaceFormatKHR> formats;
-					std::vector<VkPresentModeKHR> presentModes;
-				};
-
 				void createVulkanInstance();
 				bool checkValidationSupport();
 				void pickPhysicalDevice();
@@ -201,37 +169,49 @@ namespace love {
 				void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration);
 				graphics::StreamBuffer* createUniformBufferFromData(graphics::Shader::BuiltinUniformData);
 				graphics::Shader::BuiltinUniformData getCurrentBuiltinUniformData();
+				void setTexture(graphics::Texture* texture);
+				void updatedBatchedDrawBuffers();
+				VkDescriptorSet* getDescriptorSet(int currentFrame);
+				graphics::StreamBuffer* getUniformBuffer();
+				void createVulkanVertexFormat(VertexAttributes vertexAttributes, bool& useConstantVertexColor, GraphicsPipelineConfiguration& configuration);
 				
-				VkInstance instance;
+				VkInstance instance = VK_NULL_HANDLE;
 				VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
-				VkDevice device;
-				VkQueue graphicsQueue;
-				VkQueue presentQueue;
-				VkSurfaceKHR surface;
-				VkSwapchainKHR swapChain;
+				VkDevice device = VK_NULL_HANDLE;
+				VkQueue graphicsQueue = VK_NULL_HANDLE;
+				VkQueue presentQueue = VK_NULL_HANDLE;
+				VkSurfaceKHR surface = VK_NULL_HANDLE;
+				VkSwapchainKHR swapChain = VK_NULL_HANDLE;
 				std::vector<VkImage> swapChainImages;
-				VkFormat swapChainImageFormat;
-				VkExtent2D swapChainExtent;
+				VkFormat swapChainImageFormat = VK_FORMAT_UNDEFINED;
+				VkExtent2D swapChainExtent = VkExtent2D();
 				std::vector<VkImageView> swapChainImageViews;
-				VkDescriptorSetLayout descriptorSetLayout;
-				VkPipelineLayout pipelineLayout;
-				VkRenderPass renderPass;
+				VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
+				VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
+				VkRenderPass renderPass = VK_NULL_HANDLE;
 				VkPipeline currentGraphicsPipeline = VK_NULL_HANDLE;
 				std::vector<std::pair<GraphicsPipelineConfiguration, VkPipeline>> graphicsPipelines;	// FIXME improve performance by using a hash map
 				std::vector<VkFramebuffer> swapChainFramBuffers;
-				VkCommandPool commandPool;
+				VkCommandPool commandPool = VK_NULL_HANDLE;
 				std::vector<VkCommandBuffer> commandBuffers;
 				VkClearValue clearColor = { {{0.0f, 0.0f, 0.0f, 1.0f}} };
-				VkDescriptorPool descriptorPool;
+				VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
 				std::vector<VkSemaphore> imageAvailableSemaphores;
 				std::vector<VkSemaphore> renderFinishedSemaphores;
 				std::vector<VkFence> inFlightFences;
 				std::vector<VkFence> imagesInFlight;
 				size_t currentFrame = 0;
-				uint32_t imageIndex;
+				uint32_t imageIndex = 0;
 				bool framebufferResized = false;
-				VmaAllocator vmaAllocator;
-				graphics::Texture* standardTexture;
+				VmaAllocator vmaAllocator = VK_NULL_HANDLE;
+				graphics::Texture* standardTexture = nullptr;
+				// we need an array of draw buffers, since the frames are being rendered asynchronously
+				// and we can't (or shouldn't) update the contents of the buffers while they're still in flight / being rendered.
+				std::vector<BatchedDrawBuffers> batchedDrawBuffers;
+				StreamBuffer* quadIndexBuffer = nullptr;
+				graphics::Texture* currentTexture = nullptr;
+				std::vector<std::pair<graphics::Shader::BuiltinUniformData, graphics::StreamBuffer*>> uniformBufferMap;
+				std::vector<std::pair<DecriptorSetConfiguration, std::vector<VkDescriptorSet>>> descriptorSetsMap;
 			};
 		}
 	}

+ 29 - 0
src/modules/graphics/vulkan/Vulkan.cpp

@@ -1,5 +1,8 @@
 #include "Vulkan.h"
 
+#include <sstream>
+
+
 namespace love {
 	namespace graphics {
 		namespace vulkan {
@@ -257,6 +260,32 @@ namespace love {
 
 				return textureFormat;
 			}
+
+			// values taken from https://pcisig.com/membership/member-companies
+			// as specified at https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceProperties.html
+			std::string Vulkan::getVendorName(uint32_t vendorId) {
+				switch (vendorId) {
+				case 4318:
+					return "Nvidia";
+				case 8086:
+					return "Intel";
+				case 4130:
+					return "Advanced Micro Devices";
+				default:
+					return "unknown";
+				}
+			}
+
+			std::string Vulkan::getVulkanApiVersion(uint32_t version) {
+				std::stringstream ss;
+
+				ss << VK_API_VERSION_VARIANT(version) 
+				   << "." << VK_API_VERSION_MAJOR(version) 
+				   << "." << VK_API_VERSION_MINOR(version) 
+				   << "." << VK_API_VERSION_PATCH(version);
+
+				return ss.str();
+			}
 		}
 	}
 }

+ 2 - 0
src/modules/graphics/vulkan/Vulkan.h

@@ -20,6 +20,8 @@ namespace love {
 			public:
 				static VkFormat getVulkanVertexFormat(DataFormat format);
 				static TextureFormat getTextureFormat(PixelFormat);
+				static std::string getVendorName(uint32_t vendorId);
+				static std::string getVulkanApiVersion(uint32_t apiVersion);
 			};
 		}
 	}