Ottimizza con precisione ridotta

Il formato numerico dei dati grafici e dei calcoli dello shaker può avere un un impatto significativo sulle prestazioni del tuo gioco.

I formati ottimali sono i seguenti:

  • Aumentare l'efficienza dell'utilizzo della cache GPU
  • Riduzione del consumo di larghezza di banda della memoria, risparmio energetico e aumento delle prestazioni
  • Massimizzare la velocità effettiva di calcolo nei programmi Shar
  • Riduci al minimo l'utilizzo della RAM della CPU per il gioco
di Gemini Advanced.

Formati con virgola mobile

La maggior parte dei calcoli e dei dati nella grafica 3D moderna utilizza la rappresentazione in virgola mobile numeri. Vulkan su Android utilizza numeri in virgola mobile come 32 o a 16 bit. Un numero in virgola mobile a 32 bit è comunemente noto come precisione singola o completa; un numero in virgola mobile a 16 bit, metà la precisione.

Vulkan definisce un tipo con virgola mobile a 64 bit, ma il tipo non è comunemente utilizzato supportata dai dispositivi Vulkan su Android e il suo utilizzo è sconsigliato. A 64 bit il numero in virgola mobile è comunemente chiamato precisione doppia.

Formati interi

Per i dati e i calcoli vengono utilizzati anche i numeri interi firmati e non. La la dimensione intero standard è di 32 bit. Il supporto per altre dimensioni di bit è il dispositivo dipendono da te. I dispositivi Vulkan con sistema operativo Android in genere supportano i formati a 16 e 8 bit numeri interi. Vulkan definisce un tipo di numero intero a 64 bit, ma il tipo non è comunemente utilizzato supportata dai dispositivi Vulkan su Android e il suo utilizzo è sconsigliato.

Comportamento di mezza precisione non ottimale

Le moderne architetture GPU combinano due valori a 16 bit in una coppia a 32 bit implementare le istruzioni che operano sulla coppia. Per prestazioni ottimali, evita di utilizzando variabili scalare in virgola mobile a 16 bit; vettorializziamo i dati in due o quattro elementi vettori di rete. Il compilatore shaker può essere in grado di utilizzare valori scalari operazioni. Tuttavia, se ti affidi al compilatore per ottimizzare gli scalari, ispeziona l'output del compilatore per verificare la vettorizzazione.

La conversione in virgola mobile a e da a 32 bit e a 16 bit con precisione in virgola mobile ha un di calcolo dei costi computazionali. Riduci l'overhead riducendo al minimo le conversioni di precisione le API nel tuo codice.

Confronta le differenze di prestazioni tra le versioni a 16 e a 32 bit del tuo degli algoritmi. Una precisione dimezzata non sempre porta a un miglioramento delle prestazioni, soprattutto per i calcoli complicati. Algoritmi che fanno un uso intensivo dei le istruzioni per la moltiplicazione con aggiunta di elementi (FMA) su dati vettoriali sono buoni candidati per ha migliorato le prestazioni con una precisione dimezzata.

Supporto del formato numerico

Tutti i dispositivi Vulkan su Android supportano la modalità a precisione singola a 32 bit in virgola mobile e numeri interi a 32 bit nei calcoli dei dati e dello shaker. Supporto per la disponibilità di altri formati non è garantita e, se disponibili, non sono garantiti per tutti i casi d'uso.

Vulkan prevede due categorie di supporto per i formati numerici facoltativi: aritmetici e spazio di archiviazione. Prima di utilizzare un formato specifico, assicurati che un dispositivo lo supporti in categorie.

Supporto aritmetico

Un dispositivo Vulkan deve dichiarare il supporto aritmetico per un formato numerico perché essere utilizzabili nei programmi SHARING. I dispositivi Vulkan su Android di solito supportano seguenti formati per operazioni aritmetiche:

  • Numero intero a 32 bit (obbligatorio)
  • rappresentazione in virgola mobile a 32 bit (obbligatorio)
  • Numero intero a 8 bit (facoltativo)
  • Numero intero a 16 bit (facoltativo)
  • (Facoltativo) Virgola in virgola mobile a mezza precisione a 16 bit

Per determinare se un dispositivo Vulkan supporta numeri interi a 16 bit per l'aritmetica: recupera le funzionalità del dispositivo chiamando il vkGetPhysicalDeviceFeatures2() e controllare se il campo shaderInt16 in VkPhysicalDeviceFeatures2 che la struttura dei risultati sia vera.

Per determinare se un dispositivo Vulkan supporta numeri in virgola mobile a 16 bit o numeri interi a 8 bit, segui questi passaggi:

  1. Verifica se il dispositivo supporta VK_KHR_shader_float16_int8 Estensione Vulkan. L'estensione è richiesto per il supporto di numeri in virgola mobile a 16 bit e numeri interi a 8 bit.
  2. Se il criterio VK_KHR_shader_float16_int8 è supportato, aggiungi un Puntatore della struttura VkPhysicalDeviceShaderFloat16Int8Features a una catena VkPhysicalDeviceFeatures2.pNext.
  3. Controlla i campi shaderFloat16 e shaderInt8 della Struttura dei risultati VkPhysicalDeviceShaderFloat16Int8Features dopo la chiamata vkGetPhysicalDeviceFeatures2(). Se il valore del campo è true, il formato è supportato per l'aritmetica del programma specifico.
di Gemini Advanced.

Sebbene non sia un requisito in Vulkan 1.1 o nel 2022 Profilo Android Baseline, supporto per VK_KHR_shader_float16_int8 è molto comune sui dispositivi Android.

Supporto dello spazio di archiviazione

Un dispositivo Vulkan deve dichiarare il supporto di un formato numerico facoltativo per tipi di archiviazione specifici. Estensione VK_KHR_16bit_storage dichiara il supporto per formati interi a 16 bit e in virgola mobile a 16 bit. Quattro. i tipi di archiviazione sono definiti dall'estensione. Un dispositivo può supportare numeri a 16 bit per nessuno, alcuni o tutti i tipi di archiviazione.

I tipi di archiviazione sono:

  • Oggetti buffer di archiviazione
  • Oggetti buffer uniforme
  • Spingi blocchi costanti
  • Interfacce di input e output dello Shader
di Gemini Advanced.

La maggior parte dei dispositivi Vulkan 1.1 su Android, ma non tutti, supporta i formati a 16 bit in oggetti buffer di archiviazione. Non dare per scontato il supporto in base al modello GPU. Dispositivi con driver meno recenti per una determinata GPU, potrebbero non supportare oggetti buffer di archiviazione, mentre quelli con driver più recenti sì.

Supporto per formati a 16 bit nei buffer uniformi, push con blocchi costanti e Shar di input/output dipende in genere dal produttore della GPU. Attivato Android, una GPU in genere supporta tutti e tre questi tipi o nessuno dei due che li rappresentano.

Una funzione di esempio che verifica il supporto dell'aritmetica e dei formati di archiviazione Vulkan:

struct ReducedPrecisionSupportInfo {
  // Arithmetic support
  bool has_8_bit_int_ = false;
  bool has_16_bit_int_ = false;
  bool has_16_bit_float_ = false;
  // Storage support
  bool has_16_bit_SSBO_ = false;
  bool has_16_bit_UBO_ = false;
  bool has_16_bit_push_ = false;
  bool has_16_bit_input_output_ = false;
  // Use 16-bit floats if we have arithmetic
  // support and at least SSBO storage support.
  bool use_16bit_floats_ = false;
};

void CheckFormatSupport(VkPhysicalDevice physical_device,
    ReducedPrecisionSupportInfo &info) {

  // Retrieve the device extension list so we
  // can check for our desired extensions.
  uint32_t device_extension_count;
  vkEnumerateDeviceExtensionProperties(physical_device, nullptr,
      &device_extension_count, nullptr);
  std::vector<VkExtensionProperties> device_extensions(device_extension_count);
  vkEnumerateDeviceExtensionProperties(physical_device, nullptr,
      &device_extension_count, device_extensions.data());

  bool has_16_8_extension = HasDeviceExtension("VK_KHR_shader_float16_int8",
      device_extensions);

  // Initialize the device features structure and
  // chain the storage features structure and 8/16-bit
  // support structure if applicable.
  VkPhysicalDeviceFeatures2 device_features;
  memset(&device_features, 0, sizeof(device_features));
  device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;

  VkPhysicalDeviceShaderFloat16Int8Features f16_int8_features;
  memset(&f16_int8_features, 0, sizeof(f16_int8_features));
  f16_int8_features.sType =
      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;

  VkPhysicalDevice16BitStorageFeatures storage_features;
  memset(&storage_features, 0, sizeof(storage_features));
  storage_features.sType =
      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES;
  device_features.pNext = &storage_features;

  if (has_16_8_extension) {
    storage_features.pNext = &f16_int8_features;
  }

  vkGetPhysicalDeviceFeatures2(physical_device, &device_features);

  // Parse the storage features and determine
  // what kinds of 16-bit storage access are available.
  if (storage_features.storageBuffer16BitAccess ||
      storage_features.uniformAndStorageBuffer16BitAccess) {
    info.has_16_bit_SSBO_ = true;
  }
  info.has_16_bit_UBO_ = storage_features.uniformAndStorageBuffer16BitAccess;
  info.has_16_bit_push_ = storage_features.storagePushConstant16;
  info.has_16_bit_input_output_ = storage_features.storageInputOutput16;

  info.has_16_bit_int_ = device_features.features.shaderInt16;
  if (has_16_8_extension) {
    info.has_16_bit_float_ = f16_int8_features.shaderFloat16;
    info.has_8_bit_int_ = f16_int8_features.shaderInt8;
  }

  // Get arithmetic and at least some form of storage
  // support before enabling 16-bit float usage.
  if (info.has_16_bit_float_ && info.has_16_bit_SSBO_) {
    info.use_16bit_floats_ = true;
  }
}

Livello di precisione dei dati

Un numero in virgola mobile con mezza precisione può rappresentare un intervallo di valori minore con una precisione inferiore rispetto a un numero in virgola mobile a precisione singola. La mezza precisione è spesso una scelta semplice e percettivamente senza perdita di precisione singola. Tuttavia, la metà della precisione potrebbe non essere pratica in tutti i casi d'uso. Per alcuni tipi di dati, la riduzione dell'intervallo e della precisione può o rendering non corretto.

Tipi di dati che sono buoni candidati per la rappresentazione a metà precisione la rappresentazione in virgola mobile include:

  • Posizione dei dati nelle coordinate dello spazio locale
  • Raggi UV texture per texture più piccole con wrapping UV limitato che possono essere vincolato a un intervallo di coordinate compreso tra -1,0 e 1,0
  • Dati normali, tangenti e bitangent
  • Dati colore Vertex
  • Dati con requisiti di precisione bassi incentrati su 0,0

Tipi di dati che non sono consigliati per la rappresentazione in numero in virgola mobile a metà precisione include:

  • Posizione dei dati nelle coordinate mondiali
  • UV texture per casi d'uso ad alta precisione come le coordinate degli elementi UI in un foglio atlas

Precisione nel codice dello shaker

OpenGL Shading Language (GLSL) e Shader High-level Shader Language (HLSL) i linguaggi di programmazione supportano precisione o precisione esplicita per i tipi numerici. Viene trattata la precisione confortevole come suggerimento per il compilatore shar. La precisione esplicita è un requisito della precisione specificata. I dispositivi Vulkan su Android in genere utilizzano Formati a 16 bit suggeriti da una precisione rilassata. Altri dispositivi Vulkan in particolare sui computer che utilizzano hardware grafico non supportato per i formati a 16 bit, potrebbero ignorare una precisione rilassata e utilizzare comunque i formati a 32 bit.

Estensioni dello spazio di archiviazione in GLSL

È necessario definire le estensioni GLSL appropriate per abilitare il supporto delle versioni a 16 bit o Formati numerici a 8 bit nelle strutture di archiviazione e buffer uniformi. I contenuti pertinenti dichiarazioni di estensione sono:

// Enable 16-bit formats in storage and uniform buffers.
#extension GL_EXT_shader_16bit_storage : require
// Enable 8-bit formats in storage and uniform buffers.
#extension GL_EXT_shader_8bit_storage : require

Queste estensioni sono specifiche di GLSL e non hanno un equivalente in HLSL.

Precisione confortevole in GLSL

Utilizza il qualificatore highp prima di un tipo con rappresentazione in virgola mobile per suggerire una numero in virgola mobile a precisione singola e il qualificatore mediump per un numero in virgola mobile a mezza precisione. I compilatori GLSL per Vulkan interpretano il qualificatore lowp precedente come mediump. Alcuni esempi di precisione rilassata:

mediump vec4 my_vector; // Suggest 16-bit half precision
highp mat4 my_matrix;   // Suggest 32-bit single precision

Precisione esplicita in GLSL

Includi l'estensione GL_EXT_shader_explicit_arithmetic_types_float16 nel tuo Codice GLSL per consentire l'uso di tipi di rappresentazione in virgola mobile a 16 bit:

#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require

Dichiara i tipi di scalari, vettoriali e matrici a virgola mobile a 16 bit in GLSL utilizzando il metodo seguenti parole chiave:

float16_t   f16vec2     f16vec3    f16vec4
f16mat2     f16mat3     f16mat4
f16mat2x2   f16mat2x3   f16mat2x4
f16mat3x2   f16mat3x3   f16mat3x4
f16mat4x2   f16mat4x3   f16mat4x4

Dichiara i tipi di vettori e scalari interi a 16 bit in GLSL utilizzando quanto segue: parole chiave:

int16_t     i16vec2     i16vec3    i16vec4
uint16_t    u16vec2     u16vec3    u16vec4

Precisione rilassata in HLSL

HLSL utilizza il termine precisione minima anziché precisione rilassata. Minima precisione specifica specifica la precisione minima, ma il compilatore può sostituisci una precisione maggiore se una precisione maggiore è una scelta migliore per il hardware di destinazione. Un numero in virgola mobile a 16 bit con precisione minima viene specificato dal min16float parola chiave. I numeri interi a 16 bit con e senza segno di precisione minima sono specificate rispettivamente dalle parole chiave min16int e min16uint. Aggiuntivo esempi di dichiarazioni di precisione minima sono i seguenti:

// Four element vector and four-by-four matrix types
min16float4 my_vector4;
min16float4x4 my_matrix4x4;

Precisione esplicita in HLSL

Il valore in virgola mobile a mezza precisione è specificato dal criterio half o float16_t parole chiave. I numeri interi a 16 bit, firmati e non, vengono specificati dall'int16_t e uint16_t parole chiave. Ulteriori esempi di precisione esplicita le dichiarazioni includono:

// Four element vector and four-by-four matrix types
half4 my_vector4;
half4x4 my_matrix4x4;