Browse Source

vulkan: fix scissor on android

niki 3 years ago
parent
commit
62148790a8
2 changed files with 74 additions and 21 deletions
  1. 72 20
      src/modules/graphics/vulkan/Graphics.cpp
  2. 2 1
      src/modules/graphics/vulkan/Graphics.h

+ 72 - 20
src/modules/graphics/vulkan/Graphics.cpp

@@ -428,9 +428,58 @@ void Graphics::setColor(Colorf c) {
 	states.back().color = c;
 	states.back().color = c;
 }
 }
 
 
+static VkRect2D computeScissor(const Rect& r, double bufferWidth, double bufferHeight, double dpiScale, VkSurfaceTransformFlagBitsKHR preTransform) {
+	double x = static_cast<double>(r.x) * dpiScale;
+	double y = static_cast<double>(r.y) * dpiScale;
+	double w = static_cast<double>(r.w) * dpiScale;
+	double h = static_cast<double>(r.h) * dpiScale;
+
+	double scissorX, scissorY, scissorW, scissorH;
+
+	switch (preTransform) {
+	case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
+		scissorX = bufferWidth - h - y;
+		scissorY = x;
+		scissorW = h;
+		scissorH = w;
+		break;
+	case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
+		scissorX = bufferWidth - w - x;
+		scissorY = bufferHeight - h - y;
+		scissorW = w;
+		scissorH = h;
+		break;
+	case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
+		scissorX = y;
+		scissorY = bufferHeight - w - x;
+		scissorW = h;
+		scissorH = w;
+		break;
+	default:
+		scissorX = x;
+		scissorY = y;
+		scissorW = w;
+		scissorH = h;
+		break;
+	}
+
+	VkRect2D scissor = { 
+		{static_cast<int32_t>(scissorX), static_cast<int32_t>(scissorY)},
+		{static_cast<uint32_t>(scissorW), static_cast<uint32_t>(scissorH)}
+	};
+	return scissor;
+}
+
 void Graphics::setScissor(const Rect& rect) {
 void Graphics::setScissor(const Rect& rect) {
 	flushBatchedDraws();
 	flushBatchedDraws();
 
 
+	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;
 	states.back().scissor = true;
 	states.back().scissorRect = rect;
 	states.back().scissorRect = rect;
 }
 }
@@ -439,6 +488,12 @@ void Graphics::setScissor() {
 	flushBatchedDraws();
 	flushBatchedDraws();
 
 
 	states.back().scissor = false;
 	states.back().scissor = false;
+
+	VkRect2D scissor{};
+	scissor.offset = { 0, 0 };
+	scissor.extent = swapChainExtent;
+
+	vkCmdSetScissor(commandBuffers.at(currentFrame), 0, 1, &scissor);
 }
 }
 
 
 void Graphics::setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) {
 void Graphics::setStencilMode(StencilAction action, CompareMode compare, int value, love::uint32 readmask, love::uint32 writemask) {
@@ -511,6 +566,10 @@ void Graphics::setRenderTargetsInternal(const RenderTargets& rts, int pixelw, in
 
 
 // END IMPLEMENTATION OVERRIDDEN FUNCTIONS
 // END IMPLEMENTATION OVERRIDDEN FUNCTIONS
 
 
+void Graphics::initDynamicState() {
+	setScissor();
+}
+
 void Graphics::startRecordingGraphicsCommands() {
 void Graphics::startRecordingGraphicsCommands() {
 	vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
 	vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
 
 
@@ -544,6 +603,8 @@ void Graphics::startRecordingGraphicsCommands() {
 		throw love::Exception("failed to begin recording data transfer command buffer");
 		throw love::Exception("failed to begin recording data transfer command buffer");
 	}
 	}
 
 
+	initDynamicState();
+
 	Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), swapChainImages[imageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
 	Vulkan::cmdTransitionImageLayout(commandBuffers.at(currentFrame), swapChainImages[imageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
 
 
 	startRenderPass(nullptr, swapChainExtent.width, swapChainExtent.height);
 	startRenderPass(nullptr, swapChainExtent.width, swapChainExtent.height);
@@ -1062,6 +1123,7 @@ void Graphics::createSwapChain() {
 
 
 	swapChainImageFormat = surfaceFormat.format;
 	swapChainImageFormat = surfaceFormat.format;
 	swapChainExtent = extent;
 	swapChainExtent = extent;
+	preTransform = swapChainSupport.capabilities.currentTransform;
 }
 }
 
 
 VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {
 VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {
@@ -1374,12 +1436,6 @@ void Graphics::prepareDraw(const VertexAttributes& attributes, const BufferBindi
 	configuration.cullmode = cullmode;
 	configuration.cullmode = cullmode;
 	configuration.viewportWidth = currentViewportWidth;
 	configuration.viewportWidth = currentViewportWidth;
 	configuration.viewportHeight = currentViewportHeight;
 	configuration.viewportHeight = currentViewportHeight;
-	if (states.back().scissor) {
-		configuration.scissorRect = states.back().scissorRect;
-	}
-	else {
-		configuration.scissorRect = std::nullopt;
-	}
 	std::vector<VkBuffer> bufferVector;
 	std::vector<VkBuffer> bufferVector;
 	std::vector<VkDeviceSize> offsets;
 	std::vector<VkDeviceSize> offsets;
 
 
@@ -1546,24 +1602,11 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration config
 	viewport.minDepth = 0.0f;
 	viewport.minDepth = 0.0f;
 	viewport.maxDepth = 1.0f;
 	viewport.maxDepth = 1.0f;
 
 
-	VkRect2D scissor{};
-	if (configuration.scissorRect.has_value()) {
-		scissor.offset.x = configuration.scissorRect.value().x;
-		scissor.offset.y = configuration.scissorRect.value().y;
-		scissor.extent.width = static_cast<uint32_t>(configuration.scissorRect.value().w);
-		scissor.extent.height = static_cast<uint32_t>(configuration.scissorRect.value().h);
-	}
-	else {
-		scissor.offset = { 0, 0 };
-		scissor.extent = swapChainExtent;
-	}
-
 	VkPipelineViewportStateCreateInfo viewportState{};
 	VkPipelineViewportStateCreateInfo viewportState{};
 	viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
 	viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
 	viewportState.viewportCount = 1;
 	viewportState.viewportCount = 1;
 	viewportState.pViewports = &viewport;
 	viewportState.pViewports = &viewport;
 	viewportState.scissorCount = 1;
 	viewportState.scissorCount = 1;
-	viewportState.pScissors = &scissor;
 
 
 	VkPipelineRasterizationStateCreateInfo rasterizer{};
 	VkPipelineRasterizationStateCreateInfo rasterizer{};
 	rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
 	rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
@@ -1634,6 +1677,15 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration config
 	colorBlending.blendConstants[2] = 0.0f;
 	colorBlending.blendConstants[2] = 0.0f;
 	colorBlending.blendConstants[3] = 0.0f;
 	colorBlending.blendConstants[3] = 0.0f;
 
 
+	std::array<VkDynamicState, 1> dynamicStates = {
+		VK_DYNAMIC_STATE_SCISSOR
+	};
+
+	VkPipelineDynamicStateCreateInfo dynamicState{};
+	dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+	dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
+	dynamicState.pDynamicStates = dynamicStates.data();
+
 	VkGraphicsPipelineCreateInfo pipelineInfo{};
 	VkGraphicsPipelineCreateInfo pipelineInfo{};
 	pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
 	pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
 	pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
 	pipelineInfo.stageCount = static_cast<uint32_t>(shaderStages.size());
@@ -1645,7 +1697,7 @@ VkPipeline Graphics::createGraphicsPipeline(GraphicsPipelineConfiguration config
 	pipelineInfo.pMultisampleState = &multisampling;
 	pipelineInfo.pMultisampleState = &multisampling;
 	pipelineInfo.pDepthStencilState = &depthStencil;
 	pipelineInfo.pDepthStencilState = &depthStencil;
 	pipelineInfo.pColorBlendState = &colorBlending;
 	pipelineInfo.pColorBlendState = &colorBlending;
-	pipelineInfo.pDynamicState = nullptr;
+	pipelineInfo.pDynamicState = &dynamicState;
 	pipelineInfo.layout = configuration.shader->getGraphicsPipelineLayout();
 	pipelineInfo.layout = configuration.shader->getGraphicsPipelineLayout();
 	pipelineInfo.subpass = 0;
 	pipelineInfo.subpass = 0;
 	pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
 	pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;

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

@@ -67,7 +67,6 @@ struct GraphicsPipelineConfiguration {
 	CullMode cullmode;
 	CullMode cullmode;
 	float viewportWidth;
 	float viewportWidth;
 	float viewportHeight;
 	float viewportHeight;
-	std::optional<Rect> scissorRect;
 	StencilState stencil;
 	StencilState stencil;
 	DepthState depthState;
 	DepthState depthState;
 
 
@@ -228,6 +227,7 @@ private:
 	void cleanup();
 	void cleanup();
 	void cleanupSwapChain();
 	void cleanupSwapChain();
 	void recreateSwapChain();
 	void recreateSwapChain();
+	void initDynamicState();
 	void startRecordingGraphicsCommands();
 	void startRecordingGraphicsCommands();
 	void endRecordingGraphicsCommands();
 	void endRecordingGraphicsCommands();
 	void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration);
 	void ensureGraphicsPipelineConfiguration(GraphicsPipelineConfiguration);
@@ -250,6 +250,7 @@ private:
 	VkQueue presentQueue = VK_NULL_HANDLE;
 	VkQueue presentQueue = VK_NULL_HANDLE;
 	VkSurfaceKHR surface = VK_NULL_HANDLE;
 	VkSurfaceKHR surface = VK_NULL_HANDLE;
     VkSwapchainKHR swapChain = VK_NULL_HANDLE;
     VkSwapchainKHR swapChain = VK_NULL_HANDLE;
+	VkSurfaceTransformFlagBitsKHR preTransform;
 	Matrix4 displayRotation;
 	Matrix4 displayRotation;
 	std::vector<VkImage> swapChainImages;
 	std::vector<VkImage> swapChainImages;
 	VkFormat swapChainImageFormat = VK_FORMAT_UNDEFINED;
 	VkFormat swapChainImageFormat = VK_FORMAT_UNDEFINED;