[spline/bezier]Fix GLES texture resolution of HW tess to real 2D to avoid huge width in FF4CC mist dragon morphing.

This commit is contained in:
xebra 2018-09-22 22:06:40 +09:00
parent 89786b943d
commit 41823f8780
11 changed files with 31 additions and 24 deletions

View file

@ -56,7 +56,7 @@ struct SimpleVertex;
class TessellationDataTransfer { class TessellationDataTransfer {
public: public:
void CopyControlPoints(float *pos, float *tex, float *col, int posStride, int texStride, int colStride, const SimpleVertex *const *points, int size, u32 vertType); 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 { class DrawEngineCommon {

View file

@ -462,7 +462,7 @@ static void HardwareTessellation(OutputBuffers &output, const Patch &patch, u32
Weight2D weights(WeightType::weightsCache, key_u, key_v); Weight2D weights(WeightType::weightsCache, key_u, key_v);
weights.size_u = WeightType::CalcSize(patch.tess_u, patch.count_u); weights.size_u = WeightType::CalcSize(patch.tess_u, patch.count_u);
weights.size_v = WeightType::CalcSize(patch.tess_v, patch.count_v); 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. // Generating simple input vertices for the spline-computing vertex shader.
float inv_u = 1.0f / (float)patch.tess_u; float inv_u = 1.0f / (float)patch.tess_u;

View file

@ -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 { struct TessData {
float pos[3]; float pad1; float pos[3]; float pad1;
float uv[2]; float pad2[2]; float uv[2]; float pad2[2];
float color[4]; float color[4];
}; };
int size = size_u * size_v;
if (prevSize < size) { if (prevSize < size) {
prevSize = size; prevSize = size;
if (buf[0]) buf[0]->Release(); if (buf[0]) buf[0]->Release();

View file

@ -112,7 +112,7 @@ public:
TessellationDataTransferD3D11(ID3D11DeviceContext *context, ID3D11Device *device); TessellationDataTransferD3D11(ID3D11DeviceContext *context, ID3D11Device *device);
~TessellationDataTransferD3D11(); ~TessellationDataTransferD3D11();
// Send spline/bezier's control points and weights to vertex shader through structured shader buffer. // 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. // Handles transform, lighting and drawing.

View file

@ -625,7 +625,7 @@ rotateVBO:
GPUDebug::NotifyDraw(); 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 // TODO
} }

View file

@ -101,7 +101,7 @@ class TessellationDataTransferDX9 : public TessellationDataTransfer {
public: public:
TessellationDataTransferDX9() {} TessellationDataTransferDX9() {}
~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. // Handles transform, lighting and drawing.

View file

@ -653,35 +653,36 @@ bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const {
return decJitCache_->IsInSpace(ptr); 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 hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0; bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0;
int size = size_u * size_v;
float *pos = new float[size * 4]; float *pos = new float[size * 4];
float *tex = hasTexCoord ? new float[size * 4] : nullptr; float *tex = hasTexCoord ? new float[size * 4] : nullptr;
float *col = hasColor ? new float[size * 4] : nullptr; float *col = hasColor ? new float[size * 4] : nullptr;
int stride = 4; int stride = 4;
CopyControlPoints(pos, tex, col, stride, stride, stride, points, size, vertType); CopyControlPoints(pos, tex, col, stride, stride, stride, points, size, vertType);
// Removed the 1D texture support, it's unlikely to be relevant for performance. // Removed the 1D texture support, it's unlikely to be relevant for performance.
// Control Points // Control Points
if (prevSize < size) { if (prevSizeU < size_u || prevSizeV < size_v) {
prevSize = size; prevSizeU = size_u;
prevSizeV = size_v;
if (!data_tex[0]) if (!data_tex[0])
data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D); 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_->FinalizeTexture(data_tex[0], 0, false);
} }
renderManager_->BindTexture(TEX_SLOT_SPLINE_POINTS, data_tex[0]); renderManager_->BindTexture(TEX_SLOT_SPLINE_POINTS, data_tex[0]);
// Position // 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 // Texcoord
if (hasTexCoord) 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 // Color
if (hasColor) 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 // Weight U
if (prevSizeWU < weights.size_u) { if (prevSizeWU < weights.size_u) {
@ -713,5 +714,5 @@ void TessellationDataTransferGLES::EndFrame() {
data_tex[i] = nullptr; data_tex[i] = nullptr;
} }
} }
prevSize = prevSizeWU = prevSizeWV = 0; prevSizeU = prevSizeV = prevSizeWU = prevSizeWV = 0;
} }

View file

@ -113,7 +113,8 @@ public:
class TessellationDataTransferGLES : public TessellationDataTransfer { class TessellationDataTransferGLES : public TessellationDataTransfer {
private: private:
GLRTexture *data_tex[3]{}; GLRTexture *data_tex[3]{};
int prevSize = 0, prevSizeWU = 0, prevSizeWV = 0; int prevSizeU = 0, prevSizeV = 0;
int prevSizeWU = 0, prevSizeWV = 0;
GLRenderManager *renderManager_; GLRenderManager *renderManager_;
public: public:
TessellationDataTransferGLES(GLRenderManager *renderManager) TessellationDataTransferGLES(GLRenderManager *renderManager)
@ -122,7 +123,7 @@ public:
EndFrame(); EndFrame();
} }
// Send spline/bezier's control points and weights to vertex shader through floating point texture. // 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. void EndFrame(); // Queues textures for deletion.
}; };

View file

@ -422,15 +422,16 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
WRITE(p, " vec3 _pos[16];\n"); WRITE(p, " vec3 _pos[16];\n");
WRITE(p, " vec2 _tex[16];\n"); WRITE(p, " vec2 _tex[16];\n");
WRITE(p, " vec4 _col[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 i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) { 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, " index_u = (%i + point_pos.x);\n", j);
WRITE(p, " _pos[%i] = %s(u_tess_points, ivec2(index, 0), 0).xyz;\n", i * 4 + j, texelFetch); 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) 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) 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);
} }
} }

View file

@ -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 // 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. // also need to be 16-byte aligned, hence the padding.
struct TessData { struct TessData {
@ -1022,6 +1022,8 @@ void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const
float color[4]; float color[4];
}; };
int size = size_u * size_v;
int ssboAlignment = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minStorageBufferOffsetAlignment; 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); 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); bufInfo_[0].range = size * sizeof(TessData);

View file

@ -123,7 +123,7 @@ public:
void SetPushBuffer(VulkanPushBuffer *push) { push_ = push; } void SetPushBuffer(VulkanPushBuffer *push) { push_ = push; }
// Send spline/bezier's control points and weights to vertex shader through structured shader buffer. // 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_; } const VkDescriptorBufferInfo *GetBufferInfo() { return bufInfo_; }
private: private:
VulkanContext *vulkan_; VulkanContext *vulkan_;