Some reorganization. Start implementing framebuffer depal for Vulkan.

This commit is contained in:
Henrik Rydgård committed 2017-10-31 12:34:31 +01:00
1 parent 6253280fba
commit 65e23bb9f3
13 files changed
+295 -161

No files matched your search

+2
View File
@@ -20,4 +20,6 @@
#include "GPU/ge_constants.h"
#include "GPU/Common/ShaderCommon.h"
static const int DEPAL_TEXTURE_OLD_AGE = 120;
void GenerateDepalShader(char *buffer, GEBufferFormat pixelFormat, ShaderLanguage language);
-2
View File
@@ -29,8 +29,6 @@
#include "GPU/D3D11/D3D11Util.h"
#include "GPU/Common/DepalettizeShaderCommon.h"
static const int DEPAL_TEXTURE_OLD_AGE = 120;
#ifdef _WIN32
#define SHADERLOG
#endif
-2
View File
@@ -26,8 +26,6 @@
#include "ext/native/gfx/GLStateCache.h"
#include "GPU/Common/DepalettizeShaderCommon.h"
static const int DEPAL_TEXTURE_OLD_AGE = 120;
#ifdef _WIN32
#define SHADERLOG
#endif
+102 -11
View File
@@ -15,10 +15,29 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Common/Vulkan/VulkanContext.h"
#include "GPU/GPUState.h"
#include "GPU/Common/DepalettizeShaderCommon.h"
#include "GPU/Vulkan/DepalettizeShaderVulkan.h"
#include "GPU/Vulkan/VulkanUtil.h"
#include "Common/Vulkan/VulkanImage.h"
DepalShaderCacheVulkan::DepalShaderCacheVulkan() {
static VkFormat GetClutDestFormat(GEPaletteFormat format) {
switch (format) {
case GE_CMODE_16BIT_ABGR4444:
return VK_FORMAT_R4G4B4A4_UNORM_PACK16;
case GE_CMODE_16BIT_ABGR5551:
return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
case GE_CMODE_16BIT_BGR5650:
return VK_FORMAT_R5G6B5_UNORM_PACK16;
case GE_CMODE_32BIT_ABGR8888:
return VK_FORMAT_R8G8B8A8_UNORM;
}
return VK_FORMAT_UNDEFINED;
}
DepalShaderCacheVulkan::DepalShaderCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan)
: draw_(draw), vulkan_(vulkan) {
}
@@ -26,22 +45,94 @@ DepalShaderCacheVulkan::~DepalShaderCacheVulkan() {
}
DepalShaderVulkan *DepalShaderCacheVulkan::GetDepalettizeShader(GEPaletteFormat clutFormat, GEBufferFormat pixelFormat) {
DepalShaderVulkan *DepalShaderCacheVulkan::GetDepalettizeShader(uint32_t clutMode, GEBufferFormat pixelFormat) {
u32 id = GenerateShaderID(clutMode, pixelFormat);
auto shader = cache_.find(id);
if (shader != cache_.end()) {
return shader->second;
}
char *buffer = new char[2048];
VkRenderPass rp = (VkRenderPass)draw_->GetNativeObject(Draw::NativeObject::FRAMEBUFFER_RENDERPASS);
GenerateDepalShader(buffer, pixelFormat, GLSL_VULKAN);
std::string error;
VkShaderModule fshader = CompileShaderModule(vulkan_, VK_SHADER_STAGE_FRAGMENT_BIT, buffer, &error);
if (fshader == VK_NULL_HANDLE) {
return nullptr;
}
VkPipeline pipeline = vulkan2D_->GetPipeline(rp, vshader_, fshader);
// Can delete the shader module now that the pipeline has been created.
// Maybe don't even need to queue it..
vulkan_->Delete().QueueDeleteShaderModule(fshader);
DepalShaderVulkan *depal = new DepalShaderVulkan();
depal->pipeline = pipeline;
depal->code = buffer;
cache_[id] = depal;
return nullptr;
}
VulkanTexture *DepalShaderCacheVulkan::GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, u32 *rawClut) {
return nullptr;
VulkanTexture *DepalShaderCacheVulkan::GetClutTexture(GEPaletteFormat clutFormat, u32 clutID, u32 *rawClut) {
const u32 realClutID = clutID ^ clutFormat;
auto oldtex = texCache_.find(realClutID);
if (oldtex != texCache_.end()) {
oldtex->second->lastFrame = gpuStats.numFlips;
return oldtex->second->texture;
}
VkFormat destFormat = GetClutDestFormat(clutFormat);
int texturePixels = clutFormat == GE_CMODE_32BIT_ABGR8888 ? 256 : 512;
VkBuffer pushBuffer;
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_);
DepalTextureVulkan *tex = new DepalTextureVulkan();
tex->texture = vktex;
tex->lastFrame = gpuStats.numFlips;
texCache_[realClutID] = tex;
return tex->texture;
}
void DepalShaderCacheVulkan::Clear() {}
void DepalShaderCacheVulkan::Clear() {
for (auto shader = cache_.begin(); shader != cache_.end(); ++shader) {
// Delete the shader/pipeline too.
delete shader->second;
}
cache_.clear();
void DepalShaderCacheVulkan::Decimate() {}
for (auto tex = texCache_.begin(); tex != texCache_.end(); ++tex) {
delete tex->second->texture;
delete tex->second;
}
texCache_.clear();
u32 DepalShaderCacheVulkan::GenerateShaderID(GEPaletteFormat clutFormat, GEBufferFormat pixelFormat) {
return 0;
// TODO: Delete vertex shader.
}
bool DepalShaderCacheVulkan::CreateVertexShader() {
return false;
void DepalShaderCacheVulkan::Decimate() {
// We don't bother decimating the generated shaders, there are never very many of them.
for (auto tex = texCache_.begin(); tex != texCache_.end(); ) {
if (tex->second->lastFrame + DEPAL_TEXTURE_OLD_AGE < gpuStats.numFlips) {
delete tex->second->texture;
delete tex->second;
texCache_.erase(tex++);
} else {
++tex;
}
}
}
u32 DepalShaderCacheVulkan::GenerateShaderID(uint32_t clutMode, GEBufferFormat pixelFormat) {
return (clutMode & 0xFFFFFF) | (pixelFormat << 24);
}
+28 -11
View File
@@ -20,42 +20,59 @@
#include <map>
#include "Common/CommonTypes.h"
#include "Common/Vulkan/VulkanContext.h"
#include "Common/Vulkan/VulkanImage.h"
#include "Common/Vulkan/VulkanMemory.h"
#include "GPU/ge_constants.h"
#include "thin3d/thin3d.h"
class DepalShaderVulkan {
public:
/*
GLuint program;
GLuint fragShader;
GLint a_position;
GLint a_texcoord0;
*/
~DepalShaderVulkan() {
delete[] code;
}
// A Vulkan2D pipeline. Set texture to slot 0 and palette texture to slot 1.
VkPipeline pipeline;
const char *code = nullptr;;
};
class DepalTextureVulkan {
public:
int texture;
VulkanTexture *texture;
int lastFrame;
};
class VulkanTexture;
class Vulkan2D;
// Caches both shaders and palette textures.
// Could even avoid bothering with palette texture and just use uniform data...
class DepalShaderCacheVulkan {
public:
DepalShaderCacheVulkan();
DepalShaderCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan);
~DepalShaderCacheVulkan();
// This also uploads the palette and binds the correct texture.
DepalShaderVulkan *GetDepalettizeShader(GEPaletteFormat clutFormat, GEBufferFormat pixelFormat);
DepalShaderVulkan *GetDepalettizeShader(uint32_t clutMode, GEBufferFormat pixelFormat);
VulkanTexture *GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, u32 *rawClut);
void Clear();
void Decimate();
void SetVulkan2D(Vulkan2D *vk2d) { vulkan2D_ = vk2d; }
void SetPushBuffer(VulkanPushBuffer *push) { push_ = push; }
void SetAllocator(VulkanDeviceAllocator *alloc) { alloc_ = alloc; }
void SetVShader(VkShaderModule vshader) { vshader_ = vshader; }
private:
u32 GenerateShaderID(GEPaletteFormat clutFormat, GEBufferFormat pixelFormat);
bool CreateVertexShader();
u32 GenerateShaderID(uint32_t clutMode, GEBufferFormat pixelFormat);
VkCommandBuffer cmd_ = VK_NULL_HANDLE;
Draw::DrawContext *draw_ = nullptr;
VulkanContext *vulkan_ = nullptr;
VulkanPushBuffer *push_ = nullptr;
VulkanDeviceAllocator *alloc_ = nullptr;
VkShaderModule vshader_ = VK_NULL_HANDLE;
Vulkan2D *vulkan2D_ = nullptr;
// GLuint vertexShader_;
std::map<u32, DepalShaderVulkan *> cache_;
+27 -68
View File
@@ -88,9 +88,8 @@ FramebufferManagerVulkan::FramebufferManagerVulkan(Draw::DrawContext *draw, Vulk
convBufSize_(0),
textureCacheVulkan_(nullptr),
shaderManagerVulkan_(nullptr),
curFrame_(0),
pipelinePostShader_(VK_NULL_HANDLE),
vulkan2D_(vulkan) {
depalVulkan_(draw, vulkan) {
InitDeviceObjects();
@@ -101,7 +100,6 @@ FramebufferManagerVulkan::FramebufferManagerVulkan(Draw::DrawContext *draw, Vulk
FramebufferManagerVulkan::~FramebufferManagerVulkan() {
delete[] convBuf_;
vulkan2D_.Shutdown();
DestroyDeviceObjects();
}
@@ -121,23 +119,12 @@ void FramebufferManagerVulkan::SetDrawEngine(DrawEngineVulkan *td) {
}
void FramebufferManagerVulkan::InitDeviceObjects() {
// Initialize framedata
for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
frameData_[i].push_ = new VulkanPushBuffer(vulkan_, 64 * 1024);
}
pipelineCache2D_ = vulkan_->CreatePipelineCache();
std::string fs_errors, vs_errors;
fsBasicTex_ = CompileShaderModule(vulkan_, VK_SHADER_STAGE_FRAGMENT_BIT, tex_fs, &fs_errors);
vsBasicTex_ = CompileShaderModule(vulkan_, VK_SHADER_STAGE_VERTEX_BIT, tex_vs, &vs_errors);
assert(fsBasicTex_ != VK_NULL_HANDLE);
assert(vsBasicTex_ != VK_NULL_HANDLE);
// Prime the 2D pipeline cache.
// vulkan2D_.GetPipeline(pipelineCache2D_, (VkRenderPass)draw_->GetNativeObject(Draw::NativeObject::BACKBUFFER_RENDERPASS), vsBasicTex_, fsBasicTex_);
// vulkan2D_.GetPipeline(pipelineCache2D_, (VkRenderPass)draw_->GetNativeObject(Draw::NativeObject::FRAMEBUFFER_RENDERPASS), vsBasicTex_, fsBasicTex_);
VkSamplerCreateInfo samp = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
samp.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samp.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
@@ -153,13 +140,6 @@ void FramebufferManagerVulkan::InitDeviceObjects() {
}
void FramebufferManagerVulkan::DestroyDeviceObjects() {
for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
if (frameData_[i].push_) {
frameData_[i].push_->Destroy(vulkan_);
delete frameData_[i].push_;
frameData_[i].push_ = nullptr;
}
}
delete drawPixelsTex_;
drawPixelsTex_ = nullptr;
@@ -172,32 +152,29 @@ void FramebufferManagerVulkan::DestroyDeviceObjects() {
vulkan_->Delete().QueueDeleteSampler(linearSampler_);
if (nearestSampler_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeleteSampler(nearestSampler_);
// pipelineBasicTex_ and pipelineBasicTex_ come from vulkan2D_.
if (pipelineCache2D_ != VK_NULL_HANDLE)
vulkan_->Delete().QueueDeletePipelineCache(pipelineCache2D_);
}
void FramebufferManagerVulkan::NotifyClear(bool clearColor, bool clearAlpha, bool clearDepth, uint32_t color, float depth) {
float x, y, w, h;
CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)pixelWidth_, (float)pixelHeight_, ROTATION_LOCKED_HORIZONTAL);
float x, y, w, h;
CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)pixelWidth_, (float)pixelHeight_, ROTATION_LOCKED_HORIZONTAL);
int mask = 0;
// The Clear detection takes care of doing a regular draw instead if separate masking
// of color and alpha is needed, so we can just treat them as the same.
if (clearColor || clearAlpha)
mask |= Draw::FBChannel::FB_COLOR_BIT;
if (clearDepth)
mask |= Draw::FBChannel::FB_DEPTH_BIT;
if (clearAlpha)
mask |= Draw::FBChannel::FB_STENCIL_BIT;
int mask = 0;
// The Clear detection takes care of doing a regular draw instead if separate masking
// of color and alpha is needed, so we can just treat them as the same.
if (clearColor || clearAlpha)
mask |= Draw::FBChannel::FB_COLOR_BIT;
if (clearDepth)
mask |= Draw::FBChannel::FB_DEPTH_BIT;
if (clearAlpha)
mask |= Draw::FBChannel::FB_STENCIL_BIT;
draw_->Clear(mask, color, depth, 0);
if (clearColor || clearAlpha) {
SetColorUpdated(gstate_c.skipDrawReason);
}
if (clearDepth) {
SetDepthUpdated();
}
draw_->Clear(mask, color, depth, 0);
if (clearColor || clearAlpha) {
SetColorUpdated(gstate_c.skipDrawReason);
}
if (clearDepth) {
SetDepthUpdated();
}
}
void FramebufferManagerVulkan::UpdatePostShaderUniforms(int bufferWidth, int bufferHeight, int renderWidth, int renderHeight) {
@@ -242,6 +219,7 @@ void FramebufferManagerVulkan::MakePixelTexture(const u8 *srcPixels, GEBufferFor
// Initialize backbuffer texture for DrawPixels
drawPixelsTexFormat_ = srcPixelFormat;
} else {
// TODO: We may want to double-buffer these, when we have more frames hanging about.
drawPixelsTex_->TransitionForUpload(initCmd);
}
@@ -298,7 +276,7 @@ void FramebufferManagerVulkan::MakePixelTexture(const u8 *srcPixels, GEBufferFor
}
VkBuffer buffer;
size_t offset = frameData_[curFrame_].push_->Push(data, width * height * 4, &buffer);
size_t offset = push_->Push(data, width * height * 4, &buffer);
drawPixelsTex_->UploadMip(initCmd, 0, width, height, buffer, (uint32_t)offset, width);
drawPixelsTex_->EndCreate(initCmd);
@@ -357,22 +335,21 @@ void FramebufferManagerVulkan::DrawActiveTexture(float x, float y, float w, floa
// TODO: Should probably use draw_ directly and not go low level
VulkanPushBuffer *push = frameData_[curFrame_].push_;
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
VkImageView view = overrideImageView_ ? overrideImageView_ : (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE_IMAGEVIEW);
if ((flags & DRAWTEX_KEEP_TEX) == 0)
overrideImageView_ = VK_NULL_HANDLE;
VkDescriptorSet descSet = vulkan2D_.GetDescriptorSet(view, (flags & DRAWTEX_LINEAR) ? linearSampler_ : nearestSampler_, VK_NULL_HANDLE, VK_NULL_HANDLE);
VkDescriptorSet descSet = vulkan2D_->GetDescriptorSet(view, (flags & DRAWTEX_LINEAR) ? linearSampler_ : nearestSampler_, VK_NULL_HANDLE, VK_NULL_HANDLE);
VkBuffer vbuffer;
VkDeviceSize offset = push->Push(vtx, sizeof(vtx), &vbuffer);
VkDeviceSize offset = push_->Push(vtx, sizeof(vtx), &vbuffer);
renderManager->BindPipeline(cur2DPipeline_);
renderManager->Draw(vulkan2D_.GetPipelineLayout(), descSet, 0, nullptr, vbuffer, offset, 4);
renderManager->Draw(vulkan2D_->GetPipelineLayout(), descSet, 0, nullptr, vbuffer, offset, 4);
}
void FramebufferManagerVulkan::Bind2DShader() {
VkRenderPass rp = (VkRenderPass)draw_->GetNativeObject(Draw::NativeObject::COMPATIBLE_RENDERPASS);
cur2DPipeline_ = vulkan2D_.GetPipeline(pipelineCache2D_, rp, vsBasicTex_, fsBasicTex_);
cur2DPipeline_ = vulkan2D_->GetPipeline(rp, vsBasicTex_, fsBasicTex_);
}
void FramebufferManagerVulkan::BindPostShader(const PostShaderUniforms &uniforms) {
@@ -608,31 +585,13 @@ void ConvertFromRGBA8888_Vulkan(u8 *dst, const u8 *src, u32 dstStride, u32 srcSt
void FramebufferManagerVulkan::BeginFrameVulkan() {
BeginFrame();
vulkan2D_.BeginFrame();
FrameData &frame = frameData_[curFrame_];
frame.push_->Reset();
frame.push_->Begin(vulkan_);
}
void FramebufferManagerVulkan::EndFrame() {
// We flush to memory last requested framebuffer, if any.
// Only do this in the read-framebuffer modes.
FrameData &frame = frameData_[curFrame_];
frame.push_->End();
vulkan2D_.EndFrame();
curFrame_++;
if (curFrame_ >= vulkan_->GetInflightFrames()) {
curFrame_ = 0;
}
}
void FramebufferManagerVulkan::DeviceLost() {
vulkan2D_.DeviceLost();
vulkan2D_->DeviceLost();
DestroyAllFBOs();
DestroyDeviceObjects();
@@ -641,7 +600,7 @@ void FramebufferManagerVulkan::DeviceLost() {
void FramebufferManagerVulkan::DeviceRestore(VulkanContext *vulkan) {
vulkan_ = vulkan;
vulkan2D_.DeviceRestore(vulkan_);
vulkan2D_->DeviceRestore(vulkan_);
InitDeviceObjects();
}
+12 -14
View File
@@ -22,6 +22,7 @@
#include "GPU/GPUInterface.h"
#include "GPU/Common/GPUDebugInterface.h"
#include "GPU/Vulkan/VulkanUtil.h"
#include "GPU/Vulkan/DepalettizeShaderVulkan.h"
// TODO: Remove?
enum VulkanFBOColorDepth {
@@ -44,6 +45,8 @@ R"( vec2 texelDelta;
vec4 time;
)";
class VulkanPushBuffer;
class FramebufferManagerVulkan : public FramebufferManagerCommon {
public:
FramebufferManagerVulkan(Draw::DrawContext *draw, VulkanContext *vulkan);
@@ -52,6 +55,8 @@ public:
void SetTextureCache(TextureCacheVulkan *tc);
void SetShaderManager(ShaderManagerVulkan *sm);
void SetDrawEngine(DrawEngineVulkan *td);
void SetVulkan2D(Vulkan2D *vk2d) { vulkan2D_ = vk2d; }
void SetPushBuffer(VulkanPushBuffer *push) { push_ = push; }
// x,y,w,h are relative to destW, destH which fill out the target completely.
void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) override;
@@ -105,28 +110,21 @@ private:
// Used to keep track of command buffers here but have moved all that into Thin3D.
// Used by DrawPixels
VulkanTexture *drawPixelsTex_;
GEBufferFormat drawPixelsTexFormat_;
u8 *convBuf_;
u32 convBufSize_;
VulkanTexture *drawPixelsTex_ = nullptr;
GEBufferFormat drawPixelsTexFormat_ = GE_FORMAT_INVALID;
u8 *convBuf_ = nullptr;
u32 convBufSize_ = 0;
TextureCacheVulkan *textureCacheVulkan_;
ShaderManagerVulkan *shaderManagerVulkan_;
DrawEngineVulkan *drawEngineVulkan_;
VulkanPushBuffer *push_;
DepalShaderCacheVulkan depalVulkan_;
enum {
MAX_COMMAND_BUFFERS = 32,
};
// Commandbuffers are handled internally in thin3d, one for each framebuffer pass.
struct FrameData {
VulkanPushBuffer *push_;
};
FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES];
int curFrame_;
// This gets copied to the current frame's push buffer as needed.
PostShaderUniforms postUniforms_;
@@ -148,5 +146,5 @@ private:
VkImageView overrideImageView_ = VK_NULL_HANDLE;
// Simple 2D drawing engine.
Vulkan2D vulkan2D_;
Vulkan2D *vulkan2D_;
};
+50 -3
View File
@@ -76,7 +76,9 @@ static const VulkanCommandTableEntry commandTable[] = {
GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
: GPUCommon(gfxCtx, draw),
vulkan_((VulkanContext *)gfxCtx->GetAPIContext()),
drawEngine_(vulkan_, draw) {
drawEngine_(vulkan_, draw),
depalShaderCache_(draw, vulkan_),
vulkan2D_(vulkan_) {
UpdateVsyncInterval(true);
CheckGPUFeatures();
@@ -97,10 +99,14 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
framebufferManagerVulkan_->SetTextureCache(textureCacheVulkan_);
framebufferManagerVulkan_->SetDrawEngine(&drawEngine_);
framebufferManagerVulkan_->SetShaderManager(shaderManagerVulkan_);
textureCacheVulkan_->SetFramebufferManager(framebufferManagerVulkan_);
framebufferManagerVulkan_->SetVulkan2D(&vulkan2D_);
textureCacheVulkan_->SetDepalShaderCache(&depalShaderCache_);
textureCacheVulkan_->SetFramebufferManager(framebufferManagerVulkan_);
textureCacheVulkan_->SetShaderManager(shaderManagerVulkan_);
textureCacheVulkan_->SetDrawEngine(&drawEngine_);
textureCacheVulkan_->SetVulkan2D(&vulkan2D_);
InitDeviceObjects();
// Sanity check gstate
if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) {
@@ -155,7 +161,9 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
}
GPU_Vulkan::~GPU_Vulkan() {
DestroyDeviceObjects();
framebufferManagerVulkan_->DestroyAllFBOs();
vulkan2D_.Shutdown();
depalShaderCache_.Clear();
delete textureCacheVulkan_;
delete pipelineManager_;
@@ -209,9 +217,19 @@ void GPU_Vulkan::BeginHostFrame() {
resized_ = false;
textureCacheVulkan_->StartFrame();
depalShaderCache_.Decimate();
FrameData &frame = frameData_[curFrame_];
frame.push_->Reset();
frame.push_->Begin(vulkan_);
framebufferManagerVulkan_->BeginFrameVulkan();
framebufferManagerVulkan_->SetPushBuffer(frameData_[curFrame_].push_);
depalShaderCache_.SetPushBuffer(frameData_[curFrame_].push_);
textureCacheVulkan_->SetPushBuffer(frameData_[curFrame_].push_);
vulkan2D_.BeginFrame();
shaderManagerVulkan_->DirtyShader();
gstate_c.Dirty(DIRTY_ALL);
@@ -226,6 +244,16 @@ void GPU_Vulkan::BeginHostFrame() {
}
void GPU_Vulkan::EndHostFrame() {
FrameData &frame = frameData_[curFrame_];
frame.push_->End();
vulkan2D_.EndFrame();
curFrame_++;
if (curFrame_ >= vulkan_->GetInflightFrames()) {
curFrame_ = 0;
}
drawEngine_.EndFrame();
framebufferManagerVulkan_->EndFrame();
textureCacheVulkan_->EndFrame();
@@ -769,7 +797,26 @@ void GPU_Vulkan::FastLoadBoneMatrix(u32 target) {
gstate.FastLoadBoneMatrix(target);
}
void GPU_Vulkan::InitDeviceObjects() {
// Initialize framedata
for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
frameData_[i].push_ = new VulkanPushBuffer(vulkan_, 64 * 1024);
}
}
void GPU_Vulkan::DestroyDeviceObjects() {
for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
if (frameData_[i].push_) {
frameData_[i].push_->Destroy(vulkan_);
delete frameData_[i].push_;
frameData_[i].push_ = nullptr;
}
}
}
void GPU_Vulkan::DeviceLost() {
DestroyDeviceObjects();
framebufferManagerVulkan_->DeviceLost();
drawEngine_.DeviceLost();
pipelineManager_->DeviceLost();
+14
View File
@@ -101,6 +101,10 @@ private:
void ReinitializeInternal() override;
inline void UpdateVsyncInterval(bool force);
void UpdateCmdInfo();
void InitDeviceObjects();
void DestroyDeviceObjects();
static CommandInfo cmdInfo_[256];
VulkanContext *vulkan_;
@@ -121,4 +125,14 @@ private:
std::string reportingPrimaryInfo_;
std::string reportingFullInfo_;
// Simple 2D drawing engine.
Vulkan2D vulkan2D_;
struct FrameData {
VulkanPushBuffer *push_;
};
FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]{};
int curFrame_ = 0;
};
+38 -44
View File
@@ -152,6 +152,11 @@ void TextureCacheVulkan::SetFramebufferManager(FramebufferManagerVulkan *fbManag
framebufferManager_ = fbManager;
}
void TextureCacheVulkan::SetVulkan2D(Vulkan2D *vk2d) {
vulkan2D_ = vk2d;
depalShaderCache_->SetVulkan2D(vk2d);
}
void TextureCacheVulkan::DeviceLost() {
Clear(true);
@@ -269,6 +274,8 @@ void TextureCacheVulkan::SetFramebufferSamplingParams(u16 bufferWidth, u16 buffe
void TextureCacheVulkan::StartFrame() {
InvalidateLastTexture();
depalShaderCache_->Decimate();
timesInvalidatedAllThisFrame_ = 0;
texelsScaledThisFrame_ = 0;
@@ -343,42 +350,24 @@ void TextureCacheVulkan::Unbind() {
}
void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) {
DepalShaderVulkan *depal = nullptr;
DepalShaderVulkan *depalShader = nullptr;
const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat();
if ((entry->status & TexCacheEntry::STATUS_DEPALETTIZE) && !g_Config.bDisableSlowFramebufEffects) {
// depal = depalShaderCache_->GetDepalettizeShader(clutFormat, framebuffer->drawnFormat);
depalShader = depalShaderCache_->GetDepalettizeShader(clutFormat, framebuffer->drawnFormat);
}
if (depal) {
// VulkanTexture *clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_);
// VulkanFBO *depalFBO = framebufferManager_->GetTempFBO(framebuffer->renderWidth, framebuffer->renderHeight, VK_FBO_8888);
if (depalShader) {
depalShaderCache_->SetPushBuffer(drawEngine_->GetPushBufferForTextureData());
VulkanTexture *clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_);
//depalFBO->BeginPass(cmd);
Draw::Framebuffer *depalFBO = framebufferManager_->GetTempFBO(
framebuffer->renderWidth, framebuffer->renderHeight, Draw::FBO_8888);
draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE });
struct Pos {
Pos(float x_, float y_, float z_) : x(x_), y(y_), z(z_) {
}
float x;
float y;
float z;
};
struct UV {
UV(float u_, float v_) : u(u_), v(v_) {
}
float u;
float v;
};
Pos pos[4] = {
{ -1, -1, -1 },
{ 1, -1, -1 },
{ 1, 1, -1 },
{ -1, 1, -1 },
};
UV uv[4] = {
{ 0, 0 },
{ 1, 0 },
{ 1, 1 },
{ 0, 1 },
Vulkan2D::Vertex verts[4] = {
{ -1, -1, -1, 0, 0 },
{ 1, -1, -1, 1, 0 },
{ 1, 1, -1, 1, 1 },
{ -1, 1, -1, 0, 1 },
};
static const int indices[4] = { 0, 1, 3, 2 };
@@ -400,28 +389,32 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFr
const float top = v1 * invHalfHeight - 1.0f;
const float bottom = v2 * invHalfHeight - 1.0f;
// Points are: BL, BR, TR, TL.
pos[0] = Pos(left, bottom, -1.0f);
pos[1] = Pos(right, bottom, -1.0f);
pos[2] = Pos(right, top, -1.0f);
pos[3] = Pos(left, top, -1.0f);
verts[0].x = left;
verts[0].y = bottom;
verts[1].x = right;
verts[1].y = bottom;
verts[2].x = right;
verts[2].y = top;
verts[3].x = left;
verts[3].y = top;
// And also the UVs, same order.
const float uvleft = u1 * invWidth;
const float uvright = u2 * invWidth;
const float uvtop = v1 * invHeight;
const float uvbottom = v2 * invHeight;
uv[0] = UV(uvleft, uvbottom);
uv[1] = UV(uvright, uvbottom);
uv[2] = UV(uvright, uvtop);
uv[3] = UV(uvleft, uvtop);
verts[0].u = uvleft;
verts[0].v = uvbottom;
verts[1].u = uvright;
verts[1].v = uvbottom;
verts[2].u = uvright;
verts[2].v = uvtop;
verts[3].u = uvleft;
verts[3].v = uvtop;
}
shaderManagerVulkan_->DirtyLastShader();
//depalFBO->EndPass(cmd);
//depalFBO->TransitionToTexture(cmd);
//imageView = depalFBO->GetColorImageView();
const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);
const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor;
@@ -429,7 +422,8 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFr
gstate_c.SetTextureFullAlpha(alphaStatus == TexCacheEntry::STATUS_ALPHA_FULL);
gstate_c.SetTextureSimpleAlpha(alphaStatus == TexCacheEntry::STATUS_ALPHA_SIMPLE);
// imageView_ = depalFbo->getImageView().
draw_->BindFramebufferAsTexture(depalFBO, 0, Draw::FB_COLOR_BIT, 0);
imageView_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE_IMAGEVIEW);
} else {
entry->status &= ~TexCacheEntry::STATUS_DEPALETTIZE;
+7
View File
@@ -61,6 +61,7 @@ private:
DenseHashMap<SamplerCacheKey, VkSampler, (VkSampler)VK_NULL_HANDLE> cache_;
};
class Vulkan2D;
class TextureCacheVulkan : public TextureCacheCommon {
public:
@@ -83,6 +84,10 @@ public:
void SetDrawEngine(DrawEngineVulkan *td) {
drawEngine_ = td;
}
void SetVulkan2D(Vulkan2D *vk2d);
void SetPushBuffer(VulkanPushBuffer *push) {
push_ = push;
}
void ForgetLastTexture() override {
lastBoundTexture = nullptr;
@@ -119,6 +124,7 @@ private:
VulkanContext *vulkan_;
VulkanDeviceAllocator *allocator_;
VulkanPushBuffer *push_;
SamplerCache samplerCache_;
@@ -134,6 +140,7 @@ private:
DepalShaderCacheVulkan *depalShaderCache_;
ShaderManagerVulkan *shaderManagerVulkan_;
DrawEngineVulkan *drawEngine_;
Vulkan2D *vulkan2D_;
// Bound state to emulate an API similar to the others
VkImageView imageView_ = VK_NULL_HANDLE;
+10 -2
View File
@@ -36,6 +36,7 @@ void Vulkan2D::DestroyDeviceObjects() {
for (int i = 0; i < vulkan_->GetInflightFrames(); i++) {
if (frameData_[i].descPool != VK_NULL_HANDLE) {
vulkan_->Delete().QueueDeleteDescriptorPool(frameData_[i].descPool);
frameData_[i].descPool = VK_NULL_HANDLE;
}
}
for (auto it : pipelines_) {
@@ -52,9 +53,16 @@ void Vulkan2D::DestroyDeviceObjects() {
vkDestroyPipelineLayout(device, pipelineLayout_, nullptr);
pipelineLayout_ = VK_NULL_HANDLE;
}
// pipelineBasicTex_ and pipelineBasicTex_ come from vulkan2D_.
if (pipelineCache_ != VK_NULL_HANDLE) {
vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_);
pipelineCache_ = VK_NULL_HANDLE;
}
}
void Vulkan2D::InitDeviceObjects() {
pipelineCache_ = vulkan_->CreatePipelineCache();
// All resources we need for PSP drawing. Usually only bindings 0 and 2-4 are populated.
VkDescriptorSetLayoutBinding bindings[2] = {};
bindings[0].descriptorCount = 1;
@@ -188,7 +196,7 @@ VkDescriptorSet Vulkan2D::GetDescriptorSet(VkImageView tex1, VkSampler sampler1,
return desc;
}
VkPipeline Vulkan2D::GetPipeline(VkPipelineCache cache, VkRenderPass rp, VkShaderModule vs, VkShaderModule fs) {
VkPipeline Vulkan2D::GetPipeline(VkRenderPass rp, VkShaderModule vs, VkShaderModule fs) {
PipelineKey key;
key.vs = vs;
key.fs = fs;
@@ -298,7 +306,7 @@ VkPipeline Vulkan2D::GetPipeline(VkPipelineCache cache, VkRenderPass rp, VkShade
pipe.subpass = 0;
VkPipeline pipeline;
VkResult result = vkCreateGraphicsPipelines(vulkan_->GetDevice(), cache, 1, &pipe, nullptr, &pipeline);
VkResult result = vkCreateGraphicsPipelines(vulkan_->GetDevice(), pipelineCache_, 1, &pipe, nullptr, &pipeline);
if (result == VK_SUCCESS) {
pipelines_[key] = pipeline;
return pipeline;
+5 -4
View File
@@ -56,7 +56,7 @@ public:
void DeviceRestore(VulkanContext *vulkan);
void Shutdown();
VkPipeline GetPipeline(VkPipelineCache cache, VkRenderPass rp, VkShaderModule vs, VkShaderModule fs);
VkPipeline GetPipeline(VkRenderPass rp, VkShaderModule vs, VkShaderModule fs);
VkPipelineLayout GetPipelineLayout() const { return pipelineLayout_; }
void BeginFrame();
void EndFrame();
@@ -72,9 +72,10 @@ private:
void InitDeviceObjects();
void DestroyDeviceObjects();
VulkanContext *vulkan_;
VkDescriptorSetLayout descriptorSetLayout_;
VkPipelineLayout pipelineLayout_;
VulkanContext *vulkan_ = nullptr;
VkDescriptorSetLayout descriptorSetLayout_ = VK_NULL_HANDLE;
VkPipelineLayout pipelineLayout_ = VK_NULL_HANDLE;
VkPipelineCache pipelineCache_ = VK_NULL_HANDLE;
// Yes, another one...
struct DescriptorSetKey {