1 // Copyright 2016 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 "Config.hpp" 18 #include "Common/Configurator.hpp" 19 #include "Common/Debug.hpp" 20 #include "Common/Version.h" 21 22 #include <sstream> 23 #include <stdio.h> 24 #include <time.h> 25 #include <sys/stat.h> 26 #include <string.h> 27 #include <algorithm> 28 29 namespace sw 30 { 31 extern Profiler profiler; 32 itoa(int number)33 std::string itoa(int number) 34 { 35 std::stringstream ss; 36 ss << number; 37 return ss.str(); 38 } 39 ftoa(double number)40 std::string ftoa(double number) 41 { 42 std::stringstream ss; 43 ss << number; 44 return ss.str(); 45 } 46 SwiftConfig(bool disableServerOverride)47 SwiftConfig::SwiftConfig(bool disableServerOverride) : listenSocket(0) 48 { 49 readConfiguration(disableServerOverride); 50 51 if(!disableServerOverride) 52 { 53 writeConfiguration(); 54 } 55 56 receiveBuffer = 0; 57 58 if(!config.disableServer) 59 { 60 createServer(); 61 } 62 } 63 ~SwiftConfig()64 SwiftConfig::~SwiftConfig() 65 { 66 destroyServer(); 67 } 68 createServer()69 void SwiftConfig::createServer() 70 { 71 bufferLength = 16 * 1024; 72 receiveBuffer = new char[bufferLength]; 73 74 Socket::startup(); 75 listenSocket = new Socket("localhost", "8080"); 76 listenSocket->listen(); 77 78 terminate = false; 79 serverThread = new Thread(serverRoutine, this); 80 } 81 destroyServer()82 void SwiftConfig::destroyServer() 83 { 84 if(receiveBuffer) 85 { 86 terminate = true; 87 serverThread->join(); 88 delete serverThread; 89 90 delete listenSocket; 91 listenSocket = 0; 92 93 Socket::cleanup(); 94 95 delete[] receiveBuffer; 96 receiveBuffer = 0; 97 } 98 } 99 hasNewConfiguration(bool reset)100 bool SwiftConfig::hasNewConfiguration(bool reset) 101 { 102 bool value = newConfig; 103 104 if(reset) 105 { 106 newConfig = false; 107 } 108 109 return value; 110 } 111 getConfiguration(Configuration & configuration)112 void SwiftConfig::getConfiguration(Configuration &configuration) 113 { 114 criticalSection.lock(); 115 configuration = config; 116 criticalSection.unlock(); 117 } 118 serverRoutine(void * parameters)119 void SwiftConfig::serverRoutine(void *parameters) 120 { 121 SwiftConfig *swiftConfig = (SwiftConfig*)parameters; 122 123 swiftConfig->serverLoop(); 124 } 125 serverLoop()126 void SwiftConfig::serverLoop() 127 { 128 readConfiguration(); 129 130 while(!terminate) 131 { 132 if(listenSocket->select(100000)) 133 { 134 Socket *clientSocket = listenSocket->accept(); 135 int bytesReceived = 1; 136 137 while(bytesReceived > 0 && !terminate) 138 { 139 if(clientSocket->select(10)) 140 { 141 bytesReceived = clientSocket->receive(receiveBuffer, bufferLength); 142 143 if(bytesReceived > 0) 144 { 145 receiveBuffer[bytesReceived] = 0; 146 147 respond(clientSocket, receiveBuffer); 148 } 149 } 150 } 151 152 delete clientSocket; 153 } 154 } 155 } 156 match(const char ** url,const char * string)157 bool match(const char **url, const char *string) 158 { 159 size_t length = strlen(string); 160 161 if(strncmp(*url, string, length) == 0) 162 { 163 *url += length; 164 165 return true; 166 } 167 168 return false; 169 } 170 respond(Socket * clientSocket,const char * request)171 void SwiftConfig::respond(Socket *clientSocket, const char *request) 172 { 173 if(match(&request, "GET /")) 174 { 175 if(match(&request, "swiftshader") || match(&request, "swiftconfig")) 176 { 177 if(match(&request, " ") || match(&request, "/ ")) 178 { 179 return send(clientSocket, OK, page()); 180 } 181 } 182 } 183 else if(match(&request, "POST /")) 184 { 185 if(match(&request, "swiftshader") || match(&request, "swiftconfig")) 186 { 187 if(match(&request, " ") || match(&request, "/ ")) 188 { 189 criticalSection.lock(); 190 191 const char *postData = strstr(request, "\r\n\r\n"); 192 postData = postData ? postData + 4 : 0; 193 194 if(postData && strlen(postData) > 0) 195 { 196 parsePost(postData); 197 } 198 else // POST data in next packet 199 { 200 int bytesReceived = clientSocket->receive(receiveBuffer, bufferLength); 201 202 if(bytesReceived > 0) 203 { 204 receiveBuffer[bytesReceived] = 0; 205 parsePost(receiveBuffer); 206 } 207 } 208 209 writeConfiguration(); 210 newConfig = true; 211 212 if(config.disableServer) 213 { 214 destroyServer(); 215 } 216 217 criticalSection.unlock(); 218 219 return send(clientSocket, OK, page()); 220 } 221 else if(match(&request, "/profile ")) 222 { 223 return send(clientSocket, OK, profile()); 224 } 225 } 226 } 227 228 return send(clientSocket, NotFound); 229 } 230 page()231 std::string SwiftConfig::page() 232 { 233 std::string html; 234 235 const std::string selected = "selected='selected'"; 236 const std::string checked = "checked='checked'"; 237 const std::string empty = ""; 238 239 html += "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>\n"; 240 html += "<html>\n"; 241 html += "<head>\n"; 242 html += "<meta http-equiv='content-type' content='text/html; charset=UTF-8'>\n"; 243 html += "<title>SwiftShader Configuration Panel</title>\n"; 244 html += "</head>\n"; 245 html += "<body>\n"; 246 html += "<script type='text/javascript'>\n"; 247 html += "request();\n"; 248 html += "function request()\n"; 249 html += "{\n"; 250 html += "var xhr = new XMLHttpRequest();\n"; 251 html += "xhr.open('POST', '/swiftshader/profile', true);\n"; 252 html += "xhr.onreadystatechange = function()\n"; 253 html += "{\n"; 254 html += "if(xhr.readyState == 4 && xhr.status == 200)\n"; 255 html += "{\n"; 256 html += "document.getElementById('profile').innerHTML = xhr.responseText;\n"; 257 html += "setTimeout('request()', 1000);\n"; 258 html += "}\n"; 259 html += "}\n"; 260 html += "xhr.send();\n"; 261 html += "}\n"; 262 html += "</script>\n"; 263 html += "<form method='POST' action=''>\n"; 264 html += "<h1>SwiftShader Configuration Panel</h1>\n"; 265 html += "<div id='profile'>" + profile() + "</div>\n"; 266 html += "<hr><p>\n"; 267 html += "<input type='submit' value='Apply changes' title='Click to apply all settings.'>\n"; 268 // html += "<input type='reset' value='Reset changes' title='Click to reset your changes to the previous value.'>\n"; 269 html += "</p><hr>\n"; 270 html += "<h2><em>Device capabilities</em></h2>\n"; 271 html += "<table>\n"; 272 html += "<tr><td>Build revision:</td><td>" REVISION_STRING "</td></tr>\n"; 273 html += "<tr><td>Pixel shader model:</td><td><select name='pixelShaderVersion' title='The highest version of pixel shader supported by SwiftShader. Lower versions might be faster if supported by the application. Only effective after restarting the application.'>\n"; 274 html += "<option value='0'" + (config.pixelShaderVersion == 0 ? selected : empty) + ">0.0</option>\n"; 275 html += "<option value='11'" + (config.pixelShaderVersion == 11 ? selected : empty) + ">1.1</option>\n"; 276 html += "<option value='12'" + (config.pixelShaderVersion == 12 ? selected : empty) + ">1.2</option>\n"; 277 html += "<option value='13'" + (config.pixelShaderVersion == 13 ? selected : empty) + ">1.3</option>\n"; 278 html += "<option value='14'" + (config.pixelShaderVersion == 14 ? selected : empty) + ">1.4</option>\n"; 279 html += "<option value='20'" + (config.pixelShaderVersion == 20 ? selected : empty) + ">2.0</option>\n"; 280 html += "<option value='21'" + (config.pixelShaderVersion == 21 ? selected : empty) + ">2.x</option>\n"; 281 html += "<option value='30'" + (config.pixelShaderVersion == 30 ? selected : empty) + ">3.0 (default)</option>\n"; 282 html += "</select></td></tr>\n"; 283 html += "<tr><td>Vertex shader model:</td><td><select name='vertexShaderVersion' title='The highest version of vertex shader supported by SwiftShader. Lower versions might be faster if supported by the application. Only effective after restarting the application.'>\n"; 284 html += "<option value='0'" + (config.vertexShaderVersion == 0 ? selected : empty) + ">0.0</option>\n"; 285 html += "<option value='11'" + (config.vertexShaderVersion == 11 ? selected : empty) + ">1.1</option>\n"; 286 html += "<option value='20'" + (config.vertexShaderVersion == 20 ? selected : empty) + ">2.0</option>\n"; 287 html += "<option value='21'" + (config.vertexShaderVersion == 21 ? selected : empty) + ">2.x</option>\n"; 288 html += "<option value='30'" + (config.vertexShaderVersion == 30 ? selected : empty) + ">3.0 (default)</option>\n"; 289 html += "</select></td></tr>\n"; 290 html += "<tr><td>Texture memory:</td><td><select name='textureMemory' title='The maximum amount of memory used for textures and other resources.'>\n"; 291 html += "<option value='128'" + (config.textureMemory == 128 ? selected : empty) + ">128 MB</option>\n"; 292 html += "<option value='256'" + (config.textureMemory == 256 ? selected : empty) + ">256 MB (default)</option>\n"; 293 html += "<option value='512'" + (config.textureMemory == 512 ? selected : empty) + ">512 MB</option>\n"; 294 html += "<option value='1024'" + (config.textureMemory == 1024 ? selected : empty) + ">1024 MB</option>\n"; 295 html += "<option value='2048'" + (config.textureMemory == 2048 ? selected : empty) + ">2048 MB</option>\n"; 296 html += "</select></td></tr>\n"; 297 html += "<tr><td>Device identifier:</td><td><select name='identifier' title='The information used by some applications to determine device capabilities.'>\n"; 298 html += "<option value='0'" + (config.identifier == 0 ? selected : empty) + ">Google SwiftShader (default)</option>\n"; 299 html += "<option value='1'" + (config.identifier == 1 ? selected : empty) + ">NVIDIA GeForce 7900 GS</option>\n"; 300 html += "<option value='2'" + (config.identifier == 2 ? selected : empty) + ">ATI Mobility Radeon X1600</option>\n"; 301 html += "<option value='3'" + (config.identifier == 3 ? selected : empty) + ">Intel GMA X3100</option>\n"; 302 html += "<option value='4'" + (config.identifier == 4 ? selected : empty) + ">System device</option>\n"; 303 html += "</select></td></tr>\n"; 304 html += "</table>\n"; 305 html += "<h2><em>Cache sizes</em></h2>\n"; 306 html += "<table>\n"; 307 html += "<tr><td>Vertex routine cache size:</td><td><select name='vertexRoutineCacheSize' title='The number of dynamically generated vertex processing routines being cached for reuse. Lower numbers save memory but require more routines to be regenerated.'>\n"; 308 html += "<option value='64'" + (config.vertexRoutineCacheSize == 64 ? selected : empty) + ">64</option>\n"; 309 html += "<option value='128'" + (config.vertexRoutineCacheSize == 128 ? selected : empty) + ">128</option>\n"; 310 html += "<option value='256'" + (config.vertexRoutineCacheSize == 256 ? selected : empty) + ">256</option>\n"; 311 html += "<option value='512'" + (config.vertexRoutineCacheSize == 512 ? selected : empty) + ">512</option>\n"; 312 html += "<option value='1024'" + (config.vertexRoutineCacheSize == 1024 ? selected : empty) + ">1024 (default)</option>\n"; 313 html += "<option value='2048'" + (config.vertexRoutineCacheSize == 2048 ? selected : empty) + ">2048</option>\n"; 314 html += "<option value='4096'" + (config.vertexRoutineCacheSize == 4096 ? selected : empty) + ">4096</option>\n"; 315 html += "</select></td>\n"; 316 html += "</tr>\n"; 317 html += "<tr><td>Pixel routine cache size:</td><td><select name='pixelRoutineCacheSize' title='The number of dynamically generated pixel processing routines being cached for reuse. Lower numbers save memory but require more routines to be regenerated.'>\n"; 318 html += "<option value='64'" + (config.pixelRoutineCacheSize == 64 ? selected : empty) + ">64</option>\n"; 319 html += "<option value='128'" + (config.pixelRoutineCacheSize == 128 ? selected : empty) + ">128</option>\n"; 320 html += "<option value='256'" + (config.pixelRoutineCacheSize == 256 ? selected : empty) + ">256</option>\n"; 321 html += "<option value='512'" + (config.pixelRoutineCacheSize == 512 ? selected : empty) + ">512</option>\n"; 322 html += "<option value='1024'" + (config.pixelRoutineCacheSize == 1024 ? selected : empty) + ">1024 (default)</option>\n"; 323 html += "<option value='2048'" + (config.pixelRoutineCacheSize == 2048 ? selected : empty) + ">2048</option>\n"; 324 html += "<option value='4096'" + (config.pixelRoutineCacheSize == 4096 ? selected : empty) + ">4096</option>\n"; 325 html += "</select></td>\n"; 326 html += "</tr>\n"; 327 html += "<tr><td>Setup routine cache size:</td><td><select name='setupRoutineCacheSize' title='The number of dynamically generated primitive setup routines being cached for reuse. Lower numbers save memory but require more routines to be regenerated.'>\n"; 328 html += "<option value='64'" + (config.setupRoutineCacheSize == 64 ? selected : empty) + ">64</option>\n"; 329 html += "<option value='128'" + (config.setupRoutineCacheSize == 128 ? selected : empty) + ">128</option>\n"; 330 html += "<option value='256'" + (config.setupRoutineCacheSize == 256 ? selected : empty) + ">256</option>\n"; 331 html += "<option value='512'" + (config.setupRoutineCacheSize == 512 ? selected : empty) + ">512</option>\n"; 332 html += "<option value='1024'" + (config.setupRoutineCacheSize == 1024 ? selected : empty) + ">1024 (default)</option>\n"; 333 html += "<option value='2048'" + (config.setupRoutineCacheSize == 2048 ? selected : empty) + ">2048</option>\n"; 334 html += "<option value='4096'" + (config.setupRoutineCacheSize == 4096 ? selected : empty) + ">4096</option>\n"; 335 html += "</select></td>\n"; 336 html += "</tr>\n"; 337 html += "<tr><td>Vertex cache size:</td><td><select name='vertexCacheSize' title='The number of processed vertices being cached for reuse. Lower numbers save memory but require more vertices to be reprocessed.'>\n"; 338 html += "<option value='64'" + (config.vertexCacheSize == 64 ? selected : empty) + ">64 (default)</option>\n"; 339 html += "</select></td>\n"; 340 html += "</tr>\n"; 341 html += "</table>\n"; 342 html += "<h2><em>Quality</em></h2>\n"; 343 html += "<table>\n"; 344 html += "<tr><td>Maximum texture sampling quality:</td><td><select name='textureSampleQuality' title='The maximum texture filtering quality. Lower settings can be faster but cause visual artifacts.'>\n"; 345 html += "<option value='0'" + (config.textureSampleQuality == 0 ? selected : empty) + ">Point</option>\n"; 346 html += "<option value='1'" + (config.textureSampleQuality == 1 ? selected : empty) + ">Linear</option>\n"; 347 html += "<option value='2'" + (config.textureSampleQuality == 2 ? selected : empty) + ">Anisotropic (default)</option>\n"; 348 html += "</select></td>\n"; 349 html += "</tr>\n"; 350 html += "<tr><td>Maximum mipmapping quality:</td><td><select name='mipmapQuality' title='The maximum mipmap filtering quality. Higher settings can be more visually appealing but are slower.'>\n"; 351 html += "<option value='0'" + (config.mipmapQuality == 0 ? selected : empty) + ">Point</option>\n"; 352 html += "<option value='1'" + (config.mipmapQuality == 1 ? selected : empty) + ">Linear (default)</option>\n"; 353 html += "</select></td>\n"; 354 html += "</tr>\n"; 355 html += "<tr><td>Perspective correction:</td><td><select name='perspectiveCorrection' title='Enables or disables perspective correction. Disabling it is faster but can causes distortion. Recommended for 2D applications only.'>\n"; 356 html += "<option value='0'" + (config.perspectiveCorrection == 0 ? selected : empty) + ">Off</option>\n"; 357 html += "<option value='1'" + (config.perspectiveCorrection == 1 ? selected : empty) + ">On (default)</option>\n"; 358 html += "</select></td>\n"; 359 html += "</tr>\n"; 360 html += "<tr><td>Transcendental function precision:</td><td><select name='transcendentalPrecision' title='The precision at which log/exp/pow/rcp/rsq/nrm shader instructions are computed. Lower settings can be faster but cause visual artifacts.'>\n"; 361 html += "<option value='0'" + (config.transcendentalPrecision == 0 ? selected : empty) + ">Approximate</option>\n"; 362 html += "<option value='1'" + (config.transcendentalPrecision == 1 ? selected : empty) + ">Partial</option>\n"; 363 html += "<option value='2'" + (config.transcendentalPrecision == 2 ? selected : empty) + ">Accurate (default)</option>\n"; 364 html += "<option value='3'" + (config.transcendentalPrecision == 3 ? selected : empty) + ">WHQL</option>\n"; 365 html += "<option value='4'" + (config.transcendentalPrecision == 4 ? selected : empty) + ">IEEE</option>\n"; 366 html += "</select></td>\n"; 367 html += "</tr>\n"; 368 html += "<tr><td>Transparency anti-aliasing:</td><td><select name='transparencyAntialiasing' title='The technique used to anti-alias alpha-tested transparent textures.'>\n"; 369 html += "<option value='0'" + (config.transparencyAntialiasing == 0 ? selected : empty) + ">None (default)</option>\n"; 370 html += "<option value='1'" + (config.transparencyAntialiasing == 1 ? selected : empty) + ">Alpha-to-Coverage</option>\n"; 371 html += "</select></td>\n"; 372 html += "</table>\n"; 373 html += "<h2><em>Processor settings</em></h2>\n"; 374 html += "<table>\n"; 375 html += "<tr><td>Number of threads:</td><td><select name='threadCount' title='The number of rendering threads to be used.'>\n"; 376 html += "<option value='-1'" + (config.threadCount == -1 ? selected : empty) + ">Core count</option>\n"; 377 html += "<option value='0'" + (config.threadCount == 0 ? selected : empty) + ">Process affinity (default)</option>\n"; 378 html += "<option value='1'" + (config.threadCount == 1 ? selected : empty) + ">1</option>\n"; 379 html += "<option value='2'" + (config.threadCount == 2 ? selected : empty) + ">2</option>\n"; 380 html += "<option value='3'" + (config.threadCount == 3 ? selected : empty) + ">3</option>\n"; 381 html += "<option value='4'" + (config.threadCount == 4 ? selected : empty) + ">4</option>\n"; 382 html += "<option value='5'" + (config.threadCount == 5 ? selected : empty) + ">5</option>\n"; 383 html += "<option value='6'" + (config.threadCount == 6 ? selected : empty) + ">6</option>\n"; 384 html += "<option value='7'" + (config.threadCount == 7 ? selected : empty) + ">7</option>\n"; 385 html += "<option value='8'" + (config.threadCount == 8 ? selected : empty) + ">8</option>\n"; 386 html += "<option value='9'" + (config.threadCount == 9 ? selected : empty) + ">9</option>\n"; 387 html += "<option value='10'" + (config.threadCount == 10 ? selected : empty) + ">10</option>\n"; 388 html += "<option value='11'" + (config.threadCount == 11 ? selected : empty) + ">11</option>\n"; 389 html += "<option value='12'" + (config.threadCount == 12 ? selected : empty) + ">12</option>\n"; 390 html += "<option value='13'" + (config.threadCount == 13 ? selected : empty) + ">13</option>\n"; 391 html += "<option value='14'" + (config.threadCount == 14 ? selected : empty) + ">14</option>\n"; 392 html += "<option value='15'" + (config.threadCount == 15 ? selected : empty) + ">15</option>\n"; 393 html += "<option value='16'" + (config.threadCount == 16 ? selected : empty) + ">16</option>\n"; 394 html += "</select></td></tr>\n"; 395 html += "<tr><td>Enable SSE:</td><td><input name = 'enableSSE' type='checkbox'" + (config.enableSSE ? checked : empty) + " disabled='disabled' title='If checked enables the use of SSE instruction set extentions if supported by the CPU.'></td></tr>"; 396 html += "<tr><td>Enable SSE2:</td><td><input name = 'enableSSE2' type='checkbox'" + (config.enableSSE2 ? checked : empty) + " title='If checked enables the use of SSE2 instruction set extentions if supported by the CPU.'></td></tr>"; 397 html += "<tr><td>Enable SSE3:</td><td><input name = 'enableSSE3' type='checkbox'" + (config.enableSSE3 ? checked : empty) + " title='If checked enables the use of SSE3 instruction set extentions if supported by the CPU.'></td></tr>"; 398 html += "<tr><td>Enable SSSE3:</td><td><input name = 'enableSSSE3' type='checkbox'" + (config.enableSSSE3 ? checked : empty) + " title='If checked enables the use of SSSE3 instruction set extentions if supported by the CPU.'></td></tr>"; 399 html += "<tr><td>Enable SSE4.1:</td><td><input name = 'enableSSE4_1' type='checkbox'" + (config.enableSSE4_1 ? checked : empty) + " title='If checked enables the use of SSE4.1 instruction set extentions if supported by the CPU.'></td></tr>"; 400 html += "</table>\n"; 401 html += "<h2><em>Compiler optimizations</em></h2>\n"; 402 html += "<table>\n"; 403 404 for(int pass = 0; pass < 10; pass++) 405 { 406 html += "<tr><td>Optimization pass " + itoa(pass + 1) + ":</td><td><select name='optimization" + itoa(pass + 1) + "' title='An optimization pass for the shader compiler.'>\n"; 407 html += "<option value='0'" + (config.optimization[pass] == 0 ? selected : empty) + ">Disabled" + (pass > 0 ? " (default)" : "") + "</option>\n"; 408 html += "<option value='1'" + (config.optimization[pass] == 1 ? selected : empty) + ">Instruction Combining" + (pass == 0 ? " (default)" : "") + "</option>\n"; 409 html += "<option value='2'" + (config.optimization[pass] == 2 ? selected : empty) + ">Control Flow Simplification</option>\n"; 410 html += "<option value='3'" + (config.optimization[pass] == 3 ? selected : empty) + ">Loop Invariant Code Motion</option>\n"; 411 html += "<option value='4'" + (config.optimization[pass] == 4 ? selected : empty) + ">Aggressive Dead Code Elimination</option>\n"; 412 html += "<option value='5'" + (config.optimization[pass] == 5 ? selected : empty) + ">Global Value Numbering</option>\n"; 413 html += "<option value='6'" + (config.optimization[pass] == 6 ? selected : empty) + ">Commutative Expressions Reassociation</option>\n"; 414 html += "<option value='7'" + (config.optimization[pass] == 7 ? selected : empty) + ">Dead Store Elimination</option>\n"; 415 html += "<option value='8'" + (config.optimization[pass] == 8 ? selected : empty) + ">Sparse Conditional Copy Propagation</option>\n"; 416 html += "<option value='9'" + (config.optimization[pass] == 9 ? selected : empty) + ">Scalar Replacement of Aggregates</option>\n"; 417 html += "</select></td></tr>\n"; 418 } 419 420 html += "</table>\n"; 421 html += "<h2><em>Testing & Experimental</em></h2>\n"; 422 html += "<table>\n"; 423 html += "<tr><td>Disable SwiftConfig server:</td><td><input name = 'disableServer' type='checkbox'" + (config.disableServer == true ? checked : empty) + " title='If checked disables the web browser based control panel.'></td></tr>"; 424 html += "<tr><td>Force windowed mode:</td><td><input name = 'forceWindowed' type='checkbox'" + (config.forceWindowed == true ? checked : empty) + " title='If checked prevents the application from switching to full-screen mode.'></td></tr>"; 425 html += "<tr><td>Complementary depth buffer:</td><td><input name = 'complementaryDepthBuffer' type='checkbox'" + (config.complementaryDepthBuffer == true ? checked : empty) + " title='If checked causes 1 - z to be stored in the depth buffer.'></td></tr>"; 426 html += "<tr><td>Post alpha blend sRGB conversion:</td><td><input name = 'postBlendSRGB' type='checkbox'" + (config.postBlendSRGB == true ? checked : empty) + " title='If checked alpha blending is performed in linear color space.'></td></tr>"; 427 html += "<tr><td>Exact color rounding:</td><td><input name = 'exactColorRounding' type='checkbox'" + (config.exactColorRounding == true ? checked : empty) + " title='If checked color rounding is done at high accuracy.'></td></tr>"; 428 html += "<tr><td>Disable alpha display formats:</td><td><input name = 'disableAlphaMode' type='checkbox'" + (config.disableAlphaMode == true ? checked : empty) + " title='If checked the device does not advertise the A8R8G8B8 display mode.'></td></tr>"; 429 html += "<tr><td>Disable 10-bit display formats:</td><td><input name = 'disable10BitMode' type='checkbox'" + (config.disable10BitMode == true ? checked : empty) + " title='If checked the device does not advertise the A2R10G10B10 display mode.'></td></tr>"; 430 html += "<tr><td>Frame-buffer API:</td><td><select name='frameBufferAPI' title='The API used for displaying the rendered result on screen (requires restart).'>\n"; 431 html += "<option value='0'" + (config.frameBufferAPI == 0 ? selected : empty) + ">DirectDraw (default)</option>\n"; 432 html += "<option value='1'" + (config.frameBufferAPI == 1 ? selected : empty) + ">GDI</option>\n"; 433 html += "</select></td>\n"; 434 html += "<tr><td>DLL precaching:</td><td><input name = 'precache' type='checkbox'" + (config.precache == true ? checked : empty) + " title='If checked dynamically generated routines will be stored in a DLL for faster loading on application restart.'></td></tr>"; 435 html += "<tr><td>Shadow mapping extensions:</td><td><select name='shadowMapping' title='Features that may accelerate or improve the quality of shadow mapping.'>\n"; 436 html += "<option value='0'" + (config.shadowMapping == 0 ? selected : empty) + ">None</option>\n"; 437 html += "<option value='1'" + (config.shadowMapping == 1 ? selected : empty) + ">Fetch4</option>\n"; 438 html += "<option value='2'" + (config.shadowMapping == 2 ? selected : empty) + ">DST</option>\n"; 439 html += "<option value='3'" + (config.shadowMapping == 3 ? selected : empty) + ">Fetch4 & DST (default)</option>\n"; 440 html += "</select></td>\n"; 441 html += "<tr><td>Force clearing registers that have no default value:</td><td><input name = 'forceClearRegisters' type='checkbox'" + (config.forceClearRegisters == true ? checked : empty) + " title='Initializes shader register values to 0 even if they have no default.'></td></tr>"; 442 html += "</table>\n"; 443 #ifndef NDEBUG 444 html += "<h2><em>Debugging</em></h2>\n"; 445 html += "<table>\n"; 446 html += "<tr><td>Minimum primitives:</td><td><input type='text' size='10' maxlength='10' name='minPrimitives' value='" + itoa(config.minPrimitives) + "'></td></tr>\n"; 447 html += "<tr><td>Maximum primitives:</td><td><input type='text' size='10' maxlength='10' name='maxPrimitives' value='" + itoa(config.maxPrimitives) + "'></td></tr>\n"; 448 html += "</table>\n"; 449 #endif 450 html += "<hr><p>\n"; 451 html += "<span style='font-size:10pt'>Hover the mouse pointer over a control to get additional information.</span><br>\n"; 452 html += "<span style='font-size:10pt'>Some settings can be applied interactively, some need a restart of the application.</span><br>\n"; 453 html += "<span style='font-size:10pt'>Removing the SwiftShader.ini file results in resetting the options to their default.</span></p>\n"; 454 html += "</form>\n"; 455 html += "</body>\n"; 456 html += "</html>\n"; 457 458 profiler.reset(); 459 460 return html; 461 } 462 profile()463 std::string SwiftConfig::profile() 464 { 465 std::string html; 466 467 html += "<p>FPS: " + ftoa(profiler.FPS) + "</p>\n"; 468 html += "<p>Frame: " + itoa(profiler.framesTotal) + "</p>\n"; 469 470 #if PERF_PROFILE 471 int texTime = (int)(1000 * profiler.cycles[PERF_TEX] / profiler.cycles[PERF_PIXEL] + 0.5); 472 int shaderTime = (int)(1000 * profiler.cycles[PERF_SHADER] / profiler.cycles[PERF_PIXEL] + 0.5); 473 int pipeTime = (int)(1000 * profiler.cycles[PERF_PIPE] / profiler.cycles[PERF_PIXEL] + 0.5); 474 int ropTime = (int)(1000 * profiler.cycles[PERF_ROP] / profiler.cycles[PERF_PIXEL] + 0.5); 475 int interpTime = (int)(1000 * profiler.cycles[PERF_INTERP] / profiler.cycles[PERF_PIXEL] + 0.5); 476 int rastTime = 1000 - pipeTime; 477 478 pipeTime -= shaderTime + ropTime + interpTime; 479 shaderTime -= texTime; 480 481 double texTimeF = (double)texTime / 10; 482 double shaderTimeF = (double)shaderTime / 10; 483 double pipeTimeF = (double)pipeTime / 10; 484 double ropTimeF = (double)ropTime / 10; 485 double interpTimeF = (double)interpTime / 10; 486 double rastTimeF = (double)rastTime / 10; 487 488 double averageRopOperations = profiler.ropOperationsTotal / std::max(profiler.framesTotal, 1) / 1.0e6f; 489 double averageCompressedTex = profiler.compressedTexTotal / std::max(profiler.framesTotal, 1) / 1.0e6f; 490 double averageTexOperations = profiler.texOperationsTotal / std::max(profiler.framesTotal, 1) / 1.0e6f; 491 492 html += "<p>Raster operations (million): " + ftoa(profiler.ropOperationsFrame / 1.0e6f) + " (current), " + ftoa(averageRopOperations) + " (average)</p>\n"; 493 html += "<p>Texture operations (million): " + ftoa(profiler.texOperationsFrame / 1.0e6f) + " (current), " + ftoa(averageTexOperations) + " (average)</p>\n"; 494 html += "<p>Compressed texture operations (million): " + ftoa(profiler.compressedTexFrame / 1.0e6f) + " (current), " + ftoa(averageCompressedTex) + " (average)</p>\n"; 495 html += "<div id='profile' style='position:relative; width:1010px; height:50px; background-color:silver;'>"; 496 html += "<div style='position:relative; width:1000px; height:40px; background-color:white; left:5px; top:5px;'>"; 497 html += "<div style='position:relative; float:left; width:" + itoa(rastTime) + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#FFFF7F; overflow:hidden;'>" + ftoa(rastTimeF) + "% rast</div>\n"; 498 html += "<div style='position:relative; float:left; width:" + itoa(pipeTime) + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#FF7F7F; overflow:hidden;'>" + ftoa(pipeTimeF) + "% pipe</div>\n"; 499 html += "<div style='position:relative; float:left; width:" + itoa(interpTime) + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#7FFFFF; overflow:hidden;'>" + ftoa(interpTimeF) + "% interp</div>\n"; 500 html += "<div style='position:relative; float:left; width:" + itoa(shaderTime) + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#7FFF7F; overflow:hidden;'>" + ftoa(shaderTimeF) + "% shader</div>\n"; 501 html += "<div style='position:relative; float:left; width:" + itoa(texTime) + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#FF7FFF; overflow:hidden;'>" + ftoa(texTimeF) + "% tex</div>\n"; 502 html += "<div style='position:relative; float:left; width:" + itoa(ropTime) + "px; height:40px; border-style:none; text-align:center; line-height:40px; background-color:#7F7FFF; overflow:hidden;'>" + ftoa(ropTimeF) + "% rop</div>\n"; 503 html += "</div></div>\n"; 504 505 for(int i = 0; i < PERF_TIMERS; i++) 506 { 507 profiler.cycles[i] = 0; 508 } 509 #endif 510 511 return html; 512 } 513 send(Socket * clientSocket,Status code,std::string body)514 void SwiftConfig::send(Socket *clientSocket, Status code, std::string body) 515 { 516 std::string status; 517 char header[1024]; 518 519 switch(code) 520 { 521 case OK: status += "HTTP/1.1 200 OK\r\n"; break; 522 case NotFound: status += "HTTP/1.1 404 Not Found\r\n"; break; 523 } 524 525 sprintf(header, "Content-Type: text/html; charset=UTF-8\r\n" 526 "Content-Length: %zd\r\n" 527 "Host: localhost\r\n" 528 "\r\n", body.size()); 529 530 std::string message = status + header + body; 531 clientSocket->send(message.c_str(), (int)message.length()); 532 } 533 parsePost(const char * post)534 void SwiftConfig::parsePost(const char *post) 535 { 536 // Only enabled checkboxes appear in the POST 537 config.enableSSE = true; 538 config.enableSSE2 = false; 539 config.enableSSE3 = false; 540 config.enableSSSE3 = false; 541 config.enableSSE4_1 = false; 542 config.disableServer = false; 543 config.forceWindowed = false; 544 config.complementaryDepthBuffer = false; 545 config.postBlendSRGB = false; 546 config.exactColorRounding = false; 547 config.disableAlphaMode = false; 548 config.disable10BitMode = false; 549 config.precache = false; 550 config.forceClearRegisters = false; 551 552 while(*post != 0) 553 { 554 int integer; 555 int index; 556 557 if(sscanf(post, "pixelShaderVersion=%d", &integer)) 558 { 559 config.pixelShaderVersion = integer; 560 } 561 else if(sscanf(post, "vertexShaderVersion=%d", &integer)) 562 { 563 config.vertexShaderVersion = integer; 564 } 565 else if(sscanf(post, "textureMemory=%d", &integer)) 566 { 567 config.textureMemory = integer; 568 } 569 else if(sscanf(post, "identifier=%d", &integer)) 570 { 571 config.identifier = integer; 572 } 573 else if(sscanf(post, "vertexRoutineCacheSize=%d", &integer)) 574 { 575 config.vertexRoutineCacheSize = integer; 576 } 577 else if(sscanf(post, "pixelRoutineCacheSize=%d", &integer)) 578 { 579 config.pixelRoutineCacheSize = integer; 580 } 581 else if(sscanf(post, "setupRoutineCacheSize=%d", &integer)) 582 { 583 config.setupRoutineCacheSize = integer; 584 } 585 else if(sscanf(post, "vertexCacheSize=%d", &integer)) 586 { 587 config.vertexCacheSize = integer; 588 } 589 else if(sscanf(post, "textureSampleQuality=%d", &integer)) 590 { 591 config.textureSampleQuality = integer; 592 } 593 else if(sscanf(post, "mipmapQuality=%d", &integer)) 594 { 595 config.mipmapQuality = integer; 596 } 597 else if(sscanf(post, "perspectiveCorrection=%d", &integer)) 598 { 599 config.perspectiveCorrection = integer != 0; 600 } 601 else if(sscanf(post, "transcendentalPrecision=%d", &integer)) 602 { 603 config.transcendentalPrecision = integer; 604 } 605 else if(sscanf(post, "transparencyAntialiasing=%d", &integer)) 606 { 607 config.transparencyAntialiasing = integer; 608 } 609 else if(sscanf(post, "threadCount=%d", &integer)) 610 { 611 config.threadCount = integer; 612 } 613 else if(sscanf(post, "frameBufferAPI=%d", &integer)) 614 { 615 config.frameBufferAPI = integer; 616 } 617 else if(sscanf(post, "shadowMapping=%d", &integer)) 618 { 619 config.shadowMapping = integer; 620 } 621 else if(strstr(post, "enableSSE=on")) 622 { 623 config.enableSSE = true; 624 } 625 else if(strstr(post, "enableSSE2=on")) 626 { 627 if(config.enableSSE) 628 { 629 config.enableSSE2 = true; 630 } 631 } 632 else if(strstr(post, "enableSSE3=on")) 633 { 634 if(config.enableSSE2) 635 { 636 config.enableSSE3 = true; 637 } 638 } 639 else if(strstr(post, "enableSSSE3=on")) 640 { 641 if(config.enableSSE3) 642 { 643 config.enableSSSE3 = true; 644 } 645 } 646 else if(strstr(post, "enableSSE4_1=on")) 647 { 648 if(config.enableSSSE3) 649 { 650 config.enableSSE4_1 = true; 651 } 652 } 653 else if(sscanf(post, "optimization%d=%d", &index, &integer)) 654 { 655 config.optimization[index - 1] = (rr::Optimization)integer; 656 } 657 else if(strstr(post, "disableServer=on")) 658 { 659 config.disableServer = true; 660 } 661 else if(strstr(post, "forceWindowed=on")) 662 { 663 config.forceWindowed = true; 664 } 665 else if(strstr(post, "complementaryDepthBuffer=on")) 666 { 667 config.complementaryDepthBuffer = true; 668 } 669 else if(strstr(post, "postBlendSRGB=on")) 670 { 671 config.postBlendSRGB = true; 672 } 673 else if(strstr(post, "exactColorRounding=on")) 674 { 675 config.exactColorRounding = true; 676 } 677 else if(strstr(post, "disableAlphaMode=on")) 678 { 679 config.disableAlphaMode = true; 680 } 681 else if(strstr(post, "disable10BitMode=on")) 682 { 683 config.disable10BitMode = true; 684 } 685 else if(strstr(post, "precache=on")) 686 { 687 config.precache = true; 688 } 689 else if(strstr(post, "forceClearRegisters=on")) 690 { 691 config.forceClearRegisters = true; 692 } 693 #ifndef NDEBUG 694 else if(sscanf(post, "minPrimitives=%d", &integer)) 695 { 696 config.minPrimitives = integer; 697 } 698 else if(sscanf(post, "maxPrimitives=%d", &integer)) 699 { 700 config.maxPrimitives = integer; 701 } 702 #endif 703 else 704 { 705 ASSERT(false); 706 } 707 708 do 709 { 710 post++; 711 } 712 while(post[-1] != '&' && *post != 0); 713 } 714 } 715 readConfiguration(bool disableServerOverride)716 void SwiftConfig::readConfiguration(bool disableServerOverride) 717 { 718 Configurator ini("SwiftShader.ini"); 719 720 config.pixelShaderVersion = ini.getInteger("Capabilities", "PixelShaderVersion", 30); 721 config.vertexShaderVersion = ini.getInteger("Capabilities", "VertexShaderVersion", 30); 722 config.textureMemory = ini.getInteger("Capabilities", "TextureMemory", 256); 723 config.identifier = ini.getInteger("Capabilities", "Identifier", 0); 724 config.vertexRoutineCacheSize = ini.getInteger("Caches", "VertexRoutineCacheSize", 1024); 725 config.pixelRoutineCacheSize = ini.getInteger("Caches", "PixelRoutineCacheSize", 1024); 726 config.setupRoutineCacheSize = ini.getInteger("Caches", "SetupRoutineCacheSize", 1024); 727 config.vertexCacheSize = ini.getInteger("Caches", "VertexCacheSize", 64); 728 config.textureSampleQuality = ini.getInteger("Quality", "TextureSampleQuality", 2); 729 config.mipmapQuality = ini.getInteger("Quality", "MipmapQuality", 1); 730 config.perspectiveCorrection = ini.getBoolean("Quality", "PerspectiveCorrection", true); 731 config.transcendentalPrecision = ini.getInteger("Quality", "TranscendentalPrecision", 2); 732 config.transparencyAntialiasing = ini.getInteger("Quality", "TransparencyAntialiasing", 0); 733 config.threadCount = ini.getInteger("Processor", "ThreadCount", DEFAULT_THREAD_COUNT); 734 config.enableSSE = ini.getBoolean("Processor", "EnableSSE", true); 735 config.enableSSE2 = ini.getBoolean("Processor", "EnableSSE2", true); 736 config.enableSSE3 = ini.getBoolean("Processor", "EnableSSE3", true); 737 config.enableSSSE3 = ini.getBoolean("Processor", "EnableSSSE3", true); 738 config.enableSSE4_1 = ini.getBoolean("Processor", "EnableSSE4_1", true); 739 740 for(int pass = 0; pass < 10; pass++) 741 { 742 config.optimization[pass] = (rr::Optimization)ini.getInteger("Optimization", "OptimizationPass" + itoa(pass + 1), pass == 0 ? rr::InstructionCombining : rr::Disabled); 743 } 744 745 config.disableServer = ini.getBoolean("Testing", "DisableServer", false); 746 config.forceWindowed = ini.getBoolean("Testing", "ForceWindowed", false); 747 config.complementaryDepthBuffer = ini.getBoolean("Testing", "ComplementaryDepthBuffer", false); 748 config.postBlendSRGB = ini.getBoolean("Testing", "PostBlendSRGB", false); 749 config.exactColorRounding = ini.getBoolean("Testing", "ExactColorRounding", true); 750 config.disableAlphaMode = ini.getBoolean("Testing", "DisableAlphaMode", false); 751 config.disable10BitMode = ini.getBoolean("Testing", "Disable10BitMode", false); 752 config.frameBufferAPI = ini.getInteger("Testing", "FrameBufferAPI", 0); 753 config.precache = ini.getBoolean("Testing", "Precache", false); 754 config.shadowMapping = ini.getInteger("Testing", "ShadowMapping", 3); 755 config.forceClearRegisters = ini.getBoolean("Testing", "ForceClearRegisters", false); 756 757 #ifndef NDEBUG 758 config.minPrimitives = 1; 759 config.maxPrimitives = 1 << 21; 760 #endif 761 762 struct stat status; 763 int lastModified = ini.getInteger("LastModified", "Time", 0); 764 765 bool noConfig = stat("SwiftShader.ini", &status) != 0; 766 newConfig = !noConfig && abs((int)status.st_mtime - lastModified) > 1; 767 768 if(disableServerOverride) 769 { 770 config.disableServer = true; 771 } 772 } 773 writeConfiguration()774 void SwiftConfig::writeConfiguration() 775 { 776 Configurator ini("SwiftShader.ini"); 777 778 ini.addValue("Capabilities", "PixelShaderVersion", itoa(config.pixelShaderVersion)); 779 ini.addValue("Capabilities", "VertexShaderVersion", itoa(config.vertexShaderVersion)); 780 ini.addValue("Capabilities", "TextureMemory", itoa(config.textureMemory)); 781 ini.addValue("Capabilities", "Identifier", itoa(config.identifier)); 782 ini.addValue("Caches", "VertexRoutineCacheSize", itoa(config.vertexRoutineCacheSize)); 783 ini.addValue("Caches", "PixelRoutineCacheSize", itoa(config.pixelRoutineCacheSize)); 784 ini.addValue("Caches", "SetupRoutineCacheSize", itoa(config.setupRoutineCacheSize)); 785 ini.addValue("Caches", "VertexCacheSize", itoa(config.vertexCacheSize)); 786 ini.addValue("Quality", "TextureSampleQuality", itoa(config.textureSampleQuality)); 787 ini.addValue("Quality", "MipmapQuality", itoa(config.mipmapQuality)); 788 ini.addValue("Quality", "PerspectiveCorrection", itoa(config.perspectiveCorrection)); 789 ini.addValue("Quality", "TranscendentalPrecision", itoa(config.transcendentalPrecision)); 790 ini.addValue("Quality", "TransparencyAntialiasing", itoa(config.transparencyAntialiasing)); 791 ini.addValue("Processor", "ThreadCount", itoa(config.threadCount)); 792 // ini.addValue("Processor", "EnableSSE", itoa(config.enableSSE)); 793 ini.addValue("Processor", "EnableSSE2", itoa(config.enableSSE2)); 794 ini.addValue("Processor", "EnableSSE3", itoa(config.enableSSE3)); 795 ini.addValue("Processor", "EnableSSSE3", itoa(config.enableSSSE3)); 796 ini.addValue("Processor", "EnableSSE4_1", itoa(config.enableSSE4_1)); 797 798 for(int pass = 0; pass < 10; pass++) 799 { 800 ini.addValue("Optimization", "OptimizationPass" + itoa(pass + 1), itoa(config.optimization[pass])); 801 } 802 803 ini.addValue("Testing", "DisableServer", itoa(config.disableServer)); 804 ini.addValue("Testing", "ForceWindowed", itoa(config.forceWindowed)); 805 ini.addValue("Testing", "ComplementaryDepthBuffer", itoa(config.complementaryDepthBuffer)); 806 ini.addValue("Testing", "PostBlendSRGB", itoa(config.postBlendSRGB)); 807 ini.addValue("Testing", "ExactColorRounding", itoa(config.exactColorRounding)); 808 ini.addValue("Testing", "DisableAlphaMode", itoa(config.disableAlphaMode)); 809 ini.addValue("Testing", "Disable10BitMode", itoa(config.disable10BitMode)); 810 ini.addValue("Testing", "FrameBufferAPI", itoa(config.frameBufferAPI)); 811 ini.addValue("Testing", "Precache", itoa(config.precache)); 812 ini.addValue("Testing", "ShadowMapping", itoa(config.shadowMapping)); 813 ini.addValue("Testing", "ForceClearRegisters", itoa(config.forceClearRegisters)); 814 ini.addValue("LastModified", "Time", itoa((int)time(0))); 815 816 ini.writeFile("SwiftShader Configuration File\n" 817 ";\n" 818 "; To get an overview of the valid settings and their meaning,\n" 819 "; run the application in windowed mode and open the\n" 820 "; SwiftConfig application or go to http://localhost:8080/swiftconfig."); 821 } 822 } 823