mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
[spline/bezier]Unify hardware tessellation of bezier and spline.
This commit is contained in:
parent
3c0fb44f2e
commit
a48a5b32f0
11 changed files with 153 additions and 187 deletions
|
@ -741,7 +741,7 @@ void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim,
|
|||
}
|
||||
}
|
||||
|
||||
void DrawEngineCommon::TessellationDataTransfer::CopyControlPoints(float *pos, float *tex, float *col, int posStride, int texStride, int colStride, const SimpleVertex *const *points, int size, u32 vertType) {
|
||||
void TessellationDataTransfer::CopyControlPoints(float *pos, float *tex, float *col, int posStride, int texStride, int colStride, const SimpleVertex *const *points, int size, u32 vertType) {
|
||||
bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
|
||||
bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0;
|
||||
|
||||
|
|
|
@ -53,6 +53,12 @@ inline uint32_t GetVertTypeID(uint32_t vertType, int uvGenMode) {
|
|||
|
||||
struct SimpleVertex;
|
||||
|
||||
class TessellationDataTransfer {
|
||||
public:
|
||||
void CopyControlPoints(float *pos, float *tex, float *col, int posStride, int texStride, int colStride, const SimpleVertex *const *points, int size, u32 vertType);
|
||||
virtual void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) = 0;
|
||||
};
|
||||
|
||||
class DrawEngineCommon {
|
||||
public:
|
||||
DrawEngineCommon();
|
||||
|
@ -173,12 +179,5 @@ protected:
|
|||
|
||||
// Hardware tessellation
|
||||
int numPatches;
|
||||
class TessellationDataTransfer {
|
||||
public:
|
||||
virtual ~TessellationDataTransfer() {}
|
||||
void CopyControlPoints(float *pos, float *tex, float *col, int posStride, int texStride, int colStride, const SimpleVertex *const *points, int size, u32 vertType);
|
||||
// Send spline/bezier's control points to vertex shader through floating point texture.
|
||||
virtual void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) = 0;
|
||||
};
|
||||
TessellationDataTransfer *tessDataTransfer;
|
||||
};
|
||||
|
|
|
@ -89,6 +89,10 @@ public:
|
|||
u32 ToKey(int tess, int count, int type) {
|
||||
return tess;
|
||||
}
|
||||
|
||||
int CalcSize(int tess, int count) {
|
||||
return tess + 1;
|
||||
}
|
||||
};
|
||||
|
||||
class Spline3DWeight {
|
||||
|
@ -231,6 +235,10 @@ public:
|
|||
void FromKey(u32 key, int &tess, int &count, int &type) {
|
||||
tess = key & 0xFF; count = (key >> 8) & 0xFF; type = (key >> 16) & 0xFF;
|
||||
}
|
||||
|
||||
int CalcSize(int tess, int count) {
|
||||
return (count - 3) * tess + 1;
|
||||
}
|
||||
};
|
||||
|
||||
static WeightCache<Bezier3DWeight> bezierWeightsCache;
|
||||
|
@ -248,28 +256,6 @@ bool CanUseHardwareTessellation(GEPatchPrimType prim) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Prepare mesh of one patch for "Instanced Tessellation".
|
||||
static void TessellateSplinePatchHardware(u8 *&dest, u16 *indices, int &count, const SplinePatchLocal &spatch) {
|
||||
SimpleVertex *&vertices = (SimpleVertex*&)dest;
|
||||
|
||||
float inv_u = 1.0f / (float)spatch.tess_u;
|
||||
float inv_v = 1.0f / (float)spatch.tess_v;
|
||||
|
||||
// Generating simple input vertices for the spline-computing vertex shader.
|
||||
for (int tile_v = 0; tile_v < spatch.tess_v + 1; ++tile_v) {
|
||||
for (int tile_u = 0; tile_u < spatch.tess_u + 1; ++tile_u) {
|
||||
SimpleVertex &vert = vertices[tile_v * (spatch.tess_u + 1) + tile_u];
|
||||
vert.pos.x = (float)tile_u;
|
||||
vert.pos.y = (float)tile_v;
|
||||
// For texcoord generation
|
||||
vert.nrm.x = (float)tile_u * inv_u;
|
||||
vert.nrm.y = (float)tile_v * inv_v;
|
||||
}
|
||||
}
|
||||
|
||||
BuildIndex(indices, count, spatch.tess_u, spatch.tess_v, spatch.primType);
|
||||
}
|
||||
|
||||
// Tessellate single patch (4x4 control points)
|
||||
template<typename T>
|
||||
class Tessellator {
|
||||
|
@ -309,29 +295,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// Prepare mesh of one patch for "Instanced Tessellation".
|
||||
static void TessellateBezierPatchHardware(u8 *&dest, u16 *indices, int &count, int tess_u, int tess_v, GEPatchPrimType primType) {
|
||||
SimpleVertex *&vertices = (SimpleVertex*&)dest;
|
||||
|
||||
float inv_u = 1.0f / (float)tess_u;
|
||||
float inv_v = 1.0f / (float)tess_v;
|
||||
|
||||
// Generating simple input vertices for the bezier-computing vertex shader.
|
||||
for (int tile_v = 0; tile_v < tess_v + 1; ++tile_v) {
|
||||
for (int tile_u = 0; tile_u < tess_u + 1; ++tile_u) {
|
||||
SimpleVertex &vert = vertices[tile_v * (tess_u + 1) + tile_u];
|
||||
|
||||
vert.pos.x = (float)tile_u;
|
||||
vert.pos.y = (float)tile_v;
|
||||
// For texcoord generation
|
||||
vert.nrm.x = (float)tile_u * inv_u;
|
||||
vert.nrm.y = (float)tile_v * inv_v;
|
||||
}
|
||||
}
|
||||
|
||||
BuildIndex(indices, count, tess_u, tess_v, primType);
|
||||
}
|
||||
|
||||
class SimpleBufferManager {
|
||||
private:
|
||||
u8 *buf_;
|
||||
|
@ -466,7 +429,8 @@ public:
|
|||
};
|
||||
|
||||
template<class Patch, class Cache>
|
||||
static void SoftwareTessellation(SimpleVertex *vertices, u16 *indices, int &count, const Patch &patch, int origVertType, const SimpleVertex *const *points, SimpleBufferManager &managedBuf, Cache &weightsCache) {
|
||||
static void SoftwareTessellation(SimpleVertex *vertices, u16 *indices, int &count, const Patch &patch, u32 origVertType,
|
||||
const SimpleVertex *const *points, SimpleBufferManager &managedBuf, Cache &weightsCache) {
|
||||
u32 key_u = weightsCache.ToKey(patch.tess_u, patch.count_u, patch.type_u);
|
||||
u32 key_v = weightsCache.ToKey(patch.tess_v, patch.count_v, patch.type_v);
|
||||
Weight2D weights(weightsCache, key_u, key_v);
|
||||
|
@ -475,8 +439,31 @@ static void SoftwareTessellation(SimpleVertex *vertices, u16 *indices, int &coun
|
|||
surface.Tessellate(vertices, indices, count, origVertType);
|
||||
}
|
||||
|
||||
// This maps GEPatchPrimType to GEPrimitiveType.
|
||||
const GEPrimitiveType primType[] = { GE_PRIM_TRIANGLES, GE_PRIM_LINES, GE_PRIM_POINTS, GE_PRIM_POINTS };
|
||||
template<class Patch, class Cache>
|
||||
static void HardwareTessellation(SimpleVertex *vertices, u16 *indices, int &count, const Patch &patch, u32 origVertType,
|
||||
const SimpleVertex *const *points, Cache &weightsCache, TessellationDataTransfer *tessDataTransfer) {
|
||||
u32 key_u = weightsCache.ToKey(patch.tess_u, patch.count_u, patch.type_u);
|
||||
u32 key_v = weightsCache.ToKey(patch.tess_v, patch.count_v, patch.type_v);
|
||||
Weight2D weights(weightsCache, key_u, key_v);
|
||||
weights.size_u = weightsCache.CalcSize(patch.tess_u, patch.count_u);
|
||||
weights.size_v = weightsCache.CalcSize(patch.tess_v, patch.count_v);
|
||||
tessDataTransfer->SendDataToShader(points, patch.count_u * patch.count_v, origVertType, weights);
|
||||
|
||||
// Generating simple input vertices for the spline-computing vertex shader.
|
||||
float inv_u = 1.0f / (float)patch.tess_u;
|
||||
float inv_v = 1.0f / (float)patch.tess_v;
|
||||
for (int tile_v = 0; tile_v <= patch.tess_v; ++tile_v) {
|
||||
for (int tile_u = 0; tile_u <= patch.tess_u; ++tile_u) {
|
||||
SimpleVertex &vert = vertices[tile_v * (patch.tess_u + 1) + tile_u];
|
||||
vert.pos.x = (float)tile_u;
|
||||
vert.pos.y = (float)tile_v;
|
||||
// For texcoord generation
|
||||
vert.nrm.x = (float)tile_u * inv_u;
|
||||
vert.nrm.y = (float)tile_v * inv_v;
|
||||
}
|
||||
}
|
||||
BuildIndex(indices, count, patch.tess_u, patch.tess_v, patch.primType);
|
||||
}
|
||||
|
||||
void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead) {
|
||||
PROFILE_THIS_SCOPE("spline");
|
||||
|
@ -536,14 +523,8 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
|
|||
patch.patchFacing = patchFacing;
|
||||
|
||||
if (CanUseHardwareTessellation(prim_type)) {
|
||||
const u32 key_u = splineWeightsCache.ToKey(tess_u, count_u, type_u);
|
||||
const u32 key_v = splineWeightsCache.ToKey(tess_v, count_v, type_v);
|
||||
Weight2D weights(splineWeightsCache, key_u, key_v);
|
||||
weights.size_u = (count_u - 3) * tess_u + 1;
|
||||
weights.size_v = (count_v - 3) * tess_v + 1;
|
||||
tessDataTransfer->SendDataToShader(points, count_u * count_v, origVertType, weights);
|
||||
TessellateSplinePatchHardware(dest, quadIndices_, count, patch);
|
||||
numPatches = (count_u - 3) * (count_v - 3);
|
||||
HardwareTessellation((SimpleVertex *)splineBuffer, quadIndices_, count, patch, origVertType, points, splineWeightsCache, tessDataTransfer);
|
||||
numPatches = patch.num_patches_u * patch.num_patches_v;
|
||||
} else {
|
||||
patch.Init(SPLINE_BUFFER_SIZE / vertexSize);
|
||||
SoftwareTessellation((SimpleVertex *)splineBuffer, quadIndices_, count, patch, origVertType, points, managedBuf, splineWeightsCache);
|
||||
|
@ -621,27 +602,20 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
|
|||
u8 *dest = splineBuffer;
|
||||
u16 *inds = quadIndices_;
|
||||
|
||||
// Bezier patches share less control points than spline patches. Otherwise they are pretty much the same (except bezier don't support the open/close thing)
|
||||
int num_patches_u = (count_u - 1) / 3;
|
||||
int num_patches_v = (count_v - 1) / 3;
|
||||
if (CanUseHardwareTessellation(prim_type)) {
|
||||
Weight2D weights(bezierWeightsCache, tess_u, tess_v);
|
||||
weights.size_u = tess_u + 1;
|
||||
weights.size_v = tess_v + 1;
|
||||
tessDataTransfer->SendDataToShader(points, count_u * count_v, origVertType, weights);
|
||||
TessellateBezierPatchHardware(dest, inds, count, tess_u, tess_v, prim_type);
|
||||
numPatches = num_patches_u * num_patches_v;
|
||||
} else {
|
||||
BezierPatch patch;
|
||||
patch.tess_u = tess_u;
|
||||
patch.tess_v = tess_v;
|
||||
patch.count_u = count_u;
|
||||
patch.count_v = count_v;
|
||||
patch.num_patches_u = (count_u - 1) / 3;
|
||||
patch.num_patches_v = (count_v - 1) / 3;
|
||||
patch.primType = prim_type;
|
||||
patch.patchFacing = patchFacing;
|
||||
BezierPatch patch;
|
||||
patch.tess_u = tess_u;
|
||||
patch.tess_v = tess_v;
|
||||
patch.count_u = count_u;
|
||||
patch.count_v = count_v;
|
||||
patch.num_patches_u = (count_u - 1) / 3;
|
||||
patch.num_patches_v = (count_v - 1) / 3;
|
||||
patch.primType = prim_type;
|
||||
patch.patchFacing = patchFacing;
|
||||
|
||||
if (CanUseHardwareTessellation(prim_type)) {
|
||||
HardwareTessellation((SimpleVertex *)splineBuffer, quadIndices_, count, patch, origVertType, points, bezierWeightsCache, tessDataTransfer);
|
||||
numPatches = patch.num_patches_u * patch.num_patches_v;
|
||||
} else {
|
||||
patch.Init(SPLINE_BUFFER_SIZE / vertexSize);
|
||||
SoftwareTessellation((SimpleVertex *)splineBuffer, quadIndices_, count, patch, origVertType, points, managedBuf, bezierWeightsCache);
|
||||
}
|
||||
|
|
|
@ -111,7 +111,8 @@ void DrawEngineD3D11::InitDeviceObjects() {
|
|||
pushVerts_ = new PushBufferD3D11(device_, VERTEX_PUSH_SIZE, D3D11_BIND_VERTEX_BUFFER);
|
||||
pushInds_ = new PushBufferD3D11(device_, INDEX_PUSH_SIZE, D3D11_BIND_INDEX_BUFFER);
|
||||
|
||||
tessDataTransfer = new TessellationDataTransferD3D11(context_, device_);
|
||||
tessDataTransferD3D11 = new TessellationDataTransferD3D11(context_, device_);
|
||||
tessDataTransfer = tessDataTransferD3D11;
|
||||
}
|
||||
|
||||
void DrawEngineD3D11::ClearTrackedVertexArrays() {
|
||||
|
@ -137,7 +138,7 @@ void DrawEngineD3D11::Resized() {
|
|||
void DrawEngineD3D11::DestroyDeviceObjects() {
|
||||
ClearTrackedVertexArrays();
|
||||
ClearInputLayoutMap();
|
||||
delete tessDataTransfer;
|
||||
delete tessDataTransferD3D11;
|
||||
delete pushVerts_;
|
||||
delete pushInds_;
|
||||
depthStencilCache_.Iterate([&](const uint64_t &key, ID3D11DepthStencilState *ds) {
|
||||
|
@ -692,7 +693,22 @@ rotateVBO:
|
|||
GPUDebug::NotifyDraw();
|
||||
}
|
||||
|
||||
void DrawEngineD3D11::TessellationDataTransferD3D11::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
|
||||
TessellationDataTransferD3D11::TessellationDataTransferD3D11(ID3D11DeviceContext *context, ID3D11Device *device)
|
||||
: context_(context), device_(device) {
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
|
||||
}
|
||||
|
||||
TessellationDataTransferD3D11::~TessellationDataTransferD3D11() {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (buf[i]) buf[i]->Release();
|
||||
if (view[i]) view[i]->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void TessellationDataTransferD3D11::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
|
||||
struct TessData {
|
||||
float pos[3]; float pad1;
|
||||
float uv[2]; float pad2[2];
|
||||
|
@ -701,13 +717,11 @@ void DrawEngineD3D11::TessellationDataTransferD3D11::SendDataToShader(const Simp
|
|||
|
||||
if (prevSize < size) {
|
||||
prevSize = size;
|
||||
if (buf[0]) {
|
||||
buf[0]->Release();
|
||||
view[0]->Release();
|
||||
}
|
||||
if (buf[0]) buf[0]->Release();
|
||||
if (view[0]) view[0]->Release();
|
||||
|
||||
desc.ByteWidth = size * sizeof(TessData);
|
||||
desc.StructureByteStride = sizeof(TessData);
|
||||
|
||||
device_->CreateBuffer(&desc, nullptr, &buf[0]);
|
||||
device_->CreateShaderResourceView(buf[0], nullptr, &view[0]);
|
||||
context_->VSSetShaderResources(0, 1, &view[0]);
|
||||
|
@ -727,17 +741,14 @@ void DrawEngineD3D11::TessellationDataTransferD3D11::SendDataToShader(const Simp
|
|||
|
||||
context_->Unmap(buf[0], 0);
|
||||
|
||||
|
||||
// Weights U
|
||||
if (prevSizeWeights[0] < weights.size_u) {
|
||||
prevSizeWeights[0] = weights.size_u;
|
||||
if (buf[1]) {
|
||||
buf[1]->Release();
|
||||
view[1]->Release();
|
||||
}
|
||||
if (prevSizeWU < weights.size_u) {
|
||||
prevSizeWU = weights.size_u;
|
||||
if (buf[1]) buf[1]->Release();
|
||||
if (view[1]) view[1]->Release();
|
||||
|
||||
desc.ByteWidth = weights.size_u * sizeof(Weight);
|
||||
desc.StructureByteStride = sizeof(Weight);
|
||||
|
||||
device_->CreateBuffer(&desc, nullptr, &buf[1]);
|
||||
device_->CreateShaderResourceView(buf[1], nullptr, &view[1]);
|
||||
context_->VSSetShaderResources(1, 1, &view[1]);
|
||||
|
@ -747,15 +758,13 @@ void DrawEngineD3D11::TessellationDataTransferD3D11::SendDataToShader(const Simp
|
|||
context_->Unmap(buf[1], 0);
|
||||
|
||||
// Weights V
|
||||
if (prevSizeWeights[1] < weights.size_v) {
|
||||
prevSizeWeights[1] = weights.size_v;
|
||||
if (buf[2]) {
|
||||
buf[2]->Release();
|
||||
view[2]->Release();
|
||||
}
|
||||
if (prevSizeWV < weights.size_v) {
|
||||
prevSizeWV = weights.size_v;
|
||||
if (buf[2]) buf[2]->Release();
|
||||
if (view[2]) view[2]->Release();
|
||||
|
||||
desc.ByteWidth = weights.size_v * sizeof(Weight);
|
||||
desc.StructureByteStride = sizeof(Weight);
|
||||
|
||||
device_->CreateBuffer(&desc, nullptr, &buf[2]);
|
||||
device_->CreateShaderResourceView(buf[2], nullptr, &view[2]);
|
||||
context_->VSSetShaderResources(2, 1, &view[2]);
|
||||
|
|
|
@ -99,6 +99,22 @@ public:
|
|||
u8 flags;
|
||||
};
|
||||
|
||||
class TessellationDataTransferD3D11 : public TessellationDataTransfer {
|
||||
private:
|
||||
ID3D11DeviceContext *context_;
|
||||
ID3D11Device *device_;
|
||||
ID3D11Buffer *buf[3]{};
|
||||
ID3D11ShaderResourceView *view[3]{};
|
||||
D3D11_BUFFER_DESC desc{};
|
||||
int prevSize = 0;
|
||||
int prevSizeWU = 0, prevSizeWV = 0;
|
||||
public:
|
||||
TessellationDataTransferD3D11(ID3D11DeviceContext *context, ID3D11Device *device);
|
||||
~TessellationDataTransferD3D11();
|
||||
// Send spline/bezier's control points and weights to vertex shader through structured shader buffer.
|
||||
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) override;
|
||||
};
|
||||
|
||||
// Handles transform, lighting and drawing.
|
||||
class DrawEngineD3D11 : public DrawEngineCommon {
|
||||
public:
|
||||
|
@ -199,32 +215,5 @@ private:
|
|||
D3D11DynamicState dynState_{};
|
||||
|
||||
// Hardware tessellation
|
||||
class TessellationDataTransferD3D11 : public TessellationDataTransfer {
|
||||
private:
|
||||
ID3D11DeviceContext *context_;
|
||||
ID3D11Device *device_;
|
||||
ID3D11Buffer *buf[3];
|
||||
ID3D11ShaderResourceView *view[3];
|
||||
D3D11_BUFFER_DESC desc;
|
||||
int prevSize = 0;
|
||||
int prevSizeWeights[2] = {};
|
||||
public:
|
||||
TessellationDataTransferD3D11(ID3D11DeviceContext *context, ID3D11Device *device)
|
||||
: TessellationDataTransfer(), context_(context), device_(device), buf(), view(), desc() {
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
|
||||
}
|
||||
~TessellationDataTransferD3D11() {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (buf[i]) {
|
||||
buf[i]->Release();
|
||||
view[i]->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) override;
|
||||
};
|
||||
TessellationDataTransferD3D11 *tessDataTransferD3D11;
|
||||
};
|
||||
|
|
|
@ -101,7 +101,8 @@ DrawEngineDX9::DrawEngineDX9(Draw::DrawContext *draw) : vai_(256), vertexDeclMap
|
|||
|
||||
InitDeviceObjects();
|
||||
|
||||
tessDataTransfer = new TessellationDataTransferDX9();
|
||||
tessDataTransferDX9 = new TessellationDataTransferDX9();
|
||||
tessDataTransfer = tessDataTransferDX9;
|
||||
|
||||
device_->CreateVertexDeclaration(TransformedVertexElements, &transformedVertexDecl_);
|
||||
}
|
||||
|
@ -121,7 +122,7 @@ DrawEngineDX9::~DrawEngineDX9() {
|
|||
}
|
||||
});
|
||||
vertexDeclMap_.Clear();
|
||||
delete tessDataTransfer;
|
||||
delete tessDataTransferDX9;
|
||||
}
|
||||
|
||||
void DrawEngineDX9::InitDeviceObjects() {
|
||||
|
@ -624,7 +625,8 @@ rotateVBO:
|
|||
GPUDebug::NotifyDraw();
|
||||
}
|
||||
|
||||
void DrawEngineDX9::TessellationDataTransferDX9::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
|
||||
void TessellationDataTransferDX9::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -97,6 +97,13 @@ public:
|
|||
u8 flags;
|
||||
};
|
||||
|
||||
class TessellationDataTransferDX9 : public TessellationDataTransfer {
|
||||
public:
|
||||
TessellationDataTransferDX9() {}
|
||||
~TessellationDataTransferDX9() {}
|
||||
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) override;
|
||||
};
|
||||
|
||||
// Handles transform, lighting and drawing.
|
||||
class DrawEngineDX9 : public DrawEngineCommon {
|
||||
public:
|
||||
|
@ -158,16 +165,7 @@ private:
|
|||
FramebufferManagerDX9 *framebufferManager_ = nullptr;
|
||||
|
||||
// Hardware tessellation
|
||||
class TessellationDataTransferDX9 : public TessellationDataTransfer {
|
||||
private:
|
||||
int data_tex[3];
|
||||
public:
|
||||
TessellationDataTransferDX9() : TessellationDataTransfer(), data_tex() {
|
||||
}
|
||||
~TessellationDataTransferDX9() {
|
||||
}
|
||||
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) override;
|
||||
};
|
||||
TessellationDataTransferDX9 *tessDataTransferDX9;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -97,7 +97,7 @@ DrawEngineGLES::~DrawEngineGLES() {
|
|||
FreeMemoryPages(decIndex, DECODED_INDEX_BUFFER_SIZE);
|
||||
FreeMemoryPages(splineBuffer, SPLINE_BUFFER_SIZE);
|
||||
|
||||
delete tessDataTransfer;
|
||||
delete tessDataTransferGLES;
|
||||
}
|
||||
|
||||
void DrawEngineGLES::DeviceLost() {
|
||||
|
@ -656,7 +656,7 @@ bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const {
|
|||
return decJitCache_->IsInSpace(ptr);
|
||||
}
|
||||
|
||||
void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
|
||||
void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
|
||||
bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
|
||||
bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0;
|
||||
int sizeColor = hasColor ? size : 1;
|
||||
|
@ -703,7 +703,7 @@ void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const Simple
|
|||
|
||||
}
|
||||
|
||||
void DrawEngineGLES::TessellationDataTransferGLES::EndFrame() {
|
||||
void TessellationDataTransferGLES::EndFrame() {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (data_tex[i]) {
|
||||
renderManager_->DeleteTexture(data_tex[i]);
|
||||
|
|
|
@ -110,6 +110,21 @@ public:
|
|||
u8 flags;
|
||||
};
|
||||
|
||||
class TessellationDataTransferGLES : public TessellationDataTransfer {
|
||||
private:
|
||||
GLRTexture *data_tex[3]{};
|
||||
GLRenderManager *renderManager_;
|
||||
public:
|
||||
TessellationDataTransferGLES(GLRenderManager *renderManager)
|
||||
: renderManager_(renderManager) { }
|
||||
~TessellationDataTransferGLES() {
|
||||
EndFrame();
|
||||
}
|
||||
// Send spline/bezier's control points and weights to vertex shader through floating point texture.
|
||||
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) override;
|
||||
void EndFrame(); // Queues textures for deletion.
|
||||
};
|
||||
|
||||
// Handles transform, lighting and drawing.
|
||||
class DrawEngineGLES : public DrawEngineCommon {
|
||||
public:
|
||||
|
@ -208,18 +223,5 @@ private:
|
|||
int bufferDecimationCounter_ = 0;
|
||||
|
||||
// Hardware tessellation
|
||||
class TessellationDataTransferGLES : public TessellationDataTransfer {
|
||||
private:
|
||||
GLRTexture *data_tex[3]{};
|
||||
GLRenderManager *renderManager_;
|
||||
public:
|
||||
TessellationDataTransferGLES(GLRenderManager *renderManager)
|
||||
: renderManager_(renderManager) { }
|
||||
~TessellationDataTransferGLES() {
|
||||
EndFrame();
|
||||
}
|
||||
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) override;
|
||||
void EndFrame(); // Queues textures for deletion.
|
||||
};
|
||||
TessellationDataTransferGLES *tessDataTransferGLES;
|
||||
};
|
||||
|
|
|
@ -212,7 +212,7 @@ void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) {
|
|||
}
|
||||
|
||||
void DrawEngineVulkan::DestroyDeviceObjects() {
|
||||
delete tessDataTransfer;
|
||||
delete tessDataTransferVulkan;
|
||||
tessDataTransfer = tessDataTransferVulkan = nullptr;
|
||||
|
||||
for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) {
|
||||
|
@ -1014,14 +1014,7 @@ void DrawEngineVulkan::UpdateUBOs(FrameData *frame) {
|
|||
}
|
||||
}
|
||||
|
||||
DrawEngineVulkan::TessellationDataTransferVulkan::TessellationDataTransferVulkan(VulkanContext *vulkan)
|
||||
: TessellationDataTransfer(), vulkan_(vulkan) {
|
||||
}
|
||||
|
||||
DrawEngineVulkan::TessellationDataTransferVulkan::~TessellationDataTransferVulkan() {
|
||||
}
|
||||
|
||||
void DrawEngineVulkan::TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
|
||||
void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
|
||||
// SSBOs that are not simply float1 or float2 need to be padded up to a float4 size. vec3 members
|
||||
// also need to be 16-byte aligned, hence the padding.
|
||||
struct TessData {
|
||||
|
|
|
@ -117,6 +117,20 @@ public:
|
|||
|
||||
class VulkanRenderManager;
|
||||
|
||||
class TessellationDataTransferVulkan : public TessellationDataTransfer {
|
||||
public:
|
||||
TessellationDataTransferVulkan(VulkanContext *vulkan) : vulkan_(vulkan) {}
|
||||
|
||||
void SetPushBuffer(VulkanPushBuffer *push) { push_ = push; }
|
||||
// Send spline/bezier's control points and weights to vertex shader through structured shader buffer.
|
||||
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) override;
|
||||
const VkDescriptorBufferInfo *GetBufferInfo() { return bufInfo_; }
|
||||
private:
|
||||
VulkanContext *vulkan_;
|
||||
VulkanPushBuffer *push_; // Updated each frame.
|
||||
VkDescriptorBufferInfo bufInfo_[3]{};
|
||||
};
|
||||
|
||||
// Handles transform, lighting and drawing.
|
||||
class DrawEngineVulkan : public DrawEngineCommon {
|
||||
public:
|
||||
|
@ -278,19 +292,5 @@ private:
|
|||
int tessOffset_ = 0;
|
||||
|
||||
// Hardware tessellation
|
||||
class TessellationDataTransferVulkan : public TessellationDataTransfer {
|
||||
public:
|
||||
TessellationDataTransferVulkan(VulkanContext *vulkan);
|
||||
~TessellationDataTransferVulkan();
|
||||
|
||||
void SetPushBuffer(VulkanPushBuffer *push) { push_ = push; }
|
||||
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) override;
|
||||
const VkDescriptorBufferInfo *GetBufferInfo() { return bufInfo_; }
|
||||
private:
|
||||
VulkanContext *vulkan_;
|
||||
VulkanPushBuffer *push_; // Updated each frame.
|
||||
|
||||
VkDescriptorBufferInfo bufInfo_[3] = {};
|
||||
};
|
||||
TessellationDataTransferVulkan *tessDataTransferVulkan;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue