From 3f503ca29730203ec58cc7dda671bc17b720c114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 30 Oct 2017 15:50:02 +0100 Subject: [PATCH] Implement the rest of Vulkan framebuffer depal. Not yet working though. --- Common/Vulkan/VulkanImage.cpp | 2 ++ GPU/Common/DepalettizeShaderCommon.cpp | 4 +-- GPU/Vulkan/DepalettizeShaderVulkan.cpp | 41 +++++++++++++++++++------- GPU/Vulkan/DepalettizeShaderVulkan.h | 1 - GPU/Vulkan/TextureCacheVulkan.cpp | 26 +++++++++++++--- GPU/Vulkan/TextureCacheVulkan.h | 6 ++-- ext/native/thin3d/thin3d_vulkan.cpp | 3 +- 7 files changed, 62 insertions(+), 21 deletions(-) diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 41cf32c824..0c0a5ff061 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -269,6 +269,8 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, 0, VK_ACCESS_TRANSFER_WRITE_BIT); break; default: + // If you planned to use UploadMip, you want VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL. After the + // upload, you can transition. assert(false); break; } diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index b3d860870f..340d26ded3 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -44,7 +44,7 @@ void GenerateDepalShader300(char *buffer, GEBufferFormat pixelFormat, ShaderLang WRITE(p, "layout(set = 0, binding = 0) uniform sampler2D tex;\n"); WRITE(p, "layout(set = 0, binding = 1) uniform sampler2D pal;\n"); WRITE(p, "layout(location = 0) in vec2 v_texcoord0;\n"); - WRITE(p, "layout(location = 0) out vec4 fragColor0\n;"); + WRITE(p, "layout(location = 0) out vec4 fragColor0;\n"); } else { if (gl_extensions.IsGLES) { WRITE(p, "#version 300 es\n"); @@ -288,4 +288,4 @@ void GenerateDepalShader(char *buffer, GEBufferFormat pixelFormat, ShaderLanguag } } -#undef WRITE \ No newline at end of file +#undef WRITE diff --git a/GPU/Vulkan/DepalettizeShaderVulkan.cpp b/GPU/Vulkan/DepalettizeShaderVulkan.cpp index c785ee4372..e5814eafb2 100644 --- a/GPU/Vulkan/DepalettizeShaderVulkan.cpp +++ b/GPU/Vulkan/DepalettizeShaderVulkan.cpp @@ -22,6 +22,19 @@ #include "GPU/Vulkan/VulkanUtil.h" #include "Common/Vulkan/VulkanImage.h" +static const char depal_vs[] = R"(#version 400 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable +layout (location = 0) in vec3 a_position; +layout (location = 1) in vec2 a_texcoord0; +layout (location = 0) out vec2 v_texcoord0; +out gl_PerVertex { vec4 gl_Position; }; +void main() { + v_texcoord0 = a_texcoord0; + gl_Position = vec4(a_position, 1.0); +} +)"; + static VkFormat GetClutDestFormat(GEPaletteFormat format) { switch (format) { case GE_CMODE_16BIT_ABGR4444: @@ -38,11 +51,14 @@ static VkFormat GetClutDestFormat(GEPaletteFormat format) { DepalShaderCacheVulkan::DepalShaderCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan) : draw_(draw), vulkan_(vulkan) { - + std::string errors; + vshader_ = CompileShaderModule(vulkan_, VK_SHADER_STAGE_VERTEX_BIT, depal_vs, &errors); + assert(vshader_ != VK_NULL_HANDLE); } DepalShaderCacheVulkan::~DepalShaderCacheVulkan() { - + Clear(); + vulkan_->Delete().QueueDeleteShaderModule(vshader_); } DepalShaderVulkan *DepalShaderCacheVulkan::GetDepalettizeShader(uint32_t clutMode, GEBufferFormat pixelFormat) { @@ -53,15 +69,16 @@ DepalShaderVulkan *DepalShaderCacheVulkan::GetDepalettizeShader(uint32_t clutMod return shader->second; } - char *buffer = new char[2048]; - VkRenderPass rp = (VkRenderPass)draw_->GetNativeObject(Draw::NativeObject::FRAMEBUFFER_RENDERPASS); + char *buffer = new char[2048]; GenerateDepalShader(buffer, pixelFormat, GLSL_VULKAN); std::string error; VkShaderModule fshader = CompileShaderModule(vulkan_, VK_SHADER_STAGE_FRAGMENT_BIT, buffer, &error); if (fshader == VK_NULL_HANDLE) { + Crash(); + delete[] buffer; return nullptr; } @@ -74,10 +91,11 @@ DepalShaderVulkan *DepalShaderCacheVulkan::GetDepalettizeShader(uint32_t clutMod depal->pipeline = pipeline; depal->code = buffer; cache_[id] = depal; - return nullptr; + return depal; } VulkanTexture *DepalShaderCacheVulkan::GetClutTexture(GEPaletteFormat clutFormat, u32 clutID, u32 *rawClut) { + VkCommandBuffer cmd = (VkCommandBuffer)draw_->GetNativeObject(Draw::NativeObject::INIT_COMMANDBUFFER); const u32 realClutID = clutID ^ clutFormat; auto oldtex = texCache_.find(realClutID); @@ -93,9 +111,12 @@ VulkanTexture *DepalShaderCacheVulkan::GetClutTexture(GEPaletteFormat clutFormat uint32_t pushOffset = push_->PushAligned(rawClut, 1024, 4, &pushBuffer); VulkanTexture *vktex = new VulkanTexture(vulkan_, alloc_); - vktex->CreateDirect(cmd_, texturePixels, 1, 1, destFormat, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT, nullptr); - vktex->UploadMip(cmd_, 0, texturePixels, 1, pushBuffer, pushOffset, texturePixels); - vktex->EndCreate(cmd_); + if (!vktex->CreateDirect(cmd, texturePixels, 1, 1, destFormat, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, nullptr)) { + Crash(); + } + vktex->UploadMip(cmd, 0, texturePixels, 1, pushBuffer, pushOffset, texturePixels); + vktex->EndCreate(cmd); DepalTextureVulkan *tex = new DepalTextureVulkan(); tex->texture = vktex; @@ -107,6 +128,8 @@ VulkanTexture *DepalShaderCacheVulkan::GetClutTexture(GEPaletteFormat clutFormat void DepalShaderCacheVulkan::Clear() { for (auto shader = cache_.begin(); shader != cache_.end(); ++shader) { // Delete the shader/pipeline too. + vulkan_->Delete().QueueDeletePipeline(shader->second->pipeline); + delete[] shader->second->code; delete shader->second; } cache_.clear(); @@ -116,8 +139,6 @@ void DepalShaderCacheVulkan::Clear() { delete tex->second; } texCache_.clear(); - - // TODO: Delete vertex shader. } void DepalShaderCacheVulkan::Decimate() { diff --git a/GPU/Vulkan/DepalettizeShaderVulkan.h b/GPU/Vulkan/DepalettizeShaderVulkan.h index fb2c3db4a4..4762f07d2c 100644 --- a/GPU/Vulkan/DepalettizeShaderVulkan.h +++ b/GPU/Vulkan/DepalettizeShaderVulkan.h @@ -66,7 +66,6 @@ public: private: u32 GenerateShaderID(uint32_t clutMode, GEBufferFormat pixelFormat); - VkCommandBuffer cmd_ = VK_NULL_HANDLE; Draw::DrawContext *draw_ = nullptr; VulkanContext *vulkan_ = nullptr; VulkanPushBuffer *push_ = nullptr; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index ce5124aaa1..7d9fb06710 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -23,6 +23,8 @@ #include "math/math_util.h" #include "profiler/profiler.h" #include "thin3d/thin3d.h" +#include "thin3d/VulkanRenderManager.h" + #include "Common/ColorConv.h" #include "Core/Config.h" #include "Core/Host.h" @@ -130,10 +132,19 @@ TextureCacheVulkan::TextureCacheVulkan(Draw::DrawContext *draw, VulkanContext *v lastBoundTexture = nullptr; allocator_ = new VulkanDeviceAllocator(vulkan_, TEXCACHE_MIN_SLAB_SIZE, TEXCACHE_MAX_SLAB_SIZE); + VkSamplerCreateInfo samp{ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; + samp.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samp.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samp.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samp.magFilter = VK_FILTER_NEAREST; + samp.minFilter = VK_FILTER_NEAREST; + samp.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + vkCreateSampler(vulkan_->GetDevice(), &samp, nullptr, &samplerNearest_); SetupTextureDecoder(); } TextureCacheVulkan::~TextureCacheVulkan() { + vulkan_->Delete().QueueDeleteSampler(samplerNearest_); Clear(true); if (allocator_) { @@ -333,19 +344,19 @@ void TextureCacheVulkan::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutB void TextureCacheVulkan::BindTexture(TexCacheEntry *entry) { if (!entry || !entry->vkTex) { imageView_ = VK_NULL_HANDLE; - sampler_ = VK_NULL_HANDLE; + curSampler_ = VK_NULL_HANDLE; return; } imageView_ = entry->vkTex->texture_->GetImageView(); SamplerCacheKey key; UpdateSamplingParams(*entry, key); - sampler_ = samplerCache_.GetOrCreateSampler(key); + curSampler_ = samplerCache_.GetOrCreateSampler(key); } void TextureCacheVulkan::Unbind() { imageView_ = VK_NULL_HANDLE; - sampler_ = VK_NULL_HANDLE; + curSampler_ = VK_NULL_HANDLE; InvalidateLastTexture(); } @@ -413,6 +424,13 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFr verts[3].v = uvtop; } + VkBuffer pushed; + uint32_t offset = push_->PushAligned(verts, sizeof(verts), 4, &pushed); + VkImageView fbo = (VkImageView)draw_->GetFramebufferAPITexture(framebuffer->fbo, Draw::FB_COLOR_BIT, 0); + + VkDescriptorSet descSet = vulkan2D_->GetDescriptorSet(fbo, samplerNearest_, clutTexture->GetImageView(), samplerNearest_); + VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + renderManager->Draw(vulkan2D_->GetPipelineLayout(), descSet, 0, nullptr, pushed, offset, 4); shaderManagerVulkan_->DirtyLastShader(); const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16); @@ -435,7 +453,7 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFr SamplerCacheKey samplerKey; SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, samplerKey); - sampler_ = samplerCache_.GetOrCreateSampler(samplerKey); + curSampler_ = samplerCache_.GetOrCreateSampler(samplerKey); InvalidateLastTexture(entry); } diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index cae31787bb..1b168fd0f5 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -101,7 +101,7 @@ public: void GetVulkanHandles(VkImageView &imageView, VkSampler &sampler) { imageView = imageView_; - sampler = sampler_; + sampler = curSampler_; } void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); @@ -144,7 +144,9 @@ private: // Bound state to emulate an API similar to the others VkImageView imageView_ = VK_NULL_HANDLE; - VkSampler sampler_ = VK_NULL_HANDLE; + VkSampler curSampler_ = VK_NULL_HANDLE; + + VkSampler samplerNearest_ = VK_NULL_HANDLE; }; VkFormat getClutDestFormatVulkan(GEPaletteFormat format); diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index b031b89e76..3a05ae2813 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -1140,7 +1140,6 @@ void VKContext::DrawUP(const void *vdata, int vertexCount) { renderManager_.Draw(pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset, vertexCount); } -// TODO: We should avoid this function as much as possible, instead use renderpass on-load clearing. void VKContext::Clear(int clearMask, uint32_t colorval, float depthVal, int stencilVal) { int mask = 0; if (clearMask & FBChannel::FB_COLOR_BIT) @@ -1359,9 +1358,9 @@ void VKContext::HandleEvent(Event ev, int width, int height, void *param1, void renderManager_.CreateBackbuffers(); break; default: + assert(false); break; } - // Noop } } // namespace Draw