mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-05 18:23:39 -04:00
separated renderpasses, and more vulkan setting up
This commit is contained in:
parent
cb0d14258b
commit
1f8c5418ac
4 changed files with 231 additions and 30 deletions
|
|
@ -80,8 +80,10 @@ constexpr std::array<f32, 4 * 4> MakeOrthographicMatrix(u32 width, u32 height) {
|
|||
// clang-format on
|
||||
}
|
||||
|
||||
constexpr static std::array<vk::DescriptorSetLayoutBinding, 1> PRESENT_BINDINGS = {{
|
||||
{0, vk::DescriptorType::eCombinedImageSampler, 3, vk::ShaderStageFlagBits::eFragment},
|
||||
constexpr static std::array<vk::DescriptorSetLayoutBinding, 3> PRESENT_BINDINGS = {{
|
||||
{0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment},
|
||||
{1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment},
|
||||
{2, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment},
|
||||
}};
|
||||
|
||||
namespace {
|
||||
|
|
@ -360,17 +362,79 @@ void RendererVulkan::CreatePPTextureFramebuffers(){
|
|||
}
|
||||
};
|
||||
|
||||
void RendererVulkan::PrepareDraw(Frame* frame, const Layout::FramebufferLayout& layout) {
|
||||
//Helper Functions
|
||||
void RendererVulkan::PrepareTextureDraw(TextureInfo framebufferTexture, vk::Framebuffer framebuffer, vk::Pipeline shaderPipeline, std::vector<TextureInfo> texturesToSample, int filterMode){
|
||||
const auto sampler = present_samplers[filterMode];
|
||||
const auto present_set = present_heap.Commit();
|
||||
for (u32 i = 0; i < texturesToSample.size(); i++) {
|
||||
update_queue.AddImageSampler(present_set, i, 0, texturesToSample[i].image_view, sampler);
|
||||
}
|
||||
|
||||
renderpass_cache.EndRendering();
|
||||
scheduler.Record([this, framebufferTexture, framebuffer, shaderPipeline, present_set](vk::CommandBuffer cmdbuf) {
|
||||
const vk::Viewport viewport = {
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = static_cast<float>(framebufferTexture.width),
|
||||
.height = static_cast<float>(framebufferTexture.height),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
|
||||
const vk::Rect2D scissor = {
|
||||
.offset = {0, 0},
|
||||
.extent = {framebufferTexture.width, framebufferTexture.height},
|
||||
};
|
||||
|
||||
const vk::ClearColorValue clear_color = {
|
||||
.float32 =
|
||||
std::array{
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
},
|
||||
};
|
||||
cmdbuf.setViewport(0, viewport);
|
||||
cmdbuf.setScissor(0, scissor);
|
||||
|
||||
const vk::ClearValue clear{.color = clear_color};
|
||||
const vk::PipelineLayout layout{*present_pipeline_layout};
|
||||
const vk::RenderPassBeginInfo renderpass_begin_info = {
|
||||
.renderPass = textureRenderpass,
|
||||
.framebuffer = framebuffer,
|
||||
.renderArea =
|
||||
vk::Rect2D{
|
||||
.offset = {0, 0},
|
||||
.extent = {framebufferTexture.width, framebufferTexture.height},
|
||||
},
|
||||
.clearValueCount = 1,
|
||||
.pClearValues = &clear,
|
||||
};
|
||||
cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
|
||||
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, shaderPipeline);
|
||||
cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, layout, 0, present_set, {});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void RendererVulkan::PrepareDraw(Frame* frame, const Layout::FramebufferLayout& layout, std::vector<u32> screenids) {
|
||||
const auto sampler = present_samplers[Settings::values.filter_mode.GetValue()];
|
||||
const auto present_set = present_heap.Commit();
|
||||
for (u32 index = 0; index < screen_infos.size(); index++) {
|
||||
update_queue.AddImageSampler(present_set, 0, index, screen_infos[index].image_view,
|
||||
for (u32 i = 0; i < screenids.size(); i++) {
|
||||
update_queue.AddImageSampler(present_set, i, 0, screen_infos[screenids[i]].image_view,
|
||||
sampler);
|
||||
}
|
||||
|
||||
renderpass_cache.EndRendering();
|
||||
vk::RenderPass currentRenderPass;
|
||||
if (clearingColorAttachment){
|
||||
currentRenderPass = main_present_window.Renderpass();
|
||||
} else {
|
||||
currentRenderPass = main_present_window.LoadRenderpass();
|
||||
}
|
||||
scheduler.Record([this, layout, frame, present_set,
|
||||
renderpass = main_present_window.Renderpass(),
|
||||
currentRenderPass,
|
||||
index = current_pipeline](vk::CommandBuffer cmdbuf) {
|
||||
const vk::Viewport viewport = {
|
||||
.x = 0.0f,
|
||||
|
|
@ -392,7 +456,7 @@ void RendererVulkan::PrepareDraw(Frame* frame, const Layout::FramebufferLayout&
|
|||
const vk::ClearValue clear{.color = clear_color};
|
||||
const vk::PipelineLayout layout{*present_pipeline_layout};
|
||||
const vk::RenderPassBeginInfo renderpass_begin_info = {
|
||||
.renderPass = renderpass,
|
||||
.renderPass = currentRenderPass,
|
||||
.framebuffer = frame->framebuffer,
|
||||
.renderArea =
|
||||
vk::Rect2D{
|
||||
|
|
@ -1034,6 +1098,26 @@ void RendererVulkan::DrawSingleScreen(u32 screen_id, float screenLeft, float scr
|
|||
Layout::DisplayOrientation orientation) {
|
||||
const ScreenInfo& screen_info = screen_infos[screen_id];
|
||||
const auto& texcoords = screen_info.texcoords;
|
||||
std::vector<u32> screenids = {screen_id};
|
||||
PrepareDraw(currentFrame, currentFramebufferLayout, screenids);
|
||||
|
||||
// Apply the initial default opacity value; Needed to avoid flickering
|
||||
if (applyingOpacity){
|
||||
if (drawingPrimaryScreen){
|
||||
ApplySecondLayerOpacity(1.0f);
|
||||
} else {
|
||||
if (usingTopOpacity){
|
||||
if (currentFramebufferLayout.top_opacity < 1) {
|
||||
ApplySecondLayerOpacity(currentFramebufferLayout.top_opacity);
|
||||
}
|
||||
} else {
|
||||
if (currentFramebufferLayout.bottom_opacity < 1) {
|
||||
ApplySecondLayerOpacity(currentFramebufferLayout.bottom_opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const u32 scale_factor = GetResolutionScaleFactor();
|
||||
float textureWidth = static_cast<float>(screen_info.texture.height * scale_factor);
|
||||
|
|
@ -1074,6 +1158,52 @@ void RendererVulkan::DrawSingleScreen(u32 screen_id, float screenLeft, float scr
|
|||
ScreenRectVertex(-1.f, -1.f, 0.f, 0.f), //Left, Bottom
|
||||
ScreenRectVertex(1.f, -1.f, 1.f, 0.f), //Right, Bottom
|
||||
}};
|
||||
|
||||
// Legacy Vertices. Will be deleted when converted to multipass
|
||||
std::array<ScreenRectVertex, 4> legacy_vertices;
|
||||
float x = screenLeft;
|
||||
float y = screenTop;
|
||||
float w = screenWidth;
|
||||
float h = screenHeight;
|
||||
switch (orientation) {
|
||||
case Layout::DisplayOrientation::Landscape:
|
||||
legacy_vertices = {{
|
||||
ScreenRectVertex(x, y, texcoords.bottom, texcoords.left),
|
||||
ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.right),
|
||||
ScreenRectVertex(x, y + h, texcoords.top, texcoords.left),
|
||||
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.right),
|
||||
}};
|
||||
break;
|
||||
case Layout::DisplayOrientation::Portrait:
|
||||
legacy_vertices = {{
|
||||
ScreenRectVertex(x, y, texcoords.bottom, texcoords.right),
|
||||
ScreenRectVertex(x + w, y, texcoords.top, texcoords.right),
|
||||
ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.left),
|
||||
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left),
|
||||
}};
|
||||
std::swap(h, w);
|
||||
break;
|
||||
case Layout::DisplayOrientation::LandscapeFlipped:
|
||||
legacy_vertices = {{
|
||||
ScreenRectVertex(x, y, texcoords.top, texcoords.right),
|
||||
ScreenRectVertex(x + w, y, texcoords.top, texcoords.left),
|
||||
ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.right),
|
||||
ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.left),
|
||||
}};
|
||||
break;
|
||||
case Layout::DisplayOrientation::PortraitFlipped:
|
||||
legacy_vertices = {{
|
||||
ScreenRectVertex(x, y, texcoords.top, texcoords.left),
|
||||
ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.left),
|
||||
ScreenRectVertex(x, y + h, texcoords.top, texcoords.right),
|
||||
ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.right),
|
||||
}};
|
||||
std::swap(h, w);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Render_Vulkan, "Unknown DisplayOrientation: {}", orientation);
|
||||
break;
|
||||
}
|
||||
|
||||
// Vertices for Azahar's Output Layout
|
||||
std::array<ScreenRectVertex, 4> output_vertices;
|
||||
|
|
@ -1116,9 +1246,10 @@ void RendererVulkan::DrawSingleScreen(u32 screen_id, float screenLeft, float scr
|
|||
LOG_ERROR(Render_OpenGL, "Unknown DisplayOrientation: {}", orientation);
|
||||
break;
|
||||
}
|
||||
const u64 size = sizeof(ScreenRectVertex) * output_vertices.size();
|
||||
|
||||
const u64 size = sizeof(ScreenRectVertex) * legacy_vertices.size();
|
||||
auto [data, offset, invalidate] = vertex_buffer.Map(size, 16);
|
||||
std::memcpy(data, output_vertices.data(), size);
|
||||
std::memcpy(data, legacy_vertices.data(), size);
|
||||
vertex_buffer.Commit(size);
|
||||
|
||||
draw_info.i_resolution =
|
||||
|
|
@ -1137,6 +1268,7 @@ void RendererVulkan::DrawSingleScreen(u32 screen_id, float screenLeft, float scr
|
|||
|
||||
cmdbuf.bindVertexBuffers(0, vertex_buffer.Handle(), {0});
|
||||
cmdbuf.draw(4, 1, first_vertex, 0);
|
||||
cmdbuf.endRenderPass();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1145,7 +1277,25 @@ void RendererVulkan::DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, fl
|
|||
Layout::DisplayOrientation orientation) {
|
||||
const ScreenInfo& screen_info_l = screen_infos[screen_id_l];
|
||||
const auto& texcoords = screen_info_l.texcoords;
|
||||
std::vector<u32> screenids = {screen_id_l, screen_id_r};
|
||||
PrepareDraw(currentFrame, currentFramebufferLayout, screenids);
|
||||
|
||||
// Apply the initial default opacity value; Needed to avoid flickering
|
||||
if (applyingOpacity){
|
||||
if (drawingPrimaryScreen){
|
||||
ApplySecondLayerOpacity(1.0f);
|
||||
} else {
|
||||
if (usingTopOpacity){
|
||||
if (currentFramebufferLayout.top_opacity < 1) {
|
||||
ApplySecondLayerOpacity(currentFramebufferLayout.top_opacity);
|
||||
}
|
||||
} else {
|
||||
if (currentFramebufferLayout.bottom_opacity < 1) {
|
||||
ApplySecondLayerOpacity(currentFramebufferLayout.bottom_opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::array<ScreenRectVertex, 4> vertices;
|
||||
switch (orientation) {
|
||||
case Layout::DisplayOrientation::Landscape:
|
||||
|
|
@ -1210,6 +1360,7 @@ void RendererVulkan::DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, fl
|
|||
|
||||
cmdbuf.bindVertexBuffers(0, vertex_buffer.Handle(), {0});
|
||||
cmdbuf.draw(4, 1, first_vertex, 0);
|
||||
cmdbuf.endRenderPass();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1246,6 +1397,7 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
|||
DrawSingleScreen(leftside, top_screen_left / 2, top_screen_top, top_screen_width / 2,
|
||||
top_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
clearingColorAttachment = false;
|
||||
DrawSingleScreen(rightside, static_cast<float>((top_screen_left / 2) + (layout.width / 2)),
|
||||
top_screen_top, top_screen_width / 2, top_screen_height, orientation);
|
||||
break;
|
||||
|
|
@ -1254,6 +1406,7 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
|||
DrawSingleScreen(leftside, top_screen_left, top_screen_top, top_screen_width,
|
||||
top_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
clearingColorAttachment = false;
|
||||
DrawSingleScreen(rightside, top_screen_left + layout.width / 2, top_screen_top,
|
||||
top_screen_width, top_screen_height, orientation);
|
||||
break;
|
||||
|
|
@ -1262,6 +1415,7 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
|||
DrawSingleScreen(leftside, top_screen_left, top_screen_top, top_screen_width,
|
||||
top_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
clearingColorAttachment = false;
|
||||
DrawSingleScreen(
|
||||
rightside,
|
||||
static_cast<float>(layout.cardboard.top_screen_right_eye + (layout.width / 2)),
|
||||
|
|
@ -1347,33 +1501,34 @@ void RendererVulkan::DrawScreens(Frame* frame, const Layout::FramebufferLayout&
|
|||
ReloadPipeline(layout.render_3d_mode);
|
||||
}
|
||||
|
||||
PrepareDraw(frame, layout);
|
||||
|
||||
currentFrame = frame;
|
||||
currentFramebufferLayout = layout;
|
||||
const auto& top_screen = layout.top_screen;
|
||||
const auto& bottom_screen = layout.bottom_screen;
|
||||
draw_info.modelview = MakeOrthographicMatrix(layout.width, layout.height);
|
||||
|
||||
draw_info.layer = 0;
|
||||
|
||||
// Apply the initial default opacity value; Needed to avoid flickering
|
||||
ApplySecondLayerOpacity(1.0f);
|
||||
|
||||
clearingColorAttachment = true;
|
||||
applyingOpacity = true;
|
||||
if (!Settings::values.swap_screen.GetValue()) {
|
||||
drawingPrimaryScreen = true;
|
||||
DrawTopScreen(layout, top_screen);
|
||||
draw_info.layer = 0;
|
||||
if (layout.bottom_opacity < 1) {
|
||||
ApplySecondLayerOpacity(layout.bottom_opacity);
|
||||
}
|
||||
drawingPrimaryScreen = false;
|
||||
usingTopOpacity = false;
|
||||
clearingColorAttachment = false;
|
||||
DrawBottomScreen(layout, bottom_screen);
|
||||
} else {
|
||||
drawingPrimaryScreen = true;
|
||||
DrawBottomScreen(layout, bottom_screen);
|
||||
draw_info.layer = 0;
|
||||
if (layout.top_opacity < 1) {
|
||||
ApplySecondLayerOpacity(layout.top_opacity);
|
||||
}
|
||||
drawingPrimaryScreen = false;
|
||||
usingTopOpacity = true;
|
||||
clearingColorAttachment = false;
|
||||
DrawTopScreen(layout, top_screen);
|
||||
}
|
||||
|
||||
applyingOpacity = false;
|
||||
if (layout.additional_screen_enabled) {
|
||||
const auto& additional_screen = layout.additional_screen;
|
||||
if (!Settings::values.swap_screen.GetValue()) {
|
||||
|
|
@ -1383,9 +1538,8 @@ void RendererVulkan::DrawScreens(Frame* frame, const Layout::FramebufferLayout&
|
|||
}
|
||||
}
|
||||
|
||||
DrawCursor(layout);
|
||||
|
||||
scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.endRenderPass(); });
|
||||
// Needs to be fixed
|
||||
// DrawCursor(layout);
|
||||
}
|
||||
|
||||
void RendererVulkan::DrawCursor(const Layout::FramebufferLayout& layout) {
|
||||
|
|
|
|||
|
|
@ -98,8 +98,8 @@ private:
|
|||
void RenderScreenshot();
|
||||
void RenderScreenshotWithStagingCopy();
|
||||
bool TryRenderScreenshotWithHostMemory();
|
||||
void PrepareDraw(Frame* frame, const Layout::FramebufferLayout& layout);
|
||||
void PrepareTextureDraw(TextureInfo& textureInfo, vk::Pipeline& pipeline, int filterMode, std::vector<vk::ImageView> imageViews);
|
||||
void PrepareDraw(Frame* frame, const Layout::FramebufferLayout& layout, std::vector<u32> screenids);
|
||||
void PrepareTextureDraw(TextureInfo framebufferTexture, vk::Framebuffer framebuffer, vk::Pipeline shaderPipeline, std::vector<TextureInfo> texturesToSample, int filterMode);
|
||||
void RenderToWindow(PresentWindow& window, const Layout::FramebufferLayout& layout,
|
||||
bool flipped);
|
||||
|
||||
|
|
@ -132,7 +132,6 @@ private:
|
|||
// Create Framebuffers that are attached to the Post Processing Textures
|
||||
void CreatePPTextureFramebuffers();
|
||||
void AllocateSMAATextures();
|
||||
|
||||
private:
|
||||
Memory::MemorySystem& memory;
|
||||
Pica::PicaCore& pica;
|
||||
|
|
@ -195,7 +194,12 @@ private:
|
|||
int currBottomTextureWidth;
|
||||
int currBottomTextureHeight;
|
||||
u32 current_pipeline = 0;
|
||||
|
||||
Frame* currentFrame;
|
||||
Layout::FramebufferLayout currentFramebufferLayout;
|
||||
bool clearingColorAttachment = true;
|
||||
bool applyingOpacity = true;
|
||||
bool drawingPrimaryScreen = false;
|
||||
bool usingTopOpacity = false;
|
||||
std::array<ScreenInfo, 3> screen_infos{};
|
||||
PresentUniformData draw_info{};
|
||||
vk::ClearColorValue clear_color{};
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ PresentWindow::PresentWindow(Frontend::EmuWindow& emu_window_, const Instance& i
|
|||
surface{CreateSurface(instance.GetInstance(), emu_window)}, next_surface{surface},
|
||||
swapchain{instance, emu_window.GetFramebufferLayout().width,
|
||||
emu_window.GetFramebufferLayout().height, surface, low_refresh_rate_},
|
||||
graphics_queue{instance.GetGraphicsQueue()}, present_renderpass{CreateRenderpass()},
|
||||
graphics_queue{instance.GetGraphicsQueue()}, present_renderpass{CreateRenderpass()}, present_load_renderpass{CreateLoadRenderpass()},
|
||||
vsync_enabled{Settings::values.use_vsync.GetValue()},
|
||||
blit_supported{
|
||||
CanBlitToSwapchain(instance.GetPhysicalDevice(), swapchain.GetSurfaceFormat().format)},
|
||||
|
|
@ -157,6 +157,7 @@ PresentWindow::~PresentWindow() {
|
|||
const vk::Device device = instance.GetDevice();
|
||||
device.destroyCommandPool(command_pool);
|
||||
device.destroyRenderPass(present_renderpass);
|
||||
device.destroyRenderPass(present_load_renderpass);
|
||||
for (auto& frame : swap_chain) {
|
||||
device.destroyImageView(frame.image_view);
|
||||
device.destroyFramebuffer(frame.framebuffer);
|
||||
|
|
@ -524,4 +525,41 @@ vk::RenderPass PresentWindow::CreateRenderpass() {
|
|||
return instance.GetDevice().createRenderPass(renderpass_info);
|
||||
}
|
||||
|
||||
vk::RenderPass PresentWindow::CreateLoadRenderpass() {
|
||||
const vk::AttachmentReference color_ref = {
|
||||
.attachment = 0,
|
||||
.layout = vk::ImageLayout::eGeneral,
|
||||
};
|
||||
|
||||
const vk::SubpassDescription subpass = {
|
||||
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
|
||||
.inputAttachmentCount = 0,
|
||||
.pInputAttachments = nullptr,
|
||||
.colorAttachmentCount = 1u,
|
||||
.pColorAttachments = &color_ref,
|
||||
.pResolveAttachments = 0,
|
||||
.pDepthStencilAttachment = nullptr,
|
||||
};
|
||||
|
||||
const vk::AttachmentDescription color_attachment = {
|
||||
.format = swapchain.GetSurfaceFormat().format,
|
||||
.loadOp = vk::AttachmentLoadOp::eLoad,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||
.initialLayout = vk::ImageLayout::eUndefined,
|
||||
.finalLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||
};
|
||||
|
||||
const vk::RenderPassCreateInfo renderpass_info = {
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &color_attachment,
|
||||
.subpassCount = 1,
|
||||
.pSubpasses = &subpass,
|
||||
.dependencyCount = 0,
|
||||
.pDependencies = nullptr,
|
||||
};
|
||||
|
||||
return instance.GetDevice().createRenderPass(renderpass_info);
|
||||
}
|
||||
} // namespace Vulkan
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@ public:
|
|||
[[nodiscard]] vk::RenderPass Renderpass() const noexcept {
|
||||
return present_renderpass;
|
||||
}
|
||||
// Returns Renderpass that doesn't clear the image
|
||||
[[nodiscard]] vk::RenderPass LoadRenderpass() const noexcept {
|
||||
return present_load_renderpass;
|
||||
}
|
||||
|
||||
u32 ImageCount() const noexcept {
|
||||
return swapchain.GetImageCount();
|
||||
|
|
@ -69,7 +73,7 @@ private:
|
|||
void CopyToSwapchain(Frame* frame);
|
||||
|
||||
vk::RenderPass CreateRenderpass();
|
||||
|
||||
vk::RenderPass CreateLoadRenderpass();
|
||||
private:
|
||||
Frontend::EmuWindow& emu_window;
|
||||
const Instance& instance;
|
||||
|
|
@ -81,6 +85,7 @@ private:
|
|||
vk::CommandPool command_pool;
|
||||
vk::Queue graphics_queue;
|
||||
vk::RenderPass present_renderpass;
|
||||
vk::RenderPass present_load_renderpass;
|
||||
std::vector<Frame> swap_chain;
|
||||
std::queue<Frame*> free_queue;
|
||||
std::queue<Frame*> present_queue;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue