[spline/bezier]Instanced rendering for B-Spline is very slow when using weak GPU, so disabled it and simplify the shaders.

Add changing the quality of HW tessellation.
This commit is contained in:
xebra 2018-09-22 19:20:30 +09:00
parent d98fa06b5f
commit 89786b943d
13 changed files with 60 additions and 141 deletions

View File

@ -178,6 +178,5 @@ protected:
bool fboTexBound_ = false;
// Hardware tessellation
int numPatches;
TessellationDataTransfer *tessDataTransfer;
};

View File

@ -240,7 +240,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView
}
if (dirtyUniforms & DIRTY_BEZIERSPLINE) {
ub->spline_counts = BytesToUint32(gstate_c.spline_num_patches_u, gstate_c.spline_num_points_u, gstate_c.spline_tess_u, gstate_c.spline_tess_v);
ub->spline_counts = gstate_c.spline_num_points_u;
}
if (dirtyUniforms & DIRTY_DEPAL) {

View File

@ -467,17 +467,29 @@ static void HardwareTessellation(OutputBuffers &output, const Patch &patch, u32
// 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 = output.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;
for (int patch_u = 0; patch_u < patch.num_patches_u; ++patch_u) {
const int start_u = patch.GetTessStart(patch_u);
for (int patch_v = 0; patch_v < patch.num_patches_v; ++patch_v) {
const int start_v = patch.GetTessStart(patch_v);
for (int tile_u = start_u; tile_u <= patch.tess_u; ++tile_u) {
const int index_u = patch.GetIndexU(patch_u, tile_u);
for (int tile_v = start_v; tile_v <= patch.tess_v; ++tile_v) {
const int index_v = patch.GetIndexV(patch_v, tile_v);
SimpleVertex &vert = output.vertices[patch.GetIndex(index_u, index_v, patch_u, patch_v)];
// Index for the weights
vert.pos.x = index_u;
vert.pos.y = index_v;
// For texcoord generation
vert.nrm.x = patch_u + (float)tile_u * inv_u;
vert.nrm.y = patch_v + (float)tile_v * inv_v;
// Patch position
vert.pos.z = patch_u;
vert.nrm.z = patch_v;
}
}
}
}
BuildIndex(output.indices, output.count, patch.tess_u, patch.tess_v, patch.primType);
patch.BuildIndex(output.indices, output.count);
}
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) {
@ -538,13 +550,12 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
patch.num_patches_v = count_v - 3;
patch.primType = prim_type;
patch.patchFacing = patchFacing;
patch.Init(SPLINE_BUFFER_SIZE / vertexSize);
if (CanUseHardwareTessellation(prim_type)) {
HardwareTessellation(output, patch, origVertType, points, tessDataTransfer);
numPatches = patch.num_patches_u * patch.num_patches_v;
} else {
ControlPoints cpoints(points, count_u * count_v, managedBuf);
patch.Init(SPLINE_BUFFER_SIZE / vertexSize);
SoftwareTessellation(output, patch, origVertType, cpoints);
}
@ -630,13 +641,12 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
patch.num_patches_v = (count_v - 1) / 3;
patch.primType = prim_type;
patch.patchFacing = patchFacing;
patch.Init(SPLINE_BUFFER_SIZE / vertexSize);
if (CanUseHardwareTessellation(prim_type)) {
HardwareTessellation(output, patch, origVertType, points, tessDataTransfer);
numPatches = patch.num_patches_u * patch.num_patches_v;
} else {
ControlPoints cpoints(points, count_u * count_v, managedBuf);
patch.Init(SPLINE_BUFFER_SIZE / vertexSize);
SoftwareTessellation(output, patch, origVertType, cpoints);
}

View File

@ -540,10 +540,7 @@ rotateVBO:
memcpy(iptr, decIndex, iSize);
pushInds_->EndPush(context_);
context_->IASetIndexBuffer(pushInds_->Buf(), DXGI_FORMAT_R16_UINT, iOffset);
if (tess)
context_->DrawIndexedInstanced(vertexCount, numPatches, 0, 0, 0);
else
context_->DrawIndexed(vertexCount, 0, 0);
context_->DrawIndexed(vertexCount, 0, 0);
} else {
context_->Draw(vertexCount, 0);
}
@ -552,10 +549,7 @@ rotateVBO:
context_->IASetVertexBuffers(0, 1, &vb_, &stride, &offset);
if (useElements) {
context_->IASetIndexBuffer(ib_, DXGI_FORMAT_R16_UINT, 0);
if (tess)
context_->DrawIndexedInstanced(vertexCount, numPatches, 0, 0, 0);
else
context_->DrawIndexed(vertexCount, 0, 0);
context_->DrawIndexed(vertexCount, 0, 0);
} else {
context_->Draw(vertexCount, 0);
}

View File

@ -311,19 +311,8 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
WRITE(p, "};\n");
WRITE(p, "void tessellate(in VS_IN In, out Tess tess) {\n");
WRITE(p, " int spline_num_patches_u = int(u_spline_counts & 0xff);\n");
WRITE(p, " int spline_num_points_u = int((u_spline_counts >> 8) & 0xff);\n");
WRITE(p, " int2 spline_tess = int2((u_spline_counts >> 16) & 0xFF, (u_spline_counts >> 24) & 0xFF);\n");
// Calculate current patch position and vertex position(index for the weights)
WRITE(p, " int u = In.instanceId %% spline_num_patches_u;\n");
WRITE(p, " int v = In.instanceId / spline_num_patches_u;\n");
WRITE(p, " int2 patch_pos = int2(u, v);\n");
WRITE(p, " int2 vertex_pos = int2(In.position.xy);\n");
if (doSpline) {
WRITE(p, " bool2 isFirstEdge = !bool2(vertex_pos);\n"); // vertex_pos == 0
WRITE(p, " bool2 isNotFirstPatch = bool2(patch_pos);\n"); // patch_pos > 0
WRITE(p, " vertex_pos += patch_pos * spline_tess;\n");
}
WRITE(p, " int2 point_pos = int2(In.position.z, In.normal.z)%s;\n", doBezier ? " * 3" : "");
WRITE(p, " int2 weight_idx = int2(In.position.xy);\n");
// Load 4x4 control points
WRITE(p, " float3 _pos[16];\n");
WRITE(p, " float2 _tex[16];\n");
@ -331,7 +320,7 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
WRITE(p, " int index;\n");
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
WRITE(p, " index = (%i + v%s) * spline_num_points_u + (%i + u%s);\n", i, doBezier ? " * 3" : "", j, doBezier ? " * 3" : "");
WRITE(p, " index = (%i + point_pos.y) * u_spline_counts + (%i + point_pos.x);\n", i, j);
WRITE(p, " _pos[%i] = tess_data[index].pos;\n", i * 4 + j);
if (doTexture && hasTexcoordTess)
WRITE(p, " _tex[%i] = tess_data[index].tex;\n", i * 4 + j);
@ -341,14 +330,8 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
}
// Basis polynomials as weight coefficients
WRITE(p, " float4 basis_u = tess_weights_u[vertex_pos.x].basis;\n");
WRITE(p, " float4 basis_v = tess_weights_v[vertex_pos.y].basis;\n");
if (doSpline) {
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
WRITE(p, " basis_u = float4(basis_u.yzw, 0);\n");
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
WRITE(p, " basis_v = float4(basis_v.yzw, 0);\n");
}
WRITE(p, " float4 basis_u = tess_weights_u[weight_idx.x].basis;\n");
WRITE(p, " float4 basis_v = tess_weights_v[weight_idx.y].basis;\n");
WRITE(p, " float4x4 basis = outerProduct(basis_u, basis_v);\n");
// Tessellate
@ -357,7 +340,7 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
if (hasTexcoordTess)
WRITE(p, " tess.tex = tess_sample(_tex, basis);\n");
else
WRITE(p, " tess.tex = In.normal.xy + float2(patch_pos);\n");
WRITE(p, " tess.tex = In.normal.xy;\n");
}
if (hasColorTess)
WRITE(p, " tess.col = tess_sample(_col, basis);\n");
@ -365,14 +348,8 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
WRITE(p, " tess.col = u_matambientalpha;\n");
if (hasNormalTess) {
// Derivatives as weight coefficients
WRITE(p, " float4 deriv_u = tess_weights_u[vertex_pos.x].deriv;\n");
WRITE(p, " float4 deriv_v = tess_weights_v[vertex_pos.y].deriv;\n");
if (doSpline) {
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
WRITE(p, " deriv_u = float4(deriv_u.yzw, 0);\n");
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
WRITE(p, " deriv_v = float4(deriv_v.yzw, 0);\n");
}
WRITE(p, " float4 deriv_u = tess_weights_u[weight_idx.x].deriv;\n");
WRITE(p, " float4 deriv_v = tess_weights_v[weight_idx.y].deriv;\n");
WRITE(p, " float3 du = tess_sample(_pos, outerProduct(deriv_u, basis_v));\n");
WRITE(p, " float3 dv = tess_sample(_pos, outerProduct(basis_u, deriv_v));\n");

View File

@ -521,10 +521,7 @@ rotateVBO:
indexBufferOffset = (uint32_t)frameData.pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &indexBuffer);
render_->BindIndexBuffer(indexBuffer);
}
if (gstate_c.bezier || gstate_c.spline)
render_->DrawIndexed(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset, numPatches);
else
render_->DrawIndexed(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset);
render_->DrawIndexed(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset);
} else {
render_->Draw(glprim[prim], 0, vertexCount);
}

View File

@ -109,7 +109,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
if (g_Config.bHardwareTessellation) {
// Disable hardware tessellation if device is unsupported.
bool hasTexelFetch = gl_extensions.GLES3 || (!gl_extensions.IsGLES && gl_extensions.VersionGEThan(3, 3, 0)) || gl_extensions.EXT_gpu_shader4;
if (!gstate_c.SupportsAll(GPU_SUPPORTS_INSTANCE_RENDERING | GPU_SUPPORTS_VERTEX_TEXTURE_FETCH | GPU_SUPPORTS_TEXTURE_FLOAT) || !hasTexelFetch) {
if (!gstate_c.SupportsAll(GPU_SUPPORTS_VERTEX_TEXTURE_FETCH | GPU_SUPPORTS_TEXTURE_FLOAT) || !hasTexelFetch) {
// TODO: Check unsupported device name list.(Above gpu features are supported but it has issues with weak gpu, memory, shader compiler etc...)
g_Config.bHardwareTessellation = false;
ERROR_LOG(G3D, "Hardware Tessellation is unsupported, falling back to software tessellation");

View File

@ -162,7 +162,6 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs,
queries.push_back({ &u_tess_points, "u_tess_points" });
queries.push_back({ &u_tess_weights_u, "u_tess_weights_u" });
queries.push_back({ &u_tess_weights_v, "u_tess_weights_v" });
queries.push_back({ &u_spline_tess, "u_spline_tess" });
queries.push_back({ &u_spline_counts, "u_spline_counts" });
queries.push_back({ &u_depal, "u_depal" });
@ -565,13 +564,8 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) {
}
if (dirty & DIRTY_BEZIERSPLINE) {
if (u_spline_tess != -1) {
int tess[] = { gstate_c.spline_tess_u, gstate_c.spline_tess_v };
render_->SetUniformI(&u_spline_tess, 2, tess);
}
if (u_spline_counts != -1) {
int counts[] = { gstate_c.spline_num_patches_u, gstate_c.spline_num_points_u };
render_->SetUniformI(&u_spline_counts, 2, counts);
render_->SetUniformI1(&u_spline_counts, gstate_c.spline_num_points_u);
}
}
}

View File

@ -121,7 +121,6 @@ public:
int u_tess_points; // Control Points
int u_tess_weights_u;
int u_tess_weights_v;
int u_spline_tess;
int u_spline_counts;
};

View File

@ -384,8 +384,7 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
WRITE(p, "uniform sampler2D u_tess_weights_u;\n");
WRITE(p, "uniform sampler2D u_tess_weights_v;\n");
WRITE(p, "uniform ivec2 u_spline_counts;\n");
WRITE(p, "uniform ivec2 u_spline_tess;\n");
WRITE(p, "uniform int u_spline_counts;\n");
for (int i = 2; i <= 4; i++) {
// Define 3 types vec2, vec3, vec4
@ -416,18 +415,9 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
WRITE(p, "};\n");
WRITE(p, "void tessellate(out Tess tess) {\n");
WRITE(p, " int spline_num_patches_u = u_spline_counts[0];\n");
WRITE(p, " int spline_num_points_u = u_spline_counts[1];\n");
// Calculate current patch position and vertex position(index for the weights)
WRITE(p, " int u = gl_InstanceID %% spline_num_patches_u;\n");
WRITE(p, " int v = gl_InstanceID / spline_num_patches_u;\n");
WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n");
WRITE(p, " ivec2 vertex_pos = ivec2(position.xy);\n");
if (doSpline) {
WRITE(p, " bvec2 isFirstEdge = not(bvec2(vertex_pos));\n"); // vertex_pos == 0
WRITE(p, " bvec2 isNotFirstPatch = bvec2(patch_pos);\n"); // patch_pos > 0
WRITE(p, " vertex_pos += patch_pos * u_spline_tess;\n");
}
WRITE(p, " ivec2 point_pos = ivec2(position.z, normal.z)%s;\n", doBezier ? " * 3" : "");
WRITE(p, " ivec2 weight_idx = ivec2(position.xy);\n");
// Load 4x4 control points
WRITE(p, " vec3 _pos[16];\n");
WRITE(p, " vec2 _tex[16];\n");
@ -435,7 +425,7 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
WRITE(p, " int index;\n");
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
WRITE(p, " index = (%i + v%s) * spline_num_points_u + (%i + u%s);\n", i, doBezier ? " * 3" : "", j, doBezier ? " * 3" : "");
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);
if (doTexture && hasTexcoordTess)
WRITE(p, " _tex[%i] = %s(u_tess_points, ivec2(index, 1), 0).xy;\n", i * 4 + j, texelFetch);
@ -445,14 +435,8 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
}
// Basis polynomials as weight coefficients
WRITE(p, " vec4 basis_u = %s(u_tess_weights_u, %s, 0);\n", texelFetch, "ivec2(vertex_pos.x * 2, 0)");
WRITE(p, " vec4 basis_v = %s(u_tess_weights_v, %s, 0);\n", texelFetch, "ivec2(vertex_pos.y * 2, 0)");
if (doSpline) {
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
WRITE(p, " basis_u = vec4(basis_u.yzw, 0);\n");
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
WRITE(p, " basis_v = vec4(basis_v.yzw, 0);\n");
}
WRITE(p, " vec4 basis_u = %s(u_tess_weights_u, %s, 0);\n", texelFetch, "ivec2(weight_idx.x * 2, 0)");
WRITE(p, " vec4 basis_v = %s(u_tess_weights_v, %s, 0);\n", texelFetch, "ivec2(weight_idx.y * 2, 0)");
WRITE(p, " mat4 basis = outerProduct(basis_u, basis_v);\n");
// Tessellate
@ -461,7 +445,7 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
if (hasTexcoordTess)
WRITE(p, " tess.tex = tess_sample(_tex, basis);\n");
else
WRITE(p, " tess.tex = normal.xy + vec2(patch_pos);\n");
WRITE(p, " tess.tex = normal.xy;\n");
}
if (hasColorTess)
WRITE(p, " tess.col = tess_sample(_col, basis);\n");
@ -469,14 +453,8 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
WRITE(p, " tess.col = u_matambientalpha;\n");
if (hasNormalTess) {
// Derivatives as weight coefficients
WRITE(p, " vec4 deriv_u = %s(u_tess_weights_u, %s, 0);\n", texelFetch, "ivec2(vertex_pos.x * 2 + 1, 0)");
WRITE(p, " vec4 deriv_v = %s(u_tess_weights_v, %s, 0);\n", texelFetch, "ivec2(vertex_pos.y * 2 + 1, 0)");
if (doSpline) {
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
WRITE(p, " deriv_u = vec4(deriv_u.yzw, 0);\n");
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
WRITE(p, " deriv_v = vec4(deriv_v.yzw, 0);\n");
}
WRITE(p, " vec4 deriv_u = %s(u_tess_weights_u, %s, 0);\n", texelFetch, "ivec2(weight_idx.x * 2 + 1, 0)");
WRITE(p, " vec4 deriv_v = %s(u_tess_weights_v, %s, 0);\n", texelFetch, "ivec2(weight_idx.y * 2 + 1, 0)");
WRITE(p, " vec3 du = tess_sample(_pos, outerProduct(deriv_u, basis_v));\n");
WRITE(p, " vec3 dv = tess_sample(_pos, outerProduct(basis_u, deriv_v));\n");

View File

@ -845,8 +845,7 @@ void DrawEngineVulkan::DoFlush() {
if (useElements) {
if (!ibuf)
ibOffset = (uint32_t)frame->pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &ibuf);
int numInstances = tess ? numPatches : 1;
renderManager->DrawIndexed(pipelineLayout_, ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, numInstances, VK_INDEX_TYPE_UINT16);
renderManager->DrawIndexed(pipelineLayout_, ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, 1, VK_INDEX_TYPE_UINT16);
} else {
renderManager->Draw(pipelineLayout_, ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, vertexCount);
}

View File

@ -259,19 +259,8 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer) {
WRITE(p, "};\n");
WRITE(p, "void tessellate(out Tess tess) {\n");
WRITE(p, " int spline_num_patches_u = int(base.spline_counts & 0xff);\n");
WRITE(p, " int spline_num_points_u = int((base.spline_counts >> 8) & 0xff);\n");
WRITE(p, " ivec2 spline_tess = ivec2((base.spline_counts >> 16) & 0xff, (base.spline_counts >> 24) & 0xff);\n");
// Calculate current patch position and vertex position(index for the weights)
WRITE(p, " int u = gl_InstanceIndex %% spline_num_patches_u;\n");
WRITE(p, " int v = gl_InstanceIndex / spline_num_patches_u;\n");
WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n");
WRITE(p, " ivec2 vertex_pos = ivec2(position.xy);\n");
if (doSpline) {
WRITE(p, " bvec2 isFirstEdge = not(bvec2(vertex_pos));\n"); // vertex_pos == 0
WRITE(p, " bvec2 isNotFirstPatch = bvec2(patch_pos);\n"); // patch_pos > 0
WRITE(p, " vertex_pos += patch_pos * spline_tess;\n");
}
WRITE(p, " ivec2 point_pos = ivec2(position.z, normal.z)%s;\n", doBezier ? " * 3" : "");
WRITE(p, " ivec2 weight_idx = ivec2(position.xy);\n");
// Load 4x4 control points
WRITE(p, " vec3 _pos[16];\n");
WRITE(p, " vec2 _tex[16];\n");
@ -279,7 +268,7 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer) {
WRITE(p, " int index;\n");
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
WRITE(p, " index = (%i + v%s) * spline_num_points_u + (%i + u%s);\n", i, doBezier ? " * 3" : "", j, doBezier ? " * 3" : "");
WRITE(p, " index = (%i + point_pos.y) * int(base.spline_counts) + (%i + point_pos.x);\n", i, j);
WRITE(p, " _pos[%i] = tess_data.data[index].pos.xyz;\n", i * 4 + j);
if (doTexture && hasTexcoordTess)
WRITE(p, " _tex[%i] = tess_data.data[index].uv.xy;\n", i * 4 + j);
@ -289,14 +278,8 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer) {
}
// Basis polynomials as weight coefficients
WRITE(p, " vec4 basis_u = tess_weights_u.data[vertex_pos.x].basis;\n");
WRITE(p, " vec4 basis_v = tess_weights_v.data[vertex_pos.y].basis;\n");
if (doSpline) {
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
WRITE(p, " basis_u = vec4(basis_u.yzw, 0);\n");
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
WRITE(p, " basis_v = vec4(basis_v.yzw, 0);\n");
}
WRITE(p, " vec4 basis_u = tess_weights_u.data[weight_idx.x].basis;\n");
WRITE(p, " vec4 basis_v = tess_weights_v.data[weight_idx.y].basis;\n");
WRITE(p, " mat4 basis = outerProduct(basis_u, basis_v);\n");
// Tessellate
@ -305,7 +288,7 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer) {
if (hasTexcoordTess)
WRITE(p, " tess.tex = tess_sample(_tex, basis);\n");
else
WRITE(p, " tess.tex = normal.xy + vec2(patch_pos);\n");
WRITE(p, " tess.tex = normal.xy;\n");
}
if (hasColorTess)
WRITE(p, " tess.col = tess_sample(_col, basis);\n");
@ -313,14 +296,8 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer) {
WRITE(p, " tess.col = base.matambientalpha;\n");
if (hasNormalTess) {
// Derivatives as weight coefficients
WRITE(p, " vec4 deriv_u = tess_weights_u.data[vertex_pos.x].deriv;\n");
WRITE(p, " vec4 deriv_v = tess_weights_v.data[vertex_pos.y].deriv;\n");
if (doSpline) {
WRITE(p, " if (isFirstEdge.x && isNotFirstPatch.x)\n");
WRITE(p, " deriv_u = vec4(deriv_u.yzw, 0);\n");
WRITE(p, " if (isFirstEdge.y && isNotFirstPatch.y)\n");
WRITE(p, " deriv_v = vec4(deriv_v.yzw, 0);\n");
}
WRITE(p, " vec4 deriv_u = tess_weights_u.data[weight_idx.x].deriv;\n");
WRITE(p, " vec4 deriv_v = tess_weights_v.data[weight_idx.y].deriv;\n");
WRITE(p, " vec3 du = tess_sample(_pos, outerProduct(deriv_u, basis_v));\n");
WRITE(p, " vec3 dv = tess_sample(_pos, outerProduct(basis_u, deriv_v));\n");

View File

@ -80,7 +80,7 @@ bool GameSettingsScreen::UseVerticalLayout() const {
// This needs before run CheckGPUFeatures()
// TODO: Remove this if fix the issue
bool CheckSupportInstancedTessellationGLES() {
bool CheckSupportShaderTessellationGLES() {
#if PPSSPP_PLATFORM(UWP)
return true;
#else
@ -88,21 +88,17 @@ bool CheckSupportInstancedTessellationGLES() {
int maxVertexTextureImageUnits = gl_extensions.maxVertexTextureUnits;
bool vertexTexture = maxVertexTextureImageUnits >= 3; // At least 3 for hardware tessellation
bool canUseInstanceID = gl_extensions.EXT_draw_instanced || gl_extensions.ARB_draw_instanced;
bool canDefInstanceID = gl_extensions.IsGLES || gl_extensions.EXT_gpu_shader4 || gl_extensions.VersionGEThan(3, 1);
bool instanceRendering = gl_extensions.GLES3 || (canUseInstanceID && canDefInstanceID);
bool textureFloat = gl_extensions.ARB_texture_float || gl_extensions.OES_texture_float;
bool hasTexelFetch = gl_extensions.GLES3 || (!gl_extensions.IsGLES && gl_extensions.VersionGEThan(3, 3, 0)) || gl_extensions.EXT_gpu_shader4;
return instanceRendering && vertexTexture && textureFloat && hasTexelFetch;
return vertexTexture && textureFloat && hasTexelFetch;
#endif
}
bool DoesBackendSupportHWTess() {
switch (GetGPUBackend()) {
case GPUBackend::OPENGL:
return CheckSupportInstancedTessellationGLES();
return CheckSupportShaderTessellationGLES();
case GPUBackend::VULKAN:
case GPUBackend::DIRECT3D11:
return true;
@ -392,11 +388,10 @@ void GameSettingsScreen::CreateViews() {
}
return UI::EVENT_CONTINUE;
});
beziersChoice->SetDisabledPtr(&g_Config.bHardwareTessellation);
CheckBox *tessellationHW = graphicsSettings->Add(new CheckBox(&g_Config.bHardwareTessellation, gr->T("Hardware Tessellation")));
tessellationHW->OnClick.Add([=](EventParams &e) {
settingInfo_->Show(gr->T("HardwareTessellation Tip", "Uses hardware to make curves, always uses a fixed quality"), e.v);
settingInfo_->Show(gr->T("HardwareTessellation Tip", "Uses hardware to make curves"), e.v);
return UI::EVENT_CONTINUE;
});
tessHWEnable_ = DoesBackendSupportHWTess() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;