swr/rast: partial support for Tiled Resources
authorAlok Hota <alok.hota@intel.com>
Thu, 23 Aug 2018 23:42:25 +0000 (18:42 -0500)
committerAlok Hota <alok.hota@intel.com>
Wed, 16 Jan 2019 19:53:30 +0000 (13:53 -0600)
- updated sample from TRTT surfaces correctly
- implemented mapped status return for TRTT surfaces
- implemented per-sample instruction minLod clamp
- updated bilinear filter weight calculation to be closer to D3D specs
- implemented "ReducedTexcoordRange" operation from D3D specs to avoid
loss of precision on high-value normalized coordinates

src/gallium/drivers/swr/rasterizer/jitter/builder_misc.cpp
src/gallium/drivers/swr/rasterizer/jitter/builder_misc.h

index 26d8688f5e953cdbef8c82eda4ee990d086fdad7..65eec4e4c68540fecdb96189c073ff4229e2db4e 100644 (file)
@@ -764,6 +764,148 @@ namespace SwrJit
     /// @brief pop count on vector mask (e.g. <8 x i1>)
     Value* Builder::VPOPCNT(Value* a) { return POPCNT(VMOVMSK(a)); }
 
+    //////////////////////////////////////////////////////////////////////////
+    /// @brief Float / Fixed-point conversions
+    //////////////////////////////////////////////////////////////////////////
+    Value* Builder::VCVT_F32_FIXED_SI(Value*             vFloat,
+                                      uint32_t           numIntBits,
+                                      uint32_t           numFracBits,
+                                      const llvm::Twine& name)
+    {
+        SWR_ASSERT((numIntBits + numFracBits) <= 32, "Can only handle 32-bit fixed-point values");
+        Value* fixed = nullptr;
+        if constexpr (false) // This doesn't work for negative numbers!!
+        {
+            fixed = FP_TO_SI(VROUND(FMUL(vFloat, VIMMED1(float(1 << numFracBits))),
+                                    C(_MM_FROUND_TO_NEAREST_INT)),
+                             mSimdInt32Ty);
+        }
+        else
+        {
+            // Do round to nearest int on fractional bits first
+            // Not entirely perfect for negative numbers, but close enough
+            vFloat = VROUND(FMUL(vFloat, VIMMED1(float(1 << numFracBits))),
+                            C(_MM_FROUND_TO_NEAREST_INT));
+            vFloat = FMUL(vFloat, VIMMED1(1.0f / float(1 << numFracBits)));
+
+            // TODO: Handle INF, NAN, overflow / underflow, etc.
+
+            Value* vSgn      = FCMP_OLT(vFloat, VIMMED1(0.0f));
+            Value* vFloatInt = BITCAST(vFloat, mSimdInt32Ty);
+            Value* vFixed    = AND(vFloatInt, VIMMED1((1 << 23) - 1));
+            vFixed           = OR(vFixed, VIMMED1(1 << 23));
+            vFixed           = SELECT(vSgn, NEG(vFixed), vFixed);
+
+            Value* vExp = LSHR(SHL(vFloatInt, VIMMED1(1)), VIMMED1(24));
+            vExp        = SUB(vExp, VIMMED1(127));
+
+            Value* vExtraBits = SUB(VIMMED1(23 - numFracBits), vExp);
+
+            fixed = ASHR(vFixed, vExtraBits, name);
+        }
+
+        return fixed;
+    }
+
+    Value* Builder::VCVT_FIXED_SI_F32(Value*             vFixed,
+                                      uint32_t           numIntBits,
+                                      uint32_t           numFracBits,
+                                      const llvm::Twine& name)
+    {
+        SWR_ASSERT((numIntBits + numFracBits) <= 32, "Can only handle 32-bit fixed-point values");
+        uint32_t extraBits = 32 - numIntBits - numFracBits;
+        if (numIntBits && extraBits)
+        {
+            // Sign extend
+            Value* shftAmt = VIMMED1(extraBits);
+            vFixed         = ASHR(SHL(vFixed, shftAmt), shftAmt);
+        }
+
+        Value* fVal  = VIMMED1(0.0f);
+        Value* fFrac = VIMMED1(0.0f);
+        if (numIntBits)
+        {
+            fVal = SI_TO_FP(ASHR(vFixed, VIMMED1(numFracBits)), mSimdFP32Ty, name);
+        }
+
+        if (numFracBits)
+        {
+            fFrac = UI_TO_FP(AND(vFixed, VIMMED1((1 << numFracBits) - 1)), mSimdFP32Ty);
+            fFrac = FDIV(fFrac, VIMMED1(float(1 << numFracBits)), name);
+        }
+
+        return FADD(fVal, fFrac, name);
+    }
+
+    Value* Builder::VCVT_F32_FIXED_UI(Value*             vFloat,
+                                      uint32_t           numIntBits,
+                                      uint32_t           numFracBits,
+                                      const llvm::Twine& name)
+    {
+        SWR_ASSERT((numIntBits + numFracBits) <= 32, "Can only handle 32-bit fixed-point values");
+        Value* fixed = nullptr;
+        if constexpr (true) // KNOB_SIM_FAST_MATH?  Below works correctly from a precision
+                            // standpoint...
+        {
+            fixed = FP_TO_UI(VROUND(FMUL(vFloat, VIMMED1(float(1 << numFracBits))),
+                                    C(_MM_FROUND_TO_NEAREST_INT)),
+                             mSimdInt32Ty);
+        }
+        else
+        {
+            // Do round to nearest int on fractional bits first
+            vFloat = VROUND(FMUL(vFloat, VIMMED1(float(1 << numFracBits))),
+                            C(_MM_FROUND_TO_NEAREST_INT));
+            vFloat = FMUL(vFloat, VIMMED1(1.0f / float(1 << numFracBits)));
+
+            // TODO: Handle INF, NAN, overflow / underflow, etc.
+
+            Value* vSgn      = FCMP_OLT(vFloat, VIMMED1(0.0f));
+            Value* vFloatInt = BITCAST(vFloat, mSimdInt32Ty);
+            Value* vFixed    = AND(vFloatInt, VIMMED1((1 << 23) - 1));
+            vFixed           = OR(vFixed, VIMMED1(1 << 23));
+
+            Value* vExp = LSHR(SHL(vFloatInt, VIMMED1(1)), VIMMED1(24));
+            vExp        = SUB(vExp, VIMMED1(127));
+
+            Value* vExtraBits = SUB(VIMMED1(23 - numFracBits), vExp);
+
+            fixed = LSHR(vFixed, vExtraBits, name);
+        }
+
+        return fixed;
+    }
+
+    Value* Builder::VCVT_FIXED_UI_F32(Value*             vFixed,
+                                      uint32_t           numIntBits,
+                                      uint32_t           numFracBits,
+                                      const llvm::Twine& name)
+    {
+        SWR_ASSERT((numIntBits + numFracBits) <= 32, "Can only handle 32-bit fixed-point values");
+        uint32_t extraBits = 32 - numIntBits - numFracBits;
+        if (numIntBits && extraBits)
+        {
+            // Sign extend
+            Value* shftAmt = VIMMED1(extraBits);
+            vFixed         = ASHR(SHL(vFixed, shftAmt), shftAmt);
+        }
+
+        Value* fVal  = VIMMED1(0.0f);
+        Value* fFrac = VIMMED1(0.0f);
+        if (numIntBits)
+        {
+            fVal = UI_TO_FP(LSHR(vFixed, VIMMED1(numFracBits)), mSimdFP32Ty, name);
+        }
+
+        if (numFracBits)
+        {
+            fFrac = UI_TO_FP(AND(vFixed, VIMMED1((1 << numFracBits) - 1)), mSimdFP32Ty);
+            fFrac = FDIV(fFrac, VIMMED1(float(1 << numFracBits)), name);
+        }
+
+        return FADD(fVal, fFrac, name);
+    }
+
     //////////////////////////////////////////////////////////////////////////
     /// @brief C functions called by LLVM IR
     //////////////////////////////////////////////////////////////////////////
index f8701f9ba84a64227143c914ea29d7ffe7f753bf..91e2a32f1a142909e6e7d075c64652ed7af8e1aa 100644 (file)
@@ -122,6 +122,28 @@ Value* VMASK_16(Value* mask);
 
 Value* VMOVMSK(Value* mask);
 
+//////////////////////////////////////////////////////////////////////////
+/// @brief Float / Fixed-point conversions
+//////////////////////////////////////////////////////////////////////////
+// Signed
+Value* VCVT_F32_FIXED_SI(Value*             vFloat,
+                         uint32_t           numIntBits,
+                         uint32_t           numFracBits,
+                         const llvm::Twine& name = "");
+Value* VCVT_FIXED_SI_F32(Value*             vFixed,
+                         uint32_t           numIntBits,
+                         uint32_t           numFracBits,
+                         const llvm::Twine& name = "");
+// Unsigned
+Value* VCVT_F32_FIXED_UI(Value*             vFloat,
+                         uint32_t           numIntBits,
+                         uint32_t           numFracBits,
+                         const llvm::Twine& name = "");
+Value* VCVT_FIXED_UI_F32(Value*             vFixed,
+                         uint32_t           numIntBits,
+                         uint32_t           numFracBits,
+                         const llvm::Twine& name = "");
+
 //////////////////////////////////////////////////////////////////////////
 /// @brief functions that build IR to call x86 intrinsics directly, or
 /// emulate them with other instructions if not available on the host