rasterizer/core/blend.h \
rasterizer/core/clip.cpp \
rasterizer/core/clip.h \
+ rasterizer/core/conservativeRast.h \
rasterizer/core/context.h \
rasterizer/core/depthstencil.h \
rasterizer/core/fifo.hpp \
const bool bMultisampleEnable = ((rastState.sampleCount > SWR_MULTISAMPLE_1X) || rastState.forcedSampleCount) ? 1 : 0;
const uint32_t centroid = ((psState.barycentricsMask & SWR_BARYCENTRIC_CENTROID_MASK) > 0) ? 1 : 0;
const uint32_t canEarlyZ = (psState.forceEarlyZ || (!psState.writesODepth && !psState.usesSourceDepth && !psState.usesUAV)) ? 1 : 0;
-
- // currently only support 'normal' input coverage
- SWR_ASSERT(psState.inputCoverage == SWR_INPUT_COVERAGE_NORMAL ||
- psState.inputCoverage == SWR_INPUT_COVERAGE_NONE);
+ const uint32_t inputCoverage = (psState.inputCoverage != SWR_INPUT_COVERAGE_NONE);
SWR_BARYCENTRICS_MASK barycentricsMask = (SWR_BARYCENTRICS_MASK)psState.barycentricsMask;
{
// always need to generate I & J per sample for Z interpolation
barycentricsMask = (SWR_BARYCENTRICS_MASK)(barycentricsMask | SWR_BARYCENTRIC_PER_SAMPLE_MASK);
- backendFuncs.pfnBackend = gBackendPixelRateTable[rastState.sampleCount][rastState.samplePattern][psState.inputCoverage][centroid][forcedSampleCount][canEarlyZ];
+ backendFuncs.pfnBackend = gBackendPixelRateTable[rastState.sampleCount][rastState.samplePattern][inputCoverage][centroid][forcedSampleCount][canEarlyZ];
}
else
{
// always need to generate I & J per pixel for Z interpolation
barycentricsMask = (SWR_BARYCENTRICS_MASK)(barycentricsMask | SWR_BARYCENTRIC_PER_PIXEL_MASK);
- backendFuncs.pfnBackend = gBackendSingleSample[psState.inputCoverage][centroid][canEarlyZ];
+ backendFuncs.pfnBackend = gBackendSingleSample[inputCoverage][centroid][canEarlyZ];
}
break;
case SWR_SHADING_RATE_SAMPLE:
SWR_ASSERT(rastState.samplePattern == SWR_MSAA_STANDARD_PATTERN);
// always need to generate I & J per sample for Z interpolation
barycentricsMask = (SWR_BARYCENTRICS_MASK)(barycentricsMask | SWR_BARYCENTRIC_PER_SAMPLE_MASK);
- backendFuncs.pfnBackend = gBackendSampleRateTable[rastState.sampleCount][psState.inputCoverage][centroid][canEarlyZ];
+ backendFuncs.pfnBackend = gBackendSampleRateTable[rastState.sampleCount][inputCoverage][centroid][canEarlyZ];
break;
default:
SWR_ASSERT(0 && "Invalid shading rate");
break;
default:
pState->pfnProcessPrims = ClipTriangles;
- pfnBinner = BinTriangles;
+ pfnBinner = GetBinTrianglesFunc((rastState.conservativeRast > 0));
break;
};
PRIMITIVE_TOPOLOGY clipTopology = TOP_UNKNOWN;
if (NumVertsPerPrim == 3)
{
- pfnBinFunc = BinTriangles;
+ pfnBinFunc = GetBinTrianglesFunc((pa.pDC->pState->state.rastState.conservativeRast > 0));
clipTopology = TOP_TRIANGLE_FAN;
// so that the binner knows to bloat wide points later
pfnBinner = BinLines;
break;
default:
- pfnBinner = BinTriangles;
+ pfnBinner = GetBinTrianglesFunc((pa.pDC->pState->state.rastState.conservativeRast > 0));
break;
};
--- /dev/null
+/****************************************************************************
+* Copyright (C) 2014-2016 Intel Corporation. All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice (including the next
+* paragraph) shall be included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+* IN THE SOFTWARE.
+*
+* @file conservativerast.h
+*
+******************************************************************************/
+#pragma once
+#include <type_traits>
+#include "common/simdintrin.h"
+
+enum FixedPointFmt
+{
+ FP_UNINIT,
+ _16_8,
+ _16_9
+};
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief convenience typedefs for supported Fixed Point precisions
+typedef std::integral_constant<uint32_t, FP_UNINIT> Fixed_Uninit;
+typedef std::integral_constant<uint32_t, _16_8> Fixed_16_8;
+typedef std::integral_constant<uint32_t, _16_9> Fixed_16_9;
+
+//////////////////////////////////////////////////////////////////////////
+/// @struct FixedPointTraits
+/// @brief holds constants relating to converting between FP and Fixed point
+/// @tparam FT: fixed precision type
+template<typename FT>
+struct FixedPointTraits{};
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief Fixed_16_8 specialization of FixedPointTraits
+template<>
+struct FixedPointTraits<Fixed_16_8>
+{
+ /// multiplier to go from FP32 to Fixed Point 16.8
+ typedef std::integral_constant<uint32_t, 256> FixedPointScaleT;
+ /// number of bits to shift to go from 16.8 fixed => int32
+ typedef std::integral_constant<uint32_t, 8> FixedPointShiftT;
+ typedef Fixed_16_8 TypeT;
+};
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief Fixed_16_9 specialization of FixedPointTraits
+template<>
+struct FixedPointTraits<Fixed_16_9>
+{
+ /// multiplier to go from FP32 to Fixed Point 16.9
+ typedef std::integral_constant<uint32_t, 512> FixedPointScaleT;
+ /// number of bits to shift to go from 16.9 fixed => int32
+ typedef std::integral_constant<uint32_t, 9> FixedPointShiftT;
+ typedef Fixed_16_9 TypeT;
+};
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief convenience typedefs for conservative rasterization modes
+typedef std::false_type StandardRastT;
+typedef std::true_type ConservativeRastT;
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief convenience typedefs for Input Coverage rasterization modes
+typedef std::integral_constant<uint32_t, SWR_INPUT_COVERAGE_NONE> NoInputCoverageT;
+typedef std::integral_constant<uint32_t, SWR_INPUT_COVERAGE_NORMAL> OuterConservativeCoverageT;
+typedef std::integral_constant<uint32_t, SWR_INPUT_COVERAGE_INNER_CONSERVATIVE> InnerConservativeCoverageT;
+
+//////////////////////////////////////////////////////////////////////////
+/// @struct ConservativeRastTraits
+/// @brief primary ConservativeRastTraits template. Shouldn't be instantiated
+/// @tparam ConservativeT: type of conservative rasterization
+template <typename ConservativeT>
+struct ConservativeRastFETraits {};
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief StandardRast specialization of ConservativeRastTraits
+template <>
+struct ConservativeRastFETraits<StandardRastT>
+{
+ typedef std::false_type IsConservativeT;
+ typedef FixedPointTraits<Fixed_16_8> BBoxPrecisionT;
+ typedef FixedPointTraits<Fixed_16_8> ZeroAreaPrecisionT;
+};
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief ConservativeRastT specialization of ConservativeRastTraits
+template <>
+struct ConservativeRastFETraits<ConservativeRastT>
+{
+ typedef std::true_type IsConservativeT;
+ typedef FixedPointTraits<Fixed_16_8> ZeroAreaPrecisionT;
+
+ /// Conservative bounding box needs to expand the area around each vertex by 1/512, which
+ /// is the potential snapping error when going from FP-> 16.8 fixed
+ typedef FixedPointTraits<Fixed_16_9> BBoxPrecisionT;
+ typedef std::integral_constant<uint32_t, 1> BoundingBoxOffsetT;
+ typedef std::integral_constant<uint32_t, 1> BoundingBoxShiftT;
+};
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief convenience typedefs for ConservativeRastFETraits
+typedef ConservativeRastFETraits<StandardRastT> FEStandardRastT;
+typedef ConservativeRastFETraits<ConservativeRastT> FEConservativeRastT;
float *pUserClipBuffer;
uint64_t coverageMask[SWR_MAX_NUM_MULTISAMPLES];
+ uint64_t conservativeCoverageMask;
+ uint64_t innerConservativeCoverageMask;
uint64_t anyCoveredSamples;
TRI_FLAGS triFlags;
#include "context.h"
#include "rdtsc_core.h"
#include "rasterizer.h"
+#include "conservativeRast.h"
#include "utils.h"
#include "threads.h"
#include "pa.h"
}
}
+//////////////////////////////////////////////////////////////////////////
+/// @brief Convert the X,Y coords of a triangle to the requested Fixed
+/// Point precision from FP32.
+template <typename PT = FixedPointTraits<Fixed_16_8>>
+INLINE simdscalari fpToFixedPointVertical(const simdscalar vIn)
+{
+ simdscalar vFixed = _simd_mul_ps(vIn, _simd_set1_ps(PT::FixedPointScaleT::value));
+ return _simd_cvtps_epi32(vFixed);
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief Helper function to set the X,Y coords of a triangle to the
+/// requested Fixed Point precision from FP32. If the RequestedT
+/// FixedPointTraits precision is the same as the CurrentT, no extra
+/// conversions will be done. If they are different, convert from FP32
+/// to the Requested precision and set vXi, vYi
+/// @tparam RequestedT: requested FixedPointTraits type
+/// @tparam CurrentT: FixedPointTraits type of the last
+template<typename RequestedT, typename CurrentT = FixedPointTraits<Fixed_Uninit>>
+struct FPToFixedPoint
+{
+ //////////////////////////////////////////////////////////////////////////
+ /// @param tri: simdvector[3] of FP triangle verts
+ /// @param vXi: fixed point X coords of tri verts
+ /// @param vYi: fixed point Y coords of tri verts
+ INLINE static void Set(const simdvector * const tri, simdscalari (&vXi)[3], simdscalari (&vYi)[3])
+ {
+ vXi[0] = fpToFixedPointVertical<RequestedT>(tri[0].x);
+ vYi[0] = fpToFixedPointVertical<RequestedT>(tri[0].y);
+ vXi[1] = fpToFixedPointVertical<RequestedT>(tri[1].x);
+ vYi[1] = fpToFixedPointVertical<RequestedT>(tri[1].y);
+ vXi[2] = fpToFixedPointVertical<RequestedT>(tri[2].x);
+ vYi[2] = fpToFixedPointVertical<RequestedT>(tri[2].y);
+ };
+};
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief In the case where the RequestedT and CurrentT fixed point
+/// precisions are the same, do nothing.
+template<typename RequestedT>
+struct FPToFixedPoint<RequestedT, RequestedT>
+{
+ INLINE static void Set(const simdvector * const tri, simdscalari (&vXi)[3], simdscalari (&vYi)[3]){};
+};
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief Calculate bounding box for current triangle
+/// @tparam CT: ConservativeRastFETraits type
+/// @param vX: fixed point X position for triangle verts
+/// @param vY: fixed point Y position for triangle verts
+/// @param bbox: fixed point bbox
+/// *Note*: expects vX, vY to be in the correct precision for the type
+/// of rasterization. This avoids unnecessary FP->fixed conversions.
+template <typename CT>
+INLINE void calcBoundingBoxIntVertical(const simdvector * const tri, simdscalari (&vX)[3], simdscalari (&vY)[3], simdBBox &bbox){}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief FEStandardRastT specialization of calcBoundingBoxIntVertical
+template <>
+INLINE void calcBoundingBoxIntVertical<FEStandardRastT>(const simdvector * const tri, simdscalari (&vX)[3], simdscalari (&vY)[3], simdBBox &bbox)
+{
+ // FE conservative rast traits
+ typedef FEStandardRastT CT;
+
+ static_assert(std::is_same<CT::BBoxPrecisionT, FixedPointTraits<Fixed_16_8>>::value, "Standard rast BBox calculation needs to be in 16.8 precision");
+ // Update vXi, vYi fixed point precision for BBox calculation if necessary
+ FPToFixedPoint<CT::BBoxPrecisionT, CT::ZeroAreaPrecisionT>::Set(tri, vX, vY);
+
+ simdscalari vMinX = vX[0];
+ vMinX = _simd_min_epi32(vMinX, vX[1]);
+ vMinX = _simd_min_epi32(vMinX, vX[2]);
+
+ simdscalari vMaxX = vX[0];
+ vMaxX = _simd_max_epi32(vMaxX, vX[1]);
+ vMaxX = _simd_max_epi32(vMaxX, vX[2]);
+
+ simdscalari vMinY = vY[0];
+ vMinY = _simd_min_epi32(vMinY, vY[1]);
+ vMinY = _simd_min_epi32(vMinY, vY[2]);
+
+ simdscalari vMaxY = vY[0];
+ vMaxY = _simd_max_epi32(vMaxY, vY[1]);
+ vMaxY = _simd_max_epi32(vMaxY, vY[2]);
+
+ bbox.left = vMinX;
+ bbox.right = vMaxX;
+ bbox.top = vMinY;
+ bbox.bottom = vMaxY;
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// @brief FEConservativeRastT specialization of calcBoundingBoxIntVertical
+/// Offsets BBox for conservative rast
+template <>
+INLINE void calcBoundingBoxIntVertical<FEConservativeRastT>(const simdvector * const tri, simdscalari (&vX)[3], simdscalari (&vY)[3], simdBBox &bbox)
+{
+ // FE conservative rast traits
+ typedef FEConservativeRastT CT;
+
+ static_assert(std::is_same<CT::BBoxPrecisionT, FixedPointTraits<Fixed_16_9>>::value, "Conservative rast BBox calculation needs to be in 16.9 precision");
+ // Update vXi, vYi fixed point precision for BBox calculation if necessary
+ FPToFixedPoint<CT::BBoxPrecisionT, CT::ZeroAreaPrecisionT>::Set(tri, vX, vY);
+
+ simdscalari vMinX = vX[0];
+ vMinX = _simd_min_epi32(vMinX, vX[1]);
+ vMinX = _simd_min_epi32(vMinX, vX[2]);
+
+ simdscalari vMaxX = vX[0];
+ vMaxX = _simd_max_epi32(vMaxX, vX[1]);
+ vMaxX = _simd_max_epi32(vMaxX, vX[2]);
+
+ simdscalari vMinY = vY[0];
+ vMinY = _simd_min_epi32(vMinY, vY[1]);
+ vMinY = _simd_min_epi32(vMinY, vY[2]);
+
+ simdscalari vMaxY = vY[0];
+ vMaxY = _simd_max_epi32(vMaxY, vY[1]);
+ vMaxY = _simd_max_epi32(vMaxY, vY[2]);
+
+ /// Bounding box needs to be expanded by 1/512 before snapping to 16.8 for conservative rasterization
+ bbox.left = _simd_srli_epi32(_simd_sub_epi32(vMinX, _simd_set1_epi32(CT::BoundingBoxOffsetT::value)), CT::BoundingBoxShiftT::value);
+ bbox.right = _simd_srli_epi32(_simd_add_epi32(vMaxX, _simd_set1_epi32(CT::BoundingBoxOffsetT::value)), CT::BoundingBoxShiftT::value);
+ bbox.top = _simd_srli_epi32(_simd_sub_epi32(vMinY, _simd_set1_epi32(CT::BoundingBoxOffsetT::value)), CT::BoundingBoxShiftT::value);
+ bbox.bottom = _simd_srli_epi32(_simd_add_epi32(vMaxY, _simd_set1_epi32(CT::BoundingBoxOffsetT::value)), CT::BoundingBoxShiftT::value);
+}
+
//////////////////////////////////////////////////////////////////////////
/// @brief Bin triangle primitives to macro tiles. Performs setup, clipping
/// culling, viewport transform, etc.
/// @param workerId - thread's worker id. Even thread has a unique id.
/// @param tri - Contains triangle position data for SIMDs worth of triangles.
/// @param primID - Primitive ID for each triangle.
+/// @tparam CT - ConservativeRastFETraits
+template <typename CT>
void BinTriangles(
DRAW_CONTEXT *pDC,
PA_STATE& pa,
tri[2].x = _simd_add_ps(tri[2].x, offset);
tri[2].y = _simd_add_ps(tri[2].y, offset);
- // convert to fixed point
simdscalari vXi[3], vYi[3];
- vXi[0] = fpToFixedPointVertical(tri[0].x);
- vYi[0] = fpToFixedPointVertical(tri[0].y);
- vXi[1] = fpToFixedPointVertical(tri[1].x);
- vYi[1] = fpToFixedPointVertical(tri[1].y);
- vXi[2] = fpToFixedPointVertical(tri[2].x);
- vYi[2] = fpToFixedPointVertical(tri[2].y);
+ // Set vXi, vYi to fixed point precision required for degenerate triangle check
+ FPToFixedPoint<typename CT::ZeroAreaPrecisionT>::Set(tri, vXi, vYi);
// triangle setup
simdscalari vAi[3], vBi[3];
simdscalari vDet[2];
calcDeterminantIntVertical(vAi, vBi, vDet);
+ /// todo: handle degen tri's for Conservative Rast.
+
// cull zero area
int maskLo = _simd_movemask_pd(_simd_castsi_pd(_simd_cmpeq_epi64(vDet[0], _simd_setzero_si())));
int maskHi = _simd_movemask_pd(_simd_castsi_pd(_simd_cmpeq_epi64(vDet[1], _simd_setzero_si())));
RDTSC_EVENT(FECullZeroAreaAndBackface, _mm_popcnt_u32(origTriMask ^ triMask), 0);
}
+ /// Note: these variable initializations must stay above any 'goto endBenTriangles'
// compute per tri backface
uint32_t frontFaceMask = frontWindingTris;
// Calc bounding box of triangles
simdBBox bbox;
- calcBoundingBoxIntVertical(vXi, vYi, bbox);
+ calcBoundingBoxIntVertical<CT>(tri, vXi, vYi, bbox);
// determine if triangle falls between pixel centers and discard
- // only discard for non-MSAA case
+ // only discard for non-MSAA case and when conservative rast is disabled
// (left + 127) & ~255
// (right + 128) & ~255
-
- if(rastState.sampleCount == SWR_MULTISAMPLE_1X)
+ if(rastState.sampleCount == SWR_MULTISAMPLE_1X && (!CT::IsConservativeT::value))
{
origTriMask = triMask;
RDTSC_STOP(FEBinTriangles, 1, 0);
}
+struct FEBinTrianglesChooser
+{
+ typedef PFN_PROCESS_PRIMS FuncType;
+
+ template <typename... ArgsB>
+ static FuncType GetFunc()
+ {
+ return BinTriangles<ConservativeRastFETraits<ArgsB...>>;
+ }
+};
+// Selector for correct templated Draw front-end function
+PFN_PROCESS_PRIMS GetBinTrianglesFunc(bool IsConservative)
+{
+ return TemplateArgUnroller<FEBinTrianglesChooser>::GetFunc(IsConservative);
+}
//////////////////////////////////////////////////////////////////////////
/// @brief Bin SIMD points to the backend. Only supports point size of 1
#include "context.h"
#include <type_traits>
-INLINE
-__m128i fpToFixedPoint(const __m128 vIn)
-{
- __m128 vFixed = _mm_mul_ps(vIn, _mm_set1_ps(FIXED_POINT_SCALE));
- return _mm_cvtps_epi32(vFixed);
-}
-
-INLINE
-simdscalari fpToFixedPointVertical(const simdscalar vIn)
-{
- simdscalar vFixed = _simd_mul_ps(vIn, _simd_set1_ps(FIXED_POINT_SCALE));
- return _simd_cvtps_epi32(vFixed);
-}
-
-
// Calculates the A and B coefficients for the 3 edges of the triangle
//
// maths for edge equations:
}
-INLINE
-void calcBoundingBoxIntVertical(const simdscalari (&vX)[3], const simdscalari (&vY)[3], simdBBox &bbox)
-{
- simdscalari vMinX = vX[0];
- vMinX = _simd_min_epi32(vMinX, vX[1]);
- vMinX = _simd_min_epi32(vMinX, vX[2]);
-
- simdscalari vMaxX = vX[0];
- vMaxX = _simd_max_epi32(vMaxX, vX[1]);
- vMaxX = _simd_max_epi32(vMaxX, vX[2]);
-
- simdscalari vMinY = vY[0];
- vMinY = _simd_min_epi32(vMinY, vY[1]);
- vMinY = _simd_min_epi32(vMinY, vY[2]);
-
- simdscalari vMaxY = vY[0];
- vMaxY = _simd_max_epi32(vMaxY, vY[1]);
- vMaxY = _simd_max_epi32(vMaxY, vY[2]);
-
- bbox.left = vMinX;
- bbox.right = vMaxX;
- bbox.top = vMinY;
- bbox.bottom = vMaxY;
-}
-
INLINE
bool CanUseSimplePoints(DRAW_CONTEXT *pDC)
{
void ProcessSync(SWR_CONTEXT *pContext, DRAW_CONTEXT *pDC, uint32_t workerId, void *pUserData);
void ProcessQueryStats(SWR_CONTEXT *pContext, DRAW_CONTEXT *pDC, uint32_t workerId, void *pUserData);
+PFN_PROCESS_PRIMS GetBinTrianglesFunc(bool IsConservative);
+
struct PA_STATE_BASE; // forward decl
-void BinTriangles(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector tri[3], uint32_t primMask, simdscalari primID);
void BinPoints(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[3], uint32_t primMask, simdscalari primID);
void BinLines(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[3], uint32_t primMask, simdscalari primID);
#pragma once
#include "context.h"
+#include <type_traits>
extern PFN_WORK_FUNC gRasterizerTable[2][SWR_MULTISAMPLE_TYPE_MAX];
void RasterizeLine(DRAW_CONTEXT *pDC, uint32_t workerId, uint32_t macroTile, void *pData);
void RasterizeSimplePoint(DRAW_CONTEXT *pDC, uint32_t workerId, uint32_t macroTile, void *pData);
void RasterizeTriPoint(DRAW_CONTEXT *pDC, uint32_t workerId, uint32_t macroTile, void *pData);
+
+INLINE
+__m128i fpToFixedPoint(const __m128 vIn)
+{
+ __m128 vFixed = _mm_mul_ps(vIn, _mm_set1_ps(FIXED_POINT_SCALE));
+ return _mm_cvtps_epi32(vFixed);
+}
\ No newline at end of file
uint32_t forcedSampleCount : 1;
uint32_t pixelOffset : 1;
uint32_t depthBiasPreAdjusted : 1; ///< depth bias constant is in float units, not per-format Z units
+ uint32_t conservativeRast : 1;
float pointSize;
float lineWidth;
{
SWR_INPUT_COVERAGE_NONE,
SWR_INPUT_COVERAGE_NORMAL,
+ SWR_INPUT_COVERAGE_INNER_CONSERVATIVE,
SWR_INPUT_COVERAGE_MAX,
};
// dword 2
uint32_t killsPixel : 1; // pixel shader can kill pixels
- uint32_t inputCoverage : 1; // type of input coverage PS uses
+ uint32_t inputCoverage : 1; // ps uses input coverage
uint32_t writesODepth : 1; // pixel shader writes to depth
uint32_t usesSourceDepth : 1; // pixel shader reads depth
uint32_t shadingRate : 2; // shading per pixel / sample / coarse pixel
return TemplateArgUnroller<TermT, ArgsB..., std::false_type>::GetFunc(remainingArgs...);
}
+
+ // Last Arg Terminator
+ template <typename... TArgsT>
+ static typename TermT::FuncType GetFunc(uint32_t iArg)
+ {
+ switch(iArg)
+ {
+ case 0: return TermT::template GetFunc<ArgsB..., std::integral_constant<uint32_t, 0>>();
+ case 1: return TermT::template GetFunc<ArgsB..., std::integral_constant<uint32_t, 1>>();
+ case 2: return TermT::template GetFunc<ArgsB..., std::integral_constant<uint32_t, 2>>();
+ case 3: return TermT::template GetFunc<ArgsB..., std::integral_constant<uint32_t, 3>>();
+ case 4: return TermT::template GetFunc<ArgsB..., std::integral_constant<uint32_t, 4>>();
+ default: SWR_ASSUME(false); return nullptr;
+ }
+ }
+
+ // Recursively parse args
+ template <typename... TArgsT>
+ static typename TermT::FuncType GetFunc(uint32_t iArg, TArgsT... remainingArgs)
+ {
+ switch(iArg)
+ {
+ case 0: return TemplateArgUnroller<TermT, ArgsB..., std::integral_constant<uint32_t, 0>>::GetFunc(remainingArgs...);
+ case 1: return TemplateArgUnroller<TermT, ArgsB..., std::integral_constant<uint32_t, 1>>::GetFunc(remainingArgs...);
+ case 2: return TemplateArgUnroller<TermT, ArgsB..., std::integral_constant<uint32_t, 2>>::GetFunc(remainingArgs...);
+ case 3: return TemplateArgUnroller<TermT, ArgsB..., std::integral_constant<uint32_t, 3>>::GetFunc(remainingArgs...);
+ case 4: return TemplateArgUnroller<TermT, ArgsB..., std::integral_constant<uint32_t, 4>>::GetFunc(remainingArgs...);
+ default: SWR_ASSUME(false); return nullptr;
+ }
+ }
};