fake negative x/y viewport positions under vulkan
Since Vulkan doesn't support negative x or y viewport positions, this patch concatenates a translation matrix to the projection matrix used in Vulkan rendering. In this way, if a negative x or y coordinate would be necessary, we can instead use a 0 coordinate and a leftwards/upwards translation to achieve the same effect. This seems to work alright with overlays, so as far as I can tell this patch seems sufficient to get the behavior we want?
This commit is contained in:
parent
708a1469fb
commit
6701c0999b
|
@ -577,6 +577,8 @@ typedef struct vk
|
||||||
VkViewport vk_vp;
|
VkViewport vk_vp;
|
||||||
VkRenderPass render_pass;
|
VkRenderPass render_pass;
|
||||||
struct video_viewport vp;
|
struct video_viewport vp;
|
||||||
|
float translate_x;
|
||||||
|
float translate_y;
|
||||||
struct vk_per_frame swapchain[VULKAN_MAX_SWAPCHAIN_IMAGES];
|
struct vk_per_frame swapchain[VULKAN_MAX_SWAPCHAIN_IMAGES];
|
||||||
struct vk_image backbuffers[VULKAN_MAX_SWAPCHAIN_IMAGES];
|
struct vk_image backbuffers[VULKAN_MAX_SWAPCHAIN_IMAGES];
|
||||||
struct vk_texture default_texture;
|
struct vk_texture default_texture;
|
||||||
|
|
|
@ -3411,6 +3411,8 @@ static void *vulkan_init(const video_info_t *video,
|
||||||
video_driver_get_size(&temp_width, &temp_height);
|
video_driver_get_size(&temp_width, &temp_height);
|
||||||
vk->video_width = temp_width;
|
vk->video_width = temp_width;
|
||||||
vk->video_height = temp_height;
|
vk->video_height = temp_height;
|
||||||
|
vk->translate_x = 0.0;
|
||||||
|
vk->translate_y = 0.0;
|
||||||
|
|
||||||
RARCH_LOG("[Vulkan]: Using resolution %ux%u.\n", temp_width, temp_height);
|
RARCH_LOG("[Vulkan]: Using resolution %ux%u.\n", temp_width, temp_height);
|
||||||
|
|
||||||
|
@ -3762,17 +3764,30 @@ static void vulkan_set_projection(vk_t *vk,
|
||||||
0.0f, 0.0f, 0.0f, 0.0f ,
|
0.0f, 0.0f, 0.0f, 0.0f ,
|
||||||
0.0f, 0.0f, 0.0f, 1.0f }
|
0.0f, 0.0f, 0.0f, 1.0f }
|
||||||
};
|
};
|
||||||
|
math_matrix_4x4 trn = {
|
||||||
|
{ 1.0f, 0.0f, 0.0f, 0.0f ,
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f ,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f ,
|
||||||
|
vk->translate_x/(float)vk->vp.width,
|
||||||
|
vk->translate_y/(float)vk->vp.height,
|
||||||
|
0.0f,
|
||||||
|
1.0f }
|
||||||
|
};
|
||||||
|
math_matrix_4x4 tmp = {
|
||||||
|
{ 1.0f, 0.0f, 0.0f, 0.0f ,
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f ,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f ,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f }
|
||||||
|
};
|
||||||
|
|
||||||
/* Calculate projection. */
|
/* Calculate projection. */
|
||||||
matrix_4x4_ortho(vk->mvp_no_rot, ortho->left, ortho->right,
|
matrix_4x4_ortho(vk->mvp_no_rot, ortho->left, ortho->right,
|
||||||
ortho->bottom, ortho->top, ortho->znear, ortho->zfar);
|
ortho->bottom, ortho->top, ortho->znear, ortho->zfar);
|
||||||
|
|
||||||
if (!allow_rotate)
|
if (!allow_rotate)
|
||||||
|
tmp = vk->mvp_no_rot;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
vk->mvp = vk->mvp_no_rot;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
radians = M_PI * vk->rotation / 180.0f;
|
radians = M_PI * vk->rotation / 180.0f;
|
||||||
cosine = cosf(radians);
|
cosine = cosf(radians);
|
||||||
sine = sinf(radians);
|
sine = sinf(radians);
|
||||||
|
@ -3780,7 +3795,9 @@ static void vulkan_set_projection(vk_t *vk,
|
||||||
MAT_ELEM_4X4(rot, 0, 1) = -sine;
|
MAT_ELEM_4X4(rot, 0, 1) = -sine;
|
||||||
MAT_ELEM_4X4(rot, 1, 0) = sine;
|
MAT_ELEM_4X4(rot, 1, 0) = sine;
|
||||||
MAT_ELEM_4X4(rot, 1, 1) = cosine;
|
MAT_ELEM_4X4(rot, 1, 1) = cosine;
|
||||||
matrix_4x4_multiply(vk->mvp, rot, vk->mvp_no_rot);
|
matrix_4x4_multiply(tmp, rot, vk->mvp_no_rot);
|
||||||
|
}
|
||||||
|
matrix_4x4_multiply(vk->mvp, trn, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vulkan_set_rotation(void *data, unsigned rotation)
|
static void vulkan_set_rotation(void *data, unsigned rotation)
|
||||||
|
@ -3827,8 +3844,6 @@ static void vulkan_set_viewport(void *data, unsigned viewport_width,
|
||||||
video_driver_get_aspect_ratio(),
|
video_driver_get_aspect_ratio(),
|
||||||
vk->flags & VK_FLAG_KEEP_ASPECT,
|
vk->flags & VK_FLAG_KEEP_ASPECT,
|
||||||
true);
|
true);
|
||||||
vk->vp.x = MAX(vk->vp.x, 0);
|
|
||||||
vk->vp.y = MAX(vk->vp.y, 0);
|
|
||||||
viewport_width = vk->vp.width;
|
viewport_width = vk->vp.width;
|
||||||
viewport_height = vk->vp.height;
|
viewport_height = vk->vp.height;
|
||||||
}
|
}
|
||||||
|
@ -3846,6 +3861,21 @@ static void vulkan_set_viewport(void *data, unsigned viewport_width,
|
||||||
vk->vp.height = viewport_height;
|
vk->vp.height = viewport_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vk->vp.x < 0)
|
||||||
|
{
|
||||||
|
vk->translate_x = (float)vk->vp.x;
|
||||||
|
vk->vp.x = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vk->translate_x = 0.0;
|
||||||
|
if (vk->vp.y < 0)
|
||||||
|
{
|
||||||
|
vk->translate_y = (float)vk->vp.y;
|
||||||
|
vk->vp.y = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vk->translate_y = 0.0;
|
||||||
|
|
||||||
vulkan_set_projection(vk, &ortho, allow_rotate);
|
vulkan_set_projection(vk, &ortho, allow_rotate);
|
||||||
|
|
||||||
/* Set last backbuffer viewport. */
|
/* Set last backbuffer viewport. */
|
||||||
|
|
Loading…
Reference in New Issue