introduce sampler cache

This commit is contained in:
Asuka 2022-07-09 22:36:57 +08:00
parent 1deea05481
commit 30636e91a8
10 changed files with 266 additions and 140 deletions

View file

@ -78,6 +78,7 @@
<ClInclude Include="Graphics\Gnm\GnmRegInfo.h" />
<ClInclude Include="Graphics\Gnm\GnmRenderTarget.h" />
<ClInclude Include="Graphics\Gnm\GnmSampler.h" />
<ClInclude Include="Graphics\Gnm\GnmSamplerCache.h" />
<ClInclude Include="Graphics\Gnm\GnmShader.h" />
<ClInclude Include="Graphics\Gnm\GnmSharpBuffer.h" />
<ClInclude Include="Graphics\Gnm\GnmStructure.h" />
@ -358,6 +359,7 @@
<ClCompile Include="Graphics\Gnm\GnmConverter.cpp" />
<ClCompile Include="Graphics\Gnm\GnmDataFormat.cpp" />
<ClCompile Include="Graphics\Gnm\GnmOpCode.cpp" />
<ClCompile Include="Graphics\Gnm\GnmSamplerCache.cpp" />
<ClCompile Include="Graphics\Gnm\GnmShader.cpp" />
<ClCompile Include="Graphics\Gnm\GpuAddress\GnmGpuAddress.cpp" />
<ClCompile Include="Graphics\Gnm\GpuAddress\GnmGpuAddressInternal.cpp" />

View file

@ -985,6 +985,9 @@
<ClInclude Include="Platform\PlatModule.h">
<Filter>Source Files\Platform</Filter>
</ClInclude>
<ClInclude Include="Graphics\Gnm\GnmSamplerCache.h">
<Filter>Source Files\Graphics\Gnm</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Loader\EbootObject.cpp">
@ -1731,6 +1734,9 @@
<ClCompile Include="Platform\PlatModule.cpp">
<Filter>Source Files\Platform</Filter>
</ClCompile>
<ClCompile Include="Graphics\Gnm\GnmSamplerCache.cpp">
<Filter>Source Files\Graphics\Gnm</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="Emulator\TLSStub.asm">

View file

@ -198,13 +198,13 @@ namespace sce::Gnm
uint32_t startRegister,
VkPipelineStageFlags2 stage)
{
SceSampler sampler;
Rc<VltSampler> sampler = nullptr;
m_factory.createSampler(ssharp, sampler);
uint32_t slot = computeSamplerBinding(
gcnProgramTypeFromVkStage(stage), startRegister);
m_context->bindResourceSampler(slot, sampler.sampler);
m_context->bindResourceSampler(slot, sampler);
}
void GnmCommandBuffer::bindResource(

View file

@ -258,8 +258,21 @@ namespace sce::Gnm
}
bool GnmResourceFactory::createSampler(
const Sampler* ssharp,
SceSampler& sampler)
const Sampler* ssharp,
Rc<VltSampler>& sampler)
{
sampler = m_samplerCache.getSampler(*ssharp);
if (sampler == nullptr)
{
sampler = createSampler(ssharp);
m_samplerCache.addSampler(*ssharp, sampler);
}
return true;
}
Rc<VltSampler> GnmResourceFactory::createSampler(const Sampler* ssharp)
{
DepthCompare depthComp = ssharp->getDepthCompareFunction();
@ -281,13 +294,12 @@ namespace sce::Gnm
samplerInfo.addressModeU = cvt::convertWrapMode(ssharp->getWrapModeX());
samplerInfo.addressModeV = cvt::convertWrapMode(ssharp->getWrapModeY());
samplerInfo.addressModeW = cvt::convertWrapMode(ssharp->getWrapModeZ());
samplerInfo.compareToDepth = depthComp != kDepthCompareNever;
samplerInfo.compareToDepth = VkBool32(depthComp != kDepthCompareNever);
samplerInfo.compareOp = cvt::convertDepthCompare(depthComp);
samplerInfo.borderColor = s_borderColors[ssharp->getBorderColor()];
samplerInfo.usePixelCoord = ssharp->getForceUnnormalized();
sampler.sampler = m_device->createSampler(samplerInfo);
sampler.ssharp = *ssharp;
Rc<VltSampler> result = m_device->createSampler(samplerInfo);
// Set debug name
auto samplerName = fmt::format("Sampler_{}", s_objectId++);
@ -297,12 +309,11 @@ namespace sce::Gnm
nameInfo.pNext = nullptr;
nameInfo.objectType = VK_OBJECT_TYPE_SAMPLER;
nameInfo.pObjectName = samplerName.c_str();
nameInfo.objectHandle = (uint64_t)sampler.sampler->handle();
nameInfo.objectHandle = (uint64_t)result->handle();
m_debugUtil.setObjectName(&nameInfo);
return true;
return result;
}
} // namespace sce::Gnm

View file

@ -1,8 +1,10 @@
#pragma once
#include "GnmCommon.h"
#include "GnmSamplerCache.h"
#include "Violet/VltDebugUtil.h"
#include <atomic>
namespace sce
@ -70,12 +72,17 @@ namespace sce
SceRenderTarget& targetImage);
bool createSampler(
const Sampler* ssharp,
SceSampler& sampler);
const Sampler* ssharp,
vlt::Rc<vlt::VltSampler>& sampler);
private:
vlt::Rc<vlt::VltSampler> createSampler(
const Sampler* ssharp);
private:
vlt::VltDevice* m_device;
vlt::VltDebugUtil m_debugUtil;
GnmSamplerCache m_samplerCache;
static std::atomic_size_t s_objectId;
};

View file

@ -2,131 +2,142 @@
#include "GnmCommon.h"
#include "GnmConstant.h"
#include "GnmRegInfo.h"
#include "GnmDataFormat.h"
#include "GnmRegInfo.h"
#include "GnmSharpBuffer.h"
#include "UtilBit.h"
namespace sce::Gnm
{
class Sampler
{
public:
enum
class alignas(16) Sampler
{
kSqImgSampWord0 = 0,
kSqImgSampWord1 = 1,
kSqImgSampWord2 = 2,
kSqImgSampWord3 = 3,
kNumSqImgSampRegisters
public:
enum
{
kSqImgSampWord0 = 0,
kSqImgSampWord1 = 1,
kSqImgSampWord2 = 2,
kSqImgSampWord3 = 3,
kNumSqImgSampRegisters
};
bool operator==(const Sampler& other) const
{
return util::bit::bcmpeq(this, &other);
}
bool operator!=(const Sampler& other) const
{
return !util::bit::bcmpeq(this, &other);
}
const SSharpBuffer& getSsharp() const
{
return m_ssharp;
}
WrapMode getWrapModeX() const
{
return (WrapMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, CLAMP_X);
}
WrapMode getWrapModeY() const
{
return (WrapMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, CLAMP_Y);
}
WrapMode getWrapModeZ() const
{
return (WrapMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, CLAMP_Z);
}
FilterMode getMagFilterMode() const
{
return (FilterMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, XY_MAG_FILTER);
}
FilterMode getMinFilterMode() const
{
return (FilterMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, XY_MIN_FILTER);
}
ZFilterMode getZFilterMode() const
{
return (ZFilterMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, Z_FILTER);
}
MipFilterMode getMipFilterMode() const
{
return (MipFilterMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, MIP_FILTER);
}
FilterReductionMode getFilterReductionMode() const
{
return (FilterReductionMode)SCE_GNM_GET_FIELD(m_regs[0], SQ_IMG_SAMP_WORD0, FILTER_MODE);
}
uint32_t getMinLod() const
{
return (uint32_t)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord1], SQ_IMG_SAMP_WORD1, MIN_LOD);
}
uint32_t getMaxLod() const
{
return (uint32_t)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord1], SQ_IMG_SAMP_WORD1, MAX_LOD);
}
uint16_t getLodBias() const
{
return (uint16_t)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, LOD_BIAS);
}
uint16_t getLodBiasSecondary() const
{
return (uint16_t)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, LOD_BIAS_SEC);
}
AnisotropyRatio getAnisotropyRatio() const
{
return (AnisotropyRatio)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, MAX_ANISO_RATIO);
}
DepthCompare getDepthCompareFunction() const
{
return (DepthCompare)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, DEPTH_COMPARE_FUNC);
}
bool getForceDegamma() const
{
return SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, FORCE_DEGAMMA) ? true : false;
}
bool getForceUnnormalized(void) const
{
return SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, FORCE_UNNORMALIZED) ? true : false;
}
uint32_t getAnisotropyThreshold() const
{
return (uint32_t)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, ANISO_THRESHOLD);
}
BorderColor getBorderColor() const
{
return (BorderColor)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord3], SQ_IMG_SAMP_WORD3, BORDER_COLOR_TYPE);
}
uint32_t getBorderColorTableIndex() const
{
return SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord3], SQ_IMG_SAMP_WORD3, BORDER_COLOR_PTR);
}
union
{
uint32_t m_regs[4];
SSharpBuffer m_ssharp;
};
};
const SSharpBuffer& getSsharp() const
{
return m_ssharp;
}
WrapMode getWrapModeX() const
{
return (WrapMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, CLAMP_X);
}
WrapMode getWrapModeY() const
{
return (WrapMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, CLAMP_Y);
}
WrapMode getWrapModeZ() const
{
return (WrapMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, CLAMP_Z);
}
FilterMode getMagFilterMode() const
{
return (FilterMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, XY_MAG_FILTER);
}
FilterMode getMinFilterMode() const
{
return (FilterMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, XY_MIN_FILTER);
}
ZFilterMode getZFilterMode() const
{
return (ZFilterMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, Z_FILTER);
}
MipFilterMode getMipFilterMode() const
{
return (MipFilterMode)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, MIP_FILTER);
}
FilterReductionMode getFilterReductionMode() const
{
return (FilterReductionMode)SCE_GNM_GET_FIELD(m_regs[0], SQ_IMG_SAMP_WORD0, FILTER_MODE);
}
uint32_t getMinLod() const
{
return (uint32_t)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord1], SQ_IMG_SAMP_WORD1, MIN_LOD);
}
uint32_t getMaxLod() const
{
return (uint32_t)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord1], SQ_IMG_SAMP_WORD1, MAX_LOD);
}
uint16_t getLodBias() const
{
return (uint16_t)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, LOD_BIAS);
}
uint16_t getLodBiasSecondary() const
{
return (uint16_t)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord2], SQ_IMG_SAMP_WORD2, LOD_BIAS_SEC);
}
AnisotropyRatio getAnisotropyRatio() const
{
return (AnisotropyRatio)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, MAX_ANISO_RATIO);
}
DepthCompare getDepthCompareFunction() const
{
return (DepthCompare)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, DEPTH_COMPARE_FUNC);
}
bool getForceDegamma() const
{
return SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, FORCE_DEGAMMA) ? true : false;
}
bool getForceUnnormalized(void) const
{
return SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, FORCE_UNNORMALIZED) ? true : false;
}
uint32_t getAnisotropyThreshold() const
{
return (uint32_t)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord0], SQ_IMG_SAMP_WORD0, ANISO_THRESHOLD);
}
BorderColor getBorderColor() const
{
return (BorderColor)SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord3], SQ_IMG_SAMP_WORD3, BORDER_COLOR_TYPE);
}
uint32_t getBorderColorTableIndex() const
{
return SCE_GNM_GET_FIELD(m_regs[kSqImgSampWord3], SQ_IMG_SAMP_WORD3, BORDER_COLOR_PTR);
}
union
{
uint32_t m_regs[4];
SSharpBuffer m_ssharp;
};
};
} // namespace sce::Gnm

View file

@ -0,0 +1,46 @@
#include "GnmSamplerCache.h"
#include "Violet/VltHash.h"
using namespace sce::vlt;
namespace sce::Gnm
{
GnmSamplerCache::GnmSamplerCache()
{
}
GnmSamplerCache::~GnmSamplerCache()
{
}
Rc<VltSampler> GnmSamplerCache::getSampler(const Sampler& ssharp)
{
Rc<VltSampler> result = nullptr;
auto iter = m_samplers.find(ssharp);
if (iter != m_samplers.end())
{
result = iter->second;
}
return result;
}
void GnmSamplerCache::addSampler(
const Sampler& ssharp,
const Rc<VltSampler>& sampler)
{
m_samplers.emplace(ssharp, sampler);
}
size_t GnmSamplerHash::operator()(const Sampler& object) const
{
VltHashState state;
state.add(object.m_regs[0]);
state.add(object.m_regs[1]);
state.add(object.m_regs[2]);
state.add(object.m_regs[3]);
return state;
}
} // namespace sce::Gnm

View file

@ -0,0 +1,51 @@
#pragma once
#include "GPCS4Common.h"
#include "GnmSampler.h"
#include "Violet/VltSampler.h"
#include <unordered_map>
namespace sce::Gnm
{
struct GnmSamplerEq
{
size_t operator()(const Sampler& a, const Sampler& b) const
{
return a == b;
}
};
struct GnmSamplerHash
{
size_t operator()(const Sampler& object) const;
};
/**
* \brief Sampler cache
*
*/
class GnmSamplerCache
{
public:
GnmSamplerCache();
~GnmSamplerCache();
vlt::Rc<vlt::VltSampler> getSampler(
const Sampler& ssharp);
void addSampler(
const Sampler& ssharp,
const vlt::Rc<vlt::VltSampler>& sampler);
private:
std::unordered_map<
Sampler,
vlt::Rc<vlt::VltSampler>,
GnmSamplerHash,
GnmSamplerEq> m_samplers;
};
} // namespace sce::Gnm

View file

@ -2,6 +2,9 @@
#include "Violet/VltBuffer.h"
#include "Violet/VltImage.h"
#include "Violet/VltHash.h"
using namespace sce::vlt;
namespace sce
{

View file

@ -102,17 +102,6 @@ namespace sce
size_t memorySize() const;
};
/**
* Sampler is not memory resource so it won't be
* tracked by resource tracker.
* It is placed here just for convenience.
*/
struct SceSampler
{
Gnm::Sampler ssharp;
vlt::Rc<vlt::VltSampler> sampler;
};
/**
* \brief Represent a Gnm resource with backing memory.