mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 23:25:40 +12:00
Add display-shader presentation
Uses the graphics pipeline to both blit and transpose the 3ds-formatted textures. Does not read from the actual texture just yet since we dont write to the descriptor just yet. Some other patterns need to line up before then.
This commit is contained in:
parent
4b7bd9df3d
commit
14b1d7d8a8
2 changed files with 103 additions and 16 deletions
|
@ -5,6 +5,7 @@
|
||||||
#include "renderer.hpp"
|
#include "renderer.hpp"
|
||||||
#include "vk_api.hpp"
|
#include "vk_api.hpp"
|
||||||
#include "vk_descriptor_heap.hpp"
|
#include "vk_descriptor_heap.hpp"
|
||||||
|
#include "vk_descriptor_update_batch.hpp"
|
||||||
|
|
||||||
class GPU;
|
class GPU;
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ class RendererVK final : public Renderer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Hash(loc, size, format) -> Texture
|
// Hash(loc, size, format) -> Texture
|
||||||
std::map<u32, Texture> textureCache;
|
std::map<u64, Texture> textureCache;
|
||||||
|
|
||||||
static u32 colorBufferHash(u32 loc, u32 size, PICA::ColorFmt format);
|
static u32 colorBufferHash(u32 loc, u32 size, PICA::ColorFmt format);
|
||||||
static u32 depthBufferHash(u32 loc, u32 size, PICA::DepthFmt format);
|
static u32 depthBufferHash(u32 loc, u32 size, PICA::DepthFmt format);
|
||||||
|
@ -82,6 +83,8 @@ class RendererVK final : public Renderer {
|
||||||
|
|
||||||
// Framebuffer for the top/bottom image
|
// Framebuffer for the top/bottom image
|
||||||
std::vector<vk::UniqueImage> screenTexture = {};
|
std::vector<vk::UniqueImage> screenTexture = {};
|
||||||
|
std::vector<vk::UniqueImageView> screenTextureViews = {};
|
||||||
|
std::vector<vk::UniqueFramebuffer> screenTextureFramebuffers = {};
|
||||||
vk::UniqueDeviceMemory framebufferMemory = {};
|
vk::UniqueDeviceMemory framebufferMemory = {};
|
||||||
|
|
||||||
std::map<u64, vk::UniqueRenderPass> renderPassCache;
|
std::map<u64, vk::UniqueRenderPass> renderPassCache;
|
||||||
|
@ -89,9 +92,14 @@ class RendererVK final : public Renderer {
|
||||||
vk::RenderPass getRenderPass(vk::Format colorFormat, std::optional<vk::Format> depthFormat);
|
vk::RenderPass getRenderPass(vk::Format colorFormat, std::optional<vk::Format> depthFormat);
|
||||||
vk::RenderPass getRenderPass(PICA::ColorFmt colorFormat, std::optional<PICA::DepthFmt> depthFormat);
|
vk::RenderPass getRenderPass(PICA::ColorFmt colorFormat, std::optional<PICA::DepthFmt> depthFormat);
|
||||||
|
|
||||||
|
std::unique_ptr<Vulkan::DescriptorUpdateBatch> descriptorUpdateBatch;
|
||||||
|
|
||||||
|
// Display pipeline data
|
||||||
std::unique_ptr<Vulkan::DescriptorHeap> displayDescriptorHeap;
|
std::unique_ptr<Vulkan::DescriptorHeap> displayDescriptorHeap;
|
||||||
vk::UniquePipeline displayPipeline;
|
vk::UniquePipeline displayPipeline;
|
||||||
vk::UniquePipelineLayout displayPipelineLayout;
|
vk::UniquePipelineLayout displayPipelineLayout;
|
||||||
|
std::vector<vk::DescriptorSet> topDisplayPipelineDescriptorSet;
|
||||||
|
std::vector<vk::DescriptorSet> bottomDisplayPipelineDescriptorSet;
|
||||||
|
|
||||||
// Recreate the swapchain, possibly re-using the old one in the case of a resize
|
// Recreate the swapchain, possibly re-using the old one in the case of a resize
|
||||||
vk::Result recreateSwapchain(vk::SurfaceKHR surface, vk::Extent2D swapchainExtent);
|
vk::Result recreateSwapchain(vk::SurfaceKHR surface, vk::Extent2D swapchainExtent);
|
||||||
|
|
|
@ -595,27 +595,53 @@ void RendererVK::display() {
|
||||||
|
|
||||||
//// Render Frame(Simulated - just clear the images to different colors for now)
|
//// Render Frame(Simulated - just clear the images to different colors for now)
|
||||||
{
|
{
|
||||||
static const std::array<float, 4> frameScopeColor = {{1.0f, 0.0f, 1.0f, 1.0f}};
|
static const std::array<float, 4> renderScreenScopeColor = {{1.0f, 0.0f, 1.0f, 1.0f}};
|
||||||
|
|
||||||
Vulkan::DebugLabelScope debugScope(getCurrentCommandBuffer(), frameScopeColor, "Frame");
|
Vulkan::DebugLabelScope debugScope(getCurrentCommandBuffer(), renderScreenScopeColor, "Render Screen");
|
||||||
|
// Prepare screen texture for rendering into
|
||||||
// Prepare images for color-clear
|
|
||||||
getCurrentCommandBuffer().pipelineBarrier(
|
getCurrentCommandBuffer().pipelineBarrier(
|
||||||
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlags(), {}, {},
|
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::DependencyFlags(), {}, {},
|
||||||
{
|
{
|
||||||
vk::ImageMemoryBarrier(
|
vk::ImageMemoryBarrier(
|
||||||
vk::AccessFlagBits::eMemoryRead, vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eUndefined,
|
vk::AccessFlagBits::eMemoryRead, vk::AccessFlagBits::eColorAttachmentWrite, vk::ImageLayout::eUndefined,
|
||||||
vk::ImageLayout::eTransferDstOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, screenTexture[frameBufferingIndex].get(),
|
vk::ImageLayout::eColorAttachmentOptimal, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
|
||||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
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}};
|
vk::RenderPassBeginInfo renderPassBeginInfo = {};
|
||||||
getCurrentCommandBuffer().clearColorImage(
|
renderPassBeginInfo.renderPass = getRenderPass(vk::Format::eR8G8B8A8Unorm, {});
|
||||||
screenTexture[frameBufferingIndex].get(), vk::ImageLayout::eTransferDstOptimal, topClearColor,
|
|
||||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
|
renderPassBeginInfo.framebuffer = screenTextureFramebuffers[frameBufferingIndex].get();
|
||||||
);
|
renderPassBeginInfo.renderArea.offset = vk::Offset2D();
|
||||||
|
renderPassBeginInfo.renderArea.extent = vk::Extent2D(400, 240 * 2);
|
||||||
|
|
||||||
|
getCurrentCommandBuffer().beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline);
|
||||||
|
|
||||||
|
// Render top screen
|
||||||
|
if (topActiveFb) {
|
||||||
|
getCurrentCommandBuffer().bindDescriptorSets(
|
||||||
|
vk::PipelineBindPoint::eGraphics, displayPipelineLayout.get(), 0, {topDisplayPipelineDescriptorSet[frameBufferingIndex]}, {}
|
||||||
|
);
|
||||||
|
getCurrentCommandBuffer().bindPipeline(vk::PipelineBindPoint::eGraphics, displayPipeline.get());
|
||||||
|
getCurrentCommandBuffer().setViewport(0, vk::Viewport(0, 0, 400, 240));
|
||||||
|
getCurrentCommandBuffer().setScissor(0, vk::Rect2D({0, 0}, {400, 240}));
|
||||||
|
getCurrentCommandBuffer().draw(3, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render bottom screen
|
||||||
|
if (bottomActiveFb) {
|
||||||
|
getCurrentCommandBuffer().bindDescriptorSets(
|
||||||
|
vk::PipelineBindPoint::eGraphics, displayPipelineLayout.get(), 0, {bottomDisplayPipelineDescriptorSet[frameBufferingIndex]}, {}
|
||||||
|
);
|
||||||
|
getCurrentCommandBuffer().bindPipeline(vk::PipelineBindPoint::eGraphics, displayPipeline.get());
|
||||||
|
getCurrentCommandBuffer().setViewport(0, vk::Viewport(40, 0, 320, 240));
|
||||||
|
getCurrentCommandBuffer().setScissor(0, vk::Rect2D({40, 0}, {320, 240}));
|
||||||
|
getCurrentCommandBuffer().draw(3, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentCommandBuffer().endRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
//// Present
|
//// Present
|
||||||
|
@ -1049,8 +1075,10 @@ void RendererVK::initGraphicsContext(SDL_Window* window) {
|
||||||
screenTextureInfo.setInitialLayout(vk::ImageLayout::eUndefined);
|
screenTextureInfo.setInitialLayout(vk::ImageLayout::eUndefined);
|
||||||
|
|
||||||
screenTexture.resize(frameBufferingCount);
|
screenTexture.resize(frameBufferingCount);
|
||||||
|
screenTextureViews.resize(frameBufferingCount);
|
||||||
|
screenTextureFramebuffers.resize(frameBufferingCount);
|
||||||
|
|
||||||
for (usize i = 0; i < frameBufferingCount; i++) {
|
for (usize i = 0; i < frameBufferingCount; ++i) {
|
||||||
if (auto createResult = device->createSemaphoreUnique(semaphoreInfo); createResult.result == vk::Result::eSuccess) {
|
if (auto createResult = device->createSemaphoreUnique(semaphoreInfo); createResult.result == vk::Result::eSuccess) {
|
||||||
swapImageFreeSemaphore[i] = std::move(createResult.value);
|
swapImageFreeSemaphore[i] = std::move(createResult.value);
|
||||||
|
|
||||||
|
@ -1093,17 +1121,68 @@ void RendererVK::initGraphicsContext(SDL_Window* window) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Memory is bounded, create views and framebuffer for screentexture
|
||||||
|
vk::ImageViewCreateInfo screenTextureViewCreateInfo = {};
|
||||||
|
screenTextureViewCreateInfo.viewType = vk::ImageViewType::e2D;
|
||||||
|
screenTextureViewCreateInfo.format = vk::Format::eR8G8B8A8Unorm;
|
||||||
|
screenTextureViewCreateInfo.components.r = vk::ComponentSwizzle::eR;
|
||||||
|
screenTextureViewCreateInfo.components.g = vk::ComponentSwizzle::eG;
|
||||||
|
screenTextureViewCreateInfo.components.b = vk::ComponentSwizzle::eB;
|
||||||
|
screenTextureViewCreateInfo.components.a = vk::ComponentSwizzle::eA;
|
||||||
|
screenTextureViewCreateInfo.subresourceRange = {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1};
|
||||||
|
|
||||||
|
for (usize i = 0; i < frameBufferingCount; ++i) {
|
||||||
|
screenTextureViewCreateInfo.image = screenTexture[i].get();
|
||||||
|
|
||||||
|
if (auto createResult = device->createImageViewUnique(screenTextureViewCreateInfo); createResult.result == vk::Result::eSuccess) {
|
||||||
|
screenTextureViews[i] = std::move(createResult.value);
|
||||||
|
} else {
|
||||||
|
Helpers::panic("Error creating screen texture view: %s\n", vk::to_string(createResult.result).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::FramebufferCreateInfo framebufferInfo = {};
|
||||||
|
framebufferInfo.setRenderPass(getRenderPass(vk::Format::eR8G8B8A8Unorm, {}));
|
||||||
|
framebufferInfo.setAttachments(screenTextureViews[i].get());
|
||||||
|
framebufferInfo.setWidth(400);
|
||||||
|
framebufferInfo.setHeight(240 * 2);
|
||||||
|
framebufferInfo.setLayers(1);
|
||||||
|
if (auto createResult = device->createFramebufferUnique(framebufferInfo); createResult.result == vk::Result::eSuccess) {
|
||||||
|
screenTextureFramebuffers[i] = std::move(createResult.value);
|
||||||
|
} else {
|
||||||
|
Helpers::panic("Error creating screen-texture framebuffer: %s\n", vk::to_string(createResult.result).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static vk::DescriptorSetLayoutBinding displayShaderLayout[] = {
|
static vk::DescriptorSetLayoutBinding displayShaderLayout[] = {
|
||||||
{// Just a singular texture slot
|
{// Just a singular texture slot
|
||||||
0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment},
|
0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (auto createResult = Vulkan::DescriptorUpdateBatch::create(device.get()); createResult.has_value()) {
|
||||||
|
descriptorUpdateBatch = std::make_unique<Vulkan::DescriptorUpdateBatch>(std::move(createResult.value()));
|
||||||
|
} else {
|
||||||
|
Helpers::panic("Error creating descriptor update batch\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (auto createResult = Vulkan::DescriptorHeap::create(device.get(), displayShaderLayout); createResult.has_value()) {
|
if (auto createResult = Vulkan::DescriptorHeap::create(device.get(), displayShaderLayout); createResult.has_value()) {
|
||||||
displayDescriptorHeap = std::make_unique<Vulkan::DescriptorHeap>(std::move(createResult.value()));
|
displayDescriptorHeap = std::make_unique<Vulkan::DescriptorHeap>(std::move(createResult.value()));
|
||||||
} else {
|
} else {
|
||||||
Helpers::panic("Error creating descriptor heap\n");
|
Helpers::panic("Error creating descriptor heap\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (usize i = 0; i < frameBufferingCount; ++i) {
|
||||||
|
if (auto allocateResult = displayDescriptorHeap->allocateDescriptorSet(); allocateResult.has_value()) {
|
||||||
|
topDisplayPipelineDescriptorSet.emplace_back(allocateResult.value());
|
||||||
|
} else {
|
||||||
|
Helpers::panic("Error creating descriptor set\n");
|
||||||
|
}
|
||||||
|
if (auto allocateResult = displayDescriptorHeap->allocateDescriptorSet(); allocateResult.has_value()) {
|
||||||
|
bottomDisplayPipelineDescriptorSet.emplace_back(allocateResult.value());
|
||||||
|
} else {
|
||||||
|
Helpers::panic("Error creating descriptor set\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto vk_resources = cmrc::RendererVK::get_filesystem();
|
auto vk_resources = cmrc::RendererVK::get_filesystem();
|
||||||
auto displayVertexShader = vk_resources.open("vulkan_display.vert.spv");
|
auto displayVertexShader = vk_resources.open("vulkan_display.vert.spv");
|
||||||
auto displayFragmentShader = vk_resources.open("vulkan_display.frag.spv");
|
auto displayFragmentShader = vk_resources.open("vulkan_display.frag.spv");
|
||||||
|
|
Loading…
Add table
Reference in a new issue