renderer_vulkan: Surface fills and dual screen rendering working
This commit is contained in:
@ -39,6 +39,8 @@ struct Rectangle {
|
|||||||
return Rectangle{left, top, static_cast<T>(left + GetWidth() * s),
|
return Rectangle{left, top, static_cast<T>(left + GetWidth() * s),
|
||||||
static_cast<T>(top + GetHeight() * s)};
|
static_cast<T>(top + GetHeight() * s)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto operator <=> (const Rectangle<T>& other) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -280,7 +280,7 @@ void RendererVulkan::CreateVulkanObjects() {
|
|||||||
|
|
||||||
// Generate VBO handle for drawing
|
// Generate VBO handle for drawing
|
||||||
VKBuffer::Info vertex_info{
|
VKBuffer::Info vertex_info{
|
||||||
.size = sizeof(ScreenRectVertex) * 4,
|
.size = sizeof(ScreenRectVertex) * 10,
|
||||||
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
.properties = vk::MemoryPropertyFlagBits::eDeviceLocal,
|
||||||
.usage = vk::BufferUsageFlagBits::eVertexBuffer |
|
.usage = vk::BufferUsageFlagBits::eVertexBuffer |
|
||||||
vk::BufferUsageFlagBits::eTransferDst
|
vk::BufferUsageFlagBits::eTransferDst
|
||||||
@ -340,19 +340,23 @@ void RendererVulkan::ConfigureFramebufferTexture(ScreenInfo& screen, const GPU::
|
|||||||
* Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's LCD
|
* Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's LCD
|
||||||
* rotation.
|
* rotation.
|
||||||
*/
|
*/
|
||||||
void RendererVulkan::DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y,
|
void RendererVulkan::DrawSingleScreenRotated(u32 screen_id, float x, float y, float w, float h) {
|
||||||
float w, float h) {
|
auto& screen_info = screen_infos[screen_id];
|
||||||
const auto& texcoords = screen_info.display_texcoords;
|
const auto& texcoords = screen_info.display_texcoords;
|
||||||
|
|
||||||
|
u32 size = sizeof(ScreenRectVertex) * 4;
|
||||||
|
auto [ptr, offset, invalidate] = vertex_buffer.Map(size);
|
||||||
|
|
||||||
const std::array vertices{
|
const std::array vertices{
|
||||||
ScreenRectVertex(x, y, texcoords.bottom, texcoords.left),
|
ScreenRectVertex(x, y, texcoords.bottom, texcoords.left, screen_id),
|
||||||
ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.right),
|
ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.right, screen_id),
|
||||||
ScreenRectVertex(x, y + h, texcoords.top, texcoords.left),
|
ScreenRectVertex(x, y + h, texcoords.top, texcoords.left, screen_id),
|
||||||
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.right),
|
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.right, screen_id),
|
||||||
};
|
};
|
||||||
|
|
||||||
auto data = std::as_bytes(std::span(vertices));
|
std::memcpy(ptr, vertices.data(), size);
|
||||||
vertex_buffer.Upload(data, 0);
|
vertex_buffer.Commit(size, vk::AccessFlagBits::eVertexAttributeRead,
|
||||||
|
vk::PipelineStageFlagBits::eVertexInput);
|
||||||
|
|
||||||
// As this is the "DrawSingleScreenRotated" function, the output resolution dimensions have been
|
// As this is the "DrawSingleScreenRotated" function, the output resolution dimensions have been
|
||||||
// swapped. If a non-rotated draw-screen function were to be added for book-mode games, those
|
// swapped. If a non-rotated draw-screen function were to be added for book-mode games, those
|
||||||
@ -365,34 +369,32 @@ void RendererVulkan::DrawSingleScreenRotated(const ScreenInfo& screen_info, floa
|
|||||||
1.0f / (height * scale_factor)};
|
1.0f / (height * scale_factor)};
|
||||||
draw_info.o_resolution = glm::vec4{h, w, 1.0f / h, 1.0f / w};
|
draw_info.o_resolution = glm::vec4{h, w, 1.0f / h, 1.0f / w};
|
||||||
|
|
||||||
auto& image = swapchain->GetCurrentImage();
|
|
||||||
auto& state = VulkanState::Get();
|
auto& state = VulkanState::Get();
|
||||||
|
|
||||||
state.BeginRendering(image, std::nullopt, false, clear_color, vk::AttachmentLoadOp::eClear);
|
|
||||||
state.SetPresentData(draw_info);
|
state.SetPresentData(draw_info);
|
||||||
state.SetPresentTexture(*screen_info.display_texture);
|
|
||||||
state.ApplyPresentState();
|
|
||||||
|
|
||||||
auto cmdbuffer = g_vk_task_scheduler->GetRenderCommandBuffer();
|
auto cmdbuffer = g_vk_task_scheduler->GetRenderCommandBuffer();
|
||||||
vk::DeviceSize offset = 0;
|
|
||||||
|
|
||||||
cmdbuffer.bindVertexBuffers(0, 1, &vertex_buffer.GetBuffer(), &offset);
|
cmdbuffer.bindVertexBuffers(0, vertex_buffer.GetBuffer(), {0});
|
||||||
cmdbuffer.draw(4, 1, 0, 0);
|
cmdbuffer.draw(4, 1, offset / sizeof(ScreenRectVertex), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w,
|
void RendererVulkan::DrawSingleScreen(u32 screen_id, float x, float y, float w, float h) {
|
||||||
float h) {
|
auto& screen_info = screen_infos[screen_id];
|
||||||
const auto& texcoords = screen_info.display_texcoords;
|
const auto& texcoords = screen_info.display_texcoords;
|
||||||
|
|
||||||
|
u32 size = sizeof(ScreenRectVertex) * 4;
|
||||||
|
auto [ptr, offset, invalidate] = vertex_buffer.Map(size);
|
||||||
|
|
||||||
const std::array vertices{
|
const std::array vertices{
|
||||||
ScreenRectVertex(x, y, texcoords.bottom, texcoords.right),
|
ScreenRectVertex(x, y, texcoords.bottom, texcoords.right, screen_id),
|
||||||
ScreenRectVertex(x + w, y, texcoords.top, texcoords.right),
|
ScreenRectVertex(x + w, y, texcoords.top, texcoords.right, screen_id),
|
||||||
ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.left),
|
ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.left, screen_id),
|
||||||
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left),
|
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left, screen_id),
|
||||||
};
|
};
|
||||||
|
|
||||||
auto data = std::as_bytes(std::span(vertices));
|
std::memcpy(ptr, vertices.data(), size);
|
||||||
vertex_buffer.Upload(data, 0);
|
vertex_buffer.Commit(size, vk::AccessFlagBits::eVertexAttributeRead,
|
||||||
|
vk::PipelineStageFlagBits::eVertexInput);
|
||||||
|
|
||||||
const u16 scale_factor = VideoCore::GetResolutionScaleFactor();
|
const u16 scale_factor = VideoCore::GetResolutionScaleFactor();
|
||||||
auto [width, height] = screen_info.texture.GetArea().extent;
|
auto [width, height] = screen_info.texture.GetArea().extent;
|
||||||
@ -403,17 +405,13 @@ void RendererVulkan::DrawSingleScreen(const ScreenInfo& screen_info, float x, fl
|
|||||||
1.0f / (height * scale_factor)};
|
1.0f / (height * scale_factor)};
|
||||||
draw_info.o_resolution = glm::vec4{h, w, 1.0f / h, 1.0f / w};
|
draw_info.o_resolution = glm::vec4{h, w, 1.0f / h, 1.0f / w};
|
||||||
|
|
||||||
auto& image = swapchain->GetCurrentImage();
|
|
||||||
auto& state = VulkanState::Get();
|
auto& state = VulkanState::Get();
|
||||||
|
|
||||||
state.BeginRendering(image, std::nullopt, false, clear_color, vk::AttachmentLoadOp::eClear);
|
|
||||||
state.SetPresentData(draw_info);
|
state.SetPresentData(draw_info);
|
||||||
state.SetPresentTexture(*screen_info.display_texture);
|
|
||||||
state.ApplyPresentState();
|
|
||||||
|
|
||||||
auto cmdbuffer = g_vk_task_scheduler->GetRenderCommandBuffer();
|
auto cmdbuffer = g_vk_task_scheduler->GetRenderCommandBuffer();
|
||||||
|
|
||||||
cmdbuffer.bindVertexBuffers(0, vertex_buffer.GetBuffer(), {0});
|
cmdbuffer.bindVertexBuffers(0, vertex_buffer.GetBuffer(), {0});
|
||||||
cmdbuffer.draw(4, 1, 0, 0);
|
cmdbuffer.draw(4, 1, offset / sizeof(ScreenRectVertex), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -423,7 +421,8 @@ void RendererVulkan::DrawSingleScreen(const ScreenInfo& screen_info, float x, fl
|
|||||||
void RendererVulkan::DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,
|
void RendererVulkan::DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,
|
||||||
const ScreenInfo& screen_info_r, float x,
|
const ScreenInfo& screen_info_r, float x,
|
||||||
float y, float w, float h) {
|
float y, float w, float h) {
|
||||||
DrawSingleScreenRotated(screen_info_l, x, y, w, h);
|
ASSERT(false);
|
||||||
|
//DrawSingleScreenRotated(screen_info_l, x, y, w, h);
|
||||||
/*const auto& texcoords = screen_info_l.display_texcoords;
|
/*const auto& texcoords = screen_info_l.display_texcoords;
|
||||||
|
|
||||||
const std::array<ScreenRectVertex, 4> vertices = {{
|
const std::array<ScreenRectVertex, 4> vertices = {{
|
||||||
@ -460,7 +459,8 @@ void RendererVulkan::DrawSingleScreenStereoRotated(const ScreenInfo& screen_info
|
|||||||
void RendererVulkan::DrawSingleScreenStereo(const ScreenInfo& screen_info_l,
|
void RendererVulkan::DrawSingleScreenStereo(const ScreenInfo& screen_info_l,
|
||||||
const ScreenInfo& screen_info_r, float x, float y,
|
const ScreenInfo& screen_info_r, float x, float y,
|
||||||
float w, float h) {
|
float w, float h) {
|
||||||
DrawSingleScreen(screen_info_l, x, y, w, h);
|
ASSERT(false);
|
||||||
|
//DrawSingleScreen(screen_info_l, x, y, w, h);
|
||||||
/*const auto& texcoords = screen_info_l.display_texcoords;
|
/*const auto& texcoords = screen_info_l.display_texcoords;
|
||||||
|
|
||||||
const std::array<ScreenRectVertex, 4> vertices = {{
|
const std::array<ScreenRectVertex, 4> vertices = {{
|
||||||
@ -518,8 +518,9 @@ void RendererVulkan::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
|||||||
const auto& bottom_screen = layout.bottom_screen;
|
const auto& bottom_screen = layout.bottom_screen;
|
||||||
|
|
||||||
// Set projection matrix
|
// Set projection matrix
|
||||||
draw_info.modelview = MakeOrthographicMatrix((float)layout.width, (float)layout.height, flipped);
|
draw_info.modelview = glm::transpose(glm::ortho(0.f, static_cast<float>(layout.width),
|
||||||
|
static_cast<float>(layout.height), 0.0f,
|
||||||
|
0.f, 1.f));
|
||||||
const bool stereo_single_screen = false
|
const bool stereo_single_screen = false
|
||||||
/* Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph ||
|
/* Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph ||
|
||||||
Settings::values.render_3d == Settings::StereoRenderOption::Interlaced ||
|
Settings::values.render_3d == Settings::StereoRenderOption::Interlaced ||
|
||||||
@ -530,28 +531,37 @@ void RendererVulkan::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
|||||||
//glUniform1i(uniform_color_texture_r, 1);
|
//glUniform1i(uniform_color_texture_r, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& image = swapchain->GetCurrentImage();
|
||||||
|
auto& state = VulkanState::Get();
|
||||||
|
|
||||||
|
state.BeginRendering(image, std::nullopt, false, clear_color, vk::AttachmentLoadOp::eClear);
|
||||||
|
state.SetPresentTextures(screen_infos[0].display_texture->GetView(),
|
||||||
|
screen_infos[1].display_texture->GetView(),
|
||||||
|
screen_infos[2].display_texture->GetView());
|
||||||
|
state.ApplyPresentState();
|
||||||
|
|
||||||
draw_info.layer = 0;
|
draw_info.layer = 0;
|
||||||
if (layout.top_screen_enabled) {
|
if (layout.top_screen_enabled) {
|
||||||
if (layout.is_rotated) {
|
if (layout.is_rotated) {
|
||||||
if (Settings::values.render_3d == Settings::StereoRenderOption::Off) {
|
if (Settings::values.render_3d == Settings::StereoRenderOption::Off) {
|
||||||
DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left,
|
DrawSingleScreenRotated(0, top_screen.left,
|
||||||
(float)top_screen.top, (float)top_screen.GetWidth(),
|
top_screen.top, top_screen.GetWidth(),
|
||||||
(float)top_screen.GetHeight());
|
top_screen.GetHeight());
|
||||||
} else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) {
|
} else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) {
|
||||||
DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2,
|
DrawSingleScreenRotated(0, (float)top_screen.left / 2,
|
||||||
(float)top_screen.top, (float)top_screen.GetWidth() / 2,
|
(float)top_screen.top, (float)top_screen.GetWidth() / 2,
|
||||||
(float)top_screen.GetHeight());
|
(float)top_screen.GetHeight());
|
||||||
draw_info.layer = 1;
|
draw_info.layer = 1;
|
||||||
DrawSingleScreenRotated(screen_infos[1],
|
DrawSingleScreenRotated(1,
|
||||||
((float)top_screen.left / 2) + ((float)layout.width / 2),
|
((float)top_screen.left / 2) + ((float)layout.width / 2),
|
||||||
(float)top_screen.top, (float)top_screen.GetWidth() / 2,
|
(float)top_screen.top, (float)top_screen.GetWidth() / 2,
|
||||||
(float)top_screen.GetHeight());
|
(float)top_screen.GetHeight());
|
||||||
} else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) {
|
} else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) {
|
||||||
DrawSingleScreenRotated(screen_infos[0], layout.top_screen.left,
|
DrawSingleScreenRotated(0, layout.top_screen.left,
|
||||||
layout.top_screen.top, layout.top_screen.GetWidth(),
|
layout.top_screen.top, layout.top_screen.GetWidth(),
|
||||||
layout.top_screen.GetHeight());
|
layout.top_screen.GetHeight());
|
||||||
draw_info.layer = 1;
|
draw_info.layer = 1;
|
||||||
DrawSingleScreenRotated(screen_infos[1],
|
DrawSingleScreenRotated(1,
|
||||||
layout.cardboard.top_screen_right_eye +
|
layout.cardboard.top_screen_right_eye +
|
||||||
((float)layout.width / 2),
|
((float)layout.width / 2),
|
||||||
layout.top_screen.top, layout.top_screen.GetWidth(),
|
layout.top_screen.top, layout.top_screen.GetWidth(),
|
||||||
@ -563,21 +573,21 @@ void RendererVulkan::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Settings::values.render_3d == Settings::StereoRenderOption::Off) {
|
if (Settings::values.render_3d == Settings::StereoRenderOption::Off) {
|
||||||
DrawSingleScreen(screen_infos[0], (float)top_screen.left, (float)top_screen.top,
|
DrawSingleScreen(0, (float)top_screen.left, (float)top_screen.top,
|
||||||
(float)top_screen.GetWidth(), (float)top_screen.GetHeight());
|
(float)top_screen.GetWidth(), (float)top_screen.GetHeight());
|
||||||
} else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) {
|
} else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) {
|
||||||
DrawSingleScreen(screen_infos[0], (float)top_screen.left / 2, (float)top_screen.top,
|
DrawSingleScreen(0, (float)top_screen.left / 2, (float)top_screen.top,
|
||||||
(float)top_screen.GetWidth() / 2, (float)top_screen.GetHeight());
|
(float)top_screen.GetWidth() / 2, (float)top_screen.GetHeight());
|
||||||
draw_info.layer = 1;
|
draw_info.layer = 1;
|
||||||
DrawSingleScreen(screen_infos[1],
|
DrawSingleScreen(1,
|
||||||
((float)top_screen.left / 2) + ((float)layout.width / 2),
|
((float)top_screen.left / 2) + ((float)layout.width / 2),
|
||||||
(float)top_screen.top, (float)top_screen.GetWidth() / 2,
|
(float)top_screen.top, (float)top_screen.GetWidth() / 2,
|
||||||
(float)top_screen.GetHeight());
|
(float)top_screen.GetHeight());
|
||||||
} else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) {
|
} else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) {
|
||||||
DrawSingleScreen(screen_infos[0], layout.top_screen.left, layout.top_screen.top,
|
DrawSingleScreen(0, layout.top_screen.left, layout.top_screen.top,
|
||||||
layout.top_screen.GetWidth(), layout.top_screen.GetHeight());
|
layout.top_screen.GetWidth(), layout.top_screen.GetHeight());
|
||||||
draw_info.layer = 1;
|
draw_info.layer = 1;
|
||||||
DrawSingleScreen(screen_infos[1],
|
DrawSingleScreen(1,
|
||||||
layout.cardboard.top_screen_right_eye + ((float)layout.width / 2),
|
layout.cardboard.top_screen_right_eye + ((float)layout.width / 2),
|
||||||
layout.top_screen.top, layout.top_screen.GetWidth(),
|
layout.top_screen.top, layout.top_screen.GetWidth(),
|
||||||
layout.top_screen.GetHeight());
|
layout.top_screen.GetHeight());
|
||||||
@ -588,28 +598,29 @@ void RendererVulkan::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_info.layer = 0;
|
draw_info.layer = 0;
|
||||||
if (/*layout.bottom_screen_enabled*/false) {
|
if (layout.bottom_screen_enabled) {
|
||||||
if (layout.is_rotated) {
|
if (layout.is_rotated) {
|
||||||
if (Settings::values.render_3d == Settings::StereoRenderOption::Off) {
|
if (Settings::values.render_3d == Settings::StereoRenderOption::Off) {
|
||||||
DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left,
|
DrawSingleScreenRotated(2, (float)bottom_screen.left,
|
||||||
(float)bottom_screen.top, (float)bottom_screen.GetWidth(),
|
(float)bottom_screen.top, (float)bottom_screen.GetWidth(),
|
||||||
(float)bottom_screen.GetHeight());
|
(float)bottom_screen.GetHeight());
|
||||||
} else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) {
|
} else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) {
|
||||||
DrawSingleScreenRotated(
|
DrawSingleScreenRotated(
|
||||||
screen_infos[2], (float)bottom_screen.left / 2, (float)bottom_screen.top,
|
2, (float)bottom_screen.left / 2, (float)bottom_screen.top,
|
||||||
(float)bottom_screen.GetWidth() / 2, (float)bottom_screen.GetHeight());
|
(float)bottom_screen.GetWidth() / 2, (float)bottom_screen.GetHeight());
|
||||||
draw_info.layer = 1;
|
draw_info.layer = 1;
|
||||||
DrawSingleScreenRotated(
|
DrawSingleScreenRotated(
|
||||||
screen_infos[2], ((float)bottom_screen.left / 2) + ((float)layout.width / 2),
|
2, ((float)bottom_screen.left / 2) + ((float)layout.width / 2),
|
||||||
(float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
|
(float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
|
||||||
(float)bottom_screen.GetHeight());
|
(float)bottom_screen.GetHeight());
|
||||||
} else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) {
|
} else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) {
|
||||||
DrawSingleScreenRotated(screen_infos[2], layout.bottom_screen.left,
|
DrawSingleScreenRotated(2, layout.bottom_screen.left,
|
||||||
layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
|
layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
|
||||||
layout.bottom_screen.GetHeight());
|
layout.bottom_screen.GetHeight());
|
||||||
draw_info.layer = 1;
|
draw_info.layer = 1;
|
||||||
DrawSingleScreenRotated(screen_infos[2],
|
DrawSingleScreenRotated(2,
|
||||||
layout.cardboard.bottom_screen_right_eye +
|
layout.cardboard.bottom_screen_right_eye +
|
||||||
((float)layout.width / 2),
|
((float)layout.width / 2),
|
||||||
layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
|
layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
|
||||||
@ -622,24 +633,24 @@ void RendererVulkan::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Settings::values.render_3d == Settings::StereoRenderOption::Off) {
|
if (Settings::values.render_3d == Settings::StereoRenderOption::Off) {
|
||||||
DrawSingleScreen(screen_infos[2], (float)bottom_screen.left,
|
DrawSingleScreen(2, (float)bottom_screen.left,
|
||||||
(float)bottom_screen.top, (float)bottom_screen.GetWidth(),
|
(float)bottom_screen.top, (float)bottom_screen.GetWidth(),
|
||||||
(float)bottom_screen.GetHeight());
|
(float)bottom_screen.GetHeight());
|
||||||
} else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) {
|
} else if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) {
|
||||||
DrawSingleScreen(screen_infos[2], (float)bottom_screen.left / 2,
|
DrawSingleScreen(2, (float)bottom_screen.left / 2,
|
||||||
(float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
|
(float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
|
||||||
(float)bottom_screen.GetHeight());
|
(float)bottom_screen.GetHeight());
|
||||||
draw_info.layer = 1;
|
draw_info.layer = 1;
|
||||||
DrawSingleScreen(screen_infos[2],
|
DrawSingleScreen(2,
|
||||||
((float)bottom_screen.left / 2) + ((float)layout.width / 2),
|
((float)bottom_screen.left / 2) + ((float)layout.width / 2),
|
||||||
(float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
|
(float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
|
||||||
(float)bottom_screen.GetHeight());
|
(float)bottom_screen.GetHeight());
|
||||||
} else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) {
|
} else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) {
|
||||||
DrawSingleScreen(screen_infos[2], layout.bottom_screen.left,
|
DrawSingleScreen(2, layout.bottom_screen.left,
|
||||||
layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
|
layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
|
||||||
layout.bottom_screen.GetHeight());
|
layout.bottom_screen.GetHeight());
|
||||||
draw_info.layer = 1;
|
draw_info.layer = 1;
|
||||||
DrawSingleScreen(screen_infos[2],
|
DrawSingleScreen(2,
|
||||||
layout.cardboard.bottom_screen_right_eye +
|
layout.cardboard.bottom_screen_right_eye +
|
||||||
((float)layout.width / 2),
|
((float)layout.width / 2),
|
||||||
layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
|
layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
|
||||||
|
@ -52,8 +52,8 @@ private:
|
|||||||
void ConfigureFramebufferTexture(ScreenInfo& screen, const GPU::Regs::FramebufferConfig& framebuffer);
|
void ConfigureFramebufferTexture(ScreenInfo& screen, const GPU::Regs::FramebufferConfig& framebuffer);
|
||||||
|
|
||||||
void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped);
|
void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped);
|
||||||
void DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y, float w, float h);
|
void DrawSingleScreenRotated(u32 screen_id, float x, float y, float w, float h);
|
||||||
void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h);
|
void DrawSingleScreen(u32 screen_id, float x, float y, float w, float h);
|
||||||
void DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,
|
void DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,
|
||||||
const ScreenInfo& screen_info_r, float x, float y, float w, float h);
|
const ScreenInfo& screen_info_r, float x, float y, float w, float h);
|
||||||
void DrawSingleScreenStereo(const ScreenInfo& screen_info_l, const ScreenInfo& screen_info_r,
|
void DrawSingleScreenStereo(const ScreenInfo& screen_info_l, const ScreenInfo& screen_info_r,
|
||||||
@ -70,7 +70,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
// Vulkan state
|
// Vulkan state
|
||||||
DrawInfo draw_info{};
|
DrawInfo draw_info{};
|
||||||
VKBuffer vertex_buffer;
|
StreamBuffer vertex_buffer;
|
||||||
vk::ClearColorValue clear_color{};
|
vk::ClearColorValue clear_color{};
|
||||||
|
|
||||||
/// Display information for top and bottom screens respectively
|
/// Display information for top and bottom screens respectively
|
||||||
|
@ -133,7 +133,7 @@ std::tuple<u8*, u32, bool> StreamBuffer::Map(u32 size, u32 alignment) {
|
|||||||
auto [staging_ptr, staging_offset] = g_vk_task_scheduler->RequestStaging(size);
|
auto [staging_ptr, staging_offset] = g_vk_task_scheduler->RequestStaging(size);
|
||||||
mapped_chunk = vk::BufferCopy{staging_offset, buffer_pos, size};
|
mapped_chunk = vk::BufferCopy{staging_offset, buffer_pos, size};
|
||||||
|
|
||||||
return std::make_tuple(staging_ptr + buffer_pos, buffer_pos, invalidate);
|
return std::make_tuple(staging_ptr, buffer_pos, invalidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamBuffer::Commit(u32 size, vk::AccessFlags access_to_block,
|
void StreamBuffer::Commit(u32 size, vk::AccessFlags access_to_block,
|
||||||
@ -148,7 +148,7 @@ void StreamBuffer::Commit(u32 size, vk::AccessFlags access_to_block,
|
|||||||
vk::BufferMemoryBarrier barrier{
|
vk::BufferMemoryBarrier barrier{
|
||||||
vk::AccessFlagBits::eTransferWrite, access_to_block,
|
vk::AccessFlagBits::eTransferWrite, access_to_block,
|
||||||
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
|
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
|
||||||
buffer, mapped_chunk.srcOffset, mapped_chunk.size
|
buffer, mapped_chunk.dstOffset, mapped_chunk.size
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add a pipeline barrier for the region modified
|
// Add a pipeline barrier for the region modified
|
||||||
@ -158,9 +158,6 @@ void StreamBuffer::Commit(u32 size, vk::AccessFlags access_to_block,
|
|||||||
|
|
||||||
buffer_pos += size;
|
buffer_pos += size;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
printf("f");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -288,6 +288,55 @@ static bool BlitTextures(const Surface& src_surface, const Common::Rectangle<u32
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool FillSurface(const Surface& surface, std::array<u8, 4> fill_buffer,
|
||||||
|
Common::Rectangle<u32> rect) {
|
||||||
|
if (surface->GetScaledRect() != rect) {
|
||||||
|
// TODO: use vkCmdClearAttachments to clear subrects
|
||||||
|
LOG_ERROR(Render_Vulkan, "Partial surface fills not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::ImageSubresourceRange image_range{{}, 0, 1, 0, 1};
|
||||||
|
switch (surface->type) {
|
||||||
|
case SurfaceParams::SurfaceType::Color:
|
||||||
|
case SurfaceParams::SurfaceType::Texture:
|
||||||
|
image_range.aspectMask = vk::ImageAspectFlagBits::eColor;
|
||||||
|
break;
|
||||||
|
case SurfaceParams::SurfaceType::Depth:
|
||||||
|
image_range.aspectMask = vk::ImageAspectFlagBits::eDepth;
|
||||||
|
break;
|
||||||
|
case SurfaceParams::SurfaceType::DepthStencil:
|
||||||
|
image_range.aspectMask =
|
||||||
|
vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cmdbuffer = g_vk_task_scheduler->GetRenderCommandBuffer();
|
||||||
|
switch (surface->type) {
|
||||||
|
case SurfaceParams::SurfaceType::Color:
|
||||||
|
case SurfaceParams::SurfaceType::Texture: {
|
||||||
|
Pica::Texture::TextureInfo tex_info{};
|
||||||
|
tex_info.format = static_cast<Pica::TexturingRegs::TextureFormat>(surface->pixel_format);
|
||||||
|
|
||||||
|
auto color_vec = Pica::Texture::LookupTexture(fill_buffer.data(), 0, 0, tex_info) / 255.0f;
|
||||||
|
const std::array color{color_vec.x, color_vec.y, color_vec.z, color_vec.w};
|
||||||
|
|
||||||
|
auto& texture = surface->texture;
|
||||||
|
texture.Transition(cmdbuffer, vk::ImageLayout::eTransferDstOptimal);
|
||||||
|
|
||||||
|
cmdbuffer.clearColorImage(texture.GetHandle(), vk::ImageLayout::eTransferDstOptimal,
|
||||||
|
color, image_range);
|
||||||
|
|
||||||
|
texture.Transition(cmdbuffer, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
LOG_ERROR(Render_Vulkan, "non-color fills not implemented");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static vk::Rect2D FromRect(Common::Rectangle<u32> rect) {
|
static vk::Rect2D FromRect(Common::Rectangle<u32> rect) {
|
||||||
vk::Offset2D offset{static_cast<s32>(rect.left), static_cast<s32>(rect.bottom)};
|
vk::Offset2D offset{static_cast<s32>(rect.left), static_cast<s32>(rect.bottom)};
|
||||||
vk::Extent2D extent{rect.GetWidth(), rect.GetHeight()};
|
vk::Extent2D extent{rect.GetWidth(), rect.GetHeight()};
|
||||||
@ -412,7 +461,16 @@ void RasterizerCacheVulkan::CopySurface(const Surface& src_surface, const Surfac
|
|||||||
|
|
||||||
// This is only called when CanCopy is true, no need to run checks here
|
// This is only called when CanCopy is true, no need to run checks here
|
||||||
if (src_surface->type == SurfaceType::Fill) {
|
if (src_surface->type == SurfaceType::Fill) {
|
||||||
// NO-OP Vulkan does not allow easy clearing for arbitary textures with rectangle
|
// FillSurface needs a 4 bytes buffer
|
||||||
|
const u32 fill_offset =
|
||||||
|
(boost::icl::first(copy_interval) - src_surface->addr) % src_surface->fill_size;
|
||||||
|
std::array<u8, 4> fill_buffer;
|
||||||
|
|
||||||
|
u32 fill_buff_pos = fill_offset;
|
||||||
|
for (int i : {0, 1, 2, 3})
|
||||||
|
fill_buffer[i] = src_surface->fill_data[fill_buff_pos++ % src_surface->fill_size];
|
||||||
|
|
||||||
|
FillSurface(dst_surface, fill_buffer, dst_surface->GetScaledSubRect(subrect_params));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (src_surface->CanSubRect(subrect_params)) {
|
if (src_surface->CanSubRect(subrect_params)) {
|
||||||
|
@ -33,37 +33,30 @@ using VSOutputAttributes = RasterizerRegs::VSOutputAttributes;
|
|||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
static const char present_vertex_shader_source[] = R"(
|
static const char present_vertex_shader_source[] = R"(
|
||||||
#version 450
|
#version 450 core
|
||||||
#extension GL_ARB_separate_shader_objects : enable
|
#extension GL_ARB_separate_shader_objects : enable
|
||||||
layout (location = 0) in vec2 vert_position;
|
layout (location = 0) in vec2 vert_position;
|
||||||
layout (location = 1) in vec2 vert_tex_coord;
|
layout (location = 1) in vec3 vert_tex_coord;
|
||||||
layout (location = 0) out vec2 frag_tex_coord;
|
layout (location = 0) out vec3 frag_tex_coord;
|
||||||
|
|
||||||
// This is a truncated 3x3 matrix for 2D transformations:
|
|
||||||
// The upper-left 2x2 submatrix performs scaling/rotation/mirroring.
|
|
||||||
// The third column performs translation.
|
|
||||||
// The third row could be used for projection, which we don't need in 2D. It hence is assumed to
|
|
||||||
// implicitly be [0, 0, 1]
|
|
||||||
layout (push_constant) uniform DrawInfo {
|
layout (push_constant) uniform DrawInfo {
|
||||||
mat3x2 modelview_matrix;
|
mat4 modelview_matrix;
|
||||||
vec4 i_resolution;
|
vec4 i_resolution;
|
||||||
vec4 o_resolution;
|
vec4 o_resolution;
|
||||||
int layer;
|
int layer;
|
||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Multiply input position by the rotscale part of the matrix and then manually translate by
|
vec4 position = vec4(vert_position, 0.0, 1.0) * modelview_matrix;
|
||||||
// the last column. This is equivalent to using a full 3x3 matrix and expanding the vector
|
gl_Position = vec4(position.x, -position.y, 0.0, 1.0);
|
||||||
// to `vec3(vert_position.xy, 1.0)`
|
|
||||||
gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0);
|
|
||||||
frag_tex_coord = vert_tex_coord;
|
frag_tex_coord = vert_tex_coord;
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
static const char present_fragment_shader_source[] = R"(
|
static const char present_fragment_shader_source[] = R"(
|
||||||
#version 450
|
#version 450 core
|
||||||
#extension GL_ARB_separate_shader_objects : enable
|
#extension GL_ARB_separate_shader_objects : enable
|
||||||
layout (location = 0) in vec2 frag_tex_coord;
|
layout (location = 0) in vec3 frag_tex_coord;
|
||||||
layout (location = 0) out vec4 color;
|
layout (location = 0) out vec4 color;
|
||||||
|
|
||||||
layout (push_constant) uniform DrawInfo {
|
layout (push_constant) uniform DrawInfo {
|
||||||
@ -73,10 +66,11 @@ layout (push_constant) uniform DrawInfo {
|
|||||||
int layer;
|
int layer;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout (set = 0, binding = 0) uniform sampler2D color_texture;
|
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
color = texture(color_texture, frag_tex_coord);
|
color = texture(screen_textures[int(frag_tex_coord.z)], frag_tex_coord.xy);
|
||||||
|
//color = vec4(0.5, 0.0, 0.5, 1.0);
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
|
@ -84,25 +84,26 @@ struct HardwareVertex : public VertexBase {
|
|||||||
|
|
||||||
struct ScreenRectVertexBase {
|
struct ScreenRectVertexBase {
|
||||||
ScreenRectVertexBase() = default;
|
ScreenRectVertexBase() = default;
|
||||||
ScreenRectVertexBase(float x, float y, float u, float v) {
|
ScreenRectVertexBase(float x, float y, float u, float v, float s) {
|
||||||
position.x = x;
|
position.x = x;
|
||||||
position.y = y;
|
position.y = y;
|
||||||
tex_coord.x = u;
|
tex_coord.x = u;
|
||||||
tex_coord.y = v;
|
tex_coord.y = v;
|
||||||
|
tex_coord.z = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec2 position;
|
glm::vec2 position;
|
||||||
glm::vec2 tex_coord;
|
glm::vec3 tex_coord;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScreenRectVertex : public ScreenRectVertexBase {
|
struct ScreenRectVertex : public ScreenRectVertexBase {
|
||||||
ScreenRectVertex() = default;
|
ScreenRectVertex() = default;
|
||||||
ScreenRectVertex(float x, float y, float u, float v) : ScreenRectVertexBase(x, y, u, v) {};
|
ScreenRectVertex(float x, float y, float u, float v, float s) : ScreenRectVertexBase(x, y, u, v, s) {};
|
||||||
static constexpr auto binding_desc = vk::VertexInputBindingDescription(0, sizeof(ScreenRectVertexBase));
|
static constexpr auto binding_desc = vk::VertexInputBindingDescription(0, sizeof(ScreenRectVertexBase));
|
||||||
static constexpr std::array<vk::VertexInputAttributeDescription, 2> attribute_desc =
|
static constexpr std::array<vk::VertexInputAttributeDescription, 2> attribute_desc =
|
||||||
{
|
{
|
||||||
vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32Sfloat, offsetof(ScreenRectVertexBase, position)),
|
vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32Sfloat, offsetof(ScreenRectVertexBase, position)),
|
||||||
vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32Sfloat, offsetof(ScreenRectVertexBase, tex_coord)),
|
vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32Sfloat, offsetof(ScreenRectVertexBase, tex_coord)),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,43 +25,56 @@ auto IsStencil = [](vk::Format format) -> bool {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void DescriptorUpdater::Reset() {
|
||||||
|
write_count = 0;
|
||||||
|
buffer_count = 0;
|
||||||
|
image_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void DescriptorUpdater::Update() {
|
void DescriptorUpdater::Update() {
|
||||||
assert(update_count > 0);
|
assert(write_count > 0);
|
||||||
|
|
||||||
auto device = g_vk_instace->GetDevice();
|
auto device = g_vk_instace->GetDevice();
|
||||||
device.updateDescriptorSets(update_count, writes.data(), 0, nullptr);
|
device.updateDescriptorSets(write_count, writes.data(), 0, nullptr);
|
||||||
|
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DescriptorUpdater::PushTextureArrayUpdate(vk::DescriptorSet set, u32 binding, vk::Sampler sampler,
|
||||||
|
std::span<vk::ImageView> views) {
|
||||||
|
ASSERT(image_count < MAX_UPDATES);
|
||||||
|
|
||||||
|
u32 start = image_count;
|
||||||
|
for (auto& view : views) {
|
||||||
|
image_infos[image_count++] = {sampler, view, vk::ImageLayout::eShaderReadOnlyOptimal};
|
||||||
|
}
|
||||||
|
|
||||||
|
writes[write_count++] = vk::WriteDescriptorSet{set, binding, 0, static_cast<u32>(views.size()),
|
||||||
|
vk::DescriptorType::eCombinedImageSampler,
|
||||||
|
image_infos.data() + start};
|
||||||
|
}
|
||||||
|
|
||||||
void DescriptorUpdater::PushCombinedImageSamplerUpdate(vk::DescriptorSet set, u32 binding,
|
void DescriptorUpdater::PushCombinedImageSamplerUpdate(vk::DescriptorSet set, u32 binding,
|
||||||
vk::Sampler sampler, vk::ImageView view) {
|
vk::Sampler sampler, vk::ImageView view) {
|
||||||
assert(update_count < MAX_DESCRIPTORS);
|
ASSERT(image_count < MAX_UPDATES);
|
||||||
|
|
||||||
auto& info = update_queue[update_count];
|
image_infos[image_count] = {sampler, view, vk::ImageLayout::eShaderReadOnlyOptimal};
|
||||||
info.image_info = vk::DescriptorImageInfo{sampler, view, vk::ImageLayout::eShaderReadOnlyOptimal};
|
|
||||||
|
|
||||||
writes[update_count++] = vk::WriteDescriptorSet{
|
writes[write_count++] = vk::WriteDescriptorSet{set, binding, 0, 1,
|
||||||
set, binding, 0, 1,
|
vk::DescriptorType::eCombinedImageSampler,
|
||||||
vk::DescriptorType::eCombinedImageSampler,
|
&image_infos[image_count++]};
|
||||||
&info.image_info
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorUpdater::PushBufferUpdate(vk::DescriptorSet set, u32 binding,
|
void DescriptorUpdater::PushBufferUpdate(vk::DescriptorSet set, u32 binding,
|
||||||
vk::DescriptorType buffer_type, u32 offset, u32 size,
|
vk::DescriptorType buffer_type, u32 offset, u32 size,
|
||||||
vk::Buffer buffer, const vk::BufferView& view) {
|
vk::Buffer buffer, const vk::BufferView& view) {
|
||||||
assert(update_count < MAX_DESCRIPTORS);
|
ASSERT(buffer_count < MAX_UPDATES);
|
||||||
|
|
||||||
auto& info = update_queue[update_count];
|
buffer_infos[buffer_count] = vk::DescriptorBufferInfo{buffer, offset, size};
|
||||||
info.buffer_info = vk::DescriptorBufferInfo{buffer, offset, size};
|
|
||||||
info.buffer_view = view;
|
|
||||||
|
|
||||||
writes[update_count++] = vk::WriteDescriptorSet{
|
writes[write_count++] = vk::WriteDescriptorSet{set, binding, 0, 1, buffer_type, nullptr,
|
||||||
set, binding, 0, 1,
|
&buffer_infos[buffer_count++],
|
||||||
buffer_type, nullptr,
|
view ? &view : nullptr};
|
||||||
&info.buffer_info, &info.buffer_view
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanState::VulkanState(const std::shared_ptr<VKSwapChain>& swapchain) : swapchain(swapchain) {
|
VulkanState::VulkanState(const std::shared_ptr<VKSwapChain>& swapchain) : swapchain(swapchain) {
|
||||||
@ -169,15 +182,19 @@ void VulkanState::SetTexelBuffer(u32 binding, u32 offset, u32 size, const VKBuff
|
|||||||
descriptors_dirty = true;
|
descriptors_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanState::SetPresentTexture(const VKTexture& image) {
|
void VulkanState::SetPresentTextures(vk::ImageView view0, vk::ImageView view1, vk::ImageView view2) {
|
||||||
auto& set = descriptor_sets[3];
|
auto& set = descriptor_sets[3];
|
||||||
updater.PushCombinedImageSamplerUpdate(set, 0, present_sampler, image.GetView());
|
|
||||||
present_view = image.GetView();
|
std::array views{view0, view1, view2};
|
||||||
|
updater.PushTextureArrayUpdate(set, 0, present_sampler, views);
|
||||||
descriptors_dirty = true;
|
descriptors_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanState::SetPresentData(DrawInfo data) {
|
void VulkanState::SetPresentData(DrawInfo data) {
|
||||||
present_data = data;
|
auto cmdbuffer = g_vk_task_scheduler->GetRenderCommandBuffer();
|
||||||
|
cmdbuffer.pushConstants(present_pipeline_layout, vk::ShaderStageFlagBits::eFragment |
|
||||||
|
vk::ShaderStageFlagBits::eVertex, 0, sizeof(data), &data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanState::SetPlaceholderColor(u8 red, u8 green, u8 blue, u8 alpha) {
|
void VulkanState::SetPlaceholderColor(u8 red, u8 green, u8 blue, u8 alpha) {
|
||||||
@ -480,8 +497,6 @@ void VulkanState::ApplyPresentState() {
|
|||||||
// Bind present pipeline and descriptors
|
// Bind present pipeline and descriptors
|
||||||
auto cmdbuffer = g_vk_task_scheduler->GetRenderCommandBuffer();
|
auto cmdbuffer = g_vk_task_scheduler->GetRenderCommandBuffer();
|
||||||
cmdbuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, present_pipeline.get());
|
cmdbuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, present_pipeline.get());
|
||||||
cmdbuffer.pushConstants(present_pipeline_layout, vk::ShaderStageFlagBits::eFragment |
|
|
||||||
vk::ShaderStageFlagBits::eVertex, 0, sizeof(present_data), &present_data);
|
|
||||||
|
|
||||||
ApplyCommonState(false);
|
ApplyCommonState(false);
|
||||||
|
|
||||||
@ -561,7 +576,7 @@ void VulkanState::BuildDescriptorLayouts() {
|
|||||||
{2, vk::DescriptorType::eUniformTexelBuffer, 1, vk::ShaderStageFlagBits::eFragment} // texture_buffer_lut_rgba
|
{2, vk::DescriptorType::eUniformTexelBuffer, 1, vk::ShaderStageFlagBits::eFragment} // texture_buffer_lut_rgba
|
||||||
}};
|
}};
|
||||||
std::array<vk::DescriptorSetLayoutBinding, 1> present_set{{
|
std::array<vk::DescriptorSetLayoutBinding, 1> present_set{{
|
||||||
{0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment}
|
{0, vk::DescriptorType::eCombinedImageSampler, 3, vk::ShaderStageFlagBits::eFragment}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
std::array<vk::DescriptorSetLayoutCreateInfo, DESCRIPTOR_SET_COUNT> create_infos{{
|
std::array<vk::DescriptorSetLayoutCreateInfo, DESCRIPTOR_SET_COUNT> create_infos{{
|
||||||
|
@ -21,7 +21,7 @@ template <typename T>
|
|||||||
using OptRef = std::optional<std::reference_wrapper<T>>;
|
using OptRef = std::optional<std::reference_wrapper<T>>;
|
||||||
|
|
||||||
struct DrawInfo {
|
struct DrawInfo {
|
||||||
glm::mat2x3 modelview;
|
glm::mat4 modelview;
|
||||||
glm::vec4 i_resolution;
|
glm::vec4 i_resolution;
|
||||||
glm::vec4 o_resolution;
|
glm::vec4 o_resolution;
|
||||||
int layer;
|
int layer;
|
||||||
@ -32,9 +32,11 @@ public:
|
|||||||
DescriptorUpdater() { Reset(); }
|
DescriptorUpdater() { Reset(); }
|
||||||
~DescriptorUpdater() = default;
|
~DescriptorUpdater() = default;
|
||||||
|
|
||||||
void Reset() { update_count = 0; }
|
void Reset();
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
|
void PushTextureArrayUpdate(vk::DescriptorSet, u32 biding, vk::Sampler sampler,
|
||||||
|
std::span<vk::ImageView> views);
|
||||||
void PushCombinedImageSamplerUpdate(vk::DescriptorSet set, u32 binding,
|
void PushCombinedImageSamplerUpdate(vk::DescriptorSet set, u32 binding,
|
||||||
vk::Sampler sampler, vk::ImageView view);
|
vk::Sampler sampler, vk::ImageView view);
|
||||||
void PushBufferUpdate(vk::DescriptorSet set, u32 binding,
|
void PushBufferUpdate(vk::DescriptorSet set, u32 binding,
|
||||||
@ -43,15 +45,16 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr u32 MAX_DESCRIPTORS = 10;
|
static constexpr u32 MAX_DESCRIPTORS = 10;
|
||||||
|
static constexpr u32 MAX_UPDATES = 20;
|
||||||
struct Descriptor {
|
struct Descriptor {
|
||||||
vk::DescriptorImageInfo image_info;
|
vk::DescriptorImageInfo image_info;
|
||||||
vk::DescriptorBufferInfo buffer_info;
|
vk::DescriptorBufferInfo buffer_info;
|
||||||
vk::BufferView buffer_view;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<vk::WriteDescriptorSet, MAX_DESCRIPTORS> writes;
|
std::array<vk::WriteDescriptorSet, MAX_DESCRIPTORS> writes;
|
||||||
std::array<Descriptor, MAX_DESCRIPTORS> update_queue;
|
std::array<vk::DescriptorImageInfo, MAX_UPDATES> image_infos;
|
||||||
u32 update_count{};
|
std::array<vk::DescriptorBufferInfo, MAX_UPDATES> buffer_infos;
|
||||||
|
u32 image_count{0}, buffer_count{0}, write_count{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
class VKSwapChain;
|
class VKSwapChain;
|
||||||
@ -105,7 +108,7 @@ public:
|
|||||||
void SetUniformBuffer(u32 binding, u32 offset, u32 size, const VKBuffer& buffer);
|
void SetUniformBuffer(u32 binding, u32 offset, u32 size, const VKBuffer& buffer);
|
||||||
void SetTexture(u32 binding, const VKTexture& texture);
|
void SetTexture(u32 binding, const VKTexture& texture);
|
||||||
void SetTexelBuffer(u32 binding, u32 offset, u32 size, const VKBuffer& buffer, u32 view_index);
|
void SetTexelBuffer(u32 binding, u32 offset, u32 size, const VKBuffer& buffer, u32 view_index);
|
||||||
void SetPresentTexture(const VKTexture& image);
|
void SetPresentTextures(vk::ImageView view0, vk::ImageView view1, vk::ImageView view2);
|
||||||
void SetPresentData(DrawInfo data);
|
void SetPresentData(DrawInfo data);
|
||||||
void SetPlaceholderColor(u8 red, u8 green, u8 blue, u8 alpha);
|
void SetPlaceholderColor(u8 red, u8 green, u8 blue, u8 alpha);
|
||||||
void UnbindTexture(const VKTexture& image);
|
void UnbindTexture(const VKTexture& image);
|
||||||
@ -128,7 +131,6 @@ private:
|
|||||||
bool rendering{false};
|
bool rendering{false};
|
||||||
vk::ImageView present_view;
|
vk::ImageView present_view;
|
||||||
std::array<vk::ImageView, 4> render_views;
|
std::array<vk::ImageView, 4> render_views;
|
||||||
DrawInfo present_data;
|
|
||||||
vk::Sampler render_sampler, present_sampler;
|
vk::Sampler render_sampler, present_sampler;
|
||||||
VKTexture placeholder;
|
VKTexture placeholder;
|
||||||
|
|
||||||
|
@ -75,6 +75,8 @@ void VKTexture::Create(const Info& create_info) {
|
|||||||
info.format = vk::Format::eD32SfloatS8Uint;
|
info.format = vk::Format::eD32SfloatS8Uint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "New surface!\n";
|
||||||
|
|
||||||
// Create the texture
|
// Create the texture
|
||||||
image_size = info.width * info.height * BytesPerPixel(info.format);
|
image_size = info.width * info.height * BytesPerPixel(info.format);
|
||||||
aspect = GetImageAspect(info.format);
|
aspect = GetImageAspect(info.format);
|
||||||
@ -136,9 +138,12 @@ void VKTexture::Destroy() {
|
|||||||
|
|
||||||
auto deleter = [this]() {
|
auto deleter = [this]() {
|
||||||
auto device = g_vk_instace->GetDevice();
|
auto device = g_vk_instace->GetDevice();
|
||||||
device.destroyImage(texture);
|
if (texture) {
|
||||||
device.destroyImageView(view);
|
std::cout << "Surface destroyed!\n";
|
||||||
device.freeMemory(memory);
|
device.destroyImage(texture);
|
||||||
|
device.destroyImageView(view);
|
||||||
|
device.freeMemory(memory);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Schedule deletion of the texture after it's no longer used
|
// Schedule deletion of the texture after it's no longer used
|
||||||
@ -270,7 +275,7 @@ void VKTexture::Upload(u32 level, u32 layer, u32 row_length, vk::Rect2D region,
|
|||||||
}
|
}
|
||||||
else if (is_d24s8) {
|
else if (is_d24s8) {
|
||||||
auto data = D24S8ToD32S8(pixels);
|
auto data = D24S8ToD32S8(pixels);
|
||||||
std::memcpy(buffer, data.data(), data.size());
|
std::memcpy(buffer, data.data(), data.size() * sizeof(data[0]));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::memcpy(buffer, pixels.data(), pixels.size());
|
std::memcpy(buffer, pixels.data(), pixels.size());
|
||||||
@ -322,7 +327,7 @@ void VKTexture::Download(u32 level, u32 layer, u32 row_length, vk::Rect2D region
|
|||||||
}
|
}
|
||||||
else if (is_d24s8) {
|
else if (is_d24s8) {
|
||||||
auto data = D32S8ToD24S8(memory);
|
auto data = D32S8ToD24S8(memory);
|
||||||
std::memcpy(buffer, data.data(), data.size());
|
std::memcpy(buffer, data.data(), data.size() * sizeof(data[0]));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::memcpy(buffer, memory.data(), memory.size());
|
std::memcpy(buffer, memory.data(), memory.size());
|
||||||
|
Reference in New Issue
Block a user