mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 23:25:40 +12:00
Add cached sampler creation
Using the sampler cache we can maintain a pool of reusable samplers. The `sampler2D` utility function can help make some trivial samplers.
This commit is contained in:
parent
7a86595a1b
commit
0258640da9
2 changed files with 72 additions and 6 deletions
|
@ -6,6 +6,7 @@
|
||||||
#include "vk_api.hpp"
|
#include "vk_api.hpp"
|
||||||
#include "vk_descriptor_heap.hpp"
|
#include "vk_descriptor_heap.hpp"
|
||||||
#include "vk_descriptor_update_batch.hpp"
|
#include "vk_descriptor_update_batch.hpp"
|
||||||
|
#include "vk_sampler_cache.hpp"
|
||||||
|
|
||||||
class GPU;
|
class GPU;
|
||||||
|
|
||||||
|
@ -78,6 +79,7 @@ class RendererVK final : public Renderer {
|
||||||
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);
|
||||||
|
|
||||||
|
Texture* findColorRenderTexture(u32 addr);
|
||||||
Texture& getColorRenderTexture(u32 addr, PICA::ColorFmt format, u32 width, u32 height);
|
Texture& getColorRenderTexture(u32 addr, PICA::ColorFmt format, u32 width, u32 height);
|
||||||
Texture& getDepthRenderTexture(u32 addr, PICA::DepthFmt format, u32 width, u32 height);
|
Texture& getDepthRenderTexture(u32 addr, PICA::DepthFmt format, u32 width, u32 height);
|
||||||
|
|
||||||
|
@ -93,6 +95,7 @@ class RendererVK final : public Renderer {
|
||||||
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;
|
std::unique_ptr<Vulkan::DescriptorUpdateBatch> descriptorUpdateBatch;
|
||||||
|
std::unique_ptr<Vulkan::SamplerCache> samplerCache;
|
||||||
|
|
||||||
// Display pipeline data
|
// Display pipeline data
|
||||||
std::unique_ptr<Vulkan::DescriptorHeap> displayDescriptorHeap;
|
std::unique_ptr<Vulkan::DescriptorHeap> displayDescriptorHeap;
|
||||||
|
|
|
@ -13,6 +13,31 @@
|
||||||
|
|
||||||
CMRC_DECLARE(RendererVK);
|
CMRC_DECLARE(RendererVK);
|
||||||
|
|
||||||
|
static vk::SamplerCreateInfo sampler2D(bool filtered = true, bool clamp = false) {
|
||||||
|
vk::SamplerCreateInfo samplerInfo = {};
|
||||||
|
samplerInfo.magFilter = filtered ? vk::Filter::eLinear : vk::Filter::eNearest;
|
||||||
|
samplerInfo.minFilter = filtered ? vk::Filter::eLinear : vk::Filter::eNearest;
|
||||||
|
|
||||||
|
samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
|
||||||
|
|
||||||
|
samplerInfo.addressModeU = clamp ? vk::SamplerAddressMode::eClampToEdge : vk::SamplerAddressMode::eRepeat;
|
||||||
|
samplerInfo.addressModeV = clamp ? vk::SamplerAddressMode::eClampToEdge : vk::SamplerAddressMode::eRepeat;
|
||||||
|
samplerInfo.addressModeW = clamp ? vk::SamplerAddressMode::eClampToEdge : vk::SamplerAddressMode::eRepeat;
|
||||||
|
|
||||||
|
samplerInfo.mipLodBias = 0.0f;
|
||||||
|
samplerInfo.anisotropyEnable = VK_FALSE;
|
||||||
|
samplerInfo.maxAnisotropy = 16.0f;
|
||||||
|
|
||||||
|
samplerInfo.compareEnable = VK_FALSE;
|
||||||
|
samplerInfo.compareOp = vk::CompareOp::eAlways;
|
||||||
|
|
||||||
|
samplerInfo.minLod = 0.0f;
|
||||||
|
samplerInfo.maxLod = VK_LOD_CLAMP_NONE;
|
||||||
|
samplerInfo.borderColor = vk::BorderColor::eFloatTransparentBlack;
|
||||||
|
samplerInfo.unnormalizedCoordinates = VK_FALSE;
|
||||||
|
return samplerInfo;
|
||||||
|
}
|
||||||
|
|
||||||
static vk::UniqueShaderModule createShaderModule(vk::Device device, std::span<const std::byte> shaderCode) {
|
static vk::UniqueShaderModule createShaderModule(vk::Device device, std::span<const std::byte> shaderCode) {
|
||||||
vk::ShaderModuleCreateInfo shaderModuleInfo = {};
|
vk::ShaderModuleCreateInfo shaderModuleInfo = {};
|
||||||
shaderModuleInfo.pCode = reinterpret_cast<const u32*>(shaderCode.data());
|
shaderModuleInfo.pCode = reinterpret_cast<const u32*>(shaderCode.data());
|
||||||
|
@ -200,14 +225,37 @@ static u32 rotl32(u32 x, u32 n) { return (x << n) | (x >> (32 - n)); }
|
||||||
static u32 ror32(u32 x, u32 n) { return (x >> n) | (x << (32 - n)); }
|
static u32 ror32(u32 x, u32 n) { return (x >> n) | (x << (32 - n)); }
|
||||||
|
|
||||||
u32 RendererVK::colorBufferHash(u32 loc, u32 size, PICA::ColorFmt format) {
|
u32 RendererVK::colorBufferHash(u32 loc, u32 size, PICA::ColorFmt format) {
|
||||||
return rotl32(loc, 17) ^ ror32(size, 23) ^ (static_cast<u64>(format) << 60);
|
return loc | (static_cast<u64>(ror32(size, 23) ^ (static_cast<u32>(format))) << 32);
|
||||||
}
|
}
|
||||||
u32 RendererVK::depthBufferHash(u32 loc, u32 size, PICA::DepthFmt format) {
|
u32 RendererVK::depthBufferHash(u32 loc, u32 size, PICA::DepthFmt format) {
|
||||||
return rotl32(loc, 17) ^ ror32(size, 29) ^ (static_cast<u64>(format) << 60);
|
return loc | (static_cast<u64>(ror32(size, 29) ^ (static_cast<u32>(format))) << 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
RendererVK::Texture* RendererVK::findColorRenderTexture(u32 addr) {
|
||||||
|
const auto lower = textureCache.lower_bound(addr);
|
||||||
|
|
||||||
|
if (lower == textureCache.end()) {
|
||||||
|
// Not found
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lower == textureCache.begin()) {
|
||||||
|
return &lower->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture* texture = &lower->second;
|
||||||
|
|
||||||
|
const usize sizeInBytes = texture->size[0] * texture->size[1] * texture->sizePerPixel;
|
||||||
|
|
||||||
|
if ((addr - lower->second.loc) <= sizeInBytes) {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererVK::Texture& RendererVK::getColorRenderTexture(u32 addr, PICA::ColorFmt format, u32 width, u32 height) {
|
RendererVK::Texture& RendererVK::getColorRenderTexture(u32 addr, PICA::ColorFmt format, u32 width, u32 height) {
|
||||||
const u32 renderTextureHash = colorBufferHash(addr, width * height * PICA::sizePerPixel(format), format);
|
const u64 renderTextureHash = colorBufferHash(addr, width * height * PICA::sizePerPixel(format), format);
|
||||||
|
|
||||||
// Cache hit
|
// Cache hit
|
||||||
if (textureCache.contains(renderTextureHash)) {
|
if (textureCache.contains(renderTextureHash)) {
|
||||||
|
@ -265,7 +313,7 @@ RendererVK::Texture& RendererVK::getColorRenderTexture(u32 addr, PICA::ColorFmt
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererVK::Texture& RendererVK::getDepthRenderTexture(u32 addr, PICA::DepthFmt format, u32 width, u32 height) {
|
RendererVK::Texture& RendererVK::getDepthRenderTexture(u32 addr, PICA::DepthFmt format, u32 width, u32 height) {
|
||||||
const u32 renderTextureHash = depthBufferHash(addr, width * height * PICA::sizePerPixel(format), format);
|
const u64 renderTextureHash = depthBufferHash(addr, width * height * PICA::sizePerPixel(format), format);
|
||||||
|
|
||||||
// Cache hit
|
// Cache hit
|
||||||
if (textureCache.contains(renderTextureHash)) {
|
if (textureCache.contains(renderTextureHash)) {
|
||||||
|
@ -620,7 +668,10 @@ void RendererVK::display() {
|
||||||
getCurrentCommandBuffer().beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline);
|
getCurrentCommandBuffer().beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline);
|
||||||
|
|
||||||
// Render top screen
|
// Render top screen
|
||||||
if (topActiveFb) {
|
if (Texture* topScreen = findColorRenderTexture(topScreenAddr); topScreen) {
|
||||||
|
descriptorUpdateBatch->addImageSampler(
|
||||||
|
topDisplayPipelineDescriptorSet[frameBufferingIndex], 0, topScreen->imageView.get(), samplerCache->getSampler(sampler2D())
|
||||||
|
);
|
||||||
getCurrentCommandBuffer().bindDescriptorSets(
|
getCurrentCommandBuffer().bindDescriptorSets(
|
||||||
vk::PipelineBindPoint::eGraphics, displayPipelineLayout.get(), 0, {topDisplayPipelineDescriptorSet[frameBufferingIndex]}, {}
|
vk::PipelineBindPoint::eGraphics, displayPipelineLayout.get(), 0, {topDisplayPipelineDescriptorSet[frameBufferingIndex]}, {}
|
||||||
);
|
);
|
||||||
|
@ -631,7 +682,10 @@ void RendererVK::display() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render bottom screen
|
// Render bottom screen
|
||||||
if (bottomActiveFb) {
|
if (Texture* bottomScreen = findColorRenderTexture(bottomScreenAddr); bottomScreenAddr) {
|
||||||
|
descriptorUpdateBatch->addImageSampler(
|
||||||
|
bottomDisplayPipelineDescriptorSet[frameBufferingIndex], 0, bottomScreen->imageView.get(), samplerCache->getSampler(sampler2D())
|
||||||
|
);
|
||||||
getCurrentCommandBuffer().bindDescriptorSets(
|
getCurrentCommandBuffer().bindDescriptorSets(
|
||||||
vk::PipelineBindPoint::eGraphics, displayPipelineLayout.get(), 0, {bottomDisplayPipelineDescriptorSet[frameBufferingIndex]}, {}
|
vk::PipelineBindPoint::eGraphics, displayPipelineLayout.get(), 0, {bottomDisplayPipelineDescriptorSet[frameBufferingIndex]}, {}
|
||||||
);
|
);
|
||||||
|
@ -698,6 +752,9 @@ void RendererVK::display() {
|
||||||
Helpers::panic("Error ending command buffer recording: %s\n", vk::to_string(endResult).c_str());
|
Helpers::panic("Error ending command buffer recording: %s\n", vk::to_string(endResult).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flush all descriptor writes
|
||||||
|
descriptorUpdateBatch->flush();
|
||||||
|
|
||||||
vk::SubmitInfo submitInfo = {};
|
vk::SubmitInfo submitInfo = {};
|
||||||
// Wait for any previous uses of the image image to finish presenting
|
// Wait for any previous uses of the image image to finish presenting
|
||||||
std::vector<vk::Semaphore> waitSemaphores;
|
std::vector<vk::Semaphore> waitSemaphores;
|
||||||
|
@ -1164,6 +1221,12 @@ void RendererVK::initGraphicsContext(SDL_Window* window) {
|
||||||
Helpers::panic("Error creating descriptor update batch\n");
|
Helpers::panic("Error creating descriptor update batch\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auto createResult = Vulkan::SamplerCache::create(device.get()); createResult.has_value()) {
|
||||||
|
samplerCache = std::make_unique<Vulkan::SamplerCache>(std::move(createResult.value()));
|
||||||
|
} else {
|
||||||
|
Helpers::panic("Error creating sampler cache\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 {
|
||||||
|
|
Loading…
Add table
Reference in a new issue