Permalink
Browse files

[spline/bezier]Improve the logic of copying control-points.

  • Loading branch information...
xebra committed Jun 27, 2018
1 parent 485260c commit 966ff32ee75c9376ee9248302a88c61063534c30
@@ -739,3 +739,27 @@ 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) {
bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0;
for (int i = 0; i < size; ++i) {
memcpy(pos, points[i]->pos.AsArray(), 3 * sizeof(float));
pos += posStride;
}
if (hasTexCoord) {
for (int i = 0; i < size; ++i) {
memcpy(tex, points[i]->uv, 2 * sizeof(float));
tex += texStride;
}
}
if (hasColor) {
for (int i = 0; i < size; ++i) {
memcpy(col, Vec4f::FromRGBA(points[i]->color_32).AsArray(), 4 * sizeof(float));
col += colStride;
}
} else {
memcpy(col, Vec4f::FromRGBA(points[0]->color_32).AsArray(), 4 * sizeof(float));
}
}
@@ -50,6 +50,8 @@ inline uint32_t GetVertTypeID(uint32_t vertType, int uvGenMode) {
return (vertType & 0xFFFFFF) | (uvGenMode << 24);
}
struct SimpleVertex;
class DrawEngineCommon {
public:
DrawEngineCommon();
@@ -177,13 +179,9 @@ class DrawEngineCommon {
int prevSizeCol;
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 PrepareBuffers(float *&pos, float *&tex, float *&col, int &posStride, int &texStride, int &colStride, int size, bool hasColor, bool hasTexCoords) {
posStride = 4;
texStride = 4;
colStride = 4;
}
virtual void SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) = 0;
virtual void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType) = 0;
virtual void EndFrame() {}
};
TessellationDataTransfer *tessDataTransfer;
@@ -940,16 +940,7 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
patch.patchFacing = patchFacing;
if (CanUseHardwareTessellation(prim_type)) {
float *pos = (float*)managedBuf.Allocate(sizeof(float) * count_u * count_v * 4); // Size 4 float
float *tex = (float*)managedBuf.Allocate(sizeof(float) * count_u * count_v * 4); // Size 4 float
float *col = (float*)managedBuf.Allocate(sizeof(float) * count_u * count_v * 4); // Size 4 float
const bool hasColor = (origVertType & GE_VTYPE_COL_MASK) != 0;
const bool hasTexCoords = (origVertType & GE_VTYPE_TC_MASK) != 0;
int posStride, texStride, colStride;
tessDataTransfer->PrepareBuffers(pos, tex, col, posStride, texStride, colStride, count_u * count_v, hasColor, hasTexCoords);
CopyControlPoints(points, pos, tex, col, posStride, texStride, colStride, count_u * count_v, hasColor, hasTexCoords);
tessDataTransfer->SendDataToShader(pos, tex, col, count_u * count_v, hasColor, hasTexCoords);
tessDataTransfer->SendDataToShader(points, count_u * count_v, origVertType);
TessellateSplinePatchHardware(dest, quadIndices_, count, patch);
numPatches = (count_u - 3) * (count_v - 3);
} else {
@@ -1033,16 +1024,7 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
int num_patches_u = (count_u - 1) / 3;
int num_patches_v = (count_v - 1) / 3;
if (CanUseHardwareTessellation(prim_type)) {
float *pos = (float*)managedBuf.Allocate(sizeof(float) * count_u * count_v * 4); // Size 4 float
float *tex = (float*)managedBuf.Allocate(sizeof(float) * count_u * count_v * 4); // Size 4 float
float *col = (float*)managedBuf.Allocate(sizeof(float) * count_u * count_v * 4); // Size 4 float
const bool hasColor = (origVertType & GE_VTYPE_COL_MASK) != 0;
const bool hasTexCoords = (origVertType & GE_VTYPE_TC_MASK) != 0;
int posStride, texStride, colStride;
tessDataTransfer->PrepareBuffers(pos, tex, col, posStride, texStride, colStride, count_u * count_v, hasColor, hasTexCoords);
CopyControlPoints(points, pos, tex, col, posStride, texStride, colStride, count_u * count_v, hasColor, hasTexCoords);
tessDataTransfer->SendDataToShader(pos, tex, col, count_u * count_v, hasColor, hasTexCoords);
tessDataTransfer->SendDataToShader(points, count_u * count_v, origVertType);
TessellateBezierPatchHardware(dest, inds, count, tess_u, tess_v, prim_type);
numPatches = num_patches_u * num_patches_v;
} else {
@@ -692,7 +692,7 @@ void DrawEngineD3D11::DoFlush() {
GPUDebug::NotifyDraw();
}
void DrawEngineD3D11::TessellationDataTransferD3D11::PrepareBuffers(float *&pos, float *&tex, float *&col, int &posStride, int &texStride, int &colStride, int size, bool hasColor, bool hasTexCoords) {
void DrawEngineD3D11::TessellationDataTransferD3D11::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType) {
struct TessData {
float pos[3]; float pad1;
float uv[2]; float pad2[2];
@@ -716,14 +716,14 @@ void DrawEngineD3D11::TessellationDataTransferD3D11::PrepareBuffers(float *&pos,
context_->Map(buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
uint8_t *data = (uint8_t *)map.pData;
pos = (float *)(data);
tex = (float *)(data + offsetof(TessData, uv));
col = (float *)(data + offsetof(TessData, color));
posStride = sizeof(TessData) / sizeof(float);
colStride = hasColor ? (sizeof(TessData) / sizeof(float)) : 0;
texStride = sizeof(TessData) / sizeof(float);
}
float *pos = (float *)(data);
float *tex = (float *)(data + offsetof(TessData, uv));
float *col = (float *)(data + offsetof(TessData, color));
int stride = sizeof(TessData) / sizeof(float);
bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0;
CopyControlPoints(pos, tex, col, stride, stride, stride, points, size, vertType);
void DrawEngineD3D11::TessellationDataTransferD3D11::SendDataToShader(const float * pos, const float * tex, const float * col, int size, bool hasColor, bool hasTexCoords) {
context_->Unmap(buf, 0);
}
@@ -221,7 +221,6 @@ class DrawEngineD3D11 : public DrawEngineCommon {
}
}
void PrepareBuffers(float *&pos, float *&tex, float *&col, int &posStride, int &texStride, int &colStride, int size, bool hasColor, bool hasTexCoords) override;
void SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) override;
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType) override;
};
};
@@ -624,8 +624,7 @@ void DrawEngineDX9::DoFlush() {
GPUDebug::NotifyDraw();
}
void DrawEngineDX9::TessellationDataTransferDX9::SendDataToShader(const float * pos, const float * tex, const float * col, int size, bool hasColor, bool hasTexCoords)
{
void DrawEngineDX9::TessellationDataTransferDX9::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType) {
}
} // namespace
@@ -166,7 +166,7 @@ class DrawEngineDX9 : public DrawEngineCommon {
}
~TessellationDataTransferDX9() {
}
void SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) override;
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType) override;
};
};
@@ -655,37 +655,45 @@ bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const {
return decJitCache_->IsInSpace(ptr);
}
void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) {
void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType) {
bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0;
int sizeColor = hasColor ? size : 1;
float *pos = new float[size * 4];
float *tex = nullptr;
if (hasTexCoord)
tex = new float[size * 4];
float *col = new float[sizeColor * 4];
int stride = 4;
CopyControlPoints(pos, tex, col, stride, stride, stride, points, size, vertType);
// Removed the 1D texture support, it's unlikely to be relevant for performance.
// Position
if (data_tex[0])
renderManager_->DeleteTexture(data_tex[0]);
uint8_t *pos_data = new uint8_t[size * sizeof(float) * 4];
memcpy(pos_data, pos, size * sizeof(float) * 4);
data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D);
renderManager_->TextureImage(data_tex[0], 0, size, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, pos_data, GLRAllocType::NEW, false);
renderManager_->TextureImage(data_tex[0], 0, size, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, (u8 *)pos, GLRAllocType::NEW, false);
renderManager_->FinalizeTexture(data_tex[0], 0, false);
renderManager_->BindTexture(TEX_SLOT_SPLINE_POS, data_tex[0]);
// Texcoords
if (hasTexCoords) {
// Texcoord
if (hasTexCoord) {
if (data_tex[1])
renderManager_->DeleteTexture(data_tex[1]);
uint8_t *tex_data = new uint8_t[size * sizeof(float) * 4];
memcpy(tex_data, tex, size * sizeof(float) * 4);
data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D);
renderManager_->TextureImage(data_tex[1], 0, size, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, tex_data, GLRAllocType::NEW, false);
renderManager_->TextureImage(data_tex[1], 0, size, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, (u8 *)tex, GLRAllocType::NEW, false);
renderManager_->FinalizeTexture(data_tex[1], 0, false);
renderManager_->BindTexture(TEX_SLOT_SPLINE_NRM, data_tex[1]);
renderManager_->BindTexture(TEX_SLOT_SPLINE_TEX, data_tex[1]);
}
// Color
if (data_tex[2])
renderManager_->DeleteTexture(data_tex[2]);
data_tex[2] = renderManager_->CreateTexture(GL_TEXTURE_2D);
int sizeColor = hasColor ? size : 1;
uint8_t *col_data = new uint8_t[sizeColor * sizeof(float) * 4];
memcpy(col_data, col, sizeColor * sizeof(float) * 4);
renderManager_->TextureImage(data_tex[2], 0, sizeColor, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, col_data, GLRAllocType::NEW, false);
renderManager_->TextureImage(data_tex[2], 0, sizeColor, 1, GL_RGBA32F, GL_RGBA, GL_FLOAT, (u8 *)col, GLRAllocType::NEW, false);
renderManager_->FinalizeTexture(data_tex[2], 0, false);
renderManager_->BindTexture(TEX_SLOT_SPLINE_COL, data_tex[2]);
}
@@ -47,7 +47,7 @@ enum {
TEX_SLOT_ALPHATEST = 2,
TEX_SLOT_CLUT = 3,
TEX_SLOT_SPLINE_POS = 4,
TEX_SLOT_SPLINE_NRM = 5,
TEX_SLOT_SPLINE_TEX = 5,
TEX_SLOT_SPLINE_COL = 6,
};
@@ -218,7 +218,7 @@ class DrawEngineGLES : public DrawEngineCommon {
~TessellationDataTransferGLES() {
EndFrame();
}
void SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) override;
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType) override;
void EndFrame() override; // Queues textures for deletion.
};
};
@@ -1001,9 +1001,7 @@ DrawEngineVulkan::TessellationDataTransferVulkan::TessellationDataTransferVulkan
DrawEngineVulkan::TessellationDataTransferVulkan::~TessellationDataTransferVulkan() {
}
void DrawEngineVulkan::TessellationDataTransferVulkan::PrepareBuffers(float *&pos, float *&tex, float *&col, int &posStride, int &texStride, int &colStride, int size, bool hasColor, bool hasTexCoords) {
colStride = 4;
void DrawEngineVulkan::TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType) {
// 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 {
@@ -1016,14 +1014,10 @@ void DrawEngineVulkan::TessellationDataTransferVulkan::PrepareBuffers(float *&po
uint8_t *data = (uint8_t *)push_->PushAligned(size * sizeof(TessData), &offset_, &buf_, ssboAlignment);
range_ = size * sizeof(TessData);
pos = (float *)(data);
tex = (float *)(data + offsetof(TessData, uv));
col = (float *)(data + offsetof(TessData, color));
posStride = sizeof(TessData) / sizeof(float);
colStride = hasColor ? (sizeof(TessData) / sizeof(float)) : 0;
texStride = sizeof(TessData) / sizeof(float);
}
float *pos = (float *)(data);
float *tex = (float *)(data + offsetof(TessData, uv));
float *col = (float *)(data + offsetof(TessData, color));
int stride = sizeof(TessData) / sizeof(float);
void DrawEngineVulkan::TessellationDataTransferVulkan::SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) {
// Nothing to do here! The caller will write directly to the pushbuffer through the pointers it got through PrepareBuffers.
CopyControlPoints(pos, tex, col, stride, stride, stride, points, size, vertType);
}
@@ -284,8 +284,7 @@ class DrawEngineVulkan : public DrawEngineCommon {
~TessellationDataTransferVulkan();
void SetPushBuffer(VulkanPushBuffer *push) { push_ = push; }
void SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) override;
void PrepareBuffers(float *&pos, float *&tex, float *&col, int &posStride, int &texStride, int &colStride, int size, bool hasColor, bool hasTexCoords) override;
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType) override;
void GetBufferAndOffset(VkBuffer *buf, VkDeviceSize *offset, VkDeviceSize *range) {
*buf = buf_;

0 comments on commit 966ff32

Please sign in to comment.