Browse Source

restructure to not hardcore draw vk commands

niki 3 years ago
parent
commit
00a5d5b0a0

+ 2 - 0
src/modules/graphics/Graphics.cpp

@@ -149,8 +149,10 @@ Graphics *Graphics::createInstance()
 	{
 	{
 		for (auto r : rendererOrder)
 		for (auto r : rendererOrder)
 		{
 		{
+#ifdef LOVE_GRAPHICS_VULKAN
 			// FIX ME: proper selection of vulkan backend
 			// FIX ME: proper selection of vulkan backend
 			instance = vulkan::createInstance();
 			instance = vulkan::createInstance();
+#endif
 
 
 			if (std::find(_renderers.begin(), _renderers.end(), r) == _renderers.end())
 			if (std::find(_renderers.begin(), _renderers.end(), r) == _renderers.end())
 				continue;
 				continue;

+ 113 - 43
src/modules/graphics/vulkan/Graphics.cpp

@@ -71,6 +71,7 @@ namespace love {
 					createCommandPool();
 					createCommandPool();
 					createCommandBuffers();
 					createCommandBuffers();
 					createSyncObjects();
 					createSyncObjects();
+					startRecordingGraphicsCommands();
 				}
 				}
 			}
 			}
 
 
@@ -78,23 +79,68 @@ namespace love {
 				cleanup();
 				cleanup();
 			}
 			}
 
 
+			// START OVERRIDEN FUNCTIONS
+
 			love::graphics::Buffer* Graphics::newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector<love::graphics::Buffer::DataDeclaration>& format, const void* data, size_t size, size_t arraylength) {
 			love::graphics::Buffer* Graphics::newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector<love::graphics::Buffer::DataDeclaration>& format, const void* data, size_t size, size_t arraylength) {
+				std::cout << "newBuffer ";
 				return nullptr;
 				return nullptr;
 			}
 			}
 
 
-			void Graphics::present(void* screenshotCallbackdata) {
+			void Graphics::startRecordingGraphicsCommands() {
 				vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
 				vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
+				
+				while (true) {
+					VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
+					if (result == VK_ERROR_OUT_OF_DATE_KHR) {
+						recreateSwapChain();
+						continue;
+					}
+					else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
+						throw love::Exception("failed to acquire swap chain image");
+					}
+
+					break;
+				}
 
 
-				uint32_t imageIndex;
-				VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
+				VkCommandBufferBeginInfo beginInfo{};
+				beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+				beginInfo.flags = 0;
+				beginInfo.pInheritanceInfo = nullptr;
 
 
-				if (result == VK_ERROR_OUT_OF_DATE_KHR) {
-					recreateSwapChain();
-					return;
+				std::cout << "beginCommandBuffer(imageIndex=" << imageIndex << ") ";
+				if (vkBeginCommandBuffer(commandBuffers.at(imageIndex), &beginInfo) != VK_SUCCESS) {
+					throw love::Exception("failed to begin recording command buffer");
 				}
 				}
-				else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
-					throw love::Exception("failed to acquire swap chain image");
+
+				VkRenderPassBeginInfo renderPassInfo{};
+				renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+				renderPassInfo.renderPass = renderPass;
+				renderPassInfo.framebuffer = swapChainFramBuffers.at(imageIndex);
+				renderPassInfo.renderArea.offset = { 0, 0 };
+				renderPassInfo.renderArea.extent = swapChainExtent;
+				renderPassInfo.clearValueCount = 1;
+				renderPassInfo.pClearValues = &clearColor;
+
+				const auto& commandBuffer = commandBuffers.at(imageIndex);
+
+				vkCmdBeginRenderPass(commandBuffers.at(imageIndex), &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
+				vkCmdBindPipeline(commandBuffers.at(imageIndex), VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
+			}
+
+			void Graphics::endRecordingGraphicsCommands() {
+				const auto& commandBuffer = commandBuffers.at(imageIndex);
+
+				std::cout << "endCommandBuffer(imageIndex=" << imageIndex << ") ";
+				vkCmdEndRenderPass(commandBuffers.at(imageIndex));
+				if (vkEndCommandBuffer(commandBuffers.at(imageIndex)) != VK_SUCCESS) {
+					throw love::Exception("failed to record command buffer");
 				}
 				}
+			}
+
+			void Graphics::present(void* screenshotCallbackdata) {
+				flushBatchedDraws();
+
+				endRecordingGraphicsCommands();
 
 
 				if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
 				if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
 					vkWaitForFences(device, 1, &imagesInFlight.at(imageIndex), VK_TRUE, UINT64_MAX);
 					vkWaitForFences(device, 1, &imagesInFlight.at(imageIndex), VK_TRUE, UINT64_MAX);
@@ -135,7 +181,7 @@ namespace love {
 
 
 				presentInfo.pImageIndices = &imageIndex;
 				presentInfo.pImageIndices = &imageIndex;
 
 
-				result = vkQueuePresentKHR(presentQueue, &presentInfo);
+				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 || framebufferResized) {
 					framebufferResized = false;
 					framebufferResized = false;
@@ -146,12 +192,52 @@ namespace love {
 				}
 				}
 
 
 				currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
 				currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
+
+				std::cout << "present" << std::endl;
+
+				startRecordingGraphicsCommands();
 			}
 			}
 
 
 			void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) {
 			void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) {
+				std::cout << "setViewPortSize";
 				recreateSwapChain();
 				recreateSwapChain();
 			}
 			}
 
 
+			bool Graphics::setMode(void* context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) { 
+				std::cout << "setMode ";
+
+				if (batchedDrawState.vb[0] == nullptr)
+				{
+					// Initial sizes that should be good enough for most cases. It will
+					// resize to fit if needed, later.
+					batchedDrawState.vb[0] = new StreamBuffer(this, device, physicalDevice, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1);
+					batchedDrawState.vb[1] = new StreamBuffer(this, device, physicalDevice, BUFFERUSAGE_VERTEX, 256 * 1024 * 1);
+					batchedDrawState.indexBuffer = new StreamBuffer(this, device, physicalDevice, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
+				}
+
+				return true;
+			}
+
+			void Graphics::draw(const DrawIndexedCommand& cmd) { 
+				std::cout << "drawIndexed ";
+
+				std::vector<VkBuffer> buffers;
+				std::vector<VkDeviceSize> offsets;
+				buffers.push_back((VkBuffer)cmd.buffers->info[0].buffer->getHandle());
+				offsets.push_back((VkDeviceSize)cmd.buffers->info[0].offset);
+				buffers.push_back((VkBuffer)cmd.buffers->info[1].buffer->getHandle());
+				offsets.push_back((VkDeviceSize)cmd.buffers->info[1].offset);
+
+				vkCmdDraw(commandBuffers.at(imageIndex), 3, 1, 0, 0);	// todo adjust
+			}
+
+			graphics::StreamBuffer* Graphics::newStreamBuffer(BufferUsage type, size_t size) { 
+				std::cout << "newStreamBuffer ";
+				return new StreamBuffer(this, device, physicalDevice, type, size); 
+			}
+
+			// END IMPLEMENTATION OVERRIDDEN FUNCTIONS
+
 			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");
@@ -626,11 +712,22 @@ namespace love {
 				VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
 				VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
 				vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
 				vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
 
 
+				VkVertexInputBindingDescription vertexBindingDescription;
+				vertexBindingDescription.binding = 0;
+				vertexBindingDescription.stride = 2 * sizeof(float);	// just position for now
+				vertexBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
+
 				// todo later
 				// todo later
+				VkVertexInputAttributeDescription positionInputAttributeDescription;
+				positionInputAttributeDescription.binding = 0;
+				positionInputAttributeDescription.location = 0;
+				positionInputAttributeDescription.format = VK_FORMAT_R32G32_SFLOAT;
+				positionInputAttributeDescription.offset = 0;
+
 				vertexInputInfo.vertexBindingDescriptionCount = 0;
 				vertexInputInfo.vertexBindingDescriptionCount = 0;
-				vertexInputInfo.pVertexBindingDescriptions = nullptr;
+				vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDescription;
 				vertexInputInfo.vertexAttributeDescriptionCount = 0;
 				vertexInputInfo.vertexAttributeDescriptionCount = 0;
-				vertexInputInfo.pVertexAttributeDescriptions = nullptr;
+				vertexInputInfo.pVertexAttributeDescriptions = &positionInputAttributeDescription;
 
 
 				VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
 				VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
 				inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
 				inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
@@ -777,38 +874,6 @@ namespace love {
 				if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
 				if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
 					throw love::Exception("failed to allocate command buffers");
 					throw love::Exception("failed to allocate command buffers");
 				}
 				}
-
-				for (size_t i = 0; i < commandBuffers.size(); i++) {
-					VkCommandBufferBeginInfo beginInfo{};
-					beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
-					beginInfo.flags = 0;
-					beginInfo.pInheritanceInfo = nullptr;
-
-					if (vkBeginCommandBuffer(commandBuffers[i], &beginInfo) != VK_SUCCESS) {
-						throw love::Exception("failed to begin recording command buffer");
-					}
-
-					VkRenderPassBeginInfo renderPassInfo{};
-					renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
-					renderPassInfo.renderPass = renderPass;
-					renderPassInfo.framebuffer = swapChainFramBuffers.at(i);
-					renderPassInfo.renderArea.offset = { 0, 0 };
-					renderPassInfo.renderArea.extent = swapChainExtent;
-
-					VkClearValue clearColor = { {{0.0f, 0.0f, 0.0f, 1.0f}} };
-					renderPassInfo.clearValueCount = 1;
-					renderPassInfo.pClearValues = &clearColor;
-
-					// this definitely doesn't belong in here, but leaving here for future reference
-					vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
-					vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
-					vkCmdDraw(commandBuffers[i], 3, 1, 0, 0);
-
-					vkCmdEndRenderPass(commandBuffers[i]);
-					if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) {
-						throw love::Exception("failed to record command buffer");
-					}
-				}
 			}
 			}
 
 
 			void Graphics::createSyncObjects() {
 			void Graphics::createSyncObjects() {
@@ -834,6 +899,8 @@ namespace love {
 			}
 			}
 
 
 			void Graphics::cleanup() {
 			void Graphics::cleanup() {
+				vkDeviceWaitIdle(device);
+
 				cleanupSwapChain();
 				cleanupSwapChain();
 
 
 				for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
 				for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
@@ -864,12 +931,15 @@ namespace love {
 			void Graphics::recreateSwapChain() {
 			void Graphics::recreateSwapChain() {
 				vkDeviceWaitIdle(device);
 				vkDeviceWaitIdle(device);
 
 
+				cleanupSwapChain();
+
 				createSwapChain();
 				createSwapChain();
 				createImageViews();
 				createImageViews();
 				createRenderPass();
 				createRenderPass();
 				createGraphicsPipeline();
 				createGraphicsPipeline();
 				createFramebuffers();
 				createFramebuffers();
 				createCommandBuffers();
 				createCommandBuffers();
+				startRecordingGraphicsCommands();
 			}
 			}
 
 
 			love::graphics::Graphics* createInstance() {
 			love::graphics::Graphics* createInstance() {

+ 43 - 35
src/modules/graphics/vulkan/Graphics.h

@@ -2,6 +2,7 @@
 #define LOVE_GRAPHICS_VULKAN_GRAPHICS_H
 #define LOVE_GRAPHICS_VULKAN_GRAPHICS_H
 
 
 #include "graphics/Graphics.h"
 #include "graphics/Graphics.h"
+#include "StreamBuffer.h"
 #include <vulkan/vulkan.h>
 #include <vulkan/vulkan.h>
 
 
 #include <common/config.h>
 #include <common/config.h>
@@ -32,46 +33,46 @@ namespace love {
 				}
 				}
 
 
 				// implementation for virtual functions
 				// implementation for virtual functions
-				Texture* newTexture(const Texture::Settings& settings, const Texture::Slices* data = nullptr) override { return nullptr;  }
+				Texture* newTexture(const Texture::Settings& settings, const Texture::Slices* data = nullptr) override { std::cout << "newTexture"; return nullptr; }
 				love::graphics::Buffer* newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector<love::graphics::Buffer::DataDeclaration>& format, const void* data, size_t size, size_t arraylength) override;
 				love::graphics::Buffer* newBuffer(const love::graphics::Buffer::Settings& settings, const std::vector<love::graphics::Buffer::DataDeclaration>& format, const void* data, size_t size, size_t arraylength) override;
-				void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override {}
-				void clear(const std::vector<OptionalColorD>& colors, OptionalInt stencil, OptionalDouble depth) override {}
-				Matrix4 computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const override { return Matrix4(); }
-				void discard(const std::vector<bool>& colorbuffers, bool depthstencil) override { }
+				void clear(OptionalColorD color, OptionalInt stencil, OptionalDouble depth) override { std::cout << "clear1 "; }
+				void clear(const std::vector<OptionalColorD>& colors, OptionalInt stencil, OptionalDouble depth) override { std::cout << "clear2 "; }
+				Matrix4 computeDeviceProjection(const Matrix4& projection, bool rendertotexture) const override { std::cout << "computeDeviceProjection "; return Matrix4(); }
+				void discard(const std::vector<bool>& colorbuffers, bool depthstencil) override { std::cout << "discard "; }
 				void present(void* screenshotCallbackdata) override;
 				void present(void* screenshotCallbackdata) override;
 				void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
 				void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
-				bool setMode(void* context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override { return false;  }
-				void unSetMode() override {}
-				void setActive(bool active) override {}
-				int getRequestedBackbufferMSAA() const override { return 0;  }
-				int getBackbufferMSAA() const  override { return 0;  }
-				void setColor(Colorf c) override {}
-				void setScissor(const Rect& rect) override {}
-				void setScissor() override {}
-				void setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) override {}
-				void setDepthMode(CompareMode compare, bool write) override {}
-				void setFrontFaceWinding(Winding winding) override {}
-				void setColorMask(ColorChannelMask mask) override {}
-				void setBlendState(const BlendState& blend) override {}
-				void setPointSize(float size) override {}
-				void setWireframe(bool enable) override {}
-				PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override { return PIXELFORMAT_UNKNOWN;  }
-				bool isPixelFormatSupported(PixelFormat format, PixelFormatUsageFlags usage, bool sRGB = false) override { return false;  }
-				Renderer getRenderer() const override { return RENDERER_VULKAN; }
-				bool usesGLSLES() const override { return false;  }
-				RendererInfo getRendererInfo() const override { return {};  }
-				void draw(const DrawCommand& cmd) override {}
-				void draw(const DrawIndexedCommand& cmd) override {}
-				void drawQuads(int start, int count, const VertexAttributes& attributes, const BufferBindings& buffers, Texture* texture) override {}
+				bool setMode(void* context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override;
+				void unSetMode() override { std::cout << "unSetMode "; }
+				void setActive(bool active) override { std::cout << "setActive "; }
+				int getRequestedBackbufferMSAA() const override { std::cout << "getRequestedBackbufferMSAA "; return 0; }
+				int getBackbufferMSAA() const  override { std::cout << "getBackbufferMSAA "; return 0; }
+				void setColor(Colorf c) override { std::cout << "setColor "; }
+				void setScissor(const Rect& rect) override { std::cout << "setScissor "; }
+				void setScissor() override { std::cout << "setScissor2 "; }
+				void setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) override { std::cout << "setStencilMode "; }
+				void setDepthMode(CompareMode compare, bool write) override { std::cout << "setDepthMode "; }
+				void setFrontFaceWinding(Winding winding) override { std::cout << "setFrontFaceWinding "; }
+				void setColorMask(ColorChannelMask mask) override { std::cout << "setColorMask "; }
+				void setBlendState(const BlendState& blend) override { std::cout << "setBlendState "; }
+				void setPointSize(float size) override { std::cout << "setPointSize "; }
+				void setWireframe(bool enable) override { std::cout << "setWireframe "; }
+				PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override { std::cout << "getSizedFormat "; return PIXELFORMAT_UNKNOWN; }
+				bool isPixelFormatSupported(PixelFormat format, PixelFormatUsageFlags usage, bool sRGB = false) override { std::cout << "isPixelFormatSupported "; return false; }
+				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 {}; }
+				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, Texture* texture) override { std::cout << "drawQuads "; }
 
 
 			protected:
 			protected:
-				ShaderStage* newShaderStageInternal(ShaderStageType stage, const std::string& cachekey, const std::string& source, bool gles) override { return nullptr; }
-				Shader* newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override { return nullptr;  }
-				StreamBuffer* newStreamBuffer(BufferUsage type, size_t size) override { return nullptr;  }
-				bool dispatch(int x, int y, int z) override { return false;  }
-				void initCapabilities() override {}
-				void getAPIStats(int& shaderswitches) const override {}
-				void setRenderTargetsInternal(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture) override {}
+				graphics::ShaderStage* newShaderStageInternal(ShaderStageType stage, const std::string& cachekey, const std::string& source, bool gles) override { std::cout << "newShaderStageInternal "; return nullptr; }
+				graphics::Shader* newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override { std::cout << "newShaderInternal "; return nullptr; }
+				graphics::StreamBuffer* newStreamBuffer(BufferUsage type, size_t size) override;
+				bool dispatch(int x, int y, int z) override { std::cout << "dispatch "; return false; }
+				void initCapabilities() override { std::cout << "initCapabilities "; }
+				void getAPIStats(int& shaderswitches) const override { std::cout << "getAPIStats "; }
+				void setRenderTargetsInternal(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture) override { std::cout << "setRenderTargetsInternal "; }
 
 
 			private:
 			private:
 				bool init = false;
 				bool init = false;
@@ -116,6 +117,9 @@ namespace love {
 				void cleanupSwapChain();
 				void cleanupSwapChain();
 				void recreateSwapChain();
 				void recreateSwapChain();
 
 
+				void startRecordingGraphicsCommands();
+				void endRecordingGraphicsCommands();
+				
 				VkInstance instance;
 				VkInstance instance;
 				VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
 				VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
 				VkDevice device;
 				VkDevice device;
@@ -133,13 +137,17 @@ namespace love {
 				std::vector<VkFramebuffer> swapChainFramBuffers;
 				std::vector<VkFramebuffer> swapChainFramBuffers;
 				VkCommandPool commandPool;
 				VkCommandPool commandPool;
 				std::vector<VkCommandBuffer> commandBuffers;
 				std::vector<VkCommandBuffer> commandBuffers;
+				VkClearValue clearColor = { {{0.0f, 0.0f, 0.0f, 1.0f}} };
 
 
 				std::vector<VkSemaphore> imageAvailableSemaphores;
 				std::vector<VkSemaphore> imageAvailableSemaphores;
 				std::vector<VkSemaphore> renderFinishedSemaphores;
 				std::vector<VkSemaphore> renderFinishedSemaphores;
 				std::vector<VkFence> inFlightFences;
 				std::vector<VkFence> inFlightFences;
 				std::vector<VkFence> imagesInFlight;
 				std::vector<VkFence> imagesInFlight;
 				size_t currentFrame = 0;
 				size_t currentFrame = 0;
+				uint32_t imageIndex;
 				bool framebufferResized = false;
 				bool framebufferResized = false;
+
+				friend class StreamBuffer;
 			};
 			};
 		}
 		}
 	}
 	}