66b6d5e102abe408b87359aa8306f4629f533127
[mesa.git] / src / gallium / drivers / swr / rasterizer / core / tessellator.h
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:
6 *
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
9 * Software.
10 *
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
17 * IN THE SOFTWARE.
18 *
19 * @file tessellator.h
20 *
21 * @brief Tessellator fixed function unit interface definition
22 *
23 ******************************************************************************/
24 #pragma once
25
26 #include "tessellator.hpp"
27
28 struct SWR_TS_TESSELLATED_DATA
29 {
30 uint32_t NumPrimitives;
31 uint32_t NumDomainPoints;
32
33 uint32_t* ppIndices[3];
34 float* pDomainPointsU;
35 float* pDomainPointsV;
36 // For Tri: pDomainPointsW[i] = 1.0f - pDomainPointsU[i] - pDomainPointsV[i]
37 };
38
39 namespace Tessellator
40 {
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
44 {
45 private:
46 typedef CHWTessellator SUPER;
47 SWR_TS_DOMAIN Domain;
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];
52 uint32_t NumIndices;
53
54 public:
55 void Init(SWR_TS_DOMAIN tsDomain,
56 SWR_TS_PARTITIONING tsPartitioning,
57 SWR_TS_OUTPUT_TOPOLOGY tsOutputTopology)
58 {
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
64 };
65
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
71 };
72
73 SUPER::Init(CVT_TS_D3D_PARTITIONING[tsPartitioning],
74 CVT_TS_D3D_OUTPUT_TOPOLOGY[tsOutputTopology]);
75
76 Domain = tsDomain;
77 NumDomainPoints = 0;
78 NumIndices = 0;
79 }
80
81 void Tessellate(const SWR_TESSELLATION_FACTORS& tsTessFactors,
82 SWR_TS_TESSELLATED_DATA& tsTessellatedData)
83 {
84 uint32_t IndexDiv = 0;
85 switch (Domain)
86 {
87 case SWR_TS_QUAD:
88 IndexDiv = 3;
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]);
96 break;
97
98 case SWR_TS_TRI:
99 IndexDiv = 3;
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]);
105 break;
106
107 case SWR_TS_ISOLINE:
108 IndexDiv = 2;
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]);
112 break;
113
114 default:
115 SWR_INVALID("Invalid Tessellation Domain: %d", Domain);
116 }
117
118 NumDomainPoints = (uint32_t)SUPER::GetPointCount();
119
120 DOMAIN_POINT* pPoints = SUPER::GetPoints();
121 for (uint32_t i = 0; i < NumDomainPoints; i++) {
122 DomainPointsU[i] = pPoints[i].u;
123 DomainPointsV[i] = pPoints[i].v;
124 }
125 tsTessellatedData.NumDomainPoints = NumDomainPoints;
126 tsTessellatedData.pDomainPointsU = &DomainPointsU[0];
127 tsTessellatedData.pDomainPointsV = &DomainPointsV[0];
128
129 NumIndices = (uint32_t)SUPER::GetIndexCount();
130
131 assert(NumIndices % IndexDiv == 0);
132 tsTessellatedData.NumPrimitives = NumIndices / IndexDiv;
133
134 uint32_t* pIndices = (uint32_t*)SUPER::GetIndices();
135 for (uint32_t i = 0; i < NumIndices; i++) {
136 Indices[i % IndexDiv][i / IndexDiv] = pIndices[i];
137 }
138
139 tsTessellatedData.ppIndices[0] = &Indices[0][0];
140 tsTessellatedData.ppIndices[1] = &Indices[1][0];
141 tsTessellatedData.ppIndices[2] = &Indices[2][0];
142 }
143 };
144 } // namespace Tessellator
145
146 /// Allocate and initialize a new tessellation context
147 INLINE HANDLE SWR_API
148 TSInitCtx(SWR_TS_DOMAIN tsDomain, ///< [IN] Tessellation domain (isoline, quad, triangle)
149 SWR_TS_PARTITIONING tsPartitioning, ///< [IN] Tessellation partitioning algorithm
150 SWR_TS_OUTPUT_TOPOLOGY tsOutputTopology, ///< [IN] Tessellation output topology
151 void* pContextMem, ///< [IN] Memory to use for the context
152 size_t& memSize) ///< [INOUT] In: Amount of memory in pContextMem. Out: Mem required
153 {
154 using Tessellator::SWR_TS;
155 SWR_ASSERT(tsDomain < SWR_TS_DOMAIN_COUNT);
156 SWR_ASSERT(tsPartitioning < SWR_TS_PARTITIONING_COUNT);
157 SWR_ASSERT(tsOutputTopology < SWR_TS_OUTPUT_TOPOLOGY_COUNT);
158
159 size_t origMemSize = memSize;
160 memSize = AlignUp(sizeof(SWR_TS), 64);
161
162 if (nullptr == pContextMem || memSize > origMemSize)
163 {
164 return nullptr;
165 }
166
167 HANDLE tsCtx = pContextMem;
168 if (!tsCtx)
169 {
170 return tsCtx;
171 }
172
173 SWR_TS* pTessellator = new (tsCtx) SWR_TS();
174 SWR_ASSERT(pTessellator == tsCtx);
175
176 pTessellator->Init(tsDomain, tsPartitioning, tsOutputTopology);
177
178 return tsCtx;
179 }
180
181 /// Destroy & de-allocate tessellation context
182 INLINE void SWR_API TSDestroyCtx(HANDLE tsCtx) ///< [IN] Tessellation context to be destroyed
183 {
184 using Tessellator::SWR_TS;
185 SWR_TS* pTessellator = (SWR_TS*)tsCtx;
186
187 if (pTessellator)
188 {
189 pTessellator->~SWR_TS();
190 }
191 }
192
193 /// Perform Tessellation
194 INLINE void SWR_API
195 TSTessellate(HANDLE tsCtx, ///< [IN] Tessellation Context
196 const SWR_TESSELLATION_FACTORS& tsTessFactors, ///< [IN] Tessellation Factors
197 SWR_TS_TESSELLATED_DATA& tsTessellatedData) ///< [OUT] Tessellated Data
198 {
199 using Tessellator::SWR_TS;
200 SWR_TS* pTessellator = (SWR_TS*)tsCtx;
201 SWR_ASSERT(pTessellator);
202
203 pTessellator->Tessellate(tsTessFactors, tsTessellatedData);
204 }
205