xref: /aosp_15_r20/external/swiftshader/src/System/SwiftConfig.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1 // Copyright 2022 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "SwiftConfig.hpp"
16 
17 #include "CPUID.hpp"
18 #include "Configurator.hpp"
19 #include "Debug.hpp"
20 #include "marl/scheduler.h"
21 
22 #include <algorithm>
23 
24 namespace {
25 
toLowerStr(const std::string & str)26 std::string toLowerStr(const std::string &str)
27 {
28 	std::string lower = str;
29 	std::transform(lower.begin(), lower.end(), lower.begin(),
30 	               [](unsigned char c) { return std::tolower(c); });
31 	return lower;
32 }
33 
getCoreFromIndex(uint8_t coreIndex)34 marl::Thread::Core getCoreFromIndex(uint8_t coreIndex)
35 {
36 	marl::Thread::Core core = {};
37 #if defined(_WIN32)
38 	// We only support one processor group on Windows
39 	// when an explicit affinity mask is used.
40 	core.windows.group = 0;
41 	core.windows.index = coreIndex;
42 #else
43 	core.pthread.index = coreIndex;
44 #endif
45 	return core;
46 }
47 
getAffinityFromMask(uint64_t affinityMask)48 marl::Thread::Affinity getAffinityFromMask(uint64_t affinityMask)
49 {
50 	if(affinityMask == std::numeric_limits<uint64_t>::max())
51 	{
52 		return marl::Thread::Affinity::all();
53 	}
54 
55 	ASSERT(affinityMask != 0);
56 	marl::containers::vector<marl::Thread::Core, 32> cores;
57 	uint8_t coreIndex = 0;
58 	while(affinityMask)
59 	{
60 		if(affinityMask & 1)
61 		{
62 			cores.push_back(getCoreFromIndex(coreIndex));
63 		}
64 		++coreIndex;
65 		affinityMask >>= 1;
66 	}
67 
68 	return marl::Thread::Affinity(cores, marl::Allocator::Default);
69 }
70 
getAffinityPolicy(marl::Thread::Affinity && affinity,sw::Configuration::AffinityPolicy affinityPolicy)71 std::shared_ptr<marl::Thread::Affinity::Policy> getAffinityPolicy(marl::Thread::Affinity &&affinity, sw::Configuration::AffinityPolicy affinityPolicy)
72 {
73 	switch(affinityPolicy)
74 	{
75 	case sw::Configuration::AffinityPolicy::AnyOf:
76 		return marl::Thread::Affinity::Policy::anyOf(std::move(affinity));
77 	case sw::Configuration::AffinityPolicy::OneOf:
78 		return marl::Thread::Affinity::Policy::oneOf(std::move(affinity));
79 	default:
80 		UNREACHABLE("unknown affinity policy");
81 	}
82 	return nullptr;
83 }
84 }  // namespace
85 
86 namespace sw {
87 
readConfigurationFromFile()88 Configuration readConfigurationFromFile()
89 {
90 	Configurator ini("SwiftShader.ini");
91 	Configuration config{};
92 
93 	// Processor flags.
94 	config.threadCount = ini.getInteger<uint32_t>("Processor", "ThreadCount", 0);
95 	config.affinityMask = ini.getInteger<uint64_t>("Processor", "AffinityMask", 0xFFFFFFFFFFFFFFFFu);
96 	if(config.affinityMask == 0)
97 	{
98 		warn("Affinity mask is empty, using all-cores affinity\n");
99 		config.affinityMask = 0xFFFFFFFFFFFFFFFFu;
100 	}
101 	std::string affinityPolicy = toLowerStr(ini.getValue("Processor", "AffinityPolicy", "any"));
102 	if(affinityPolicy == "one")
103 	{
104 		config.affinityPolicy = Configuration::AffinityPolicy::OneOf;
105 	}
106 	else
107 	{
108 		// Default.
109 		config.affinityPolicy = Configuration::AffinityPolicy::AnyOf;
110 	}
111 
112 	// Profiling flags.
113 	config.enableSpirvProfiling = ini.getBoolean("Profiler", "EnableSpirvProfiling");
114 	config.spvProfilingReportPeriodMs = ini.getInteger<uint64_t>("Profiler", "SpirvProfilingReportPeriodMs");
115 	config.spvProfilingReportDir = ini.getValue("Profiler", "SpirvProfilingReportDir");
116 
117 	return config;
118 }
119 
getConfiguration()120 const Configuration &getConfiguration()
121 {
122 	static Configuration config = readConfigurationFromFile();
123 	return config;
124 }
125 
getSchedulerConfiguration(const Configuration & config)126 marl::Scheduler::Config getSchedulerConfiguration(const Configuration &config)
127 {
128 	uint32_t threadCount = (config.threadCount == 0) ? std::min<size_t>(marl::Thread::numLogicalCPUs(), 16)
129 	                                                 : config.threadCount;
130 	auto affinity = getAffinityFromMask(config.affinityMask);
131 	auto affinityPolicy = getAffinityPolicy(std::move(affinity), config.affinityPolicy);
132 
133 	marl::Scheduler::Config cfg;
134 	cfg.setWorkerThreadCount(threadCount);
135 	cfg.setWorkerThreadAffinityPolicy(affinityPolicy);
136 	cfg.setWorkerThreadInitializer([](int) {
137 		sw::CPUID::setFlushToZero(true);
138 		sw::CPUID::setDenormalsAreZero(true);
139 	});
140 	return cfg;
141 }
142 
143 }  // namespace sw