Minor optimizations (use the new hashmap in a few more places)
This commit is contained in:
parent
9bce767b73
commit
2f85e6516e
17 changed files with 75 additions and 94 deletions
|
@ -178,6 +178,7 @@ struct TexCacheEntry {
|
||||||
|
|
||||||
class FramebufferManagerCommon;
|
class FramebufferManagerCommon;
|
||||||
// Can't be unordered_map, we use lower_bound ... although for some reason that compiles on MSVC.
|
// Can't be unordered_map, we use lower_bound ... although for some reason that compiles on MSVC.
|
||||||
|
// Would really like to replace this with DenseHashMap but can't as long as we need lower_bound.
|
||||||
typedef std::map<u64, std::unique_ptr<TexCacheEntry>> TexCache;
|
typedef std::map<u64, std::unique_ptr<TexCacheEntry>> TexCache;
|
||||||
|
|
||||||
class TextureCacheCommon {
|
class TextureCacheCommon {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "ppsspp_config.h"
|
#include "ppsspp_config.h"
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
|
#include "Common/Hashmaps.h"
|
||||||
#include "Common/Log.h"
|
#include "Common/Log.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Core/Reporting.h"
|
#include "Core/Reporting.h"
|
||||||
|
|
|
@ -543,14 +543,16 @@ void GPU_D3D11::Execute_Prim(u32 op, u32 diff) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) {
|
||||||
|
vertexCost_ = EstimatePerVertexCost();
|
||||||
|
}
|
||||||
|
gpuStats.vertexGPUCycles += vertexCost_ * count;
|
||||||
|
cyclesExecuted += vertexCost_* count;
|
||||||
|
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
UpdateUVScaleOffset();
|
UpdateUVScaleOffset();
|
||||||
drawEngine_.SubmitPrim(verts, inds, prim, count, vertexType, &bytesRead);
|
drawEngine_.SubmitPrim(verts, inds, prim, count, vertexType, &bytesRead);
|
||||||
|
|
||||||
int vertexCost = EstimatePerVertexCost() * count;
|
|
||||||
gpuStats.vertexGPUCycles += vertexCost;
|
|
||||||
cyclesExecuted += vertexCost;
|
|
||||||
|
|
||||||
// After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed).
|
// After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed).
|
||||||
// Some games rely on this, they don't bother reloading VADDR and IADDR.
|
// Some games rely on this, they don't bother reloading VADDR and IADDR.
|
||||||
// The VADDR/IADDR registers are NOT updated.
|
// The VADDR/IADDR registers are NOT updated.
|
||||||
|
|
|
@ -117,6 +117,7 @@ private:
|
||||||
static CommandInfo cmdInfo_[256];
|
static CommandInfo cmdInfo_[256];
|
||||||
|
|
||||||
int lastVsync_;
|
int lastVsync_;
|
||||||
|
int vertexCost_ = 0;
|
||||||
|
|
||||||
std::string reportingPrimaryInfo_;
|
std::string reportingPrimaryInfo_;
|
||||||
std::string reportingFullInfo_;
|
std::string reportingFullInfo_;
|
||||||
|
|
|
@ -509,14 +509,16 @@ void GPU_DX9::Execute_Prim(u32 op, u32 diff) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) {
|
||||||
|
vertexCost_ = EstimatePerVertexCost();
|
||||||
|
}
|
||||||
|
gpuStats.vertexGPUCycles += vertexCost_ * count;
|
||||||
|
cyclesExecuted += vertexCost_* count;
|
||||||
|
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
UpdateUVScaleOffset();
|
UpdateUVScaleOffset();
|
||||||
drawEngine_.SubmitPrim(verts, inds, prim, count, vertexType, &bytesRead);
|
drawEngine_.SubmitPrim(verts, inds, prim, count, vertexType, &bytesRead);
|
||||||
|
|
||||||
int vertexCost = EstimatePerVertexCost() * count;
|
|
||||||
gpuStats.vertexGPUCycles += vertexCost;
|
|
||||||
cyclesExecuted += vertexCost;
|
|
||||||
|
|
||||||
// After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed).
|
// After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed).
|
||||||
// Some games rely on this, they don't bother reloading VADDR and IADDR.
|
// Some games rely on this, they don't bother reloading VADDR and IADDR.
|
||||||
// The VADDR/IADDR registers are NOT updated.
|
// The VADDR/IADDR registers are NOT updated.
|
||||||
|
|
|
@ -117,6 +117,7 @@ private:
|
||||||
static CommandInfo cmdInfo_[256];
|
static CommandInfo cmdInfo_[256];
|
||||||
|
|
||||||
int lastVsync_;
|
int lastVsync_;
|
||||||
|
int vertexCost_ = 0;
|
||||||
|
|
||||||
std::string reportingPrimaryInfo_;
|
std::string reportingPrimaryInfo_;
|
||||||
std::string reportingFullInfo_;
|
std::string reportingFullInfo_;
|
||||||
|
|
|
@ -681,14 +681,16 @@ void GPU_GLES::Execute_Prim(u32 op, u32 diff) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) {
|
||||||
|
vertexCost_ = EstimatePerVertexCost();
|
||||||
|
}
|
||||||
|
gpuStats.vertexGPUCycles += vertexCost_ * count;
|
||||||
|
cyclesExecuted += vertexCost_* count;
|
||||||
|
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
UpdateUVScaleOffset();
|
UpdateUVScaleOffset();
|
||||||
drawEngine_.SubmitPrim(verts, inds, prim, count, gstate.vertType, &bytesRead);
|
drawEngine_.SubmitPrim(verts, inds, prim, count, gstate.vertType, &bytesRead);
|
||||||
|
|
||||||
int vertexCost = EstimatePerVertexCost();
|
|
||||||
gpuStats.vertexGPUCycles += vertexCost * count;
|
|
||||||
cyclesExecuted += vertexCost * count;
|
|
||||||
|
|
||||||
// After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed).
|
// After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed).
|
||||||
// Some games rely on this, they don't bother reloading VADDR and IADDR.
|
// Some games rely on this, they don't bother reloading VADDR and IADDR.
|
||||||
// The VADDR/IADDR registers are NOT updated.
|
// The VADDR/IADDR registers are NOT updated.
|
||||||
|
|
|
@ -120,6 +120,7 @@ private:
|
||||||
ShaderManagerGLES *shaderManagerGL_;
|
ShaderManagerGLES *shaderManagerGL_;
|
||||||
|
|
||||||
int lastVsync_;
|
int lastVsync_;
|
||||||
|
int vertexCost_ = 0;
|
||||||
|
|
||||||
std::string reportingPrimaryInfo_;
|
std::string reportingPrimaryInfo_;
|
||||||
std::string reportingFullInfo_;
|
std::string reportingFullInfo_;
|
||||||
|
|
|
@ -207,16 +207,6 @@ private:
|
||||||
VkSampler sampler_;
|
VkSampler sampler_;
|
||||||
VkBuffer base_, light_, bone_; // All three UBO slots will be set to this. This will usually be identical
|
VkBuffer base_, light_, bone_; // All three UBO slots will be set to this. This will usually be identical
|
||||||
// for all draws in a frame, except when the buffer has to grow.
|
// for all draws in a frame, except when the buffer has to grow.
|
||||||
|
|
||||||
bool operator < (const DescriptorSetKey &other) const {
|
|
||||||
if (imageView_ < other.imageView_) return true; else if (imageView_ > other.imageView_) return false;
|
|
||||||
if (sampler_ < other.sampler_) return true; else if (sampler_ > other.sampler_) return false;
|
|
||||||
if (secondaryImageView_ < other.secondaryImageView_) return true; else if (secondaryImageView_ > other.secondaryImageView_) return false;
|
|
||||||
if (base_ < other.base_) return true; else if (base_ > other.base_) return false;
|
|
||||||
if (light_ < other.light_) return true; else if (light_ > other.light_) return false;
|
|
||||||
if (bone_ < other.bone_) return true; else if (bone_ > other.bone_) return false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// We alternate between these.
|
// We alternate between these.
|
||||||
|
|
|
@ -511,14 +511,16 @@ void GPU_Vulkan::Execute_Prim(u32 op, u32 diff) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) {
|
||||||
|
vertexCost_ = EstimatePerVertexCost();
|
||||||
|
}
|
||||||
|
gpuStats.vertexGPUCycles += vertexCost_ * count;
|
||||||
|
cyclesExecuted += vertexCost_* count;
|
||||||
|
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
UpdateUVScaleOffset();
|
UpdateUVScaleOffset();
|
||||||
drawEngine_.SubmitPrim(verts, inds, prim, count, gstate.vertType, &bytesRead);
|
drawEngine_.SubmitPrim(verts, inds, prim, count, gstate.vertType, &bytesRead);
|
||||||
|
|
||||||
int vertexCost = EstimatePerVertexCost() * count;
|
|
||||||
gpuStats.vertexGPUCycles += vertexCost;
|
|
||||||
cyclesExecuted += vertexCost;
|
|
||||||
|
|
||||||
// After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed).
|
// After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed).
|
||||||
// Some games rely on this, they don't bother reloading VADDR and IADDR.
|
// Some games rely on this, they don't bother reloading VADDR and IADDR.
|
||||||
// The VADDR/IADDR registers are NOT updated.
|
// The VADDR/IADDR registers are NOT updated.
|
||||||
|
|
|
@ -120,6 +120,7 @@ private:
|
||||||
|
|
||||||
int lastVsync_;
|
int lastVsync_;
|
||||||
VkCommandBuffer curCmd_;
|
VkCommandBuffer curCmd_;
|
||||||
|
int vertexCost_ = 0;
|
||||||
|
|
||||||
std::string reportingPrimaryInfo_;
|
std::string reportingPrimaryInfo_;
|
||||||
std::string reportingFullInfo_;
|
std::string reportingFullInfo_;
|
||||||
|
|
|
@ -45,16 +45,6 @@ struct VulkanPipelineKey {
|
||||||
VkShaderModule vShader;
|
VkShaderModule vShader;
|
||||||
VkShaderModule fShader;
|
VkShaderModule fShader;
|
||||||
|
|
||||||
// TODO: Probably better to use a hash function instead.
|
|
||||||
bool operator < (const VulkanPipelineKey &other) const {
|
|
||||||
if (raster < other.raster) return true; else if (other.raster < raster) return false;
|
|
||||||
if (renderPass < other.renderPass) return true; else if (other.renderPass < renderPass) return false;
|
|
||||||
if (useHWTransform < other.useHWTransform) return true; else if (other.useHWTransform < useHWTransform) return false;
|
|
||||||
if (vtxDec < other.vtxDec) return true; else if (other.vtxDec < vtxDec) return false;
|
|
||||||
if (vShader < other.vShader) return true; else if (other.vShader < vShader) return false;
|
|
||||||
if (fShader < other.fShader) return true; else if (other.fShader < fShader) return false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
void ToString(std::string *str) const {
|
void ToString(std::string *str) const {
|
||||||
str->resize(sizeof(*this));
|
str->resize(sizeof(*this));
|
||||||
memcpy(&(*str)[0], this, sizeof(*this));
|
memcpy(&(*str)[0], this, sizeof(*this));
|
||||||
|
|
|
@ -154,7 +154,7 @@ std::string VulkanVertexShader::GetShaderString(DebugShaderStringType type) cons
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderManagerVulkan::ShaderManagerVulkan(VulkanContext *vulkan)
|
ShaderManagerVulkan::ShaderManagerVulkan(VulkanContext *vulkan)
|
||||||
: vulkan_(vulkan), lastVShader_(nullptr), lastFShader_(nullptr) {
|
: vulkan_(vulkan), lastVShader_(nullptr), lastFShader_(nullptr), fsCache_(16), vsCache_(16) {
|
||||||
codeBuffer_ = new char[16384];
|
codeBuffer_ = new char[16384];
|
||||||
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment;
|
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment;
|
||||||
memset(&ub_base, 0, sizeof(ub_base));
|
memset(&ub_base, 0, sizeof(ub_base));
|
||||||
|
@ -177,14 +177,14 @@ void ShaderManagerVulkan::DeviceRestore(VulkanContext *vulkan) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderManagerVulkan::Clear() {
|
void ShaderManagerVulkan::Clear() {
|
||||||
for (auto iter = fsCache_.begin(); iter != fsCache_.end(); ++iter) {
|
fsCache_.Iterate([&](const ShaderID &key, VulkanFragmentShader *shader) {
|
||||||
delete iter->second;
|
delete shader;
|
||||||
}
|
});
|
||||||
for (auto iter = vsCache_.begin(); iter != vsCache_.end(); ++iter) {
|
vsCache_.Iterate([&](const ShaderID &key, VulkanVertexShader *shader) {
|
||||||
delete iter->second;
|
delete shader;
|
||||||
}
|
});
|
||||||
fsCache_.clear();
|
fsCache_.Clear();
|
||||||
vsCache_.clear();
|
vsCache_.Clear();
|
||||||
lastFSID_.clear();
|
lastFSID_.clear();
|
||||||
lastVSID_.clear();
|
lastVSID_.clear();
|
||||||
}
|
}
|
||||||
|
@ -248,28 +248,22 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VSCache::iterator vsIter = vsCache_.find(VSID);
|
VulkanVertexShader *vs = vsCache_.Get(VSID);
|
||||||
VulkanVertexShader *vs;
|
if (!vs) {
|
||||||
if (vsIter == vsCache_.end()) {
|
|
||||||
// Vertex shader not in cache. Let's compile it.
|
// Vertex shader not in cache. Let's compile it.
|
||||||
bool usesLighting;
|
bool usesLighting;
|
||||||
GenerateVulkanGLSLVertexShader(VSID, codeBuffer_, &usesLighting);
|
GenerateVulkanGLSLVertexShader(VSID, codeBuffer_, &usesLighting);
|
||||||
vs = new VulkanVertexShader(vulkan_, VSID, codeBuffer_, vertType, useHWTransform, usesLighting);
|
vs = new VulkanVertexShader(vulkan_, VSID, codeBuffer_, vertType, useHWTransform, usesLighting);
|
||||||
vsCache_[VSID] = vs;
|
vsCache_.Insert(VSID, vs);
|
||||||
} else {
|
|
||||||
vs = vsIter->second;
|
|
||||||
}
|
}
|
||||||
lastVSID_ = VSID;
|
lastVSID_ = VSID;
|
||||||
|
|
||||||
FSCache::iterator fsIter = fsCache_.find(FSID);
|
VulkanFragmentShader *fs = fsCache_.Get(FSID);
|
||||||
VulkanFragmentShader *fs;
|
if (!fs) {
|
||||||
if (fsIter == fsCache_.end()) {
|
|
||||||
// Fragment shader not in cache. Let's compile it.
|
// Fragment shader not in cache. Let's compile it.
|
||||||
GenerateVulkanGLSLFragmentShader(FSID, codeBuffer_);
|
GenerateVulkanGLSLFragmentShader(FSID, codeBuffer_);
|
||||||
fs = new VulkanFragmentShader(vulkan_, FSID, codeBuffer_, useHWTransform);
|
fs = new VulkanFragmentShader(vulkan_, FSID, codeBuffer_, useHWTransform);
|
||||||
fsCache_[FSID] = fs;
|
fsCache_.Insert(FSID, fs);
|
||||||
} else {
|
|
||||||
fs = fsIter->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastFSID_ = FSID;
|
lastFSID_ = FSID;
|
||||||
|
@ -282,23 +276,24 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> ShaderManagerVulkan::DebugGetShaderIDs(DebugShaderType type) {
|
std::vector<std::string> ShaderManagerVulkan::DebugGetShaderIDs(DebugShaderType type) {
|
||||||
std::string id;
|
|
||||||
std::vector<std::string> ids;
|
std::vector<std::string> ids;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SHADER_TYPE_VERTEX:
|
case SHADER_TYPE_VERTEX:
|
||||||
{
|
{
|
||||||
for (auto iter : vsCache_) {
|
vsCache_.Iterate([&](const ShaderID &id, VulkanVertexShader *shader) {
|
||||||
iter.first.ToString(&id);
|
std::string idstr;
|
||||||
ids.push_back(id);
|
id.ToString(&idstr);
|
||||||
}
|
ids.push_back(idstr);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SHADER_TYPE_FRAGMENT:
|
case SHADER_TYPE_FRAGMENT:
|
||||||
{
|
{
|
||||||
for (auto iter : fsCache_) {
|
fsCache_.Iterate([&](const ShaderID &id, VulkanFragmentShader *shader) {
|
||||||
iter.first.ToString(&id);
|
std::string idstr;
|
||||||
ids.push_back(id);
|
id.ToString(&idstr);
|
||||||
}
|
ids.push_back(idstr);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -313,20 +308,14 @@ std::string ShaderManagerVulkan::DebugGetShaderString(std::string id, DebugShade
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SHADER_TYPE_VERTEX:
|
case SHADER_TYPE_VERTEX:
|
||||||
{
|
{
|
||||||
auto iter = vsCache_.find(shaderId);
|
VulkanVertexShader *vs = vsCache_.Get(shaderId);
|
||||||
if (iter == vsCache_.end()) {
|
return vs ? vs->GetShaderString(stringType) : "";
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return iter->second->GetShaderString(stringType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case SHADER_TYPE_FRAGMENT:
|
case SHADER_TYPE_FRAGMENT:
|
||||||
{
|
{
|
||||||
auto iter = fsCache_.find(shaderId);
|
VulkanFragmentShader *fs = fsCache_.Get(shaderId);
|
||||||
if (iter == fsCache_.end()) {
|
return fs ? fs->GetShaderString(stringType) : "";
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return iter->second->GetShaderString(stringType);
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return "N/A";
|
return "N/A";
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
|
#include "Common/Hashmaps.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Common/Vulkan/VulkanMemory.h"
|
#include "Common/Vulkan/VulkanMemory.h"
|
||||||
#include "GPU/Common/ShaderCommon.h"
|
#include "GPU/Common/ShaderCommon.h"
|
||||||
|
@ -130,10 +131,10 @@ private:
|
||||||
|
|
||||||
VulkanContext *vulkan_;
|
VulkanContext *vulkan_;
|
||||||
|
|
||||||
typedef std::map<ShaderID, VulkanFragmentShader *> FSCache;
|
typedef DenseHashMap<ShaderID, VulkanFragmentShader *, nullptr> FSCache;
|
||||||
FSCache fsCache_;
|
FSCache fsCache_;
|
||||||
|
|
||||||
typedef std::map<ShaderID, VulkanVertexShader *> VSCache;
|
typedef DenseHashMap<ShaderID, VulkanVertexShader *, nullptr> VSCache;
|
||||||
VSCache vsCache_;
|
VSCache vsCache_;
|
||||||
|
|
||||||
char *codeBuffer_;
|
char *codeBuffer_;
|
||||||
|
|
|
@ -72,16 +72,13 @@ CachedTextureVulkan::~CachedTextureVulkan() {
|
||||||
}
|
}
|
||||||
|
|
||||||
SamplerCache::~SamplerCache() {
|
SamplerCache::~SamplerCache() {
|
||||||
for (auto iter : cache_) {
|
DeviceLost();
|
||||||
vulkan_->Delete().QueueDeleteSampler(iter.second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSampler SamplerCache::GetOrCreateSampler(const SamplerCacheKey &key) {
|
VkSampler SamplerCache::GetOrCreateSampler(const SamplerCacheKey &key) {
|
||||||
auto iter = cache_.find(key);
|
VkSampler sampler = cache_.Get(key);
|
||||||
if (iter != cache_.end()) {
|
if (sampler != VK_NULL_HANDLE)
|
||||||
return iter->second;
|
return sampler;
|
||||||
}
|
|
||||||
|
|
||||||
VkSamplerCreateInfo samp = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
|
VkSamplerCreateInfo samp = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
|
||||||
samp.addressModeU = key.sClamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
samp.addressModeU = key.sClamp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
|
@ -107,18 +104,17 @@ VkSampler SamplerCache::GetOrCreateSampler(const SamplerCacheKey &key) {
|
||||||
samp.minLod = 0.0f;
|
samp.minLod = 0.0f;
|
||||||
samp.mipLodBias = 0.0f;
|
samp.mipLodBias = 0.0f;
|
||||||
|
|
||||||
VkSampler sampler;
|
|
||||||
VkResult res = vkCreateSampler(vulkan_->GetDevice(), &samp, nullptr, &sampler);
|
VkResult res = vkCreateSampler(vulkan_->GetDevice(), &samp, nullptr, &sampler);
|
||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
cache_[key] = sampler;
|
cache_.Insert(key, sampler);
|
||||||
return sampler;
|
return sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SamplerCache::DeviceLost() {
|
void SamplerCache::DeviceLost() {
|
||||||
for (auto iter : cache_) {
|
cache_.Iterate([&](const SamplerCacheKey &key, VkSampler sampler) {
|
||||||
vulkan_->Delete().QueueDeleteSampler(iter.second);
|
vulkan_->Delete().QueueDeleteSampler(sampler);
|
||||||
}
|
});
|
||||||
cache_.clear();
|
cache_.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SamplerCache::DeviceRestore(VulkanContext *vulkan) {
|
void SamplerCache::DeviceRestore(VulkanContext *vulkan) {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "Common/Hashmaps.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "GPU/GPUInterface.h"
|
#include "GPU/GPUInterface.h"
|
||||||
#include "GPU/GPUState.h"
|
#include "GPU/GPUState.h"
|
||||||
|
@ -49,7 +50,7 @@ public:
|
||||||
|
|
||||||
class SamplerCache {
|
class SamplerCache {
|
||||||
public:
|
public:
|
||||||
SamplerCache(VulkanContext *vulkan) : vulkan_(vulkan) {}
|
SamplerCache(VulkanContext *vulkan) : vulkan_(vulkan), cache_(16) {}
|
||||||
~SamplerCache();
|
~SamplerCache();
|
||||||
VkSampler GetOrCreateSampler(const SamplerCacheKey &key);
|
VkSampler GetOrCreateSampler(const SamplerCacheKey &key);
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VulkanContext *vulkan_;
|
VulkanContext *vulkan_;
|
||||||
std::map<SamplerCacheKey, VkSampler> cache_;
|
DenseHashMap<SamplerCacheKey, VkSampler, VK_NULL_HANDLE> cache_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue