mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-06 22:25:41 +12:00
Separate present/graphics workloads
Separate the "Display" texture from the cache of framebuffer textures, move present/graphics into separate command buffers.
This commit is contained in:
parent
50029e1333
commit
c778c34433
2 changed files with 192 additions and 74 deletions
|
@ -44,15 +44,21 @@ class RendererVK final : public Renderer {
|
|||
|
||||
// Frame-buffering data
|
||||
// Each vector is `frameBufferingCount` in size
|
||||
std::vector<vk::UniqueCommandBuffer> frameCommandBuffers = {};
|
||||
std::vector<vk::UniqueCommandBuffer> framePresentCommandBuffers = {};
|
||||
std::vector<vk::UniqueSemaphore> swapImageFreeSemaphore = {};
|
||||
std::vector<vk::UniqueSemaphore> renderFinishedSemaphore = {};
|
||||
std::vector<vk::UniqueFence> frameFinishedFences = {};
|
||||
std::vector<std::vector<vk::UniqueFramebuffer>> frameFramebuffers = {};
|
||||
std::vector<vk::UniqueCommandBuffer> frameGraphicsCommandBuffers = {};
|
||||
|
||||
// Todo:
|
||||
// Use `{colourBuffer,depthBuffer}Loc` to maintain an std::map-cache of framebuffers
|
||||
struct Texture {
|
||||
vk::UniqueImage image;
|
||||
vk::UniqueDeviceMemory imageMemory;
|
||||
vk::UniqueImageView imageView;
|
||||
};
|
||||
// Hash(loc, size, format) -> Texture
|
||||
std::map<u32, Texture> textureCache;
|
||||
|
||||
static u32 colorBufferHash(u32 loc, u32 size, PICA::ColorFmt format);
|
||||
|
@ -61,8 +67,9 @@ class RendererVK final : public Renderer {
|
|||
Texture& getColorRenderTexture();
|
||||
Texture& getDepthRenderTexture();
|
||||
|
||||
std::vector<vk::UniqueImage> topScreenImages = {};
|
||||
std::vector<vk::UniqueImage> bottomScreenImages = {};
|
||||
// Use `lower_bound` to find nearest texture for an address
|
||||
// Blit them during `display()`
|
||||
std::vector<vk::UniqueImage> screenTexture = {};
|
||||
|
||||
std::map<u32, vk::UniqueRenderPass> renderPassCache;
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ RendererVK::Texture& RendererVK::getDepthRenderTexture() {
|
|||
textureInfo.setSamples(vk::SampleCountFlagBits::e1);
|
||||
textureInfo.setTiling(vk::ImageTiling::eOptimal);
|
||||
textureInfo.setUsage(
|
||||
vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eInputAttachment | vk::ImageUsageFlagBits::eTransferSrc |
|
||||
vk::ImageUsageFlagBits::eDepthStencilAttachment | vk::ImageUsageFlagBits::eInputAttachment | vk::ImageUsageFlagBits::eTransferSrc |
|
||||
vk::ImageUsageFlagBits::eTransferDst
|
||||
);
|
||||
textureInfo.setSharingMode(vk::SharingMode::eExclusive);
|
||||
|
@ -125,7 +125,7 @@ RendererVK::Texture& RendererVK::getDepthRenderTexture() {
|
|||
viewInfo.viewType = vk::ImageViewType::e2D;
|
||||
viewInfo.format = Vulkan::depthFormatToVulkan(depthBufferFormat);
|
||||
viewInfo.components = vk::ComponentMapping();
|
||||
viewInfo.subresourceRange = vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1);
|
||||
viewInfo.subresourceRange = vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil, 0, 1, 0, 1);
|
||||
|
||||
if (auto createResult = device->createImageViewUnique(viewInfo); createResult.result == vk::Result::eSuccess) {
|
||||
newTexture.imageView = std::move(createResult.value);
|
||||
|
@ -364,12 +364,6 @@ RendererVK::~RendererVK() {}
|
|||
void RendererVK::reset() { renderPassCache.clear(); }
|
||||
|
||||
void RendererVK::display() {
|
||||
// Block, on the CPU, to ensure that this buffered-frame is ready for more work
|
||||
if (auto waitResult = device->waitForFences({frameFinishedFences[frameBufferingIndex].get()}, true, std::numeric_limits<u64>::max());
|
||||
waitResult != vk::Result::eSuccess) {
|
||||
Helpers::panic("Error waiting on swapchain fence: %s\n", vk::to_string(waitResult).c_str());
|
||||
}
|
||||
|
||||
// Get the next available swapchain image, and signal the semaphore when it's ready
|
||||
static constexpr u32 swapchainImageInvalid = std::numeric_limits<u32>::max();
|
||||
u32 swapchainImageIndex = swapchainImageInvalid;
|
||||
|
@ -405,7 +399,11 @@ void RendererVK::display() {
|
|||
}
|
||||
}
|
||||
|
||||
const vk::UniqueCommandBuffer& frameCommandBuffer = frameCommandBuffers[frameBufferingIndex];
|
||||
if (const vk::Result endResult = frameGraphicsCommandBuffers[frameBufferingIndex]->end(); endResult != vk::Result::eSuccess) {
|
||||
Helpers::panic("Error ending command buffer recording: %s\n", vk::to_string(endResult).c_str());
|
||||
}
|
||||
|
||||
const vk::UniqueCommandBuffer& frameCommandBuffer = framePresentCommandBuffers[frameBufferingIndex];
|
||||
|
||||
vk::CommandBufferBeginInfo beginInfo = {};
|
||||
beginInfo.flags = vk::CommandBufferUsageFlagBits::eSimultaneousUse;
|
||||
|
@ -426,24 +424,15 @@ void RendererVK::display() {
|
|||
{
|
||||
vk::ImageMemoryBarrier(
|
||||
vk::AccessFlagBits::eMemoryRead, vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eUndefined,
|
||||
vk::ImageLayout::eTransferDstOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
|
||||
topScreenImages[frameBufferingIndex].get(), vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
),
|
||||
vk::ImageMemoryBarrier(
|
||||
vk::AccessFlagBits::eMemoryRead, vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eUndefined,
|
||||
vk::ImageLayout::eTransferDstOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
|
||||
bottomScreenImages[frameBufferingIndex].get(), vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
vk::ImageLayout::eTransferDstOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, screenTexture[frameBufferingIndex].get(),
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
),
|
||||
}
|
||||
);
|
||||
static const std::array<float, 4> topClearColor = {{1.0f, 0.0f, 0.0f, 1.0f}};
|
||||
static const std::array<float, 4> bottomClearColor = {{0.0f, 1.0f, 0.0f, 1.0f}};
|
||||
frameCommandBuffer->clearColorImage(
|
||||
topScreenImages[frameBufferingIndex].get(), vk::ImageLayout::eTransferDstOptimal, topClearColor,
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
);
|
||||
frameCommandBuffer->clearColorImage(
|
||||
bottomScreenImages[frameBufferingIndex].get(), vk::ImageLayout::eTransferDstOptimal, bottomClearColor,
|
||||
screenTexture[frameBufferingIndex].get(), vk::ImageLayout::eTransferDstOptimal, topClearColor,
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
);
|
||||
}
|
||||
|
@ -464,13 +453,8 @@ void RendererVK::display() {
|
|||
),
|
||||
vk::ImageMemoryBarrier(
|
||||
vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eTransferRead, vk::ImageLayout::eTransferDstOptimal,
|
||||
vk::ImageLayout::eTransferSrcOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
|
||||
topScreenImages[frameBufferingIndex].get(), vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
),
|
||||
vk::ImageMemoryBarrier(
|
||||
vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eTransferRead, vk::ImageLayout::eTransferDstOptimal,
|
||||
vk::ImageLayout::eTransferSrcOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
|
||||
bottomScreenImages[frameBufferingIndex].get(), vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
vk::ImageLayout::eTransferSrcOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, screenTexture[frameBufferingIndex].get(),
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
),
|
||||
}
|
||||
);
|
||||
|
@ -483,22 +467,13 @@ void RendererVK::display() {
|
|||
|
||||
// Blit top/bottom screen into swapchain image
|
||||
|
||||
static const vk::ImageBlit topScreenBlit(
|
||||
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), {vk::Offset3D{}, vk::Offset3D{400, 240, 1}},
|
||||
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), {vk::Offset3D{}, vk::Offset3D{400, 240, 1}}
|
||||
);
|
||||
static const vk::ImageBlit bottomScreenBlit(
|
||||
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), {vk::Offset3D{}, vk::Offset3D{320, 240, 1}},
|
||||
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1),
|
||||
{vk::Offset3D{(400 / 2) - (320 / 2), 240, 0}, vk::Offset3D{(400 / 2) + (320 / 2), 240 + 240, 1}}
|
||||
static const vk::ImageBlit screenBlit(
|
||||
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), {vk::Offset3D{}, vk::Offset3D{400, 240 * 2, 1}},
|
||||
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), {vk::Offset3D{}, vk::Offset3D{400, 240 * 2, 1}}
|
||||
);
|
||||
frameCommandBuffer->blitImage(
|
||||
topScreenImages[frameBufferingIndex].get(), vk::ImageLayout::eTransferSrcOptimal, swapchainImages[swapchainImageIndex],
|
||||
vk::ImageLayout::eTransferDstOptimal, {topScreenBlit}, vk::Filter::eNearest
|
||||
);
|
||||
frameCommandBuffer->blitImage(
|
||||
bottomScreenImages[frameBufferingIndex].get(), vk::ImageLayout::eTransferSrcOptimal, swapchainImages[swapchainImageIndex],
|
||||
vk::ImageLayout::eTransferDstOptimal, {bottomScreenBlit}, vk::Filter::eNearest
|
||||
screenTexture[frameBufferingIndex].get(), vk::ImageLayout::eTransferSrcOptimal, swapchainImages[swapchainImageIndex],
|
||||
vk::ImageLayout::eTransferDstOptimal, {screenBlit}, vk::Filter::eNearest
|
||||
);
|
||||
|
||||
// Prepare swapchain image for present
|
||||
|
@ -565,6 +540,27 @@ void RendererVK::display() {
|
|||
}
|
||||
|
||||
frameBufferingIndex = ((frameBufferingIndex + 1) % frameBufferingCount);
|
||||
|
||||
// Wait for next frame to be ready
|
||||
|
||||
// Block, on the CPU, to ensure that this buffered-frame is ready for more work
|
||||
if (auto waitResult = device->waitForFences({frameFinishedFences[frameBufferingIndex].get()}, true, std::numeric_limits<u64>::max());
|
||||
waitResult != vk::Result::eSuccess) {
|
||||
Helpers::panic("Error waiting on swapchain fence: %s\n", vk::to_string(waitResult).c_str());
|
||||
}
|
||||
|
||||
{
|
||||
frameFramebuffers[frameBufferingIndex].clear();
|
||||
|
||||
frameGraphicsCommandBuffers[frameBufferingIndex]->reset();
|
||||
|
||||
vk::CommandBufferBeginInfo beginInfo = {};
|
||||
beginInfo.flags = vk::CommandBufferUsageFlagBits::eSimultaneousUse;
|
||||
|
||||
if (const vk::Result beginResult = frameGraphicsCommandBuffers[frameBufferingIndex]->begin(beginInfo); beginResult != vk::Result::eSuccess) {
|
||||
Helpers::panic("Error beginning command buffer recording: %s\n", vk::to_string(beginResult).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RendererVK::initGraphicsContext(SDL_Window* window) {
|
||||
|
@ -608,7 +604,7 @@ void RendererVK::initGraphicsContext(SDL_Window* window) {
|
|||
|
||||
#if defined(__APPLE__)
|
||||
if (instanceExtensionsAvailable.contains(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) {
|
||||
instanceExtensionNames.emplace_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
||||
instanceExtensions.emplace_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -817,11 +813,25 @@ void RendererVK::initGraphicsContext(SDL_Window* window) {
|
|||
commandBuffersInfo.commandBufferCount = frameBufferingCount;
|
||||
|
||||
if (auto allocateResult = device->allocateCommandBuffersUnique(commandBuffersInfo); allocateResult.result == vk::Result::eSuccess) {
|
||||
frameCommandBuffers = std::move(allocateResult.value);
|
||||
framePresentCommandBuffers = std::move(allocateResult.value);
|
||||
} else {
|
||||
Helpers::panic("Error allocating command buffer: %s\n", vk::to_string(allocateResult.result).c_str());
|
||||
}
|
||||
|
||||
if (auto allocateResult = device->allocateCommandBuffersUnique(commandBuffersInfo); allocateResult.result == vk::Result::eSuccess) {
|
||||
frameGraphicsCommandBuffers = std::move(allocateResult.value);
|
||||
} else {
|
||||
Helpers::panic("Error allocating command buffer: %s\n", vk::to_string(allocateResult.result).c_str());
|
||||
}
|
||||
|
||||
vk::CommandBufferBeginInfo beginInfo = {};
|
||||
beginInfo.flags = vk::CommandBufferUsageFlagBits::eSimultaneousUse;
|
||||
for (const auto& graphicsCommandBuffer : frameGraphicsCommandBuffers) {
|
||||
if (const vk::Result beginResult = graphicsCommandBuffer->begin(beginInfo); beginResult != vk::Result::eSuccess) {
|
||||
Helpers::panic("Error beginning command buffer recording: %s\n", vk::to_string(beginResult).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Frame-buffering synchronization primitives
|
||||
vk::FenceCreateInfo fenceInfo = {};
|
||||
fenceInfo.flags = vk::FenceCreateFlagBits::eSignaled;
|
||||
|
@ -831,27 +841,25 @@ void RendererVK::initGraphicsContext(SDL_Window* window) {
|
|||
swapImageFreeSemaphore.resize(frameBufferingCount);
|
||||
renderFinishedSemaphore.resize(frameBufferingCount);
|
||||
frameFinishedFences.resize(frameBufferingCount);
|
||||
frameFramebuffers.resize(frameBufferingCount);
|
||||
frameGraphicsCommandBuffers.resize(frameBufferingCount);
|
||||
|
||||
vk::ImageCreateInfo topScreenInfo = {};
|
||||
topScreenInfo.setImageType(vk::ImageType::e2D);
|
||||
topScreenInfo.setFormat(vk::Format::eR8G8B8A8Unorm);
|
||||
topScreenInfo.setExtent(vk::Extent3D(400, 240, 1));
|
||||
topScreenInfo.setMipLevels(1);
|
||||
topScreenInfo.setArrayLayers(1);
|
||||
topScreenInfo.setSamples(vk::SampleCountFlagBits::e1);
|
||||
topScreenInfo.setTiling(vk::ImageTiling::eOptimal);
|
||||
topScreenInfo.setUsage(
|
||||
vk::ImageCreateInfo screenTextureInfo = {};
|
||||
screenTextureInfo.setImageType(vk::ImageType::e2D);
|
||||
screenTextureInfo.setFormat(vk::Format::eR8G8B8A8Unorm);
|
||||
screenTextureInfo.setExtent(vk::Extent3D(400, 240, 1));
|
||||
screenTextureInfo.setMipLevels(1);
|
||||
screenTextureInfo.setArrayLayers(1);
|
||||
screenTextureInfo.setSamples(vk::SampleCountFlagBits::e1);
|
||||
screenTextureInfo.setTiling(vk::ImageTiling::eOptimal);
|
||||
screenTextureInfo.setUsage(
|
||||
vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eInputAttachment | vk::ImageUsageFlagBits::eTransferSrc |
|
||||
vk::ImageUsageFlagBits::eTransferDst
|
||||
);
|
||||
topScreenInfo.setSharingMode(vk::SharingMode::eExclusive);
|
||||
topScreenInfo.setInitialLayout(vk::ImageLayout::eUndefined);
|
||||
screenTextureInfo.setSharingMode(vk::SharingMode::eExclusive);
|
||||
screenTextureInfo.setInitialLayout(vk::ImageLayout::eUndefined);
|
||||
|
||||
vk::ImageCreateInfo bottomScreenInfo = topScreenInfo;
|
||||
bottomScreenInfo.setExtent(vk::Extent3D(320, 240, 1));
|
||||
|
||||
topScreenImages.resize(frameBufferingCount);
|
||||
bottomScreenImages.resize(frameBufferingCount);
|
||||
screenTexture.resize(frameBufferingCount);
|
||||
|
||||
for (usize i = 0; i < frameBufferingCount; i++) {
|
||||
if (auto createResult = device->createSemaphoreUnique(semaphoreInfo); createResult.result == vk::Result::eSuccess) {
|
||||
|
@ -872,25 +880,18 @@ void RendererVK::initGraphicsContext(SDL_Window* window) {
|
|||
Helpers::panic("Error creating 'frame-finished' fence: %s\n", vk::to_string(createResult.result).c_str());
|
||||
}
|
||||
|
||||
if (auto createResult = device->createImageUnique(topScreenInfo); createResult.result == vk::Result::eSuccess) {
|
||||
topScreenImages[i] = std::move(createResult.value);
|
||||
if (auto createResult = device->createImageUnique(screenTextureInfo); createResult.result == vk::Result::eSuccess) {
|
||||
screenTexture[i] = std::move(createResult.value);
|
||||
} else {
|
||||
Helpers::panic("Error creating top-screen image: %s\n", vk::to_string(createResult.result).c_str());
|
||||
}
|
||||
|
||||
if (auto createResult = device->createImageUnique(bottomScreenInfo); createResult.result == vk::Result::eSuccess) {
|
||||
bottomScreenImages[i] = std::move(createResult.value);
|
||||
} else {
|
||||
Helpers::panic("Error creating bottom-screen image: %s\n", vk::to_string(createResult.result).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Commit memory to all of our images
|
||||
{
|
||||
const auto getImage = [](const vk::UniqueImage& image) -> vk::Image { return image.get(); };
|
||||
std::vector<vk::Image> images;
|
||||
std::transform(topScreenImages.begin(), topScreenImages.end(), std::back_inserter(images), getImage);
|
||||
std::transform(bottomScreenImages.begin(), bottomScreenImages.end(), std::back_inserter(images), getImage);
|
||||
std::transform(screenTexture.begin(), screenTexture.end(), std::back_inserter(images), getImage);
|
||||
|
||||
if (auto [result, imageMemory] = Vulkan::commitImageHeap(device.get(), physicalDevice, images); result == vk::Result::eSuccess) {
|
||||
framebufferMemory = std::move(imageMemory);
|
||||
|
@ -902,7 +903,112 @@ void RendererVK::initGraphicsContext(SDL_Window* window) {
|
|||
|
||||
void RendererVK::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) {}
|
||||
|
||||
void RendererVK::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) {}
|
||||
void RendererVK::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) {
|
||||
return;
|
||||
if (fbSize[0] == 0 || fbSize[1] == 0) {
|
||||
return;
|
||||
}
|
||||
const u32 inputWidth = inputSize & 0xffff;
|
||||
const u32 inputGap = inputSize >> 16;
|
||||
|
||||
const u32 outputWidth = outputSize & 0xffff;
|
||||
const u32 outputGap = outputSize >> 16;
|
||||
|
||||
Texture& colorTexture = getColorRenderTexture();
|
||||
|
||||
vk::ImageBlit blitRegion = {};
|
||||
// Hack: Detect whether we are writing to the top or bottom screen by checking output gap and drawing to the proper part of the output texture
|
||||
// We consider output gap == 320 to mean bottom, and anything else to mean top
|
||||
if (outputGap == 320) {
|
||||
// Bottom screen
|
||||
blitRegion = vk::ImageBlit(
|
||||
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), {vk::Offset3D{0, 0, 0}, vk::Offset3D{320, 240, 1}},
|
||||
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), {vk::Offset3D{40, 240, 0}, vk::Offset3D{40 + 320, 240 + 240, 1}}
|
||||
);
|
||||
} else {
|
||||
// Top screen
|
||||
blitRegion = vk::ImageBlit(
|
||||
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), {vk::Offset3D{0, 0, 0}, vk::Offset3D{400, 240, 1}},
|
||||
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), {vk::Offset3D{0, 0, 0}, vk::Offset3D{400, 240, 1}}
|
||||
);
|
||||
}
|
||||
|
||||
vk::CommandBufferAllocateInfo commandBuffersInfo = {};
|
||||
commandBuffersInfo.commandPool = commandPool.get();
|
||||
commandBuffersInfo.level = vk::CommandBufferLevel::ePrimary;
|
||||
commandBuffersInfo.commandBufferCount = 1;
|
||||
|
||||
vk::UniqueCommandBuffer blitCommandBuffer = {};
|
||||
if (auto allocateResult = device->allocateCommandBuffersUnique(commandBuffersInfo); allocateResult.result == vk::Result::eSuccess) {
|
||||
blitCommandBuffer = std::move(allocateResult.value[0]);
|
||||
} else {
|
||||
Helpers::panic("Error allocating command buffer: %s\n", vk::to_string(allocateResult.result).c_str());
|
||||
}
|
||||
|
||||
vk::CommandBufferBeginInfo beginInfo = {};
|
||||
beginInfo.flags = vk::CommandBufferUsageFlagBits::eSimultaneousUse;
|
||||
|
||||
if (const vk::Result beginResult = blitCommandBuffer->begin(beginInfo); beginResult != vk::Result::eSuccess) {
|
||||
Helpers::panic("Error beginning command buffer recording: %s\n", vk::to_string(beginResult).c_str());
|
||||
}
|
||||
|
||||
blitCommandBuffer->pipelineBarrier(
|
||||
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlags(), {}, {},
|
||||
{
|
||||
vk::ImageMemoryBarrier(
|
||||
vk::AccessFlagBits::eColorAttachmentWrite, vk::AccessFlagBits::eTransferRead, vk::ImageLayout::eColorAttachmentOptimal,
|
||||
vk::ImageLayout::eTransferSrcOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, colorTexture.image.get(),
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
),
|
||||
vk::ImageMemoryBarrier(
|
||||
vk::AccessFlagBits::eColorAttachmentWrite, vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eColorAttachmentOptimal,
|
||||
vk::ImageLayout::eTransferDstOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, screenTexture[frameBufferingIndex].get(),
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
blitCommandBuffer->blitImage(
|
||||
colorTexture.image.get(), vk::ImageLayout::eTransferSrcOptimal, screenTexture[frameBufferingIndex].get(),
|
||||
vk::ImageLayout::eTransferDstOptimal, {blitRegion}, vk::Filter::eNearest
|
||||
);
|
||||
|
||||
if (const vk::Result endResult = frameGraphicsCommandBuffers[frameBufferingIndex]->end(); endResult != vk::Result::eSuccess) {
|
||||
Helpers::panic("Error ending command buffer recording: %s\n", vk::to_string(endResult).c_str());
|
||||
}
|
||||
|
||||
blitCommandBuffer->pipelineBarrier(
|
||||
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlags(), {}, {},
|
||||
{
|
||||
vk::ImageMemoryBarrier(
|
||||
vk::AccessFlagBits::eTransferRead, vk::AccessFlagBits::eColorAttachmentWrite, vk::ImageLayout::eTransferSrcOptimal,
|
||||
vk::ImageLayout::eColorAttachmentOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, colorTexture.image.get(),
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
),
|
||||
vk::ImageMemoryBarrier(
|
||||
vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eColorAttachmentWrite, vk::ImageLayout::eTransferDstOptimal,
|
||||
vk::ImageLayout::eColorAttachmentOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, screenTexture[frameBufferingIndex].get(),
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
vk::FenceCreateInfo fenceInfo = {};
|
||||
vk::UniqueFence finishedFence = {};
|
||||
if (auto createResult = device->createFenceUnique(fenceInfo); createResult.result == vk::Result::eSuccess) {
|
||||
finishedFence = std::move(createResult.value);
|
||||
} else {
|
||||
Helpers::panic("Error creating fence: %s\n", vk::to_string(createResult.result).c_str());
|
||||
}
|
||||
|
||||
vk::SubmitInfo submitInfo = {};
|
||||
|
||||
submitInfo.setCommandBuffers(blitCommandBuffer.get());
|
||||
|
||||
if (const vk::Result submitResult = graphicsQueue.submit({submitInfo}, finishedFence.get()); submitResult != vk::Result::eSuccess) {
|
||||
Helpers::panic("Error submitting to graphics queue: %s\n", vk::to_string(submitResult).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void RendererVK::textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) {}
|
||||
|
||||
|
@ -955,6 +1061,11 @@ void RendererVK::drawVertices(PICA::PrimType primType, std::span<const PICA::Ver
|
|||
renderBeginInfo.renderArea.extent.width = fbSize[0];
|
||||
renderBeginInfo.renderArea.extent.height = fbSize[1];
|
||||
renderBeginInfo.framebuffer = curFramebuffer;
|
||||
|
||||
const vk::UniqueCommandBuffer& commandBuffer = frameGraphicsCommandBuffers[frameBufferingIndex];
|
||||
|
||||
commandBuffer->beginRenderPass(renderBeginInfo, vk::SubpassContents::eInline);
|
||||
commandBuffer->endRenderPass();
|
||||
}
|
||||
|
||||
void RendererVK::screenshot(const std::string& name) {}
|
||||
|
|
Loading…
Add table
Reference in a new issue