SwiftShader Documentation

repository·master·Indexed 25 days ago

https://github.com/google/swiftshader

A high-performance, CPU-based implementation of the Vulkan 1.3 graphics API that acts as a software rasterizer to provide hardware independence for advanced 3D graphics. The documentation covers building the project via CMake or Visual Studio, using SwiftShader as a drop-in graphics driver replacement, and verifying the implementation using the dEQP test suite.

Tokens
45.7K
Snippets
72
Records
244
Agent score
77%

What's inside SwiftShader

  1. What is Regres?

    master

    Regres is a collection of tools designed for automated testing of SwiftShader. It facilitates dEQP testing, including presubmit checks for Gerrit patchsets, nightly continuous integration (CI) testing against the master branch, and code coverage evaluation. It also includes a local test runner for efficient, sandboxed dEQP test execution.

    The Regres source root is located at <swiftshader>/tests/regres/.

  2. Optimization patterns and limitations in LLVM/Clang

    master

    This document serves as a collection of test cases and observations regarding optimization failures in the LLVM/Clang toolchain (specifically when using clang -emit-llvm-bc | opt -O3). It highlights scenarios where the compiler fails to perform expected algebraic simplifications, folding, or instruction combining.

    Key categories of optimization issues identified include:

    • Algebraic Simplification & Folding: Failure to combine bitwise operations (e.g., (b << 31) | (b << 30)) or fold logical expressions (e.g., (a&&b) || (a&&!b) into a).
    • Integer Arithmetic: Failure to optimize signed/unsigned arithmetic with known properties like Non-Standard/Non-Associative (nsw) behavior (e.g., (x - 10) < 0 not becoming x <= 9).
    • Store Sinking: Failure to move partially dead stores out of loops (DSE - Dead Store Elimination) or sink loads/stores into conditional blocks to avoid redundant memory traffic.
    • Load PRE (Partial Redundancy Elimination): Failure to hoist loads out of critical edges or common blocks to reduce redundant memory access.
    • Scalar PRE: Failure to hoist computations (like multiplications) out of conditional branches to reduce code size and redundant work.
  3. Optimization opportunities in LLVM Target backend

    master

    This document outlines various optimization opportunities and patterns for the LLVM Target backend, focusing on instruction selection, DAG combining, and code simplification. Key areas for improvement include:

    • Instruction Sinking: Moving computations (like PIC base computations or argument loads) from the entry block into specific blocks where they are actually used to avoid unnecessary work on early-out paths.
    • Instruction Combining: Converting sequences like load + fabs + store into integer operations to leverage faster read/modify/write instructions on specific architectures (e.g., X86).
    • DAG Combiner Improvements: Combining small, fragmented loads into single larger loads when profitable.
    • Loop Unrolling: Implementing partial unrolling to eliminate redundant checks (e.g., bitwise operations) within the loop body, potentially reducing code size.
    • Strength Reduction: Merging library call simplifications, such as converting memcpy(a, b, strlen(b)) into strcpy where safe.
    • Bitwise and Arithmetic Simplifications:
      • Optimizing bitwise patterns (e.g., i | (i<<8) | (i<<16) | (i<<24)) into more efficient forms like multiplications or iterative shifts.
      • Simplifying divisibility checks (n % 3 == 0) into multiplicative inverse comparisons.
      • Combining multiple bitwise checks into a single operation (e.g., ((a & mask) != 0) || ((b & mask) != 0) into ((a | b) & mask) != 0).
  4. Demangle C++ symbols using the Itanium Name Demangler Library

    master

    The Itanium Name Demangler library is used to convert mangled C++ symbol strings (e.g., _Z1fv) into human-readable demangled names (e.g., f()).

    Users can interact with the library in three primary ways:

    1. Basic Demangling: Convert a mangled string directly to its demangled representation.
    2. Symbol Analysis: Use the ManglingParser (via the CRTP base) to perform simple analysis on a mangled name.
    3. AST Querying: In LLVM-based environments, use the ItaniumPartialDemangler to query the demangled Abstract Syntax Tree (AST).
  5. Features of the SPIR-V disassembly VS Code extension

    master

    The extension provides language server support for SPIR-V assembly files (.spvasm) with the following capabilities:

    • Syntax highlighting for assembly code.
    • Navigation: Jump to definition and Find all references.
    • Refactoring: Symbol renaming.
    • Intellisense: Operand hover information and completion suggestions for all Opcodes and Ids.
    • Code Quality: Formatting support.
  6. Demangle C++ symbols with the Itanium Name Demangler Library

    master

    The Itanium Name Demangler library provides tools to convert mangled C++ symbols (e.g., _Z1fv) into human-readable formats (e.g., f()).

    Key capabilities include:

    • Basic Demangling: Converting mangled strings to readable names.
    • Symbol Analysis: Using the ManglingParser (via CRTP base) to perform simple analysis on mangled names.
    • AST Querying: Using ItaniumPartialDemangler (available in LLVM) to query the demangled Abstract Syntax Tree (AST).
  7. Optimization Notes for PowerPC Code Generation

    master

    This document serves as a collection of technical notes and TODOs for improving the PowerPC-specific code generation in the LLVM backend. It identifies several areas where code quality (specifically instruction selection and scheduling) can be improved to match or exceed GCC's performance.

    Key areas for improvement include:

    • Prolog/Epilog Optimization: Implementing lmw/stmw passes similar to ARM's load/store optimizer.
    • Constant Pool Management: Improving how constant pools are handled in PIC (Position Independent Code) mode by materializing base addresses into registers to avoid repeated lis instructions.
    • Loop Optimization: Improving loop structures (e.g., using bdnz instead of bdz) and strength-reducing remainder/division operations.
    • Register Spilling: Optimizing the handling of the Link Register (LR) to avoid unnecessary stack spills by using GPRs instead.
    • Instruction Fusion: Implementing infrastructure to recognize and schedule instruction fusion opportunities introduced in ISA 2.06 and 2.07.
    • Floating Point Comparisons: Reducing the sequence of mfcr, rlwinm, and or instructions into more efficient single-instruction patterns.
  8. Subzero Design Goals and Performance Targets

    master

    Subzero is designed as a fast code generator for the Portable Native Client (PNaCl) project, intended to replace or augment the LLVM-based translator. Its primary goals are:

    • Translation Speed: Target a 10x improvement over LLVM. The goal is to translate .pexe files at a rate comparable to download speeds (e.g., ~6 MB/sec on high-end workstations).
    • Code Quality: Aim to meet or exceed LLVM's -O0 quality, with a stretch goal of approaching LLVM's -O2 quality.
    • Binary Size: Target a 10x reduction in translator size (aiming for ~1 MB) compared to the ~10 MB pnacl-llc binary. This is achieved via MINIMAL builds that compile out unnecessary features.
    • Memory Footprint: Maintain a stable memory footprint proportional to the largest input function size, rather than the total .pexe file size, to prevent OOM (Out-of-Memory) issues on constrained devices.
    • Multithreaded Scalability: Support concurrent translation of different functions with deterministic output (functions and data must always appear in the same order).
  9. What is Marl and how does it work?

    master

    Marl is a C++ 11 hybrid thread/fiber task scheduler. It uses a combination of fibers and threads to allow efficient execution of tasks that can block while maintaining a fixed number of hardware threads. This design allows the scheduler to yield execution when a task blocks on a Marl synchronization primitive, enabling other tasks to run on the same hardware thread.

    Key characteristics:

    • Fluent interface for running tasks across multiple threads.
    • No external dependencies (except googletest for optional unit tests).
    • Supports Windows, macOS, Linux, FreeBSD, Fuchsia, Emscripten, Android, and iOS.
  10. What is SVA (SPIR-V Assembler for WebGPU)

    master

    SVA is a JavaScript library designed to convert SPIR-V assembly (typically produced by spirv-dis from SPIR-V Tools) into SPIR-V binary format. It is specifically optimized for generating WebGPU-compatible SPIR-V.

    Limitations:

    • Supports only 32-bit integers and floats.
    • Only GLSL is accepted as an extended instruction set.
    • Does not support ! syntax for integers.
    • Does not support hex encoding for floats.
  11. What is Reactor and how is it used for code generation?

    master

    Reactor is an embedded language for C++ designed to generate specialized processing routines (called Routines) in a WYSIWYG fashion. It allows developers to write code that looks like standard C/C++ but is actually recorded as an intermediate form to be compiled by a JIT.

    Key Features:

    • Simplified Syntax: Uses C++ operator overloading to avoid the verbosity of direct LLVM API calls. For example, instead of complex LLVM Value creation, you can use standard operators.
    • Type System: Reactor types use the same names as C types but start with a capital letter (e.g., Float, Int32).
    • Control Flow: Implements C-like counterparts such as If(), Else, and For(,,).
    • Specialization: Allows for highly efficient code by specializing routines for the exact state and shaders used in a draw call. For example, x = addOrSub ? x + y : x - y; results in only one specific operation being generated in the final code.
  12. Define and use IDs in SPIR-V assembly

    master

    IDs are used to reference values within a module.

    • Syntax: An ID begins with % followed by a name consisting of letters, numbers, or underscores (e.g., %main, %void, %fnMain).
    • ID Definition: Occurs when an instruction generates a <result-id> (e.g., %void = OpTypeVoid).
    • ID Usage: Occurs when an existing ID is passed as an operand to an instruction (e.g., %3 = OpFunction %1 None %2).
    • Internal Numbers: The assembler assigns a unique internal number to every ID. The disassembler typically generates IDs using decimal numbers greater than 0.
              OpCapability Shader
              OpMemoryModel Logical Simple
              OpEntryPoint GLCompute %main "main"
              OpExecutionMode %main LocalSize 64 64 1
      %void = OpTypeVoid
    %fnMain = OpTypeFunction %void
      %main = OpFunction %void None %fnMain
    %lbMain = OpLabel
              OpReturn
              OpFunctionEnd