Use static vector for shader bytecode to prevent constant reallocation

Using `std::vector` for shader bytecode led to a lot of reallocation due to constant resizing, switching over the static vector allows for a single static allocation of the maximum possible guest shader size (1 MiB) to be done for every stage resulting in a 6 MiB preallocation which is unnoticeable given the total memory overhead of running a Switch application.
This commit is contained in:
PixelyIon 2022-01-11 20:01:54 +05:30
parent 21a6866def
commit a2285669b3
2 changed files with 20 additions and 20 deletions

View File

@ -138,8 +138,8 @@ namespace skyline {
* @return If returning was caused by the supplied function returning a non-nullopt value or other conditions * @return If returning was caused by the supplied function returning a non-nullopt value or other conditions
* @note The function will **NOT** be run on any sparse block * @note The function will **NOT** be run on any sparse block
*/ */
template<typename Function> template<typename Function, typename Container>
bool ReadTill(std::vector<u8>& destination, VaType virt, Function function) { bool ReadTill(Container& destination, VaType virt, Function function) {
//TRACE_EVENT("containers", "FlatMemoryManager::ReadTill"); //TRACE_EVENT("containers", "FlatMemoryManager::ReadTill");
std::scoped_lock lock(this->blockMutex); std::scoped_lock lock(this->blockMutex);

View File

@ -618,6 +618,8 @@ namespace skyline::gpu::interconnect {
/* Shader Program */ /* Shader Program */
private: private:
constexpr static size_t MaxShaderBytecodeSize{1 * 1024 * 1024}; //!< The largest shader binary that we support (1 MiB)
struct Shader { struct Shader {
bool enabled{false}; bool enabled{false};
ShaderCompiler::Stage stage; ShaderCompiler::Stage stage;
@ -625,7 +627,7 @@ namespace skyline::gpu::interconnect {
bool invalidated{true}; //!< If the shader that existed earlier has been invalidated bool invalidated{true}; //!< If the shader that existed earlier has been invalidated
bool shouldCheckSame{false}; //!< If we should do a check for the shader being the same as before bool shouldCheckSame{false}; //!< If we should do a check for the shader being the same as before
u32 offset{}; //!< Offset of the shader from the base IOVA u32 offset{}; //!< Offset of the shader from the base IOVA
std::vector<u8> data; //!< The shader bytecode in a vector boost::container::static_vector<u8, MaxShaderBytecodeSize> data; //!< The shader bytecode in a statically allocated vector
std::optional<ShaderCompiler::IR::Program> program; std::optional<ShaderCompiler::IR::Program> program;
Shader(ShaderCompiler::Stage stage) : stage(stage) {} Shader(ShaderCompiler::Stage stage) : stage(stage) {}
@ -657,14 +659,14 @@ namespace skyline::gpu::interconnect {
}; };
struct ShaderSet : public std::array<Shader, maxwell3d::ShaderStageCount> { struct ShaderSet : public std::array<Shader, maxwell3d::ShaderStageCount> {
ShaderSet() : array({ ShaderSet() : array{
Shader{ShaderCompiler::Stage::VertexA}, Shader{ShaderCompiler::Stage::VertexA},
Shader{ShaderCompiler::Stage::VertexB}, Shader{ShaderCompiler::Stage::VertexB},
Shader{ShaderCompiler::Stage::TessellationControl}, Shader{ShaderCompiler::Stage::TessellationControl},
Shader{ShaderCompiler::Stage::TessellationEval}, Shader{ShaderCompiler::Stage::TessellationEval},
Shader{ShaderCompiler::Stage::Geometry}, Shader{ShaderCompiler::Stage::Geometry},
Shader{ShaderCompiler::Stage::Fragment}, Shader{ShaderCompiler::Stage::Fragment},
}) {} } {}
Shader &at(maxwell3d::ShaderStage stage) { Shader &at(maxwell3d::ShaderStage stage) {
return array::at(static_cast<size_t>(stage)); return array::at(static_cast<size_t>(stage));
@ -692,13 +694,13 @@ namespace skyline::gpu::interconnect {
}; };
struct PipelineStages : public std::array<PipelineStage, maxwell3d::PipelineStageCount> { struct PipelineStages : public std::array<PipelineStage, maxwell3d::PipelineStageCount> {
PipelineStages() : array({ PipelineStages() : array{
PipelineStage{vk::ShaderStageFlagBits::eVertex}, PipelineStage{vk::ShaderStageFlagBits::eVertex},
PipelineStage{vk::ShaderStageFlagBits::eTessellationControl}, PipelineStage{vk::ShaderStageFlagBits::eTessellationControl},
PipelineStage{vk::ShaderStageFlagBits::eTessellationEvaluation}, PipelineStage{vk::ShaderStageFlagBits::eTessellationEvaluation},
PipelineStage{vk::ShaderStageFlagBits::eGeometry}, PipelineStage{vk::ShaderStageFlagBits::eGeometry},
PipelineStage{vk::ShaderStageFlagBits::eFragment}, PipelineStage{vk::ShaderStageFlagBits::eFragment},
}) {} } {}
PipelineStage &at(maxwell3d::PipelineStage stage) { PipelineStage &at(maxwell3d::PipelineStage stage) {
return array::at(static_cast<size_t>(stage)); return array::at(static_cast<size_t>(stage));
@ -715,8 +717,6 @@ namespace skyline::gpu::interconnect {
ShaderCompiler::RuntimeInfo runtimeInfo{}; ShaderCompiler::RuntimeInfo runtimeInfo{};
constexpr static size_t MaxShaderBytecodeSize{1 * 1024 * 1024}; //!< The largest shader binary that we support (1 MiB)
constexpr static size_t PipelineUniqueDescriptorTypeCount{2}; //!< The amount of unique descriptor types that may be bound to a pipeline constexpr static size_t PipelineUniqueDescriptorTypeCount{2}; //!< The amount of unique descriptor types that may be bound to a pipeline
constexpr static size_t MaxPipelineDescriptorWriteCount{maxwell3d::PipelineStageCount * PipelineUniqueDescriptorTypeCount}; //!< The maxium amount of descriptors writes that are used to bind a pipeline constexpr static size_t MaxPipelineDescriptorWriteCount{maxwell3d::PipelineStageCount * PipelineUniqueDescriptorTypeCount}; //!< The maxium amount of descriptors writes that are used to bind a pipeline
constexpr static size_t MaxPipelineDescriptorCount{100}; //!< The maxium amount of descriptors we support being bound to a pipeline constexpr static size_t MaxPipelineDescriptorCount{100}; //!< The maxium amount of descriptors we support being bound to a pipeline