mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 21:39:52 +00:00
Merge pull request #12419 from hrydgard/vk-scissor-rotation-clamp
Vulkan: Move viewport/scissor rotation to the QueueRunner instead of RenderManager.
This commit is contained in:
commit
aca18a188f
@ -1,5 +1,5 @@
|
||||
#include <algorithm>
|
||||
#include "base/display.h"
|
||||
#include "math/math_util.h"
|
||||
|
||||
int dp_xres;
|
||||
int dp_yres;
|
||||
@ -19,7 +19,8 @@ float display_hz = 60.0f;
|
||||
DisplayRotation g_display_rotation;
|
||||
Matrix4x4 g_display_rot_matrix;
|
||||
|
||||
void RotateRectToDisplay(FRect &rect, float curRTWidth, float curRTHeight) {
|
||||
template<class T>
|
||||
void RotateRectToDisplayImpl(DisplayRect<T> &rect, T curRTWidth, T curRTHeight) {
|
||||
switch (g_display_rotation) {
|
||||
case DisplayRotation::ROTATE_180:
|
||||
rect.x = curRTWidth - rect.w - rect.x;
|
||||
@ -27,23 +28,27 @@ void RotateRectToDisplay(FRect &rect, float curRTWidth, float curRTHeight) {
|
||||
break;
|
||||
case DisplayRotation::ROTATE_90: {
|
||||
// Note that curRTWidth_ and curRTHeight_ are "swapped"!
|
||||
float origX = rect.x;
|
||||
float origY = rect.y;
|
||||
float rtw = curRTHeight;
|
||||
float rth = curRTWidth;
|
||||
rect.x = rth - rect.h - origY;
|
||||
T origX = rect.x;
|
||||
T origY = rect.y;
|
||||
T rtw = curRTHeight;
|
||||
T rth = curRTWidth;
|
||||
rect.x = clamp_value(rth - rect.h - origY, T{}, curRTHeight);
|
||||
rect.y = origX;
|
||||
std::swap(rect.w, rect.h);
|
||||
T temp = rect.w;
|
||||
rect.w = rect.h;
|
||||
rect.h = temp;
|
||||
break;
|
||||
}
|
||||
case DisplayRotation::ROTATE_270: {
|
||||
float origX = rect.x;
|
||||
float origY = rect.y;
|
||||
float rtw = curRTHeight;
|
||||
float rth = curRTWidth;
|
||||
T origX = rect.x;
|
||||
T origY = rect.y;
|
||||
T rtw = curRTHeight;
|
||||
T rth = curRTWidth;
|
||||
rect.x = origY;
|
||||
rect.y = rtw - rect.w - origX;
|
||||
std::swap(rect.w, rect.h);
|
||||
rect.y = clamp_value(rtw - rect.w - origX, T{}, curRTWidth);
|
||||
T temp = rect.w;
|
||||
rect.w = rect.h;
|
||||
rect.h = temp;
|
||||
break;
|
||||
}
|
||||
case DisplayRotation::ROTATE_0:
|
||||
@ -51,3 +56,11 @@ void RotateRectToDisplay(FRect &rect, float curRTWidth, float curRTHeight) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RotateRectToDisplay(DisplayRect<int> &rect, int curRTWidth, int curRTHeight) {
|
||||
RotateRectToDisplayImpl<int>(rect, curRTWidth, curRTHeight);
|
||||
}
|
||||
|
||||
void RotateRectToDisplay(DisplayRect<float> &rect, float curRTWidth, float curRTHeight) {
|
||||
RotateRectToDisplayImpl<float>(rect, curRTWidth, curRTHeight);
|
||||
}
|
||||
|
@ -31,7 +31,10 @@ enum class DisplayRotation {
|
||||
extern DisplayRotation g_display_rotation;
|
||||
extern Matrix4x4 g_display_rot_matrix;
|
||||
|
||||
struct FRect {
|
||||
float x, y, w, h;
|
||||
template<class T>
|
||||
struct DisplayRect {
|
||||
T x, y, w, h;
|
||||
};
|
||||
void RotateRectToDisplay(FRect &rect, float curRTWidth, float curRTHeight);
|
||||
|
||||
void RotateRectToDisplay(DisplayRect<float> &rect, float rtWidth, float rtHeight);
|
||||
void RotateRectToDisplay(DisplayRect<int> &rect, int rtWidth, int rtHeight);
|
||||
|
@ -1007,12 +1007,39 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
||||
break;
|
||||
|
||||
case VKRRenderCommand::VIEWPORT:
|
||||
vkCmdSetViewport(cmd, 0, 1, &c.viewport.vp);
|
||||
if (fb != nullptr) {
|
||||
vkCmdSetViewport(cmd, 0, 1, &c.viewport.vp);
|
||||
} else {
|
||||
const VkViewport &vp = c.viewport.vp;
|
||||
DisplayRect<float> rc{ vp.x, vp.y, vp.width, vp.height };
|
||||
RotateRectToDisplay(rc, (float)vulkan_->GetBackbufferWidth(), (float)vulkan_->GetBackbufferHeight());
|
||||
VkViewport final_vp;
|
||||
final_vp.x = rc.x;
|
||||
final_vp.y = rc.y;
|
||||
final_vp.width = rc.w;
|
||||
final_vp.height = rc.h;
|
||||
final_vp.maxDepth = vp.maxDepth;
|
||||
final_vp.minDepth = vp.minDepth;
|
||||
vkCmdSetViewport(cmd, 0, 1, &final_vp);
|
||||
}
|
||||
break;
|
||||
|
||||
case VKRRenderCommand::SCISSOR:
|
||||
vkCmdSetScissor(cmd, 0, 1, &c.scissor.scissor);
|
||||
{
|
||||
if (fb != nullptr) {
|
||||
vkCmdSetScissor(cmd, 0, 1, &c.scissor.scissor);
|
||||
} else {
|
||||
// Rendering to backbuffer. Might need to rotate.
|
||||
const VkRect2D &rc = c.scissor.scissor;
|
||||
DisplayRect<int> rotated_rc{ rc.offset.x, rc.offset.y, (int)rc.extent.width, (int)rc.extent.height };
|
||||
RotateRectToDisplay(rotated_rc, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight());
|
||||
_dbg_assert_(G3D, rotated_rc.x >= 0);
|
||||
_dbg_assert_(G3D, rotated_rc.y >= 0);
|
||||
VkRect2D finalRect = VkRect2D{ { rotated_rc.x, rotated_rc.y }, { (uint32_t)rotated_rc.w, (uint32_t)rotated_rc.h} };
|
||||
vkCmdSetScissor(cmd, 0, 1, &finalRect);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case VKRRenderCommand::BLEND:
|
||||
{
|
||||
|
@ -120,21 +120,17 @@ public:
|
||||
void SetViewport(const VkViewport &vp) {
|
||||
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER);
|
||||
_dbg_assert_(G3D, (int)vp.width >= 0);
|
||||
FRect rc{ vp.x, vp.y, vp.width, vp.height };
|
||||
if (curRenderStep_->render.framebuffer == nullptr) { // Only the backbuffer is actually rotated wrong!
|
||||
RotateRectToDisplay(rc, (float)vulkan_->GetBackbufferWidth(), (float)vulkan_->GetBackbufferHeight());
|
||||
}
|
||||
_dbg_assert_(G3D, (int)vp.height >= 0);
|
||||
VkRenderData data{ VKRRenderCommand::VIEWPORT };
|
||||
data.viewport.vp.x = rc.x;
|
||||
data.viewport.vp.y = rc.y;
|
||||
data.viewport.vp.width = rc.w;
|
||||
data.viewport.vp.height = rc.h;
|
||||
data.viewport.vp.x = vp.x;
|
||||
data.viewport.vp.y = vp.y;
|
||||
data.viewport.vp.width = vp.width;
|
||||
data.viewport.vp.height = vp.height;
|
||||
// We can't allow values outside this range unless we use VK_EXT_depth_range_unrestricted.
|
||||
// Sometimes state mapping produces 65536/65535 which is slightly outside.
|
||||
// TODO: This should be fixed at the source.
|
||||
data.viewport.vp.maxDepth = clamp_value(vp.maxDepth, 0.0f, 1.0f);
|
||||
data.viewport.vp.minDepth = clamp_value(vp.minDepth, 0.0f, 1.0f);
|
||||
|
||||
data.viewport.vp.maxDepth = clamp_value(vp.maxDepth, 0.0f, 1.0f);
|
||||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
|
||||
@ -143,15 +139,7 @@ public:
|
||||
_dbg_assert_(G3D, (int)rc.extent.width >= 0);
|
||||
_dbg_assert_(G3D, (int)rc.extent.height >= 0);
|
||||
VkRenderData data{ VKRRenderCommand::SCISSOR };
|
||||
if (curRenderStep_->render.framebuffer == nullptr) {
|
||||
FRect frc{ (float)rc.offset.x, (float)rc.offset.y, (float)rc.extent.width, (float)rc.extent.height };
|
||||
if (curRenderStep_->render.framebuffer == nullptr) { // Only the backbuffer is actually rotated wrong!
|
||||
RotateRectToDisplay(frc, (float)vulkan_->GetBackbufferWidth(), (float)vulkan_->GetBackbufferHeight());
|
||||
}
|
||||
data.scissor.scissor = VkRect2D{ { (int32_t)frc.x, (int32_t)frc.y }, { (uint32_t)frc.w, (uint32_t)frc.h} };
|
||||
} else {
|
||||
data.scissor.scissor = rc;
|
||||
}
|
||||
data.scissor.scissor = rc;
|
||||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
|
||||
|
@ -360,7 +360,7 @@ void D3D11DrawContext::HandleEvent(Event ev, int width, int height, void *param1
|
||||
void D3D11DrawContext::SetViewports(int count, Viewport *viewports) {
|
||||
D3D11_VIEWPORT vp[4];
|
||||
for (int i = 0; i < count; i++) {
|
||||
FRect rc{ viewports[i].TopLeftX , viewports[i].TopLeftY, viewports[i].Width, viewports[i].Height };
|
||||
DisplayRect<float> rc{ viewports[i].TopLeftX , viewports[i].TopLeftY, viewports[i].Width, viewports[i].Height };
|
||||
if (curRenderTargetView_ == bbRenderTargetView_) // Only the backbuffer is actually rotated wrong!
|
||||
RotateRectToDisplay(rc, curRTWidth_, curRTHeight_);
|
||||
vp[i].TopLeftX = rc.x;
|
||||
@ -374,7 +374,7 @@ void D3D11DrawContext::SetViewports(int count, Viewport *viewports) {
|
||||
}
|
||||
|
||||
void D3D11DrawContext::SetScissorRect(int left, int top, int width, int height) {
|
||||
FRect frc{ (float)left, (float)top, (float)width, (float)height };
|
||||
DisplayRect<float> frc{ (float)left, (float)top, (float)width, (float)height };
|
||||
if (curRenderTargetView_ == bbRenderTargetView_) // Only the backbuffer is actually rotated wrong!
|
||||
RotateRectToDisplay(frc, curRTWidth_, curRTHeight_);
|
||||
D3D11_RECT rc{};
|
||||
|
@ -1043,11 +1043,10 @@ void VKContext::SetViewports(int count, Viewport *viewports) {
|
||||
if (count > 0) {
|
||||
// Ignore viewports more than the first.
|
||||
VkViewport viewport;
|
||||
FRect rc{ viewports[0].TopLeftX , viewports[0].TopLeftY, viewports[0].Width, viewports[0].Height };
|
||||
viewport.x = rc.x;
|
||||
viewport.y = rc.y;
|
||||
viewport.width = rc.w;
|
||||
viewport.height = rc.h;
|
||||
viewport.x = viewports[0].TopLeftX;
|
||||
viewport.y = viewports[0].TopLeftY;
|
||||
viewport.width = viewports[0].Width;
|
||||
viewport.height = viewports[0].Height;
|
||||
viewport.minDepth = viewports[0].MinDepth;
|
||||
viewport.maxDepth = viewports[0].MaxDepth;
|
||||
renderManager_.SetViewport(viewport);
|
||||
|
Loading…
Reference in New Issue
Block a user