1 /****************************************************************************
2 * Copyright (C) 2014-2019 without restriction, including without limitation
3 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
4 * and/or sell copies of the Software, and to permit persons to whom the
5 * Software is furnished to do so, subject to the following conditions:
7 * The above copyright notice and this permission notice (including the next
8 * paragraph) shall be included in all copies or substantial portions of the
11 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
14 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
16 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * @brief Tessellator fixed function unit interface definition
23 ******************************************************************************/
26 #include "tessellator.hpp"
28 struct SWR_TS_TESSELLATED_DATA
30 uint32_t NumPrimitives
;
31 uint32_t NumDomainPoints
;
33 uint32_t* ppIndices
[3];
34 float* pDomainPointsU
;
35 float* pDomainPointsV
;
36 // For Tri: pDomainPointsW[i] = 1.0f - pDomainPointsU[i] - pDomainPointsV[i]
41 /// Wrapper class for the CHWTessellator reference tessellator from MSFT
42 /// This class will store data not originally stored in CHWTessellator
43 class SWR_TS
: private CHWTessellator
46 typedef CHWTessellator SUPER
;
48 OSALIGNSIMD(float) DomainPointsU
[MAX_POINT_COUNT
];
49 OSALIGNSIMD(float) DomainPointsV
[MAX_POINT_COUNT
];
50 uint32_t NumDomainPoints
;
51 OSALIGNSIMD(uint32_t) Indices
[3][MAX_INDEX_COUNT
/ 3];
55 void Init(SWR_TS_DOMAIN tsDomain
,
56 SWR_TS_PARTITIONING tsPartitioning
,
57 SWR_TS_OUTPUT_TOPOLOGY tsOutputTopology
)
59 static D3D11_TESSELLATOR_PARTITIONING CVT_TS_D3D_PARTITIONING
[] = {
60 D3D11_TESSELLATOR_PARTITIONING_INTEGER
, // SWR_TS_INTEGER
61 D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD
, // SWR_TS_ODD_FRACTIONAL
62 D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN
, // SWR_TS_EVEN_FRACTIONAL
63 D3D11_TESSELLATOR_PARTITIONING_POW2
// SWR_TS_POW2
66 static D3D11_TESSELLATOR_OUTPUT_PRIMITIVE CVT_TS_D3D_OUTPUT_TOPOLOGY
[] = {
67 D3D11_TESSELLATOR_OUTPUT_POINT
, // SWR_TS_OUTPUT_POINT
68 D3D11_TESSELLATOR_OUTPUT_LINE
, // SWR_TS_OUTPUT_LINE
69 D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CCW
, // SWR_TS_OUTPUT_TRI_CW - inverted logic, because DX
70 D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CW
// SWR_TS_OUTPUT_TRI_CCW - inverted logic, because DX
73 SUPER::Init(CVT_TS_D3D_PARTITIONING
[tsPartitioning
],
74 CVT_TS_D3D_OUTPUT_TOPOLOGY
[tsOutputTopology
]);
81 void Tessellate(const SWR_TESSELLATION_FACTORS
& tsTessFactors
,
82 SWR_TS_TESSELLATED_DATA
& tsTessellatedData
)
84 uint32_t IndexDiv
= 0;
89 SUPER::TessellateQuadDomain(
90 tsTessFactors
.OuterTessFactors
[SWR_QUAD_U_EQ0_TRI_U_LINE_DETAIL
],
91 tsTessFactors
.OuterTessFactors
[SWR_QUAD_V_EQ0_TRI_W
],
92 tsTessFactors
.OuterTessFactors
[SWR_QUAD_U_EQ1_TRI_V_LINE_DENSITY
],
93 tsTessFactors
.OuterTessFactors
[SWR_QUAD_V_EQ1
],
94 tsTessFactors
.InnerTessFactors
[SWR_QUAD_U_TRI_INSIDE
],
95 tsTessFactors
.InnerTessFactors
[SWR_QUAD_V_INSIDE
]);
100 SUPER::TessellateTriDomain(
101 tsTessFactors
.OuterTessFactors
[SWR_QUAD_U_EQ0_TRI_U_LINE_DETAIL
],
102 tsTessFactors
.OuterTessFactors
[SWR_QUAD_U_EQ1_TRI_V_LINE_DENSITY
],
103 tsTessFactors
.OuterTessFactors
[SWR_QUAD_V_EQ0_TRI_W
],
104 tsTessFactors
.InnerTessFactors
[SWR_QUAD_U_TRI_INSIDE
]);
109 SUPER::TessellateIsoLineDomain(
110 tsTessFactors
.OuterTessFactors
[SWR_QUAD_U_EQ1_TRI_V_LINE_DENSITY
],
111 tsTessFactors
.OuterTessFactors
[SWR_QUAD_U_EQ0_TRI_U_LINE_DETAIL
]);
115 SWR_INVALID("Invalid Tessellation Domain: %d", Domain
);
119 NumDomainPoints
= (uint32_t)SUPER::GetPointCount();
121 DOMAIN_POINT
* pPoints
= SUPER::GetPoints();
122 for (uint32_t i
= 0; i
< NumDomainPoints
; i
++) {
123 DomainPointsU
[i
] = pPoints
[i
].u
;
124 DomainPointsV
[i
] = pPoints
[i
].v
;
126 tsTessellatedData
.NumDomainPoints
= NumDomainPoints
;
127 tsTessellatedData
.pDomainPointsU
= &DomainPointsU
[0];
128 tsTessellatedData
.pDomainPointsV
= &DomainPointsV
[0];
130 NumIndices
= (uint32_t)SUPER::GetIndexCount();
132 assert(NumIndices
% IndexDiv
== 0);
133 tsTessellatedData
.NumPrimitives
= NumIndices
/ IndexDiv
;
135 uint32_t* pIndices
= (uint32_t*)SUPER::GetIndices();
136 for (uint32_t i
= 0; i
< NumIndices
; i
++) {
137 Indices
[i
% IndexDiv
][i
/ IndexDiv
] = pIndices
[i
];
140 tsTessellatedData
.ppIndices
[0] = &Indices
[0][0];
141 tsTessellatedData
.ppIndices
[1] = &Indices
[1][0];
142 tsTessellatedData
.ppIndices
[2] = &Indices
[2][0];
145 } // namespace Tessellator
147 /// Allocate and initialize a new tessellation context
148 INLINE HANDLE SWR_API
149 TSInitCtx(SWR_TS_DOMAIN tsDomain
, ///< [IN] Tessellation domain (isoline, quad, triangle)
150 SWR_TS_PARTITIONING tsPartitioning
, ///< [IN] Tessellation partitioning algorithm
151 SWR_TS_OUTPUT_TOPOLOGY tsOutputTopology
, ///< [IN] Tessellation output topology
152 void* pContextMem
, ///< [IN] Memory to use for the context
153 size_t& memSize
) ///< [INOUT] In: Amount of memory in pContextMem. Out: Mem required
155 using Tessellator::SWR_TS
;
156 SWR_ASSERT(tsDomain
< SWR_TS_DOMAIN_COUNT
);
157 SWR_ASSERT(tsPartitioning
< SWR_TS_PARTITIONING_COUNT
);
158 SWR_ASSERT(tsOutputTopology
< SWR_TS_OUTPUT_TOPOLOGY_COUNT
);
160 size_t origMemSize
= memSize
;
161 memSize
= AlignUp(sizeof(SWR_TS
), 64);
163 if (nullptr == pContextMem
|| memSize
> origMemSize
)
168 HANDLE tsCtx
= pContextMem
;
174 SWR_TS
* pTessellator
= new (tsCtx
) SWR_TS();
175 SWR_ASSERT(pTessellator
== tsCtx
);
177 pTessellator
->Init(tsDomain
, tsPartitioning
, tsOutputTopology
);
182 /// Destroy & de-allocate tessellation context
183 INLINE
void SWR_API
TSDestroyCtx(HANDLE tsCtx
) ///< [IN] Tessellation context to be destroyed
185 using Tessellator::SWR_TS
;
186 SWR_TS
* pTessellator
= (SWR_TS
*)tsCtx
;
190 pTessellator
->~SWR_TS();
194 /// Perform Tessellation
196 TSTessellate(HANDLE tsCtx
, ///< [IN] Tessellation Context
197 const SWR_TESSELLATION_FACTORS
& tsTessFactors
, ///< [IN] Tessellation Factors
198 SWR_TS_TESSELLATED_DATA
& tsTessellatedData
) ///< [OUT] Tessellated Data
200 using Tessellator::SWR_TS
;
201 SWR_TS
* pTessellator
= (SWR_TS
*)tsCtx
;
202 SWR_ASSERT(pTessellator
);
204 pTessellator
->Tessellate(tsTessFactors
, tsTessellatedData
);