Browse Source

use default texture when rendering primitives

niki 3 years ago
parent
commit
c16c07780f

+ 3 - 1
src/modules/graphics/Shader.cpp

@@ -460,8 +460,10 @@ layout(location = 0) in vec4 fragColor;
 
 layout(location = 0) out vec4 outColor;
 
+layout(binding = 1) uniform sampler2D texSampler;
+
 void main() {
-    outColor = fragColor;
+    outColor = fragColor * texture(texSampler, vec2(0, 0));
 }
 )";
 

+ 73 - 40
src/modules/graphics/vulkan/Graphics.cpp

@@ -4,12 +4,14 @@
 #include "window/Window.h"
 #include "common/Exception.h"
 #include "Shader.h"
+#include "graphics/Texture.h"
 
 #include <vector>
 #include <cstring>
 #include <set>
 #include <fstream>
 #include <iostream>
+#include <array>
 
 
 namespace love {
@@ -59,30 +61,8 @@ namespace love {
 			void Graphics::initVulkan() {
 				if (!init) {
 					init = true;
-					createVulkanInstance();
-					createSurface();
-					pickPhysicalDevice();
-					createLogicalDevice();
-					initVMA();
-					createSwapChain();
-					createImageViews();
-					createRenderPass();
-					createDefaultShaders();
-					createDescriptorSetLayout();
-					createGraphicsPipeline();
-					createFramebuffers();
-					createCommandPool();
-					createCommandBuffers();
-					createUniformBuffers();
-					createDescriptorPool();
-					createDescriptorSets();
-					createSyncObjects();
-					startRecordingGraphicsCommands();
-				}
-			}
 
-			Graphics::~Graphics() {
-				cleanup();
+				}
 			}
 
 			// START OVERRIDEN FUNCTIONS
@@ -214,7 +194,27 @@ namespace love {
 			bool Graphics::setMode(void* context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) {
 				std::cout << "setMode ";
 
+				createVulkanInstance();
+				createSurface();
+				pickPhysicalDevice();
+				createLogicalDevice();
+				initVMA();
 				initCapabilities();
+				createSwapChain();
+				createImageViews();
+				createRenderPass();
+				createDefaultShaders();
+				createDescriptorSetLayout();
+				createGraphicsPipeline();
+				createFramebuffers();
+				createCommandPool();
+				createCommandBuffers();
+				createUniformBuffers();
+				createDefaultTexture();
+				createDescriptorPool();
+				createDescriptorSets();
+				createSyncObjects();
+				startRecordingGraphicsCommands();
 
 				created = true;
 
@@ -279,6 +279,7 @@ namespace love {
 
 			void Graphics::unSetMode() {
 				created = false;
+				cleanup();
 
 				std::cout << "unSetMode ";
 			}
@@ -469,6 +470,9 @@ namespace love {
 				return requiredExtensions.empty();
 			}
 
+			// if the score is nonzero then the device is suitable.
+			// A higher rating means generally better performance
+			// if the score is 0 the device is unsuitable
 			int Graphics::rateDeviceSuitability(VkPhysicalDevice device) {
 				VkPhysicalDeviceProperties deviceProperties;
 				VkPhysicalDeviceFeatures deviceFeatures;
@@ -835,10 +839,18 @@ namespace love {
 				uboLayoutBinding.descriptorCount = 1;
 				uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
 
+				VkDescriptorSetLayoutBinding samplerLayoutBinding{};
+				samplerLayoutBinding.binding = 1;
+				samplerLayoutBinding.descriptorCount = 1;
+				samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+				samplerLayoutBinding.pImmutableSamplers = nullptr;
+				samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+
+				std::array<VkDescriptorSetLayoutBinding, 2> bindings = { uboLayoutBinding, samplerLayoutBinding };
 				VkDescriptorSetLayoutCreateInfo layoutInfo{};
 				layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
-				layoutInfo.bindingCount = 1;
-				layoutInfo.pBindings = &uboLayoutBinding;
+				layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
+				layoutInfo.pBindings = bindings.data();
 
 				if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
 					throw love::Exception("failed to create descriptor set layout");
@@ -854,14 +866,16 @@ namespace love {
 			}
 
 			void Graphics::createDescriptorPool() {
-				VkDescriptorPoolSize poolSize{};
-				poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
-				poolSize.descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
+				std::array<VkDescriptorPoolSize, 2> poolSizes{};
+				poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+				poolSizes[0].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
+				poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+				poolSizes[1].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.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
+				poolInfo.pPoolSizes = poolSizes.data();
 				poolInfo.maxSets = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
 
 				if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
@@ -888,16 +902,30 @@ namespace love {
 					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);
+					VkDescriptorImageInfo imageInfo{};
+					imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+					Texture* vkTexture = (Texture*)standardTexture;
+					imageInfo.imageView = vkTexture->getImageView();
+					imageInfo.sampler = vkTexture->getSampler();
+
+					std::array<VkWriteDescriptorSet, 2> descriptorWrite{};
+					descriptorWrite[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+					descriptorWrite[0].dstSet = descriptorSets[i];
+					descriptorWrite[0].dstBinding = 0;
+					descriptorWrite[0].dstArrayElement = 0;
+					descriptorWrite[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+					descriptorWrite[0].descriptorCount = 1;
+					descriptorWrite[0].pBufferInfo = &bufferInfo;
+
+					descriptorWrite[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+					descriptorWrite[1].dstSet = descriptorSets[i];
+					descriptorWrite[1].dstBinding = 1;
+					descriptorWrite[1].dstArrayElement = 0;
+					descriptorWrite[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+					descriptorWrite[1].descriptorCount = 1;
+					descriptorWrite[1].pImageInfo = &imageInfo;
+
+					vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrite.size()), descriptorWrite.data(), 0, nullptr);
 				}
 			}
 
@@ -1090,6 +1118,11 @@ namespace love {
 				}
 			}
 
+			void Graphics::createDefaultTexture() {
+				Texture::Settings settings;
+				standardTexture = newTexture(settings);
+			}
+
 			void Graphics::cleanup() {
 				vkDeviceWaitIdle(device);
 

+ 3 - 1
src/modules/graphics/vulkan/Graphics.h

@@ -25,7 +25,7 @@ namespace love {
 
 				void initVulkan();
 
-				virtual ~Graphics();
+				virtual ~Graphics() = default;
 
 				const char* getName() const override;
 
@@ -139,6 +139,7 @@ namespace love {
 				void createCommandPool();
 				void createCommandBuffers();
 				void createSyncObjects();
+				void createDefaultTexture();
 				void cleanup();
 				void cleanupSwapChain();
 				void recreateSwapChain();
@@ -178,6 +179,7 @@ namespace love {
 				uint32_t imageIndex;
 				bool framebufferResized = false;
 				VmaAllocator vmaAllocator;
+				graphics::Texture* standardTexture;
 			};
 		}
 	}

+ 18 - 24
src/modules/graphics/vulkan/Texture.cpp

@@ -8,38 +8,32 @@ namespace love {
 	namespace graphics {
 		namespace vulkan {
 			Texture::Texture(love::graphics::Graphics* gfx, const Settings& settings, const Slices* data)
-				: love::graphics::Texture(gfx, settings, data), slices(settings.type), gfx(gfx) {
+				: love::graphics::Texture(gfx, settings, data), gfx(gfx) {
 				allocator = vgfx->getVmaAllocator();
 				device = vgfx->getDevice();
 
-				if (data != nullptr) {
-					slices = *data;
+				if (data) {
+					auto sliceData = data->get(0, 0);
+					auto size = sliceData->getSize();
+					auto dataPtr = sliceData->getData();
+					Rect rect;
+					rect.x = 0;
+					rect.y = 0;
+					rect.w = sliceData->getWidth();
+					rect.h = sliceData->getHeight();
+
+					uploadByteData(PIXELFORMAT_BGRA8_UNORM, dataPtr, size, 0, 0, rect);
+				}
+				else {
+					uint8 defaultPixel[] = { 255, 255, 255, 255 };
+					Rect rect = { 0, 0, 1, 1 };
+					uploadByteData(PIXELFORMAT_BGRA8_UNORM, defaultPixel, sizeof(defaultPixel), 0, 0, rect);
 				}
-				loadVolatile();
-			}
-
-			Texture::~Texture() {
-				unloadVolatile();
-			}
-
-			bool Texture::loadVolatile() {
-				auto data = slices.get(0, 0);
-				auto size = data->getSize();
-				auto dataPtr = data->getData();
-				Rect rect;
-				rect.x = 0;
-				rect.y = 0;
-				rect.w = data->getWidth();
-				rect.h = data->getHeight();
-
-				uploadByteData(PIXELFORMAT_BGRA8_UNORM, dataPtr, size, 0, 0, rect);
 				createTextureImageView();
 				createTextureSampler();
-
-				return true;
 			}
 
-			void Texture::unloadVolatile() {
+			Texture::~Texture() {
 				// vkDestroySampler(device, textureSampler, nullptr);
 				// vkDestroyImageView(device, textureImageView, nullptr);
 				// vmaDestroyImage(allocator, textureImage, nullptr);

+ 4 - 7
src/modules/graphics/vulkan/Texture.h

@@ -12,15 +12,11 @@
 namespace love {
 	namespace graphics {
 		namespace vulkan {
-			class Texture : public graphics::Texture, public graphics::Volatile {
+			class Texture : public graphics::Texture {
 			public:
 				Texture(love::graphics::Graphics* gfx, const Settings& settings, const Slices* data);
 				~Texture();
 
-				bool loadVolatile() override;
-
-				void unloadVolatile() override;
-
 				void copyFromBuffer(graphics::Buffer* source, size_t sourceoffset, int sourcewidth, size_t size, int slice, int mipmap, const Rect& rect) override { std::cout << "Texture::copyFromBuffer "; };
 				void copyToBuffer(graphics::Buffer* dest, int slice, int mipmap, const Rect& rect, size_t destoffset, int destwidth, size_t size) override { std::cout << "Texture::copyToBuffer "; };
 
@@ -33,7 +29,9 @@ namespace love {
 				void readbackImageData(love::image::ImageData* imagedata, int slice, int mipmap, const Rect& rect)  override { std::cout << "Texture::readbackImageData "; };
 
 				int getMSAA() const override { std::cout << "Texture::getMSAA "; return 0; };
-				ptrdiff_t getHandle() const override { std::cout << "Texture::getHandle "; return (ptrdiff_t)0; }
+				ptrdiff_t getHandle() const override { std::cout << "Texture::getHandle "; return (ptrdiff_t)textureImage; }
+				VkImageView getImageView() const { return textureImageView; }
+				VkSampler getSampler() const { return textureSampler; }
 
 			private:
 				void transitionImageLayout(VkImage, VkFormat, VkImageLayout oldLayout, VkImageLayout newLayout);
@@ -43,7 +41,6 @@ namespace love {
 
 				graphics::Graphics* gfx;
 				VkDevice device;
-				Slices slices;
 				VmaAllocator allocator;
 				VkImage textureImage;
 				VmaAllocation textureImageAllocation;