diff --git a/CMakeLists.txt b/CMakeLists.txt index 402a7900f8..b7aac9ca2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2013,8 +2013,6 @@ set(GPU_SOURCES GPU/Common/FragmentShaderGenerator.h GPU/Common/VertexShaderGenerator.cpp GPU/Common/VertexShaderGenerator.h - GPU/Common/GeometryShaderGenerator.cpp - GPU/Common/GeometryShaderGenerator.h GPU/Common/FramebufferManagerCommon.cpp GPU/Common/FramebufferManagerCommon.h GPU/Common/GPUDebugInterface.cpp diff --git a/GPU/Common/GeometryShaderGenerator.cpp b/GPU/Common/GeometryShaderGenerator.cpp deleted file mode 100644 index d09775cf76..0000000000 --- a/GPU/Common/GeometryShaderGenerator.cpp +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright (c) 2012- PPSSPP Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include -#include -#include - -#include "Common/StringUtils.h" -#include "Common/GPU/OpenGL/GLFeatures.h" -#include "Common/GPU/ShaderWriter.h" -#include "Common/GPU/thin3d.h" -#include "Core/Config.h" -#include "GPU/ge_constants.h" -#include "GPU/GPUState.h" -#include "GPU/Common/ShaderId.h" -#include "GPU/Common/ShaderUniforms.h" -#include "GPU/Common/GeometryShaderGenerator.h" - -#undef WRITE - -#define WRITE(p, ...) p.F(__VA_ARGS__) - -// TODO: Could support VK_NV_geometry_shader_passthrough, though the hardware that supports -// it is already pretty fast at geometry shaders.. - - -bool GenerateGeometryShader(const GShaderID &id, char *buffer, const ShaderLanguageDesc &compat, const Draw::Bugs bugs, std::string *errorString) { - std::vector extensions; - if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) { - if (gl_extensions.EXT_gpu_shader4) { - extensions.push_back("#extension GL_EXT_gpu_shader4 : enable"); - } - } - bool vertexRangeCulling = !id.Bit(GS_BIT_CURVE); - bool clipClampedDepth = gstate_c.Use(GPU_USE_DEPTH_CLAMP); - - ShaderWriter p(buffer, compat, ShaderStage::Geometry, extensions); - - p.F("// %s\n", GeometryShaderDesc(id).c_str()); - - p.C("layout(triangles) in;\n"); - if (clipClampedDepth && vertexRangeCulling && !gstate_c.Use(GPU_USE_CLIP_DISTANCE)) { - p.C("layout(triangle_strip, max_vertices = 12) out;\n"); - } else { - p.C("layout(triangle_strip, max_vertices = 6) out;\n"); - } - - if (compat.shaderLanguage == GLSL_VULKAN) { - WRITE(p, "\n"); - WRITE(p, "layout (std140, set = 0, binding = 3) uniform baseVars {\n%s};\n", ub_baseStr); - } else if (compat.shaderLanguage == HLSL_D3D11) { - WRITE(p, "cbuffer base : register(b0) {\n%s};\n", ub_baseStr); - } - - std::vector varyings, outVaryings; - - if (id.Bit(GS_BIT_DO_TEXTURE)) { - varyings.push_back(VaryingDef{ "vec3", "v_texcoord", Draw::SEM_TEXCOORD0, 0, "highp" }); - outVaryings.push_back(VaryingDef{ "vec3", "v_texcoordOut", Draw::SEM_TEXCOORD0, 0, "highp" }); - } - varyings.push_back(VaryingDef{ "vec4", "v_color0", Draw::SEM_COLOR0, 1, "lowp" }); - outVaryings.push_back(VaryingDef{ "vec4", "v_color0Out", Draw::SEM_COLOR0, 1, "lowp" }); - if (id.Bit(GS_BIT_LMODE)) { - varyings.push_back(VaryingDef{ "vec3", "v_color1", Draw::SEM_COLOR1, 2, "lowp" }); - outVaryings.push_back(VaryingDef{ "vec3", "v_color1Out", Draw::SEM_COLOR1, 2, "lowp" }); - } - varyings.push_back(VaryingDef{ "float", "v_fogdepth", Draw::SEM_TEXCOORD1, 3, "highp" }); - outVaryings.push_back(VaryingDef{ "float", "v_fogdepthOut", Draw::SEM_TEXCOORD1, 3, "highp" }); - - p.BeginGSMain(varyings, outVaryings); - - // Apply culling. - if (vertexRangeCulling) { - p.C(" bool anyInside = false;\n"); - } - // And apply manual clipping if necessary. - if (!gstate_c.Use(GPU_USE_CLIP_DISTANCE)) { - p.C(" float clip0[3];\n"); - if (clipClampedDepth) { - p.C(" float clip1[3];\n"); - } - } - - p.C(" for (int i = 0; i < 3; i++) {\n"); // TODO: 3 or gl_in.length()? which will be faster? - p.C(" vec4 outPos = gl_in[i].gl_Position;\n"); - p.C(" vec3 projPos = outPos.xyz / outPos.w;\n"); - - if (vertexRangeCulling) { - p.C(" float projZ = (projPos.z - u_depthRange.z) * u_depthRange.w;\n"); - // Vertex range culling doesn't happen when Z clips, note sign of w is important. - p.C(" if (u_cullRangeMin.w <= 0.0 || projZ * outPos.w > -outPos.w) {\n"); - const char *outMin = "projPos.x < u_cullRangeMin.x || projPos.y < u_cullRangeMin.y"; - const char *outMax = "projPos.x > u_cullRangeMax.x || projPos.y > u_cullRangeMax.y"; - p.F(" if ((%s) || (%s)) {\n", outMin, outMax); - p.C(" return;\n"); // Cull! - p.C(" }\n"); - p.C(" }\n"); - p.C(" if (u_cullRangeMin.w <= 0.0) {\n"); - p.C(" if (projPos.z < u_cullRangeMin.z || projPos.z > u_cullRangeMax.z) {\n"); - // When not clamping depth, cull the triangle of Z is outside the valid range (not based on clip Z.) - p.C(" return;\n"); - p.C(" }\n"); - p.C(" } else {\n"); - p.C(" if (projPos.z >= u_cullRangeMin.z) { anyInside = true; }\n"); - p.C(" if (projPos.z <= u_cullRangeMax.z) { anyInside = true; }\n"); - p.C(" }\n"); - } - - if (!gstate_c.Use(GPU_USE_CLIP_DISTANCE)) { - // This is basically the same value as gl_ClipDistance would take, z + w. - if (vertexRangeCulling) { - // We add a small amount to prevent error as in #15816 (PSP Z is only 16-bit fixed point, anyway.) - p.F(" clip0[i] = projZ * outPos.w + outPos.w + %f;\n", 0.0625 / 65536.0); - } else { - // Let's not complicate the code overly for this case. We'll clipClampedDepth. - p.C(" clip0[i] = 0.0;\n"); - } - - // This one does happen for rectangles. - if (clipClampedDepth) { - if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) { - // On OpenGL/GLES, these values account for the -1 -> 1 range. - p.C(" if (u_depthRange.y - u_depthRange.x >= 1.0) {\n"); - p.C(" clip1[i] = outPos.w + outPos.z;\n"); - } else { - // Everywhere else, it's 0 -> 1, simpler. - p.C(" if (u_depthRange.y >= 1.0) {\n"); - p.C(" clip1[i] = outPos.z;\n"); - } - // This is similar, but for maxz when it's below 65535.0. -1/0 don't matter here. - p.C(" } else if (u_depthRange.x + u_depthRange.y <= 65534.0) {\n"); - p.C(" clip1[i] = outPos.w - outPos.z;\n"); - p.C(" } else {\n"); - p.C(" clip1[i] = 0.0;\n"); - p.C(" }\n"); - } - } - - p.C(" } // for\n"); - - // Cull any triangle fully outside in the same direction when depth clamp enabled. - // Basically simulate cull distances. - if (vertexRangeCulling) { - p.C(" if (u_cullRangeMin.w > 0.0 && !anyInside) {\n"); - p.C(" return;\n"); - p.C(" }\n"); - } - - if (!gstate_c.Use(GPU_USE_CLIP_DISTANCE)) { - // Clipping against one half-space cuts a triangle (17/27), culls (7/27), or creates two triangles (3/27). - // We clip against two, so we can generate up to 4 triangles, a polygon with 6 points. - p.C(" int indices[6];\n"); - p.C(" float factors[6];\n"); - p.C(" int ind = 0;\n"); - - // Pass 1 - clip against first half-space. - p.C(" for (int i = 0; i < 3; i++) {\n"); - // First, use this vertex if it doesn't need clipping. - p.C(" if (clip0[i] >= 0.0) {\n"); - p.C(" indices[ind] = i;\n"); - p.C(" factors[ind] = 0.0;\n"); - p.C(" ind++;\n"); - p.C(" }\n"); - - // Next, we generate an interpolated vertex if signs differ. - p.C(" int inext = i == 2 ? 0 : i + 1;\n"); - p.C(" if (clip0[i] * clip0[inext] < 0.0) {\n"); - p.C(" float t = clip0[i] < 0.0 ? clip0[i] / (clip0[i] - clip0[inext]) : 1.0 - (clip0[inext] / (clip0[inext] - clip0[i]));\n"); - p.C(" indices[ind] = i;\n"); - p.C(" factors[ind] = t;\n"); - p.C(" ind++;\n"); - p.C(" }\n"); - - p.C(" }\n"); - - // Pass 2 - further clip against clamped Z. - if (clipClampedDepth) { - p.C(" int count0 = ind;\n"); - p.C(" int indices1[6];\n"); - p.C(" float factors1[6];\n"); - p.C(" ind = 0;\n"); - - // Let's start by interpolating the clip values. - p.C(" float clip1after[4];\n"); - p.C(" for (int i = 0; i < count0; i++) {\n"); - p.C(" int idx = indices[i];\n"); - p.C(" float factor = factors[i];\n"); - p.C(" int next = idx == 2 ? 0 : idx + 1;\n"); - p.C(" clip1after[i] = mix(clip1[idx], clip1[next], factor);\n"); - p.C(" }\n"); - - // Alright, now time to clip, again. - p.C(" for (int i = 0; i < count0; i++) {\n"); - // First, use this vertex if it doesn't need clipping. - p.C(" if (clip1after[i] >= 0.0) {\n"); - p.C(" indices1[ind] = i;\n"); - p.C(" factors1[ind] = 0.0;\n"); - p.C(" ind++;\n"); - p.C(" }\n"); - - // Next, we generate an interpolated vertex if signs differ. - p.C(" int inext = i == count0 - 1 ? 0 : i + 1;\n"); - p.C(" if (clip1after[i] * clip1after[inext] < 0.0) {\n"); - p.C(" float t = clip1after[i] < 0.0 ? clip1after[i] / (clip1after[i] - clip1after[inext]) : 1.0 - (clip1after[inext] / (clip1after[inext] - clip1after[i]));\n"); - p.C(" indices1[ind] = i;\n"); - p.C(" factors1[ind] = t;\n"); - p.C(" ind++;\n"); - p.C(" }\n"); - - p.C(" }\n"); - } - - p.C(" if (ind < 3) {\n"); - p.C(" return;\n"); - p.C(" }\n"); - - p.C(" int idx;\n"); - p.C(" int next;\n"); - p.C(" float factor;\n"); - - auto emitIndex = [&](const char *which) { - if (clipClampedDepth) { - // We have to interpolate between four vertices. - p.F(" idx = indices1[%s];\n", which); - p.F(" factor = factors1[%s];\n", which); - p.C(" next = idx == count0 - 1 ? 0 : idx + 1;\n"); - p.C(" gl_Position = mix(mix(gl_in[indices[idx]].gl_Position, gl_in[(indices[idx] + 1) % 3].gl_Position, factors[idx]), mix(gl_in[indices[next]].gl_Position, gl_in[(indices[next] + 1) % 3].gl_Position, factors[next]), factor);\n"); - for (size_t i = 0; i < varyings.size(); i++) { - const VaryingDef &in = varyings[i]; - const VaryingDef &out = outVaryings[i]; - p.F(" %s = mix(mix(%s[indices[idx]], %s[(indices[idx] + 1) % 3], factors[idx]), mix(%s[indices[next]], %s[(indices[next] + 1) % 3], factors[next]), factor);\n", out.name, in.name, in.name, in.name, in.name); - } - } else { - p.F(" idx = indices[%s];\n", which); - p.F(" factor = factors[%s];\n", which); - p.C(" next = idx == 2 ? 0 : idx + 1;\n"); - p.C(" gl_Position = mix(gl_in[idx].gl_Position, gl_in[next].gl_Position, factor);\n"); - for (size_t i = 0; i < varyings.size(); i++) { - const VaryingDef &in = varyings[i]; - const VaryingDef &out = outVaryings[i]; - p.F(" %s = mix(%s[idx], %s[next], factor);\n", out.name, in.name, in.name); - } - } - p.C(" EmitVertex();\n"); - }; - - // Alright, time to actually emit the first triangle. - p.C(" for (int i = 0; i < 3; i++) {\n"); - emitIndex("i"); - p.C(" }\n"); - - // Did we end up with additional triangles? We'll do three points each for the rest. - p.C(" for (int i = 3; i < ind; i++) {\n"); - p.C(" EndPrimitive();\n"); - - // Point one, always index zero. - emitIndex("0"); - - // After that, one less than i (basically a triangle fan.) - emitIndex("(i - 1)"); - - // And the new vertex itself. - emitIndex("i"); - - p.C(" }\n"); - } else { - const char *clipSuffix0 = compat.shaderLanguage == HLSL_D3D11 ? ".x" : "[0]"; - const char *clipSuffix1 = compat.shaderLanguage == HLSL_D3D11 ? ".y" : "[1]"; - - p.C(" for (int i = 0; i < 3; i++) {\n"); // TODO: 3 or gl_in.length()? which will be faster? - p.C(" vec4 outPos = gl_in[i].gl_Position;\n"); - p.C(" vec3 projPos = outPos.xyz / outPos.w;\n"); - p.C(" float projZ = (projPos.z - u_depthRange.z) * u_depthRange.w;\n"); - if (clipClampedDepth) { - // Copy the clip distance from the vertex shader. - p.F(" gl_ClipDistance%s = gl_in[i].gl_ClipDistance%s;\n", clipSuffix0, clipSuffix0); - p.F(" gl_ClipDistance%s = projZ * outPos.w + outPos.w;\n", clipSuffix1); - } else { - // We shouldn't need to worry about rectangles-as-triangles here, since we don't use geometry shaders for that. - // We add a small amount to prevent error as in #15816 (PSP Z is only 16-bit fixed point, anyway.) - p.F(" gl_ClipDistance%s = projZ * outPos.w + outPos.w + %f;\n", clipSuffix0, 0.0625 / 65536.0); - } - p.C(" gl_Position = outPos;\n"); - if (gstate_c.Use(GPU_USE_CLIP_DISTANCE)) { - } - - for (size_t i = 0; i < varyings.size(); i++) { - const VaryingDef &in = varyings[i]; - const VaryingDef &out = outVaryings[i]; - p.F(" %s = %s[i];\n", out.name, in.name); - } - // Debug - null the red channel - //p.C(" if (i == 0) v_color0Out.x = 0.0;\n"); - p.C(" EmitVertex();\n"); - p.C(" }\n"); - } - - p.EndGSMain(); - - return true; -} diff --git a/GPU/Common/GeometryShaderGenerator.h b/GPU/Common/GeometryShaderGenerator.h deleted file mode 100644 index 9848ffde18..0000000000 --- a/GPU/Common/GeometryShaderGenerator.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "GPU/Common/ShaderId.h" - -bool GenerateGeometryShader(const GShaderID &id, char *buffer, const ShaderLanguageDesc &compat, const Draw::Bugs bugs, std::string *errorString); diff --git a/GPU/Common/ShaderCommon.h b/GPU/Common/ShaderCommon.h index f2cb2daace..c08d07457d 100644 --- a/GPU/Common/ShaderCommon.h +++ b/GPU/Common/ShaderCommon.h @@ -119,13 +119,13 @@ enum : uint64_t { DIRTY_VIEWPORTSCISSOR_STATE = 1ULL << 50, DIRTY_VERTEXSHADER_STATE = 1ULL << 51, DIRTY_FRAGMENTSHADER_STATE = 1ULL << 52, - DIRTY_GEOMETRYSHADER_STATE = 1ULL << 53, + // Free bit 53, // Note that the top 8 bits (54-63) cannot be dirtied through the commonCommandTable due to packing of other flags. // Everything that's not uniforms. Use this after using thin3d. // TODO: Should we also add DIRTY_FRAMEBUF here? It kinda generally takes care of itself. - DIRTY_ALL_RENDER_STATE = DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS, + DIRTY_ALL_RENDER_STATE = DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS, DIRTY_ALL = 0xFFFFFFFFFFFFFFFF }; diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index 78d3415352..64f6fe0bc9 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -423,51 +423,3 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip *id_out = id; } - -std::string GeometryShaderDesc(const GShaderID &id) { - std::stringstream desc; - desc << StringFromFormat("%08x:%08x ", id.d[1], id.d[0]); - if (id.Bit(GS_BIT_ENABLED)) desc << "ENABLED "; - if (id.Bit(GS_BIT_DO_TEXTURE)) desc << "TEX "; - if (id.Bit(GS_BIT_LMODE)) desc << "LM "; - return desc.str(); -} - -void ComputeGeometryShaderID(GShaderID *id_out, const Draw::Bugs &bugs, int prim) { - GShaderID id; - // Early out. - if (!gstate_c.Use(GPU_USE_GS_CULLING)) { - *id_out = id; - return; - } - - bool isModeThrough = gstate.isModeThrough(); - bool isCurve = gstate_c.submitType != SubmitType::DRAW; - bool isTriangle = prim == GE_PRIM_TRIANGLES || prim == GE_PRIM_TRIANGLE_FAN || prim == GE_PRIM_TRIANGLE_STRIP; - - bool vertexRangeCulling = !isCurve; - bool clipClampedDepth = gstate_c.Use(GPU_USE_DEPTH_CLAMP) && !gstate_c.Use(GPU_USE_CLIP_DISTANCE); - - // Only use this for triangle primitives, and if we actually need it. - if ((!vertexRangeCulling && !clipClampedDepth) || isModeThrough || !isTriangle) { - *id_out = id; - return; - } - - id.SetBit(GS_BIT_ENABLED, true); - // Vertex range culling doesn't seem tno happen for spline/bezier, see #11692. - id.SetBit(GS_BIT_CURVE, isCurve); - - if (gstate.isModeClear()) { - // No attribute bits. - } else { - bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled() && !isModeThrough; - - id.SetBit(GS_BIT_LMODE, lmode); - if (gstate.isTextureMapEnabled()) { - id.SetBit(GS_BIT_DO_TEXTURE); - } - } - - *id_out = id; -} diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index 35f0747558..535058957e 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -109,18 +109,6 @@ static inline FShaderBit operator +(FShaderBit bit, int i) { return FShaderBit((int)bit + i); } -// Some of these bits are straight from FShaderBit, since they essentially enable attributes directly. -enum GShaderBit : uint8_t { - GS_BIT_ENABLED = 0, // If not set, we don't use a geo shader. - GS_BIT_DO_TEXTURE = 1, // presence of texcoords - GS_BIT_LMODE = 2, - GS_BIT_CURVE = 3, // curve, which means don't do range culling. -}; - -static inline GShaderBit operator +(GShaderBit bit, int i) { - return GShaderBit((int)bit + i); -} - struct ShaderID { ShaderID() { clear(); @@ -251,31 +239,6 @@ struct FShaderID : ShaderID { } }; -struct GShaderID : ShaderID { - GShaderID() : ShaderID() { - } - - explicit GShaderID(ShaderID &src) { - memcpy(d, src.d, sizeof(d)); - } - - bool Bit(GShaderBit bit) const { - return ShaderID::Bit((int)bit); - } - - int Bits(GShaderBit bit, int count) const { - return ShaderID::Bits((int)bit, count); - } - - void SetBit(GShaderBit bit, bool value = true) { - ShaderID::SetBit((int)bit, value); - } - - void SetBits(GShaderBit bit, int count, int value) { - ShaderID::SetBits((int)bit, count, value); - } -}; - namespace Draw { class Bugs; } @@ -289,8 +252,5 @@ struct ComputedPipelineState; void ComputeFragmentShaderID(FShaderID *id, const ComputedPipelineState &pipelineState, const Draw::Bugs &bugs); std::string FragmentShaderDesc(const FShaderID &id); -void ComputeGeometryShaderID(GShaderID *id, const Draw::Bugs &bugs, int prim); -std::string GeometryShaderDesc(const GShaderID &id); - // For sanity checking. bool FragmentIdNeedsFramebufferRead(const FShaderID &id); diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 41f1384e4a..4c02d7f78a 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -260,7 +260,6 @@ - @@ -365,7 +364,6 @@ - diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index 585a95dfde..e7e3d17f4a 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -243,9 +243,6 @@ Debugger - - Common - Common @@ -497,9 +494,6 @@ Debugger - - Common - Common diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 63fa7977e4..026ceb8a19 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -280,14 +280,14 @@ protected: void SetDrawType(DrawType type, GEPrimitiveType prim) { if (type != lastDraw_) { // We always flush when drawing splines/beziers so no need to do so here - gstate_c.Dirty(DIRTY_UVSCALEOFFSET | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + gstate_c.Dirty(DIRTY_UVSCALEOFFSET | DIRTY_VERTEXSHADER_STATE); lastDraw_ = type; } // Prim == RECTANGLES can cause CanUseHardwareTransform to flip, so we need to dirty. // Also, culling may be affected so dirty the raster state. if (IsTrianglePrim(prim) != IsTrianglePrim(lastPrim_)) { Flush(); - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE); lastPrim_ = prim; } } diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index b582208024..7c28dd24d6 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -75,8 +75,8 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_FOG2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FOGCOEF }, // These affect the fragment shader so need flushing. - { GE_CMD_CLEARMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE }, - { GE_CMD_TEXTUREMAPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE }, + { GE_CMD_CLEARMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_TEXTUREMAPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE }, { GE_CMD_FOGENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAGMENTSHADER_STATE }, { GE_CMD_TEXMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS | DIRTY_FRAGMENTSHADER_STATE }, { GE_CMD_TEXSHADELS, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, @@ -90,7 +90,7 @@ const CommonCommandTableEntry commonCommandTable[] = { // These change the vertex shader so need flushing. { GE_CMD_REVERSENORMAL, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, - { GE_CMD_LIGHTINGENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE }, + { GE_CMD_LIGHTINGENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE }, { GE_CMD_LIGHTENABLE0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, { GE_CMD_LIGHTENABLE1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, { GE_CMD_LIGHTENABLE2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, @@ -102,7 +102,7 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_MATERIALUPDATE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, // These change all shaders so need flushing. - { GE_CMD_LIGHTMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE }, + { GE_CMD_LIGHTMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE }, { GE_CMD_TEXFILTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, { GE_CMD_TEXWRAP, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS | DIRTY_FRAGMENTSHADER_STATE }, @@ -852,7 +852,7 @@ void GPUCommonHW::Execute_VertexType(u32 op, u32 diff) { if (diff & GE_VTYPE_THROUGH_MASK) { // Switching between through and non-through, we need to invalidate a bunch of stuff. - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE); } } } @@ -873,7 +873,7 @@ void GPUCommonHW::Execute_VertexTypeSkinning(u32 op, u32 diff) { gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); } if (diff & GE_VTYPE_THROUGH_MASK) - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE); } void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { @@ -1338,7 +1338,7 @@ void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) { SetDrawType(DRAW_BEZIER, PatchPrimToPrim(surface.primType)); // We need to dirty UVSCALEOFFSET here because we look at the submit type when setting that uniform. - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_UVSCALEOFFSET); if (drawEngineCommon_->CanUseHardwareTessellation(surface.primType)) { gstate_c.submitType = SubmitType::HW_BEZIER; if (gstate_c.spline_num_points_u != surface.num_points_u) { @@ -1353,7 +1353,7 @@ void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) { gstate_c.UpdateUVScaleOffset(); drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "bezier"); - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_UVSCALEOFFSET); gstate_c.submitType = SubmitType::DRAW; // After drawing, we advance pointers - see SubmitPrim which does the same. @@ -1418,7 +1418,7 @@ void GPUCommonHW::Execute_Spline(u32 op, u32 diff) { SetDrawType(DRAW_SPLINE, PatchPrimToPrim(surface.primType)); // We need to dirty UVSCALEOFFSET here because we look at the submit type when setting that uniform. - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_UVSCALEOFFSET); if (drawEngineCommon_->CanUseHardwareTessellation(surface.primType)) { gstate_c.submitType = SubmitType::HW_SPLINE; if (gstate_c.spline_num_points_u != surface.num_points_u) { @@ -1433,7 +1433,7 @@ void GPUCommonHW::Execute_Spline(u32 op, u32 diff) { gstate_c.UpdateUVScaleOffset(); drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "spline"); - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_UVSCALEOFFSET); gstate_c.submitType = SubmitType::DRAW; // After drawing, we advance pointers - see SubmitPrim which does the same. diff --git a/GPU/GPUState.h b/GPU/GPUState.h index e380140841..145f82d10a 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -484,7 +484,7 @@ enum : u32 { GPU_USE_TEXTURE_LOD_CONTROL = FLAG_BIT(15), GPU_USE_DEPTH_TEXTURE = FLAG_BIT(16), // Free bit: 17 - GPU_USE_GS_CULLING = FLAG_BIT(18), // Geometry shader + // Free bit: 18 GPU_USE_FRAMEBUFFER_ARRAYS = FLAG_BIT(19), GPU_USE_FRAMEBUFFER_FETCH = FLAG_BIT(20), // Free bit: 21, diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 5357a89328..6d4c93e785 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -304,18 +304,17 @@ void DrawEngineVulkan::Flush() { sampler = nullSampler_; } - if (!lastPipeline_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE) || prim != lastPrim_) { + if (!lastPipeline_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE) || prim != lastPrim_) { if (prim != lastPrim_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE)) { ConvertStateToVulkanKey(*framebufferManager_, shaderManager_, prim, pipelineKey_, dynState_); } VulkanVertexShader *vshader = nullptr; VulkanFragmentShader *fshader = nullptr; - VulkanGeometryShader *gshader = nullptr; - shaderManager_->GetShaders(prim, dec_->VertexType(), &vshader, &fshader, &gshader, pipelineState_, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat, applySkinInDecode_); + shaderManager_->GetShaders(prim, dec_->VertexType(), &vshader, &fshader, pipelineState_, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat, applySkinInDecode_); _dbg_assert_msg_(vshader->UseHWTransform(), "Bad vshader"); - VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &dec_->decFmt, vshader, fshader, gshader, true, 0, framebufferManager_->GetMSAALevel(), false); + VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &dec_->decFmt, vshader, fshader, true, 0, framebufferManager_->GetMSAALevel(), false); if (!pipeline || !pipeline->pipeline) { // Already logged, let's bail out. ResetAfterSkippedDraw(); @@ -473,18 +472,17 @@ void DrawEngineVulkan::Flush() { gstate_c.Dirty(DIRTY_BLEND_STATE); } } - if (!lastPipeline_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE) || prim != lastPrim_) { + if (!lastPipeline_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE) || prim != lastPrim_) { if (prim != lastPrim_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE)) { ConvertStateToVulkanKey(*framebufferManager_, shaderManager_, prim, pipelineKey_, dynState_); } VulkanVertexShader *vshader = nullptr; VulkanFragmentShader *fshader = nullptr; - VulkanGeometryShader *gshader = nullptr; - shaderManager_->GetShaders(prim, swDec->VertexType(), &vshader, &fshader, &gshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true); + shaderManager_->GetShaders(prim, swDec->VertexType(), &vshader, &fshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true); _dbg_assert_msg_(!vshader->UseHWTransform(), "Bad vshader"); - VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &swDec->decFmt, vshader, fshader, gshader, false, 0, framebufferManager_->GetMSAALevel(), false); + VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &swDec->decFmt, vshader, fshader, false, 0, framebufferManager_->GetMSAALevel(), false); if (!pipeline || !pipeline->pipeline) { // Already logged, let's bail out. ResetAfterSkippedDraw(); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 3fee7b7017..aaa5871baa 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -218,18 +218,6 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { features |= GPU_USE_VERTEX_TEXTURE_FETCH; features |= GPU_USE_TEXTURE_FLOAT; - // Fall back to geometry shader culling if we can't do vertex range culling. - // Checking accurate depth here because the old depth path is uncommon and not well tested for this. - if (draw_->GetDeviceCaps().geometryShaderSupported) { - const bool useGeometry = g_Config.bUseGeometryShader && !draw_->GetBugs().Has(Draw::Bugs::GEOMETRY_SHADERS_SLOW_OR_BROKEN); - const bool vertexSupported = draw_->GetDeviceCaps().maxClipDistances >= 2 && draw_->GetDeviceCaps().maxCullDistances >= 1; - if (useGeometry && (!vertexSupported || (features & GPU_USE_VS_RANGE_CULLING) == 0)) { - // Switch to culling via the geometry shader if not fully supported in vertex. - features |= GPU_USE_GS_CULLING; - features &= ~GPU_USE_VS_RANGE_CULLING; - } - } - if (!draw_->GetBugs().Has(Draw::Bugs::PVR_BAD_16BIT_TEXFORMATS)) { // These are VULKAN_4444_FORMAT and friends. // Note that we are now using the correct set of formats - the only cases where some may be missing @@ -247,12 +235,6 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { if (g_Config.bStereoRendering && draw_->GetDeviceCaps().multiViewSupported) { features |= GPU_USE_SINGLE_PASS_STEREO; features |= GPU_USE_SIMPLE_STEREO_PERSPECTIVE; - - if (features & GPU_USE_GS_CULLING) { - // Many devices that support stereo and GS don't support GS during stereo. - features &= ~GPU_USE_GS_CULLING; - features |= GPU_USE_VS_RANGE_CULLING; - } } // Attempt to workaround #17386 diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index cb44051fdb..5b81420858 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -186,7 +186,7 @@ static std::string CutFromMain(const std::string &str) { static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, VkPipelineCache pipelineCache, VKRPipelineLayout *layout, PipelineFlags pipelineFlags, VkSampleCountFlagBits sampleCount, const VulkanPipelineRasterStateKey &key, - const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, VulkanGeometryShader *gs, bool useHwTransform, u32 variantBitmask, bool cacheLoad) { + const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform, u32 variantBitmask, bool cacheLoad) { _assert_(fs && vs); if (!fs || !fs->GetModule()) { @@ -197,10 +197,6 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, ERROR_LOG(Log::G3D, "Vertex shader missing in CreateVulkanPipeline"); return nullptr; } - if (gs && !gs->GetModule()) { - ERROR_LOG(Log::G3D, "Geometry shader missing in CreateVulkanPipeline"); - return nullptr; - } VulkanPipeline *vulkanPipeline = new VulkanPipeline(); vulkanPipeline->desc = new VKRGraphicsPipelineDesc(); @@ -209,7 +205,7 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, desc->fragmentShader = fs->GetModule(); desc->vertexShader = vs->GetModule(); - desc->geometryShader = gs ? gs->GetModule() : nullptr; + desc->geometryShader = nullptr; PROFILE_THIS_SCOPE("pipelinebuild"); bool useBlendConstant = false; @@ -290,9 +286,6 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, desc->fragmentShaderSource = fs->GetShaderString(SHADER_STRING_SOURCE_CODE); desc->vertexShaderSource = vs->GetShaderString(SHADER_STRING_SOURCE_CODE); - if (gs) { - desc->geometryShaderSource = gs->GetShaderString(SHADER_STRING_SOURCE_CODE); - } _dbg_assert_(key.topology != VK_PRIMITIVE_TOPOLOGY_POINT_LIST); _dbg_assert_(key.topology != VK_PRIMITIVE_TOPOLOGY_LINE_LIST); @@ -344,9 +337,6 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, if (useBlendConstant) { pipelineFlags |= PipelineFlags::USES_BLEND_CONSTANT; } - if (gs) { - pipelineFlags |= PipelineFlags::USES_GEOMETRY_SHADER; - } if (dss.depthTestEnable || dss.stencilTestEnable) { pipelineFlags |= PipelineFlags::USES_DEPTH_STENCIL; } @@ -354,7 +344,7 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, return vulkanPipeline; } -VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager *renderManager, VKRPipelineLayout *layout, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, VulkanGeometryShader *gs, bool useHwTransform, u32 variantBitmask, int multiSampleLevel, bool cacheLoad) { +VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager *renderManager, VKRPipelineLayout *layout, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform, u32 variantBitmask, int multiSampleLevel, bool cacheLoad) { if (!pipelineCache_) { VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_); @@ -367,7 +357,6 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager * key.useHWTransform = useHwTransform; key.vShader = vs->GetModule(); key.fShader = fs->GetModule(); - key.gShader = gs ? gs->GetModule() : VK_NULL_HANDLE; key.vtxFmtId = useHwTransform ? decFmt->id : 0; VulkanPipeline *pipeline; @@ -390,7 +379,7 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager * pipeline = CreateVulkanPipeline( renderManager, pipelineCache_, layout, pipelineFlags, sampleCount, - rasterKey, decFmt, vs, fs, gs, useHwTransform, variantBitmask, cacheLoad); + rasterKey, decFmt, vs, fs, useHwTransform, variantBitmask, cacheLoad); // If the above failed, we got a null pipeline. We still insert it to keep track. pipelines_.Insert(key, pipeline); @@ -592,14 +581,10 @@ std::string VulkanPipelineKey::GetDescription(DebugShaderStringType stringType, // More detailed description of all the parts of the pipeline. VkShaderModule fsModule = this->fShader->BlockUntilReady(); VkShaderModule vsModule = this->vShader->BlockUntilReady(); - VkShaderModule gsModule = this->gShader ? this->gShader->BlockUntilReady() : VK_NULL_HANDLE; std::stringstream str; str << "VS: " << VertexShaderDesc(shaderManager->GetVertexShaderFromModule(vsModule)->GetID()) << std::endl; str << "FS: " << FragmentShaderDesc(shaderManager->GetFragmentShaderFromModule(fsModule)->GetID()) << std::endl; - if (gsModule) { - str << "GS: " << GeometryShaderDesc(shaderManager->GetGeometryShaderFromModule(gsModule)->GetID()) << std::endl; - } str << GetRasterStateDesc(true); return str.str(); } @@ -622,7 +607,7 @@ struct StoredVulkanPipelineKey { VulkanPipelineRasterStateKey raster; VShaderID vShaderID; FShaderID fShaderID; - GShaderID gShaderID; + FShaderID gShaderID; // keep the file format compatible uint32_t vtxFmtId; uint32_t variants; bool useHWTransform; // TODO: Still needed? @@ -673,13 +658,7 @@ void PipelineManagerVulkan::SavePipelineCache(FILE *file, bool saveRawPipelineCa return; VulkanVertexShader *vshader = shaderManager->GetVertexShaderFromModule(pkey.vShader->BlockUntilReady()); VulkanFragmentShader *fshader = shaderManager->GetFragmentShaderFromModule(pkey.fShader->BlockUntilReady()); - VulkanGeometryShader *gshader = nullptr; - if (pkey.gShader) { - gshader = shaderManager->GetGeometryShaderFromModule(pkey.gShader->BlockUntilReady()); - if (!gshader) - failed = true; - } - if (!vshader || !fshader || failed) { + if (!vshader || !fshader) { failed = true; return; } @@ -689,7 +668,7 @@ void PipelineManagerVulkan::SavePipelineCache(FILE *file, bool saveRawPipelineCa key.useHWTransform = pkey.useHWTransform; key.fShaderID = fshader->GetID(); key.vShaderID = vshader->GetID(); - key.gShaderID = gshader ? gshader->GetID() : GShaderID(); + key.gShaderID = {}; key.variants = value->GetVariantsBitmask(); if (key.useHWTransform) { // NOTE: This is not a vtype, but a decoded vertex format. @@ -804,13 +783,6 @@ bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCa VulkanVertexShader *vs = shaderManager->GetVertexShaderFromID(key.vShaderID); VulkanFragmentShader *fs = shaderManager->GetFragmentShaderFromID(key.fShaderID); - VulkanGeometryShader *gs = shaderManager->GetGeometryShaderFromID(key.gShaderID); - if (!vs || !fs || (!gs && key.gShaderID.Bit(GS_BIT_ENABLED))) { - // We just ignore this one, it'll get created later if needed. - // Probably some useFlags mismatch. - WARN_LOG(Log::G3D, "Failed to find vs or fs in pipeline %d in cache, skipping pipeline", (int)i); - continue; - } // Avoid creating multisampled shaders if it's not enabled, as that results in an invalid combination. // Note that variantsToBuild is NOT directly a RenderPassType! instead, it's a collection of (1 << RenderPassType). @@ -826,7 +798,7 @@ bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCa DecVtxFormat fmt; fmt.InitializeFromID(key.vtxFmtId); VulkanPipeline *pipeline = GetOrCreatePipeline( - rm, layout, key.raster, key.useHWTransform ? &fmt : 0, vs, fs, gs, key.useHWTransform, variantsToBuild, multiSampleLevel, true); + rm, layout, key.raster, key.useHWTransform ? &fmt : 0, vs, fs, key.useHWTransform, variantsToBuild, multiSampleLevel, true); if (!pipeline) { pipelineCreateFailCount += 1; } diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index f96b3d50b4..e7598fe0e9 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -46,7 +46,6 @@ struct VulkanPipelineKey { VKRRenderPass *renderPass; Promise *vShader; Promise *fShader; - Promise *gShader; uint32_t vtxFmtId; bool useHWTransform; @@ -88,7 +87,8 @@ public: ~PipelineManagerVulkan(); // variantMask is only used when loading pipelines from cache. - VulkanPipeline *GetOrCreatePipeline(VulkanRenderManager *renderManager, VKRPipelineLayout *layout, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, VulkanGeometryShader *gs, bool useHwTransform, u32 variantMask, int multiSampleLevel, bool cacheLoad); + VulkanPipeline *GetOrCreatePipeline(VulkanRenderManager *renderManager, VKRPipelineLayout *layout, const VulkanPipelineRasterStateKey &rasterKey, const DecVtxFormat *decFmt, + VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform, u32 variantMask, int multiSampleLevel, bool cacheLoad); int GetNumPipelines() const { return (int)pipelines_.size(); } void Clear(); @@ -97,7 +97,6 @@ public: void DeviceRestore(VulkanContext *vulkan); void InvalidateMSAAPipelines(); - void BlockUntilReady(); std::string DebugGetObjectString(const std::string &id, DebugShaderType type, DebugShaderStringType stringType, ShaderManagerVulkan *shaderManager); std::vector DebugGetObjectIDs(DebugShaderType type) const; diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index fc1da3a430..6ce54d62cc 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -33,7 +33,6 @@ #include "GPU/GPUState.h" #include "GPU/Common/FragmentShaderGenerator.h" #include "GPU/Common/VertexShaderGenerator.h" -#include "GPU/Common/GeometryShaderGenerator.h" #include "GPU/Vulkan/ShaderManagerVulkan.h" #include "GPU/Vulkan/DrawEngineVulkan.h" @@ -167,42 +166,10 @@ std::string VulkanVertexShader::GetShaderString(DebugShaderStringType type) cons } } -VulkanGeometryShader::VulkanGeometryShader(VulkanContext *vulkan, GShaderID id, const char *code) - : vulkan_(vulkan), id_(id) { - _assert_(!id.is_invalid()); - source_ = code; - module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_GEOMETRY_BIT, source_.c_str(), new std::string(GeometryShaderDesc(id).c_str())); - VERBOSE_LOG(Log::G3D, "Compiled geometry shader:\n%s\n", (const char *)code); -} - -VulkanGeometryShader::~VulkanGeometryShader() { - if (module_) { - VkShaderModule shaderModule = module_->BlockUntilReady(); - if (shaderModule) { - vulkan_->Delete().QueueDeleteShaderModule(shaderModule); - } - vulkan_->Delete().QueueCallback([](VulkanContext *vulkan, void *m) { - auto module = (Promise *)m; - delete module; - }, module_); - } -} - -std::string VulkanGeometryShader::GetShaderString(DebugShaderStringType type) const { - switch (type) { - case SHADER_STRING_SOURCE_CODE: - return source_; - case SHADER_STRING_SHORT_DESC: - return GeometryShaderDesc(id_); - default: - return "N/A"; - } -} - static constexpr size_t CODE_BUFFER_SIZE = 32768; ShaderManagerVulkan::ShaderManagerVulkan(Draw::DrawContext *draw) - : ShaderManagerCommon(draw), compat_(GLSL_VULKAN), fsCache_(16), vsCache_(16), gsCache_(16) { + : ShaderManagerCommon(draw), compat_(GLSL_VULKAN), fsCache_(16), vsCache_(16) { codeBuffer_ = new char[CODE_BUFFER_SIZE]; VulkanContext *vulkan = (VulkanContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); uboAlignment_ = vulkan->GetPhysicalDeviceProperties().properties.limits.minUniformBufferOffsetAlignment; @@ -239,36 +206,28 @@ void ShaderManagerVulkan::Clear() { vsCache_.Iterate([&](const VShaderID &key, VulkanVertexShader *shader) { delete shader; }); - gsCache_.Iterate([&](const GShaderID &key, VulkanGeometryShader *shader) { - delete shader; - }); fsCache_.Clear(); vsCache_.Clear(); - gsCache_.Clear(); lastFSID_.set_invalid(); lastVSID_.set_invalid(); - lastGSID_.set_invalid(); lastVShader_ = nullptr; lastFShader_ = nullptr; - lastGShader_ = nullptr; - gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); } void ShaderManagerVulkan::ClearShaders() { Clear(); DirtyLastShader(); - gstate_c.Dirty(DIRTY_ALL_UNIFORMS | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + gstate_c.Dirty(DIRTY_ALL_UNIFORMS | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); } void ShaderManagerVulkan::DirtyLastShader() { // Forget the last shader ID lastFSID_.set_invalid(); lastVSID_.set_invalid(); - lastGSID_.set_invalid(); lastVShader_ = nullptr; lastFShader_ = nullptr; - lastGShader_ = nullptr; - gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); } uint64_t ShaderManagerVulkan::UpdateUniforms(bool useBufferedRendering) { @@ -285,7 +244,7 @@ uint64_t ShaderManagerVulkan::UpdateUniforms(bool useBufferedRendering) { return dirty; } -void ShaderManagerVulkan::GetShaders(int prim, u32 vertexType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, VulkanGeometryShader **gshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode) { +void ShaderManagerVulkan::GetShaders(int prim, u32 vertexType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode) { VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); VShaderID VSID; @@ -346,41 +305,8 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertexType, VulkanVertexShade } *fshader = fs; - GShaderID GSID; - VulkanGeometryShader *gs = nullptr; - if (gstate_c.IsDirty(DIRTY_GEOMETRYSHADER_STATE)) { - gstate_c.Clean(DIRTY_GEOMETRYSHADER_STATE); - ComputeGeometryShaderID(&GSID, draw_->GetBugs(), prim); - if (GSID == lastGSID_) { - // it's ok for this to be null. - gs = lastGShader_; - } else if (GSID.Bit(GS_BIT_ENABLED)) { - if (!gsCache_.Get(GSID, &gs)) { - // Geometry shader not in cache. Let's compile it. - std::string genErrorString; - bool success = GenerateGeometryShader(GSID, codeBuffer_, compat_, draw_->GetBugs(), &genErrorString); - _assert_msg_(success, "GS gen error: %s", genErrorString.c_str()); - _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "GS length error: %d", (int)strlen(codeBuffer_)); - - gs = new VulkanGeometryShader(vulkan, GSID, codeBuffer_); - gsCache_.Insert(GSID, gs); - } - } else { - gs = nullptr; - } - lastGShader_ = gs; - lastGSID_ = GSID; - } else { - GSID = lastGSID_; - gs = lastGShader_; - } - *gshader = gs; - _dbg_assert_(FSID.Bit(FS_BIT_FLATSHADE) == VSID.Bit(VS_BIT_FLATSHADE)); _dbg_assert_(FSID.Bit(FS_BIT_LMODE) == VSID.Bit(VS_BIT_LMODE)); - if (GSID.Bit(GS_BIT_ENABLED)) { - _dbg_assert_(GSID.Bit(GS_BIT_LMODE) == VSID.Bit(VS_BIT_LMODE)); - } _dbg_assert_msg_((*vshader)->UseHWTransform() == useHWTransform, "Bad vshader was computed"); } @@ -403,12 +329,7 @@ std::vector ShaderManagerVulkan::DebugGetShaderIDs(DebugShaderType }); break; case SHADER_TYPE_GEOMETRY: - gsCache_.Iterate([&](const GShaderID &id, VulkanGeometryShader *shader) { - std::string idstr; - id.ToString(&idstr); - ids.push_back(idstr); - }); - break; + return ids; default: break; } @@ -439,12 +360,7 @@ std::string ShaderManagerVulkan::DebugGetShaderString(std::string id, DebugShade } case SHADER_TYPE_GEOMETRY: { - VulkanGeometryShader *gs; - if (gsCache_.Get(GShaderID(shaderId), &gs)) { - return gs ? gs->GetShaderString(stringType) : "null (bad)"; - } else { - return ""; - } + return ""; } default: return "N/A"; @@ -473,17 +389,6 @@ VulkanFragmentShader *ShaderManagerVulkan::GetFragmentShaderFromModule(VkShaderM return fs; } -VulkanGeometryShader *ShaderManagerVulkan::GetGeometryShaderFromModule(VkShaderModule module) { - VulkanGeometryShader *gs = nullptr; - gsCache_.Iterate([&](const GShaderID &id, VulkanGeometryShader *shader) { - Promise *p = shader->GetModule(); - VkShaderModule m = p->BlockUntilReady(); - if (m == module) - gs = shader; - }); - return gs; -} - // Shader cache. // // We simply store the IDs of the shaders used during gameplay. On next startup of @@ -497,7 +402,7 @@ enum class VulkanCacheDetectFlags { }; #define CACHE_HEADER_MAGIC 0xff51f420 -#define CACHE_VERSION 53 +#define CACHE_VERSION 54 struct VulkanCacheHeader { uint32_t magic; @@ -592,29 +497,6 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) { } } - // If it's not enabled, don't create shaders cached from earlier runs - creation will likely fail. - if (gstate_c.Use(GPU_USE_GS_CULLING)) { - for (int i = 0; i < header.numGeometryShaders; i++) { - GShaderID id; - if (fread(&id, sizeof(id), 1, f) != 1) { - ERROR_LOG(Log::G3D, "Vulkan shader cache truncated (in GeometryShaders)"); - return false; - } - std::string genErrorString; - if (!GenerateGeometryShader(id, codeBuffer_, compat_, draw_->GetBugs(), &genErrorString)) { - ERROR_LOG(Log::G3D, "Failed to generate geometry shader during cache load"); - // We just ignore this one and carry on. - failCount++; - continue; - } - _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "GS length error: %d", (int)strlen(codeBuffer_)); - if (!gsCache_.ContainsKey(id)) { - VulkanGeometryShader *gs = new VulkanGeometryShader(vulkan, id, codeBuffer_); - gsCache_.Insert(id, gs); - } - } - } - NOTICE_LOG(Log::G3D, "ShaderCache: Loaded %d vertex, %d fragment shaders and %d geometry shaders (failed %d)", header.numVertexShaders, header.numFragmentShaders, header.numGeometryShaders, failCount); return true; } @@ -627,7 +509,7 @@ void ShaderManagerVulkan::SaveCache(FILE *f, DrawEngineVulkan *drawEngine) { header.detectFlags = 0; header.numVertexShaders = (int)vsCache_.size(); header.numFragmentShaders = (int)fsCache_.size(); - header.numGeometryShaders = (int)gsCache_.size(); + header.numGeometryShaders = 0; bool writeFailed = fwrite(&header, sizeof(header), 1, f) != 1; vsCache_.Iterate([&](const VShaderID &id, VulkanVertexShader *vs) { writeFailed = writeFailed || fwrite(&id, sizeof(id), 1, f) != 1; @@ -635,9 +517,6 @@ void ShaderManagerVulkan::SaveCache(FILE *f, DrawEngineVulkan *drawEngine) { fsCache_.Iterate([&](const FShaderID &id, VulkanFragmentShader *fs) { writeFailed = writeFailed || fwrite(&id, sizeof(id), 1, f) != 1; }); - gsCache_.Iterate([&](const GShaderID &id, VulkanGeometryShader *gs) { - writeFailed = writeFailed || fwrite(&id, sizeof(id), 1, f) != 1; - }); if (writeFailed) { ERROR_LOG(Log::G3D, "Failed to write Vulkan shader cache, disk full?"); } else { diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index f49f2de125..fcbbbb97ab 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -85,26 +85,6 @@ protected: VertexShaderFlags flags_; }; -class VulkanGeometryShader { -public: - VulkanGeometryShader(VulkanContext *vulkan, GShaderID id, const char *code); - ~VulkanGeometryShader(); - - const std::string &source() const { return source_; } - - std::string GetShaderString(DebugShaderStringType type) const; - - Promise *GetModule() const { return module_; } - const GShaderID &GetID() { return id_; } - -protected: - Promise *module_ = nullptr; - - VulkanContext *vulkan_; - std::string source_; - GShaderID id_; -}; - struct Uniforms { // Uniform block scratchpad. These (the relevant ones) are copied to the current pushbuffer at draw time. UB_VS_FS_Base ub_base{}; @@ -120,22 +100,19 @@ public: void DeviceLost() override; void DeviceRestore(Draw::DrawContext *draw) override; - void GetShaders(int prim, u32 vertexType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, VulkanGeometryShader **gshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode); + void GetShaders(int prim, u32 vertexType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode); void ClearShaders() override; void DirtyLastShader() override; int GetNumVertexShaders() const { return (int)vsCache_.size(); } int GetNumFragmentShaders() const { return (int)fsCache_.size(); } - int GetNumGeometryShaders() const { return (int)gsCache_.size(); } // Used for saving/loading the cache. Don't need to be particularly fast. VulkanVertexShader *GetVertexShaderFromID(VShaderID id) { return vsCache_.GetOrNull(id); } VulkanFragmentShader *GetFragmentShaderFromID(FShaderID id) { return fsCache_.GetOrNull(id); } - VulkanGeometryShader *GetGeometryShaderFromID(GShaderID id) { return gsCache_.GetOrNull(id); } VulkanVertexShader *GetVertexShaderFromModule(VkShaderModule module); VulkanFragmentShader *GetFragmentShaderFromModule(VkShaderModule module); - VulkanGeometryShader *GetGeometryShaderFromModule(VkShaderModule module); std::vector DebugGetShaderIDs(DebugShaderType type) override; std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) override; @@ -174,9 +151,6 @@ private: typedef DenseHashMap VSCache; VSCache vsCache_; - typedef DenseHashMap GSCache; - GSCache gsCache_; - char *codeBuffer_; uint64_t uboAlignment_; @@ -185,9 +159,7 @@ private: VulkanFragmentShader *lastFShader_ = nullptr; VulkanVertexShader *lastVShader_ = nullptr; - VulkanGeometryShader *lastGShader_ = nullptr; FShaderID lastFSID_; VShaderID lastVSID_; - GShaderID lastGSID_; }; diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index d94174bc18..8d70015794 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -94,7 +94,6 @@ - @@ -163,7 +162,6 @@ - @@ -239,4 +237,4 @@ - \ No newline at end of file + diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters index 31d14b549f..ac38125fe6 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters @@ -50,7 +50,6 @@ - @@ -132,7 +131,6 @@ - @@ -171,4 +169,4 @@ {49bcf7f6-518a-4ecd-af55-bda3a344efe7} - \ No newline at end of file + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 6c86d25454..aa3fbf51c1 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -560,7 +560,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/GPU/Common/PostShader.cpp \ $(SRC)/GPU/Common/ShaderUniforms.cpp \ $(SRC)/GPU/Common/VertexShaderGenerator.cpp \ - $(SRC)/GPU/Common/GeometryShaderGenerator.cpp \ $(SRC)/GPU/Common/TextureReplacer.cpp \ $(SRC)/GPU/Common/ReplacedTexture.cpp \ $(SRC)/GPU/Debugger/Breakpoints.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 6bdb4effac..226147a92f 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -591,7 +591,6 @@ SOURCES_CXX += \ $(GPUDIR)/Debugger/Stepping.cpp \ $(GPUDIR)/Common/FragmentShaderGenerator.cpp \ $(GPUDIR)/Common/VertexShaderGenerator.cpp \ - $(GPUDIR)/Common/GeometryShaderGenerator.cpp \ $(GPUDIR)/Common/TextureCacheCommon.cpp \ $(GPUDIR)/Common/TextureScalerCommon.cpp \ $(GPUDIR)/Common/SoftwareTransformCommon.cpp \ diff --git a/unittest/TestShaderGenerators.cpp b/unittest/TestShaderGenerators.cpp index ccfc9afaa4..298b762900 100644 --- a/unittest/TestShaderGenerators.cpp +++ b/unittest/TestShaderGenerators.cpp @@ -12,7 +12,6 @@ #include "GPU/Common/FragmentShaderGenerator.h" #include "GPU/Common/VertexShaderGenerator.h" -#include "GPU/Common/GeometryShaderGenerator.h" #include "GPU/Common/ReinterpretFramebuffer.h" #include "GPU/Common/StencilCommon.h" #include "GPU/Common/DepalettizeShaderCommon.h" @@ -90,34 +89,6 @@ bool GenerateVShader(VShaderID id, char *buffer, ShaderLanguage lang, Draw::Bugs } } -bool GenerateGShader(GShaderID id, char *buffer, ShaderLanguage lang, Draw::Bugs bugs, std::string *errorString) { - buffer[0] = '\0'; - - errorString->clear(); - - switch (lang) { - case ShaderLanguage::GLSL_VULKAN: - { - ShaderLanguageDesc compat(ShaderLanguage::GLSL_VULKAN); - return GenerateGeometryShader(id, buffer, compat, bugs, errorString); - } - /* - case ShaderLanguage::GLSL_3xx: - { - ShaderLanguageDesc compat(ShaderLanguage::GLSL_3xx); - return GenerateGeometryShader(id, buffer, compat, bugs, errorString); - } - case ShaderLanguage::HLSL_D3D11: - { - ShaderLanguageDesc compat(ShaderLanguage::HLSL_D3D11); - return GenerateGeometryShader(id, buffer, compat, bugs, errorString); - } - */ - default: - return false; - } -} - static VkShaderStageFlagBits StageToVulkan(ShaderStage stage) { switch (stage) { case ShaderStage::Vertex: return VK_SHADER_STAGE_VERTEX_BIT; @@ -521,77 +492,6 @@ bool TestFragmentShaders() { return true; } - -bool TestGeometryShaders() { - char *buffer[numLanguages]; - - for (int i = 0; i < numLanguages; i++) { - buffer[i] = new char[65536]; - } - GMRng rng; - int successes = 0; - int count = 30; - - Draw::Bugs bugs; - - // Generate a bunch of random fragment shader IDs, try to generate shader source. - // Then compile it and check that it's ok. - for (int i = 0; i < count; i++) { - uint32_t bottom = i << 1; - GShaderID id; - id.d[0] = bottom; - id.d[1] = 0; - - id.SetBit(GS_BIT_ENABLED, true); - - bool generateSuccess[numLanguages]{}; - std::string genErrorString[numLanguages]; - - for (int j = 0; j < numLanguages; j++) { - buffer[j][0] = 0; - generateSuccess[j] = GenerateGShader(id, buffer[j], languages[j], bugs, &genErrorString[j]); - if (!genErrorString[j].empty()) { - printf("%s\n", genErrorString[j].c_str()); - } - // We ignore the contents of the error string here, not even gonna try to compile if it errors. - } - - for (int j = 0; j < numLanguages; j++) { - if (strlen(buffer[j]) >= CODE_BUFFER_SIZE) { - printf("Geometry shader exceeded buffer:\n\n%s\n", LineNumberString(buffer[j]).c_str()); - for (int i = 0; i < numLanguages; i++) { - delete[] buffer[i]; - } - return false; - } - } - - // Now that we have the strings ready for easy comparison (buffer,4 in the watch window), - // let's try to compile them. - for (int j = 0; j < numLanguages; j++) { - if (generateSuccess[j]) { - std::string errorMessage; - if (!TestCompileShader(buffer[j], languages[j], ShaderStage::Geometry, &errorMessage)) { - printf("Error compiling geometry shader:\n\n%s\n\n%s\n", LineNumberString(buffer[j]).c_str(), errorMessage.c_str()); - for (int i = 0; i < numLanguages; i++) { - delete[] buffer[i]; - } - return false; - } - successes++; - } - } - } - - printf("%d/%d geometry shaders generated (it's normal that it's not all, there are invalid bit combos)\n", successes, count * numLanguages); - - for (int i = 0; i < numLanguages; i++) { - delete[] buffer[i]; - } - return true; -} - - bool TestShaderGenerators() { #if PPSSPP_PLATFORM(WINDOWS) LoadD3D11(); @@ -604,10 +504,6 @@ bool TestShaderGenerators() { return false; } - if (!TestGeometryShaders()) { - return false; - } - if (!TestReinterpretShaders()) { return false; }