gallium/auxiliary: add the microsoft tessellator and a pipe wrapper.
This adds the same tessellator code that swr uses, swr should move to using this copy, unfortunately that wasn't trivial on my first look. The p_tessellator wrapper wraps it in a form that is a useful interface for draw. Reviewed-by: Roland Scheidegger <sroland@vmware.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3841>
This commit is contained in:
parent
bf16ff3172
commit
bd0188f9ea
|
@ -154,6 +154,10 @@ C_SOURCES := \
|
|||
rtasm/rtasm_execmem.h \
|
||||
rtasm/rtasm_x86sse.c \
|
||||
rtasm/rtasm_x86sse.h \
|
||||
tessellator/p_tessellator.cpp \
|
||||
tessellator/p_tessellator.h \
|
||||
tessellator/tessellator.cpp \
|
||||
tessellator/tessellator.hpp \
|
||||
tgsi/tgsi_aa_point.c \
|
||||
tgsi/tgsi_aa_point.h \
|
||||
tgsi/tgsi_build.c \
|
||||
|
|
|
@ -419,6 +419,10 @@ if with_llvm
|
|||
'draw/draw_llvm_sample.c',
|
||||
'draw/draw_pt_fetch_shade_pipeline_llvm.c',
|
||||
'draw/draw_vs_llvm.c',
|
||||
'tessellator/tessellator.cpp',
|
||||
'tessellator/tessellator.hpp',
|
||||
'tessellator/p_tessellator.cpp',
|
||||
'tessellator/p_tessellator.h',
|
||||
'nir/nir_to_tgsi_info.c',
|
||||
'nir/nir_to_tgsi_info.h',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2020 Red Hat.
|
||||
* 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 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "p_tessellator.h"
|
||||
#include "tessellator.hpp"
|
||||
|
||||
#include <new>
|
||||
|
||||
namespace pipe_tessellator_wrap
|
||||
{
|
||||
/// Wrapper class for the CHWTessellator reference tessellator from MSFT
|
||||
/// This class will store data not originally stored in CHWTessellator
|
||||
class pipe_ts : private CHWTessellator
|
||||
{
|
||||
private:
|
||||
typedef CHWTessellator SUPER;
|
||||
enum pipe_prim_type prim_mode;
|
||||
PIPE_ALIGN_VAR(32) float domain_points_u[MAX_POINT_COUNT];
|
||||
PIPE_ALIGN_VAR(32) float domain_points_v[MAX_POINT_COUNT];
|
||||
uint32_t num_domain_points;
|
||||
PIPE_ALIGN_VAR(32) uint32_t indices[3][MAX_INDEX_COUNT / 3];
|
||||
|
||||
public:
|
||||
void Init(enum pipe_prim_type tes_prim_mode,
|
||||
enum pipe_tess_spacing ts_spacing,
|
||||
bool tes_vertex_order_cw, bool tes_point_mode)
|
||||
{
|
||||
static D3D11_TESSELLATOR_PARTITIONING CVT_TS_D3D_PARTITIONING[] = {
|
||||
D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD, // PIPE_TESS_SPACING_ODD
|
||||
D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN, // PIPE_TESS_SPACING_EVEN
|
||||
D3D11_TESSELLATOR_PARTITIONING_INTEGER, // PIPE_TESS_SPACING_EQUAL
|
||||
};
|
||||
|
||||
D3D11_TESSELLATOR_OUTPUT_PRIMITIVE out_prim;
|
||||
if (tes_point_mode)
|
||||
out_prim = D3D11_TESSELLATOR_OUTPUT_POINT;
|
||||
else if (tes_prim_mode == PIPE_PRIM_LINES)
|
||||
out_prim = D3D11_TESSELLATOR_OUTPUT_LINE;
|
||||
else if (tes_vertex_order_cw)
|
||||
out_prim = D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CW;
|
||||
else
|
||||
out_prim = D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CCW;
|
||||
|
||||
SUPER::Init(CVT_TS_D3D_PARTITIONING[ts_spacing],
|
||||
out_prim);
|
||||
|
||||
prim_mode = tes_prim_mode;
|
||||
num_domain_points = 0;
|
||||
}
|
||||
|
||||
void Tessellate(const struct pipe_tessellation_factors *tess_factors,
|
||||
struct pipe_tessellator_data *tess_data)
|
||||
{
|
||||
switch (prim_mode)
|
||||
{
|
||||
case PIPE_PRIM_QUADS:
|
||||
SUPER::TessellateQuadDomain(
|
||||
tess_factors->outer_tf[0],
|
||||
tess_factors->outer_tf[1],
|
||||
tess_factors->outer_tf[2],
|
||||
tess_factors->outer_tf[3],
|
||||
tess_factors->inner_tf[0],
|
||||
tess_factors->inner_tf[1]);
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_TRIANGLES:
|
||||
SUPER::TessellateTriDomain(
|
||||
tess_factors->outer_tf[0],
|
||||
tess_factors->outer_tf[1],
|
||||
tess_factors->outer_tf[2],
|
||||
tess_factors->inner_tf[0]);
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_LINES:
|
||||
SUPER::TessellateIsoLineDomain(
|
||||
tess_factors->outer_tf[0],
|
||||
tess_factors->outer_tf[1]);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
num_domain_points = (uint32_t)SUPER::GetPointCount();
|
||||
|
||||
DOMAIN_POINT *points = SUPER::GetPoints();
|
||||
for (uint32_t i = 0; i < num_domain_points; i++) {
|
||||
domain_points_u[i] = points[i].u;
|
||||
domain_points_v[i] = points[i].v;
|
||||
}
|
||||
tess_data->num_domain_points = num_domain_points;
|
||||
tess_data->domain_points_u = &domain_points_u[0];
|
||||
tess_data->domain_points_v = &domain_points_v[0];
|
||||
|
||||
tess_data->num_indices = (uint32_t)SUPER::GetIndexCount();
|
||||
|
||||
tess_data->indices = (uint32_t*)SUPER::GetIndices();
|
||||
}
|
||||
};
|
||||
} // namespace Tessellator
|
||||
|
||||
/* allocate tessellator */
|
||||
struct pipe_tessellator *
|
||||
p_tess_init(enum pipe_prim_type tes_prim_mode,
|
||||
enum pipe_tess_spacing spacing,
|
||||
bool tes_vertex_order_cw, bool tes_point_mode)
|
||||
{
|
||||
void *mem;
|
||||
using pipe_tessellator_wrap::pipe_ts;
|
||||
|
||||
mem = align_malloc(sizeof(pipe_ts), 256);
|
||||
|
||||
pipe_ts* tessellator = new (mem) pipe_ts();
|
||||
|
||||
tessellator->Init(tes_prim_mode, spacing, tes_vertex_order_cw, tes_point_mode);
|
||||
|
||||
return (struct pipe_tessellator *)tessellator;
|
||||
}
|
||||
|
||||
/* destroy tessellator */
|
||||
void p_tess_destroy(struct pipe_tessellator *pipe_tess)
|
||||
{
|
||||
using pipe_tessellator_wrap::pipe_ts;
|
||||
pipe_ts *tessellator = (pipe_ts*)pipe_tess;
|
||||
|
||||
tessellator->~pipe_ts();
|
||||
align_free(tessellator);
|
||||
}
|
||||
|
||||
/* perform tessellation */
|
||||
void p_tessellate(struct pipe_tessellator *pipe_tess,
|
||||
const struct pipe_tessellation_factors *tess_factors,
|
||||
struct pipe_tessellator_data *tess_data)
|
||||
{
|
||||
using pipe_tessellator_wrap::pipe_ts;
|
||||
pipe_ts *tessellator = (pipe_ts*)pipe_tess;
|
||||
|
||||
tessellator->Tessellate(tess_factors, tess_data);
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2020 Red Hat.
|
||||
* 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 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
#ifndef PIPE_TESSELLATOR_H
|
||||
#define PIPE_TESSELLATOR_H
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct pipe_tessellator;
|
||||
struct pipe_tessellation_factors
|
||||
{
|
||||
float outer_tf[4];
|
||||
float inner_tf[2];
|
||||
float pad[2];
|
||||
};
|
||||
|
||||
struct pipe_tessellator_data
|
||||
{
|
||||
uint32_t num_indices;
|
||||
uint32_t num_domain_points;
|
||||
|
||||
uint32_t *indices;
|
||||
float *domain_points_u;
|
||||
float *domain_points_v;
|
||||
// For Tri: domain_points_w[i] = 1.0f - domain_points_u[i] - domain_points_v[i]
|
||||
};
|
||||
|
||||
/// Allocate and initialize a new tessellation context
|
||||
struct pipe_tessellator *p_tess_init(enum pipe_prim_type tes_prim_mode,
|
||||
enum pipe_tess_spacing spacing,
|
||||
bool tes_vertex_order_cw, bool tes_point_mode);
|
||||
/// Destroy & de-allocate tessellation context
|
||||
void p_tess_destroy(struct pipe_tessellator *pipe_ts);
|
||||
|
||||
|
||||
/// Perform Tessellation
|
||||
void p_tessellate(struct pipe_tessellator *pipe_ts,
|
||||
const struct pipe_tessellation_factors *tess_factors,
|
||||
struct pipe_tessellator_data *tess_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,471 @@
|
|||
/*
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
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 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
//=================================================================================================================================
|
||||
// Microsoft D3D11 Fixed Function Tessellator Reference - May 7, 2012
|
||||
// amar.patel@microsoft.com
|
||||
//
|
||||
// CHWTessellator demonstrates what is expected of hardware in the D3D11 fixed function Tessellator stage. Hardware
|
||||
// implementers need only look at this class.
|
||||
//
|
||||
// CHLSLTessellator is a wrapper for CHWTessellator, representing the effect of shader code that will
|
||||
// be autogenerated by HLSL in the Hull Shader, both for plumbing data around, and to precondition TessFactor values before they
|
||||
// are passed to the hardware (such as deriving inside TessFactors from edge TessFactors). The algorithms used
|
||||
// in CHLSLTessellator are subject to change, but since they represent shader code auto-generated by the HLSL compiler,
|
||||
// CHLSLTessellator has no effect on hardware design at all. Note the HLSL compiler will expose all the raw hardware
|
||||
// control illustrated by CHWTessellator for those who don't need the helper functionality illustrated by CHLSLTessellator.
|
||||
//
|
||||
// Usage: (1) Create either a CHLSLTessellator or CHWTessellator object, depending on which you want to verify.
|
||||
// (2) Call C*Tessellator::Init()
|
||||
// (3) Call C*Tessellator::Tessellate[IsoLine|Tri|Quad]Domain()
|
||||
// - Here you pass in TessFactors (how much to tessellate)
|
||||
// (4) Call C*Tessellator::GetPointCount(), C*Tessellator::GetIndexCount() to see how much data was generated.
|
||||
// (5) Call C*Tessellator::GetPoints() and C*Tessellator::GetIndices() to get pointers to the data.
|
||||
// The pointers are fixed for the lifetime of the object (storage for max tessellation),
|
||||
// so if you ::Tessellate again, the data in the buffers is overwritten.
|
||||
// (6) There are various other Get() methods to retrieve TessFactors that have been processed from
|
||||
// what you passed in at step 3. You can retrieve separate TessFactors that the tessellator
|
||||
// produced after clamping but before rounding, and also after rounding (say in pow2 mode).
|
||||
// These numbers can be useful information if you are geomorphing displacement maps.
|
||||
// (7) Goto Step 2 or 3 if you want to animate TessFactors or tessellate a different patch
|
||||
//
|
||||
// Code implementation details:
|
||||
//
|
||||
// There is lots of headroom to make this code run faster on CPUs. It was written merely as a reference for
|
||||
// what results hardware should produce, with CPU performance not a consideration. It is nice that this implementation
|
||||
// only generates the exact number of vertices needed (no duplicates) in the output vertex buffer. Also, the number
|
||||
// of calculations done for each U/V domain coordinate is minimized by doing some precalculation of some patch or edge
|
||||
// invariant numbers (see TESS_FACTOR_CONTEXT). All the vertex coordinate calculations could be computed with as much
|
||||
// parallelism as you like. Similarly the calculation of connectivity itself is highly parallelizable, and can also
|
||||
// be done independent of the vertex calculations.
|
||||
//
|
||||
//=================================================================================================================================
|
||||
|
||||
#define D3D11_TESSELLATOR_MIN_ODD_TESSELLATION_FACTOR 1
|
||||
#define D3D11_TESSELLATOR_MAX_ODD_TESSELLATION_FACTOR 63
|
||||
#define D3D11_TESSELLATOR_MIN_EVEN_TESSELLATION_FACTOR 2
|
||||
#define D3D11_TESSELLATOR_MAX_EVEN_TESSELLATION_FACTOR 64
|
||||
|
||||
#define D3D11_TESSELLATOR_MIN_ISOLINE_DENSITY_TESSELLATION_FACTOR 1
|
||||
#define D3D11_TESSELLATOR_MAX_ISOLINE_DENSITY_TESSELLATION_FACTOR 64
|
||||
|
||||
#define D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR 64 // max of even and odd tessFactors
|
||||
|
||||
#define MAX_POINT_COUNT ((D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR+1)*(D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR+1))
|
||||
#define MAX_INDEX_COUNT (D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR*D3D11_TESSELLATOR_MAX_TESSELLATION_FACTOR*2*3)
|
||||
|
||||
//=================================================================================================================================
|
||||
// Data types for the caller
|
||||
//=================================================================================================================================
|
||||
enum D3D11_TESSELLATOR_PARTITIONING
|
||||
{
|
||||
D3D11_TESSELLATOR_PARTITIONING_INTEGER,
|
||||
D3D11_TESSELLATOR_PARTITIONING_POW2,
|
||||
D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD,
|
||||
D3D11_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN
|
||||
};
|
||||
|
||||
enum D3D11_TESSELLATOR_REDUCTION
|
||||
{
|
||||
D3D11_TESSELLATOR_REDUCTION_MIN,
|
||||
D3D11_TESSELLATOR_REDUCTION_MAX,
|
||||
D3D11_TESSELLATOR_REDUCTION_AVERAGE
|
||||
};
|
||||
|
||||
enum D3D11_TESSELLATOR_QUAD_REDUCTION_AXIS
|
||||
{
|
||||
D3D11_TESSELLATOR_QUAD_REDUCTION_1_AXIS,
|
||||
D3D11_TESSELLATOR_QUAD_REDUCTION_2_AXIS
|
||||
};
|
||||
|
||||
enum D3D11_TESSELLATOR_OUTPUT_PRIMITIVE
|
||||
{
|
||||
D3D11_TESSELLATOR_OUTPUT_POINT,
|
||||
D3D11_TESSELLATOR_OUTPUT_LINE,
|
||||
D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CW,
|
||||
D3D11_TESSELLATOR_OUTPUT_TRIANGLE_CCW,
|
||||
};
|
||||
|
||||
typedef struct DOMAIN_POINT
|
||||
{
|
||||
float u;
|
||||
float v; // for tri, w = 1 - u - v;
|
||||
} DOMAIN_POINT;
|
||||
|
||||
//=================================================================================================================================
|
||||
// CHWTessellator: D3D11 Tessellation Fixed Function Hardware Reference
|
||||
//=================================================================================================================================
|
||||
typedef unsigned int FXP; // fixed point number
|
||||
|
||||
class CHWTessellator
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------
|
||||
public:
|
||||
void Init( D3D11_TESSELLATOR_PARTITIONING partitioning,
|
||||
D3D11_TESSELLATOR_OUTPUT_PRIMITIVE outputPrimitive);
|
||||
|
||||
void TessellateIsoLineDomain( float TessFactor_V_LineDensity,
|
||||
float TessFactor_U_LineDetail );
|
||||
|
||||
void TessellateTriDomain( float TessFactor_Ueq0,
|
||||
float TessFactor_Veq0,
|
||||
float TessFactor_Weq0,
|
||||
float TessFactor_Inside );
|
||||
|
||||
void TessellateQuadDomain( float TessFactor_Ueq0,
|
||||
float TessFactor_Veq0,
|
||||
float TessFactor_Ueq1,
|
||||
float TessFactor_Veq1,
|
||||
float TessFactor_InsideU,
|
||||
float TessFactor_InsideV );
|
||||
|
||||
int GetPointCount();
|
||||
int GetIndexCount();
|
||||
|
||||
DOMAIN_POINT* GetPoints(); // Get CHWTessellator owned pointer to vertices (UV values).
|
||||
// Pointer is fixed for lifetime of CHWTessellator object.
|
||||
int* GetIndices(); // Get CHWTessellator owned pointer to vertex indices.
|
||||
// Pointer is fixed for lifetime of CHWTessellator object.
|
||||
|
||||
#define ALLOW_XBOX_360_COMPARISON // Different vertex splitting order. This is NOT D3D11 behavior, just available here for comparison.
|
||||
// Setting this define true just allows the XBox split style to be enabled via
|
||||
// SetXBox360Mode() below, but by default this XBox360 mode still always starts off DISABLED.
|
||||
// The XBox360 always splits from the center of an edge (D3D11 uses ruler function). Splitting
|
||||
// from the center causes sliver triangles in transition areas, which cause numerous problems.
|
||||
// Note the XBox360 only supports adaptive tessellation via fractional_even partitioning,
|
||||
// though this #define lets you try the XBox vertex splitting order with any of the
|
||||
// partitioning modes: even, odd, integer or pow2.
|
||||
#ifdef ALLOW_XBOX_360_COMPARISON
|
||||
void SetXBox360Mode(bool bXboxMode) {m_bXBox360Mode = bXboxMode;}
|
||||
#endif
|
||||
CHWTessellator();
|
||||
~CHWTessellator();
|
||||
//---------------------------------------------------------------------------------------------------------------------------------
|
||||
//=============================================================================================================================
|
||||
// Some defines so that numbers are usually self commenting
|
||||
//=============================================================================================================================
|
||||
static const int U = 0; // points on a tri patch
|
||||
static const int V = 1;
|
||||
static const int W = 2;
|
||||
static const int Ueq0 = 0; // edges on a tri patch
|
||||
static const int Veq0 = 1;
|
||||
static const int Weq0 = 2;
|
||||
|
||||
static const int Ueq1 = 2; // edges on a quad patch: Ueq0, Veq0, Ueq1, Veq1
|
||||
static const int Veq1 = 3;
|
||||
|
||||
static const int QUAD_AXES = 2;
|
||||
static const int QUAD_EDGES = 4;
|
||||
static const int TRI_EDGES = 3;
|
||||
//=============================================================================================================================
|
||||
|
||||
enum TESSELLATOR_PARITY // derived from D3D11_TESSELLATOR_PARTITIONING
|
||||
{ // (note: for integer tessellation, both parities are used)
|
||||
TESSELLATOR_PARITY_EVEN,
|
||||
TESSELLATOR_PARITY_ODD
|
||||
};
|
||||
private:
|
||||
TESSELLATOR_PARITY m_originalParity; // user chosen parity
|
||||
TESSELLATOR_PARITY m_parity; // current parity: if allowing mix of even/odd during discrete
|
||||
// tessellation, this can vary from the user defined parity
|
||||
D3D11_TESSELLATOR_PARTITIONING m_originalPartitioning; // user chosen partitioning
|
||||
D3D11_TESSELLATOR_PARTITIONING m_partitioning; // current partitioning. IsoLines overrides for line density
|
||||
D3D11_TESSELLATOR_OUTPUT_PRIMITIVE m_outputPrimitive;
|
||||
DOMAIN_POINT* m_Point; // array where we will store u/v's for the points we generate
|
||||
int* m_Index; // array where we will store index topology
|
||||
int m_NumPoints;
|
||||
int m_NumIndices;
|
||||
#ifdef ALLOW_XBOX_360_COMPARISON
|
||||
bool m_bXBox360Mode;
|
||||
#endif
|
||||
// PlacePointIn1D below is the workhorse for all position placement.
|
||||
// It is code that could run as preamble in a Domain Shader, so the tessellator itself
|
||||
// doesn't necessarily need to have floating point.
|
||||
// Some per-TessFactor fixed context is needed, and that can be computed wherever
|
||||
// the TessFactor reduction is done, perhaps as Hull Shader postamble - this is shared
|
||||
// for all point evaluation.
|
||||
typedef struct TESS_FACTOR_CONTEXT
|
||||
{
|
||||
FXP fxpInvNumSegmentsOnFloorTessFactor;
|
||||
FXP fxpInvNumSegmentsOnCeilTessFactor;
|
||||
FXP fxpHalfTessFactorFraction;
|
||||
int numHalfTessFactorPoints;
|
||||
int splitPointOnFloorHalfTessFactor;
|
||||
} TESS_FACTOR_CONTEXT;
|
||||
void ComputeTessFactorContext( FXP fxpTessFactor, TESS_FACTOR_CONTEXT& TessFactorCtx );
|
||||
void PlacePointIn1D( const TESS_FACTOR_CONTEXT& TessFactorCtx, int point, FXP& fxpLocation );
|
||||
|
||||
int NumPointsForTessFactor(FXP fxpTessFactor);
|
||||
|
||||
// Tessellation parity control
|
||||
bool Odd() {return (m_parity == TESSELLATOR_PARITY_ODD) ? true : false;}
|
||||
void SetTessellationParity(TESSELLATOR_PARITY parity) {m_parity = parity;}
|
||||
|
||||
// HWIntegerPartitioning() - hardware doesn't care about what pow2 partitioning is - the query below is true for
|
||||
// both integer and pow2.
|
||||
bool HWIntegerPartitioning() {return ((m_partitioning == D3D11_TESSELLATOR_PARTITIONING_INTEGER)||
|
||||
(m_partitioning == D3D11_TESSELLATOR_PARTITIONING_POW2)) ? true : false;}
|
||||
|
||||
// Tesselation Partitioning control
|
||||
void RestorePartitioning() {m_partitioning = m_originalPartitioning;};
|
||||
void OverridePartitioning(D3D11_TESSELLATOR_PARTITIONING partitioning) {m_partitioning = partitioning;} //isoline uses this for density
|
||||
|
||||
// Call these to generate new points and indices. Max TessFactor storage is already allocated.
|
||||
int DefinePoint(FXP u, FXP v, int pointStorageOffset);
|
||||
void DefineIndex(int index, int indexStorageOffset);
|
||||
void DefineClockwiseTriangle(int index0, int index1, int index2, int indexStorageBaseOffset);
|
||||
|
||||
// Couple of trivial ways to generate index data just given points and no other connectivity.
|
||||
void DumpAllPoints(); // Make point indices for point rendering mode -
|
||||
// redundant, but just here for orthogonality.
|
||||
void DumpAllPointsAsInOrderLineList(); // A debug visualization of all the points connected
|
||||
// in the order they were generated.
|
||||
// Asking to draw line topology on a tri or quad patch will do this
|
||||
|
||||
|
||||
// The structures below define the data that is derived given input TessFactors and which
|
||||
// is used by point generation and connectivity generation steps (each of which are independent)
|
||||
typedef struct PROCESSED_TESS_FACTORS_ISOLINE
|
||||
{
|
||||
TESSELLATOR_PARITY lineDensityParity;
|
||||
TESSELLATOR_PARITY lineDetailParity;
|
||||
TESS_FACTOR_CONTEXT lineDensityTessFactorCtx;
|
||||
TESS_FACTOR_CONTEXT lineDetailTessFactorCtx;
|
||||
bool bPatchCulled;
|
||||
int numPointsPerLine;
|
||||
int numLines;
|
||||
} PROCESSED_TESS_FACTORS_ISOLINE;
|
||||
typedef struct PROCESSED_TESS_FACTORS_TRI
|
||||
{
|
||||
FXP outsideTessFactor[TRI_EDGES];
|
||||
FXP insideTessFactor;
|
||||
TESSELLATOR_PARITY outsideTessFactorParity[TRI_EDGES];
|
||||
TESSELLATOR_PARITY insideTessFactorParity;
|
||||
TESS_FACTOR_CONTEXT outsideTessFactorCtx[TRI_EDGES];
|
||||
TESS_FACTOR_CONTEXT insideTessFactorCtx;
|
||||
bool bJustDoMinimumTessFactor;
|
||||
bool bPatchCulled;
|
||||
// Stuff below is just specific to the traversal order
|
||||
// this code happens to use to generate points/lines
|
||||
int numPointsForOutsideEdge[TRI_EDGES];
|
||||
int numPointsForInsideTessFactor;
|
||||
int insideEdgePointBaseOffset;
|
||||
} PROCESSED_TESS_FACTORS_TRI;
|
||||
typedef struct PROCESSED_TESS_FACTORS_QUAD
|
||||
{
|
||||
FXP outsideTessFactor[QUAD_EDGES];
|
||||
FXP insideTessFactor[QUAD_AXES];
|
||||
TESSELLATOR_PARITY outsideTessFactorParity[QUAD_EDGES];
|
||||
TESSELLATOR_PARITY insideTessFactorParity[QUAD_AXES];
|
||||
TESS_FACTOR_CONTEXT outsideTessFactorCtx[QUAD_EDGES];
|
||||
TESS_FACTOR_CONTEXT insideTessFactorCtx[QUAD_AXES];
|
||||
bool bJustDoMinimumTessFactor;
|
||||
bool bPatchCulled;
|
||||
// Stuff below is just specific to the traversal order
|
||||
// this code happens to use to generate points/lines
|
||||
int numPointsForOutsideEdge[QUAD_EDGES];
|
||||
int numPointsForInsideTessFactor[QUAD_AXES];
|
||||
int insideEdgePointBaseOffset;
|
||||
} PROCESSED_TESS_FACTORS_QUAD;
|
||||
|
||||
// These are the workhorse functions for tessellation:
|
||||
// (1) Process input TessFactors
|
||||
// (2) Generate points
|
||||
// (3) Generate connectivity (can be done in parallel to (2))
|
||||
void IsoLineProcessTessFactors( float TessFactor_V_LineDensity, float TessFactor_U_LineDetail, PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors );
|
||||
void IsoLineGeneratePoints( const PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors );
|
||||
void IsoLineGenerateConnectivity( const PROCESSED_TESS_FACTORS_ISOLINE& processedTessFactors );
|
||||
void TriProcessTessFactors( float tessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Weq0, float insideTessFactor, PROCESSED_TESS_FACTORS_TRI& processedTessFactors );
|
||||
void TriGeneratePoints( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors );
|
||||
void TriGenerateConnectivity( const PROCESSED_TESS_FACTORS_TRI& processedTessFactors );
|
||||
void QuadProcessTessFactors( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Ueq1, float tessFactor_Veq1,
|
||||
float insideTessFactor_U, float insideTessFactor_V, PROCESSED_TESS_FACTORS_QUAD& processedTessFactors );
|
||||
void QuadGeneratePoints( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors );
|
||||
void QuadGenerateConnectivity( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors );
|
||||
|
||||
// Stitching
|
||||
// ---------
|
||||
// Given pointers to the beginning of 2 parallel rows of points, and TessFactors for each, stitch them.
|
||||
// The assumption is the stitch is symmetric.
|
||||
void StitchTransition(int baseIndexOffset, int insideEdgePointBaseOffset, int insideNumHalfTessFactorPoints,
|
||||
TESSELLATOR_PARITY insideEdgeTessFactorParity,
|
||||
int outsideEdgePointBaseOffset, int outsideNumHalfTessFactorPoints,
|
||||
TESSELLATOR_PARITY outsideEdgeTessFactorParity );
|
||||
// The interior can just use a simpler stitch.
|
||||
enum DIAGONALS
|
||||
{
|
||||
DIAGONALS_INSIDE_TO_OUTSIDE,
|
||||
DIAGONALS_INSIDE_TO_OUTSIDE_EXCEPT_MIDDLE,
|
||||
DIAGONALS_MIRRORED
|
||||
};
|
||||
|
||||
void StitchRegular(bool bTrapezoid, DIAGONALS diagonals, int baseIndexOffset, int numInsideEdgePoints,
|
||||
int insideEdgePointBaseOffset, int outsideEdgePointBaseOffset);
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------
|
||||
// Index Patching
|
||||
// --------------
|
||||
// The code below patches index values produces during triangulation, so triangulation doesn't have to know
|
||||
// where points should go. I happened to never produce duplicate vertices, but the patching would
|
||||
// be simpler if some duplicate vertices were introduced in practice. During point rendering mode however,
|
||||
// it is not permitted for duplicate points to show up.
|
||||
|
||||
// Since the points are generated in concentric rings, most of the time, the point locations are
|
||||
// sequentially increasing in memory for each side of a ring, which the stitch can take advantage of.
|
||||
// However, there are exceptions where the points are not sequentially increasing, such as
|
||||
// the 4th row in a given ring, where the last point on the outside of each row is actually the beginning
|
||||
// point.
|
||||
// So we let the stitching code think it sees sequential vertices, and when it emits a vertex index,
|
||||
// we patch it to be the real location.
|
||||
int PatchIndexValue(int index);
|
||||
typedef struct INDEX_PATCH_CONTEXT
|
||||
{
|
||||
int insidePointIndexDeltaToRealValue;
|
||||
int insidePointIndexBadValue;
|
||||
int insidePointIndexReplacementValue;
|
||||
int outsidePointIndexPatchBase;
|
||||
int outsidePointIndexDeltaToRealValue;
|
||||
int outsidePointIndexBadValue;
|
||||
int outsidePointIndexReplacementValue;
|
||||
} INDEX_PATCH_CONTEXT;
|
||||
void SetUsingPatchedIndices(bool bUsingPatchedIndices) {m_bUsingPatchedIndices = bUsingPatchedIndices;}
|
||||
|
||||
// A second index patch we have to do handles the leftover strip of quads in the middle of an odd quad patch after
|
||||
// finishing all the concentric rings.
|
||||
// This also handles the leftover strip of points in the middle of an even quad
|
||||
// patch, when stitching the row of triangles up the left side (V major quad) or bottom (U major quad) of the
|
||||
// inner ring
|
||||
typedef struct INDEX_PATCH_CONTEXT2
|
||||
{
|
||||
int baseIndexToInvert;
|
||||
int indexInversionEndPoint;
|
||||
int cornerCaseBadValue;
|
||||
int cornerCaseReplacementValue;
|
||||
} INDEX_PATCH_CONTEXT2;
|
||||
void SetUsingPatchedIndices2(bool bUsingPatchedIndices) {m_bUsingPatchedIndices2 = bUsingPatchedIndices;}
|
||||
bool m_bUsingPatchedIndices;
|
||||
bool m_bUsingPatchedIndices2;
|
||||
INDEX_PATCH_CONTEXT m_IndexPatchContext;
|
||||
INDEX_PATCH_CONTEXT2 m_IndexPatchContext2;
|
||||
|
||||
};
|
||||
|
||||
//=================================================================================================================================
|
||||
// CHLSLTessellator: D3D11 Tessellation HLSL Tessellator Interface
|
||||
// Demonstrates TessFactor preconditioning code auto-generated by HLSL. Subject to change, but this
|
||||
// just represents the effect of shader code the HLSL compiler will generate in the Hull Shader,
|
||||
// so it does not affect hardware design at all.
|
||||
//=================================================================================================================================
|
||||
class CHLSLTessellator : public CHWTessellator
|
||||
{
|
||||
public:
|
||||
void Init( D3D11_TESSELLATOR_PARTITIONING partitioning,
|
||||
D3D11_TESSELLATOR_REDUCTION insideTessFactorReduction,
|
||||
D3D11_TESSELLATOR_QUAD_REDUCTION_AXIS quadInsideTessFactorReductionAxis,
|
||||
D3D11_TESSELLATOR_OUTPUT_PRIMITIVE outputPrimitive);
|
||||
|
||||
void TessellateIsoLineDomain( float TessFactor_V_LineDensity,
|
||||
float TessFactor_U_LineDetail );
|
||||
|
||||
void TessellateTriDomain( float tessFactor_Ueq0,
|
||||
float TessFactor_Veq0,
|
||||
float TessFactor_Weq0,
|
||||
float insideTessFactorScale /*[0..1]*/ );
|
||||
|
||||
void TessellateQuadDomain( float TessFactorUeq0,
|
||||
float TessFactorVeq0,
|
||||
float TessFactorUeq1,
|
||||
float TessFactorVeq1,
|
||||
float insideTessFactorScaleU /*[0..1]*/,
|
||||
float insideTessFactorScaleV /*[0..1]*/ );
|
||||
|
||||
int GetPointCount() {return CHWTessellator::GetPointCount();};
|
||||
int GetIndexCount() {return CHWTessellator::GetIndexCount();}
|
||||
|
||||
DOMAIN_POINT* GetPoints() {return CHWTessellator::GetPoints();} // Get CHLSLTessellator owned pointer to vertices (UV values).
|
||||
// Pointer is fixed for lifetime of CHLSLTessellator object.
|
||||
int* GetIndices() {return CHWTessellator::GetIndices();} // Get CHLSLTessellator owned pointer to vertex indices.
|
||||
// Pointer is fixed for lifetime of CHLSLTessellator object.
|
||||
|
||||
// Retrieve TessFactors actually used by the "hardware"
|
||||
// This includes clamping to valid range, and more interestingly
|
||||
// if integer or pow2 partitioning is being done, the rounded TessFactors can be retrieved.
|
||||
// Getting the rounded TessFactors can be useful for geomorphing of displacement maps.
|
||||
float GetIsoLineDensityTessFactor() {return m_LastComputedTessFactors[0];}
|
||||
float GetIsoLineDetailTessFactor() {return m_LastComputedTessFactors[1];}
|
||||
float GetTriUeq0TessFactor() {return m_LastComputedTessFactors[0];}
|
||||
float GetTriVeq0TessFactor() {return m_LastComputedTessFactors[1];}
|
||||
float GetTriWeq0TessFactor() {return m_LastComputedTessFactors[2];}
|
||||
float GetTriInsideTessFactor() {return m_LastComputedTessFactors[3];}
|
||||
float GetQuadUeq0TessFactor() {return m_LastComputedTessFactors[0];}
|
||||
float GetQuadVeq0TessFactor() {return m_LastComputedTessFactors[1];}
|
||||
float GetQuadUeq1TessFactor() {return m_LastComputedTessFactors[2];}
|
||||
float GetQuadVeq1TessFactor() {return m_LastComputedTessFactors[3];}
|
||||
float GetQuadInsideUTessFactor() {return m_LastComputedTessFactors[4];}
|
||||
float GetQuadInsideVTessFactor() {return m_LastComputedTessFactors[5];}
|
||||
float GetUnRoundedIsoLineDensityTessFactor() {return m_LastUnRoundedComputedTessFactors[0];}
|
||||
float GetUnRoundedIsoLineDetailTessFactor() {return m_LastUnRoundedComputedTessFactors[1];}
|
||||
float GetUnRoundedTriUeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[0];}
|
||||
float GetUnRoundedTriVeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[1];}
|
||||
float GetUnRoundedTriWeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[2];}
|
||||
float GetUnRoundedTriInsideTessFactor() {return m_LastUnRoundedComputedTessFactors[3];}
|
||||
float GetUnRoundedQuadUeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[0];}
|
||||
float GetUnRoundedQuadVeq0TessFactor() {return m_LastUnRoundedComputedTessFactors[1];}
|
||||
float GetUnRoundedQuadUeq1TessFactor() {return m_LastUnRoundedComputedTessFactors[2];}
|
||||
float GetUnRoundedQuadVeq1TessFactor() {return m_LastUnRoundedComputedTessFactors[3];}
|
||||
float GetUnRoundedQuadInsideUTessFactor() {return m_LastUnRoundedComputedTessFactors[4];}
|
||||
float GetUnRoundedQuadInsideVTessFactor() {return m_LastUnRoundedComputedTessFactors[5];}
|
||||
|
||||
CHLSLTessellator();
|
||||
//---------------------------------------------------------------------------------------------------------------------------------
|
||||
private:
|
||||
TESSELLATOR_PARITY m_originalParity; // user chosen parity
|
||||
TESSELLATOR_PARITY m_parity; // current parity: if allowing mix of even/odd during discrete
|
||||
// tessellation, this can vary from the user defined parity
|
||||
D3D11_TESSELLATOR_PARTITIONING m_originalPartitioning; // user chosen partitioning
|
||||
D3D11_TESSELLATOR_PARTITIONING m_partitioning; // current partitioning. IsoLines overrides for line density
|
||||
D3D11_TESSELLATOR_OUTPUT_PRIMITIVE m_outputPrimitive;
|
||||
D3D11_TESSELLATOR_REDUCTION m_insideTessFactorReduction;
|
||||
D3D11_TESSELLATOR_QUAD_REDUCTION_AXIS m_quadInsideTessFactorReductionAxis;
|
||||
float m_LastComputedTessFactors[6]; // TessFactors used for last tessellation
|
||||
float m_LastUnRoundedComputedTessFactors[6]; // TessFactors used for last tessellation (before they were rounded)
|
||||
bool IntegerPartitioning() {return (m_partitioning == D3D11_TESSELLATOR_PARTITIONING_INTEGER) ? true : false;}
|
||||
bool Pow2Partitioning() {return (m_partitioning == D3D11_TESSELLATOR_PARTITIONING_POW2)? true : false;}
|
||||
void ClampTessFactor(float& TessFactor);
|
||||
void RoundUpTessFactor(float& TessFactor);
|
||||
void CleanupFloatTessFactor(float& input); // clamp float to [1.0f... +INF] (incl NaN->1.0f)
|
||||
void ClampFloatTessFactorScale(float& input); // clamp float to [0.0f... +INF] (incl NaN->0.0f)
|
||||
|
||||
// Tessellation parity control
|
||||
bool Odd() {return (m_parity == TESSELLATOR_PARITY_ODD) ? true : false;}
|
||||
void SetTessellationParity(TESSELLATOR_PARITY parity) {m_parity = parity;}
|
||||
|
||||
// Tesselation Partitioning control
|
||||
void RestorePartitioning() {m_partitioning = m_originalPartitioning;};
|
||||
void OverridePartitioning(D3D11_TESSELLATOR_PARTITIONING partitioning) {m_partitioning = partitioning;} //isoline uses this for density
|
||||
|
||||
void IsoLineHLSLProcessTessFactors( float TessFactor_V_LineDensity, float TessFactor_U_LineDetail );
|
||||
void TriHLSLProcessTessFactors( float tessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Weq0, float insideTessFactor );
|
||||
void QuadHLSLProcessTessFactors( float TessFactor_Ueq0, float TessFactor_Veq0, float TessFactor_Ueq1, float TessFactor_Veq1,
|
||||
float insideTessFactor_U, float insideTessFactor_V );
|
||||
|
||||
};
|
||||
|
Loading…
Reference in New Issue