Permalink
Browse files

[spline/bezier]Fix GLES texture resolution of HW tess to real 2D to a…

…void huge width in FF4CC mist dragon morphing.
  • Loading branch information...
xebra committed Sep 22, 2018
1 parent 89786b9 commit 41823f8780ce77ffe9fcaf37bf55da2b59682c76
@@ -56,7 +56,7 @@ 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;
virtual void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) = 0;
};
class DrawEngineCommon {
@@ -462,7 +462,7 @@ static void HardwareTessellation(OutputBuffers &output, const Patch &patch, u32
Weight2D weights(WeightType::weightsCache, key_u, key_v);
weights.size_u = WeightType::CalcSize(patch.tess_u, patch.count_u);
weights.size_v = WeightType::CalcSize(patch.tess_v, patch.count_v);
tessDataTransfer->SendDataToShader(points, patch.count_u * patch.count_v, origVertType, weights);
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;
@@ -702,13 +702,15 @@ TessellationDataTransferD3D11::~TessellationDataTransferD3D11() {
}
}
void TessellationDataTransferD3D11::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
void TessellationDataTransferD3D11::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) {
struct TessData {
float pos[3]; float pad1;
float uv[2]; float pad2[2];
float color[4];
};
int size = size_u * size_v;
if (prevSize < size) {
prevSize = size;
if (buf[0]) buf[0]->Release();
@@ -112,7 +112,7 @@ class TessellationDataTransferD3D11 : public TessellationDataTransfer {
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;
void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) override;
};
// Handles transform, lighting and drawing.
@@ -625,7 +625,7 @@ void DrawEngineDX9::DoFlush() {
GPUDebug::NotifyDraw();
}
void TessellationDataTransferDX9::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
void TessellationDataTransferDX9::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) {
// TODO
}
@@ -101,7 +101,7 @@ class TessellationDataTransferDX9 : public TessellationDataTransfer {
public:
TessellationDataTransferDX9() {}
~TessellationDataTransferDX9() {}
void SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) override;
void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) override;
};
// Handles transform, lighting and drawing.
@@ -653,35 +653,36 @@ bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const {
return decJitCache_->IsInSpace(ptr);
}
void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) {
bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0;
int size = size_u * size_v;
float *pos = new float[size * 4];
float *tex = hasTexCoord ? new float[size * 4] : nullptr;
float *col = hasColor ? new float[size * 4] : nullptr;
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.
// Control Points
if (prevSize < size) {
prevSize = size;
if (prevSizeU < size_u || prevSizeV < size_v) {
prevSizeU = size_u;
prevSizeV = size_v;
if (!data_tex[0])
data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D);
renderManager_->TextureImage(data_tex[0], 0, size, 3, GL_RGBA32F, GL_RGBA, GL_FLOAT, nullptr, GLRAllocType::NONE, false);
renderManager_->TextureImage(data_tex[0], 0, size_u * 3, size_v, GL_RGBA32F, GL_RGBA, GL_FLOAT, nullptr, GLRAllocType::NONE, false);
renderManager_->FinalizeTexture(data_tex[0], 0, false);
}
renderManager_->BindTexture(TEX_SLOT_SPLINE_POINTS, data_tex[0]);
// Position
renderManager_->TextureSubImage(data_tex[0], 0, 0, 0, size, 1, GL_RGBA, GL_FLOAT, (u8 *)pos, GLRAllocType::NEW);
renderManager_->TextureSubImage(data_tex[0], 0, 0, 0, size_u, size_v, GL_RGBA, GL_FLOAT, (u8 *)pos, GLRAllocType::NEW);
// Texcoord
if (hasTexCoord)
renderManager_->TextureSubImage(data_tex[0], 0, 0, 1, size, 1, GL_RGBA, GL_FLOAT, (u8 *)tex, GLRAllocType::NEW);
renderManager_->TextureSubImage(data_tex[0], 0, size_u, 0, size_u, size_v, GL_RGBA, GL_FLOAT, (u8 *)tex, GLRAllocType::NEW);
// Color
if (hasColor)
renderManager_->TextureSubImage(data_tex[0], 0, 0, 2, size, 1, GL_RGBA, GL_FLOAT, (u8 *)col, GLRAllocType::NEW);
renderManager_->TextureSubImage(data_tex[0], 0, size_u * 2, 0, size_u, size_v, GL_RGBA, GL_FLOAT, (u8 *)col, GLRAllocType::NEW);
// Weight U
if (prevSizeWU < weights.size_u) {
@@ -713,5 +714,5 @@ void TessellationDataTransferGLES::EndFrame() {
data_tex[i] = nullptr;
}
}
prevSize = prevSizeWU = prevSizeWV = 0;
prevSizeU = prevSizeV = prevSizeWU = prevSizeWV = 0;
}
@@ -113,7 +113,8 @@ class VertexArrayInfo {
class TessellationDataTransferGLES : public TessellationDataTransfer {
private:
GLRTexture *data_tex[3]{};
int prevSize = 0, prevSizeWU = 0, prevSizeWV = 0;
int prevSizeU = 0, prevSizeV = 0;
int prevSizeWU = 0, prevSizeWV = 0;
GLRenderManager *renderManager_;
public:
TessellationDataTransferGLES(GLRenderManager *renderManager)
@@ -122,7 +123,7 @@ class TessellationDataTransferGLES : public TessellationDataTransfer {
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 SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) override;
void EndFrame(); // Queues textures for deletion.
};
@@ -422,15 +422,16 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
WRITE(p, " vec3 _pos[16];\n");
WRITE(p, " vec2 _tex[16];\n");
WRITE(p, " vec4 _col[16];\n");
WRITE(p, " int index;\n");
WRITE(p, " int index_u, index_v;\n");
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
WRITE(p, " index = (%i + point_pos.y) * u_spline_counts + (%i + point_pos.x);\n", i, j);
WRITE(p, " _pos[%i] = %s(u_tess_points, ivec2(index, 0), 0).xyz;\n", i * 4 + j, texelFetch);
WRITE(p, " index_u = (%i + point_pos.x);\n", j);
WRITE(p, " index_v = (%i + point_pos.y);\n", i);
WRITE(p, " _pos[%i] = %s(u_tess_points, ivec2(index_u, index_v), 0).xyz;\n", i * 4 + j, texelFetch);
if (doTexture && hasTexcoordTess)
WRITE(p, " _tex[%i] = %s(u_tess_points, ivec2(index, 1), 0).xy;\n", i * 4 + j, texelFetch);
WRITE(p, " _tex[%i] = %s(u_tess_points, ivec2(index_u + u_spline_counts, index_v), 0).xy;\n", i * 4 + j, texelFetch);
if (hasColorTess)
WRITE(p, " _col[%i] = %s(u_tess_points, ivec2(index, 2), 0).rgba;\n", i * 4 + j, texelFetch);
WRITE(p, " _col[%i] = %s(u_tess_points, ivec2(index_u + u_spline_counts * 2, index_v), 0).rgba;\n", i * 4 + j, texelFetch);
}
}
@@ -1013,7 +1013,7 @@ void DrawEngineVulkan::UpdateUBOs(FrameData *frame) {
}
}
void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const *points, int size, u32 vertType, const Weight2D &weights) {
void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, 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 {
@@ -1022,6 +1022,8 @@ void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const
float color[4];
};
int size = size_u * size_v;
int ssboAlignment = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minStorageBufferOffsetAlignment;
uint8_t *data = (uint8_t *)push_->PushAligned(size * sizeof(TessData), (uint32_t *)&bufInfo_[0].offset, &bufInfo_[0].buffer, ssboAlignment);
bufInfo_[0].range = size * sizeof(TessData);
@@ -123,7 +123,7 @@ class TessellationDataTransferVulkan : public TessellationDataTransfer {
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;
void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Weight2D &weights) override;
const VkDescriptorBufferInfo *GetBufferInfo() { return bufInfo_; }
private:
VulkanContext *vulkan_;

0 comments on commit 41823f8

Please sign in to comment.