mirror of
https://github.com/Inori/GPCS4.git
synced 2024-06-01 19:08:08 -04:00
introduce sampler cache
This commit is contained in:
parent
1deea05481
commit
30636e91a8
|
@ -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" />
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
46
GPCS4/Graphics/Gnm/GnmSamplerCache.cpp
Normal file
46
GPCS4/Graphics/Gnm/GnmSamplerCache.cpp
Normal 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
|
51
GPCS4/Graphics/Gnm/GnmSamplerCache.h
Normal file
51
GPCS4/Graphics/Gnm/GnmSamplerCache.h
Normal 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
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#include "Violet/VltBuffer.h"
|
||||
#include "Violet/VltImage.h"
|
||||
#include "Violet/VltHash.h"
|
||||
|
||||
using namespace sce::vlt;
|
||||
|
||||
namespace sce
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue