Regler för datakonvertering

I följande avsnitt beskrivs hur Direct3D hanterar konverteringar mellan datatyper.

Terminologi för datatyp

Följande uppsättning termer används senare för att karakterisera olika formatkonverteringar.

Term Definition
SNORM Signerat normaliserat heltal, vilket innebär att för ett 2-bitars komplementnummer betyder det maximala värdet 1,0f (t.ex. 5-bitarsvärdet 01111 mappar till 1,0f) och det minsta värdet betyder -1,0f (t.ex. 5-bitarsvärdet 10000 mappar till -1,0f). Dessutom mappas det näst lägsta antalet till -1,0f (t.ex. 5-bitarsvärdet 10001 mappar till -1,0f). Det finns alltså två heltalsrepresentationer för -1.0f. Det finns en enda representation för 0,0f och en enda representation för 1,0f. Detta resulterar i en uppsättning heltalsrepresentationer för jämnt fördelade flyttalvärden i intervallet (-1,0f... 0,0f), och även en kompletterande uppsättning representationer för tal i intervallet (0,0f... 1.0f)
UNORM Osignerat normaliserat heltal, vilket innebär att för ett n-bitars tal betyder alla 0:or 0,0f och alla 1:or betyder 1,0f. En sekvens med jämnt fördelade flyttalvärden från 0,0f till 1,0f representeras. T.ex. representerar en 2-bitars UNORM 0.0f, 1/3, 2/3 och 1.0f.
SINT Signerat heltal. 2:s komplement heltal. En 3-bitars SINT representerar till exempel integralvärdena -4, -3, -2, -1, 0, 1, 2, 3.
UINT Osignerat heltal. T.ex. en 3-bitars UINT representerar integralvärdena 0, 1, 2, 3, 4, 5, 6, 7.
FLYTA Ett flyttalsvärde i någon av de representationer som definieras av Direct3D.
SRGB På samma sätt som UNORM innebär alla 0:or 0,0f och alla 1:or 1:or 1,0f för ett n-bitars tal. Men till skillnad från UNORM, med SRGB representerar sekvensen av osignerade heltalskodningar mellan alla 0:or till alla 1:or en icke-linjär progression i flyttalstolkningen av talen, mellan 0,0f till 1,0f. Ungefär, om denna icke-linjära progression, SRGB, visas som en sekvens av färger, skulle det visas som en linjär ramp med luminositetsnivåer till en "genomsnittlig" observatör, under "genomsnittliga" visningsförhållanden, på en "genomsnittlig" skärm. Fullständig information finns i färgstandarden SRGB, IEC 61996-2-1, på IEC (International Electrotechnical Commission).

 

Flyttalskonvertering

När en flyttalkonvertering mellan olika representationer sker, inklusive till eller från icke-flyttalsrepresentationer, gäller följande regler.

Konverververing från en representation med högre intervall till en representation med lägre intervall

  • Round-to-zero används under konverteringen till ett annat flyttalformat. Om målet är ett heltals- eller fastpunktsformat används avrunda till närmaste till och med, såvida inte konverteringen uttryckligen dokumenteras som att använda ett annat avrundningsbeteende, till exempel avrundning till närmaste för FLOAT till SNORM, FLOAT till UNORM eller FLOAT till SRGB. Andra undantag är ftoi- och ftou shader-instruktionerna, som använder round-to-zero. Slutligen har de float-to-fixed-konverteringar som används av texturen sampler och rastrizer en angiven tolerans som mäts i Unit-Last-Place från ett oändligt exakt ideal.
  • För källvärden som är större än det dynamiska intervallet i ett målformat med lägre intervall (t.ex. ett stort 32-bitars flyttalvärde skrivs till en 16-bitars float RenderTarget), det maximala representerande (lämpligt signerade) värdet resultat, INTE inklusive signerad oändlighet (på grund av avrunda till noll som beskrivs ovan).
  • NaN i ett format med högre intervall konverteras till NaN-representation i det lägre intervallformatet om NaN-representationen finns i formatet med lägre intervall. Om det lägre formatet inte har en NaN-representation blir resultatet 0.
  • INF i ett format med högre intervall konverteras till INF i det lägre intervallformatet om det är tillgängligt. Om det lägre formatet inte har någon INF-representation konverteras det till det maximala värde som kan representeras. Tecknet bevaras om det är tillgängligt i målformatet.
  • Denorm i ett format med högre intervall konverteras till Denorm-representationen i det lägre intervallformatet om det är tillgängligt i formatet med lägre intervall och konverteringen är möjlig, annars blir resultatet 0. Teckenbiten bevaras om den är tillgänglig i målformatet.

Konvertera från en representation med lägre intervall till en representation med högre intervall

  • NaN i ett format med lägre intervall konverteras till NaN-representationen i formatet för högre intervall om det är tillgängligt i högre intervallformat. Om det högre intervallformatet inte har en NaN-representation konverteras det till 0.
  • INF i ett format med lägre intervall konverteras till INF-representationen i högre intervallformat om det är tillgängligt i högre intervallformat. Om det högre formatet inte har någon INF-representation konverteras det till det maximala värde som kan representeras (MAX_FLOAT i det formatet). Tecknet bevaras om det är tillgängligt i målformatet.
  • Denorm i ett format med lägre intervall konverteras till en normaliserad representation i formatet med högre intervall om möjligt, eller till en Denorm-representation i högre intervallformat om Denorm-representationen finns. Om de misslyckas konverteras det till 0 om det högre intervallformatet inte har en Denorm-representation. Tecknet bevaras om det är tillgängligt i målformatet. Observera att 32-bitars flyttalsnummer räknas som ett format utan en Denorm-representation (eftersom Denorms i åtgärder på 32-bitars floats töms till tecken bevarade 0).

Heltalskonvertering

I följande tabell beskrivs konverteringar från olika representationer som beskrivs ovan till andra representationer. Endast konverteringar som faktiskt sker i Direct3D visas.

Källdatatyp Måldatatyp Konverteringsregel
SNORM FLYTA Med tanke på ett n-bitars heltalsvärde som representerar det signerade intervallet [-1,0f till 1,0f] är konverteringen till flyttal följande.
  • Det mest negativa värdet mappar till -1,0f. t.ex. 5-bitarsvärdet 10000 mappar till -1,0f.
  • Alla andra värden konverteras till en flyttal (kalla det c) och resulterar sedan = c * (1,0f / (2⁽ⁿ⁻¹⁾-1)). Till exempel konverteras 5-bitarsvärdet 10001 till -15,0f och divideras sedan med 15,0f, vilket ger -1,0f.
FLYTA SNORM Med ett flyttalsnummer är konverteringen till ett heltalsvärde i n-bitar som representerar det signerade intervallet [-1,0f till 1,0f] följande.
  • Låt c representera startvärdet.
  • Om c är NaN är resultatet 0.
  • Om c > 1,0f, inklusive INF, är den fastklämd till 1,0f.
  • Om c < -1.0f, inklusive -INF, kläms den till -1.0f.
  • Konvertera från flyttalsskala till heltalsskala: c = c * (2ⁿ⁻¹-1).
  • Konvertera till ett heltal enligt följande.
    • Om c >= 0 så c = c + 0,5f, annars c = c - 0,5f.
    • Släpp decimaltecknet och det återstående flyttalsvärdet (integral) konverteras direkt till ett heltal.
Den här konverteringen tillåts en tolerans för D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_Unit-Last-Place Unit-Last-Place (på heltalssidan). Det innebär att efter konvertering från flyttal till heltalsskala tillåts alla värden i D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit –Last-Place av ett målformatvärde som kan representeras mappas till det värdet. Det ytterligare kravet på inverterbarhet för data säkerställer att konverteringen inte ökar i intervallet och att alla utdatavärden kan uppnås. (I konstanterna som visas här bör xx ersättas med Direct3D-versionen, till exempel 10, 11 eller 12.)
UNORM FLYTA Startvärdet för n-bit konverteras till float (0,0f, 1,0f, 2,0f osv.) och divideras sedan med (2ⁿ-1).
FLYTA UNORM Låt c representera startvärdet.
  • Om c är NaN är resultatet 0.
  • Om c > 1,0f, inklusive INF, är den fastklämd till 1,0f.
  • Om c < 0,0f, inklusive -INF, är den fastklämd till 0,0f.
  • Konvertera från flyttalsskala till heltalsskala: c = c * (2ⁿ-1).
  • Konvertera till heltal.
    • c = c + 0,5f.
    • Decimalfraktionen tas bort och det återstående flyttalsvärdet (integralvärdet) konverteras direkt till ett heltal.
Den här konverteringen tillåts en tolerans på D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place (på heltalssidan). Det innebär att efter konvertering från flyttal till heltalsskala tillåts alla värden i D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit –Last-Place av ett målformatvärde som kan representeras mappas till det värdet. Det ytterligare kravet på inverterbarhet för data säkerställer att konverteringen inte ökar i intervallet och att alla utdatavärden kan uppnås.
SRGB FLYTA Följande är den idealiska SRGB till FLOAT-konverteringen.
  • Ta startvärdet n-bit, konvertera det till en float (0.0f, 1.0f, 2.0f, etc.); anropa detta c.
  • c = c * (1.0f / (2ⁿ-1))
  • Om (c < = D3Dxx_SRGB_TO_FLOAT_THRESHOLD) så: result = c / D3Dxx_SRGB_TO_FLOAT_DENOMINATOR_1, else: result = ((c + D3Dxx_SRGB_TO_FLOAT_OFFSET)/D3Dxx_SRGB_TO_FLOAT_DENOMINATOR_2)D3Dxx_SRGB_TO_FLOAT_EXPONENT
Den här konverteringen tillåts en tolerans för D3Dxx_SRGB_TO_FLOAT_TOLERANCE_IN_ULP Unit-Last-Place (på SRGB-sidan).
FLYTA SRGB Följande är den perfekta FLOAT-> SRGB-konverteringen.
Förutsatt att mål-SRGB-färgkomponenten har n bitar:
  • Anta att startvärdet är c.
  • Om c är NaN är resultatet 0.
  • Om c > 1,0f, inklusive INF, kläms till 1,0f.
  • Om c < 0,0f, inklusive -INF, är den fastklämd till 0,0f.
  • Om (c <= D3Dxx_FLOAT_TO_SRGB_THRESHOLD) då: c = D3Dxx_FLOAT_TO_SRGB_SCALE_1 * c, annars: c = D3Dxx_FLOAT_TO_SRGB_SCALE_2 * c(D3Dxx_FLOAT_TO_SRGB_EXPONENT_NUMERATOR/D3Dxx_FLOAT_TO_SRGB_EXPONENT_DENOMINATOR) - D3Dxx_FLOAT_TO_SRGB_OFFSET
  • Konvertera från flyttalsskala till heltalsskala: c = c * (2ⁿ-1).
  • Konvertera till heltal:
    • c = c + 0,5f.
    • Decimalfraktionen tas bort och det återstående flyttalsvärdet (integralvärdet) konverteras direkt till ett heltal.
Den här konverteringen tillåts en tolerans på D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place (på heltalssidan). Det innebär att efter konvertering från flyttal till heltalsskala tillåts alla värden i D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit –Last-Place av ett målformatvärde som kan representeras mappas till det värdet. Det ytterligare kravet på inverterbarhet för data säkerställer att konverteringen inte ökar i intervallet och att alla utdatavärden kan uppnås.
SINT SINT med fler bitar Om du vill konvertera från SINT till en SINT med fler bitar är den viktigaste biten (MSB) av startnumret "sign-extended" till de ytterligare bitar som är tillgängliga i målformatet.
UINT SINT med fler bitar Om du vill konvertera från UINT till en SINT med fler bitar kopieras talet till målformatets minst betydande bitar (LSB) och ytterligare MSB:er är vadderade med 0.
SINT UINT med fler bitar Konvertera från SINT till UINT med fler bitar: Om det är negativt kläms värdet till 0. Annars kopieras talet till målformatets LSB:er och ytterligare MSB:er är vadderade med 0.
UINT UINT med fler bitar Om du vill konvertera från UINT till UINT med fler bitar kopieras talet till målformatets LSB:er och ytterligare MSB:er är vadderade med 0.
SINT eller UINT SINT eller UINT med färre eller lika många bitar Om du vill konvertera från en SINT eller UINT till SINT eller UINT med färre eller lika stora bitar (och/eller ändring i signitet) kläms startvärdet helt enkelt fast i målformatets intervall.

 

Konvertering av heltal med fast punkt

Heltal med fast punkt är helt enkelt heltal av viss bitstorlek som har en implicit decimalpunkt på en fast plats.

Den allestädes närvarande datatypen "heltal" är ett specialfall för ett heltal med fast punkt med decimaltecknet i slutet av talet.

Representationer av fast punktnummer karakteriseras som: i.f, där jag är antalet heltalsbitar och f är antalet bråkbitar. t.ex. 16,8 innebär 16 bitar heltal följt av 8 bitar bråk. Heltalsdelen lagras i 2:s komplement, åtminstone enligt definitionen här (även om den kan definieras lika för osignerade heltal). Bråkdelen lagras i osignerad form. Bråkdelen representerar alltid det positiva bråket mellan de två närmaste integralvärdena, med början från de mest negativa.

Additions- och subtraktionsåtgärder på fasta punktnummer utförs helt enkelt med hjälp av standard heltalsaritmetik, utan hänsyn till var den underförstådda decimalen ligger. Att lägga till 1 till ett fast punktnummer på 16,8 innebär bara att 256 läggs till, eftersom decimaltecknet är 8 platser från den minst signifikanta änden av talet. Andra åtgärder, till exempel multiplikation, kan också utföras med heltalsaritmetik, förutsatt att effekten på den fasta decimalen redovisas. Om du till exempel multiplicerar två heltal med 16,8 med ett heltals multiplikering får du ett resultat på 32,16.

Heltalsrepresentationer med fast punkt används på två sätt i Direct3D.

  • Efterklippta hörnpositioner i rastreringsverktyget fästs till fast punkt för att fördela precisionen jämnt över RenderTarget-området. Många rastreringsåtgärder, inklusive ansiktsgallring som ett exempel, sker på fasta punktsnäppta positioner, medan andra åtgärder, till exempel konfiguration av attributinterpolator, använder positioner som har konverterats tillbaka till flyttal från de fasta punktsnäppta positionerna.
  • Strukturkoordinater för samplingsåtgärder fästs på fast punkt (efter att ha skalats efter strukturstorlek) för att fördela precisionen jämnt över texturutrymmet genom att välja filterkranplatser/vikter. Viktvärden konverteras tillbaka till flyttal innan den faktiska filtreringsaritmetiken utförs.
Källdatatyp Måldatatyp Konverteringsregel
FLYTA Heltal för fast punkt Följande är den allmänna proceduren för att konvertera ett flyttalsnummer n till ett heltal med fast punkt i.f, där jag är antalet (signerade) heltalsbitar och f är antalet bråkbitar.
  • Compute FixedMin = -2⁽ⁱ⁻¹⁾
  • Compute FixedMax = 2⁽ⁱ⁻¹⁾ - 2(-f)
  • Om n är ett NaN, resultat = 0; om n är +Inf, result = FixedMax*2f; om n är -Inf, result = FixedMin*2f
  • Om n >= FixedMax, resultat = Fixedmax*2f; if n <= FixedMin, result = FixedMin*2f
  • Annars beräknar du n*2f och konverterar till heltal.
Implementeringar tillåts D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit –Last-Place tolerans i heltalsresultatet, i stället för det oändligt exakta värdet n*2f efter det sista steget ovan.
Heltal för fast punkt FLYTA Anta att den specifika representationen av fast punkt som konverteras till flyttal inte innehåller mer än totalt 24 bitar information, varav högst 23 bitar finns i bråkkomponenten. Anta att ett visst fast punktnummer, fxp, är i i.f-format (i bits heltal, f bits fraction). Konverteringen till float liknar följande pseudokod.
float result = (float)(fxp >> f) + // extract heltal
((float)(fxp & (2f - 1)) / (2f)); extrahera bråk

 

resurser (Direct3D 10)