diff --git a/Common/GPU/ShaderWriter.h b/Common/GPU/ShaderWriter.h index 7ffcaaef99..4dd3414fb6 100644 --- a/Common/GPU/ShaderWriter.h +++ b/Common/GPU/ShaderWriter.h @@ -57,10 +57,11 @@ public: return *this; } // W: Writes a zero-terminated string to the stream. - ShaderWriter &W(const char *text) { - size_t len = strlen(text); - memcpy(p_, text, len + 1); + ShaderWriter &W(std::string_view text) { + size_t len = text.size(); + memcpy(p_, text.data(), len); p_ += len; + *p_ = '\0'; return *this; } diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index e4e101f1d7..96c4428939 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -101,7 +101,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu } ShaderWriter p(buffer, compat, ShaderStage::Fragment, extensions, flags); - p.F("// %s\n", FragmentShaderDesc(id).c_str()); + p.C("// %").W(id.Description()).endl(); p.ApplySamplerMetadata(arrayTexture ? samplersStereo : samplersMono); diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index 2fcfd03c66..b851a00240 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -19,56 +19,56 @@ std::string ShaderID::ToDebugString() const { return StringFromFormat("%08x:%08x", d >> 32, d & 0xFFFFFFFF); } -std::string VertexShaderDesc(const VShaderID &id) { +std::string VShaderID::Description() const { char buffer[512]; StringWriter desc(buffer, sizeof(buffer)); - desc.W(id.ToDebugString()).C(" "); - if (id.Bit(VS_BIT_IS_THROUGH)) desc.C("THR "); - if (id.Bit(VS_BIT_USE_HW_TRANSFORM)) desc.C("HWX "); else desc.C("SWX "); - if (id.Bit(VS_BIT_HAS_NORMAL)) desc.C("N "); - if (id.Bit(VS_BIT_HAS_TEXCOORD)) desc.C("T "); - if (id.Bit(VS_BIT_HAS_COLOR)) desc.C("C "); - if (id.Bit(VS_BIT_LMODE)) desc.C("LM "); - if (id.Bit(VS_BIT_NORM_REVERSE)) desc.C("RevN "); - if (id.Bit(VS_BIT_FLATSHADE)) desc.C("Flat "); - if (id.Bits(VS_BIT_MATERIAL_UPDATE, 3)) desc.C("MatUp:").F("%d", id.Bits(VS_BIT_MATERIAL_UPDATE, 3)).C(" "); + desc.W(ToDebugString()).C(" "); + if (Bit(VS_BIT_IS_THROUGH)) desc.C("THR "); + if (Bit(VS_BIT_USE_HW_TRANSFORM)) desc.C("HWX "); else desc.C("SWX "); + if (Bit(VS_BIT_HAS_NORMAL)) desc.C("N "); + if (Bit(VS_BIT_HAS_TEXCOORD)) desc.C("T "); + if (Bit(VS_BIT_HAS_COLOR)) desc.C("C "); + if (Bit(VS_BIT_LMODE)) desc.C("LM "); + if (Bit(VS_BIT_NORM_REVERSE)) desc.C("RevN "); + if (Bit(VS_BIT_FLATSHADE)) desc.C("Flat "); + if (Bits(VS_BIT_MATERIAL_UPDATE, 3)) desc.C("MatUp:").F("%d", Bits(VS_BIT_MATERIAL_UPDATE, 3)).C(" "); - int uvgMode = id.Bits(VS_BIT_UVGEN_MODE, 2); + int uvgMode = Bits(VS_BIT_UVGEN_MODE, 2); static constexpr std::string_view uvgModes[4] = {"UV ", "UVMtx ", "UVEnv ", "UVUnk "}; if (uvgMode) desc.W(uvgModes[uvgMode]); if (uvgMode == GE_TEXMAP_TEXTURE_MATRIX) { - int uvprojMode = id.Bits(VS_BIT_UVPROJ_MODE, 2); + int uvprojMode = Bits(VS_BIT_UVPROJ_MODE, 2); static constexpr std::string_view uvprojModes[4] = { "TexProjPos ", "TexProjUV ", "TexProjNNrm ", "TexProjNrm " }; desc.W(uvprojModes[uvprojMode]); } - if (id.Bit(VS_BIT_ENABLE_BONES)) desc.F("Bones:%d ", id.Bits(VS_BIT_BONES, 3) + 1); - if (id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2)) desc.F("WScale:%d ", id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2)); + if (Bit(VS_BIT_ENABLE_BONES)) desc.F("Bones:%d ", Bits(VS_BIT_BONES, 3) + 1); + if (Bits(VS_BIT_WEIGHT_FMTSCALE, 2)) desc.F("WScale:%d ", Bits(VS_BIT_WEIGHT_FMTSCALE, 2)); - int ls0 = id.Bits(VS_BIT_LS0, 2); - int ls1 = id.Bits(VS_BIT_LS1, 2); + int ls0 = Bits(VS_BIT_LS0, 2); + int ls1 = Bits(VS_BIT_LS1, 2); - if (id.Bit(VS_BIT_FS_MINMAX_DISCARD)) desc.C("FSMinMax "); - if (id.Bit(VS_BIT_FS_DEPTH_CLAMP)) desc.C("FSDepthClamp "); + if (Bit(VS_BIT_FS_MINMAX_DISCARD)) desc.C("FSMinMax "); + if (Bit(VS_BIT_FS_DEPTH_CLAMP)) desc.C("FSDepthClamp "); // Lights - if (id.Bit(VS_BIT_LIGHTING_ENABLE)) { + if (Bit(VS_BIT_LIGHTING_ENABLE)) { desc.C("Light: "); } - if (id.Bit(VS_BIT_LIGHT_UBERSHADER)) { + if (Bit(VS_BIT_LIGHT_UBERSHADER)) { desc.C("LightUberShader "); } for (int i = 0; i < 4; i++) { - bool enabled = id.Bit(VS_BIT_LIGHT0_ENABLE + i) && id.Bit(VS_BIT_LIGHTING_ENABLE); + bool enabled = Bit(VS_BIT_LIGHT0_ENABLE + i) && Bit(VS_BIT_LIGHTING_ENABLE); if (enabled || (uvgMode == GE_TEXMAP_ENVIRONMENT_MAP && (ls0 == i || ls1 == i))) { desc.F("%d: ", i); - desc.F("c:%d t:%d ", id.Bits(VS_BIT_LIGHT0_COMP + 4 * i, 2), id.Bits(VS_BIT_LIGHT0_TYPE + 4 * i, 2)); + desc.F("c:%d t:%d ", Bits(VS_BIT_LIGHT0_COMP + 4 * i, 2), Bits(VS_BIT_LIGHT0_TYPE + 4 * i, 2)); } } - if (id.Bit(VS_BIT_SIMPLE_STEREO)) desc.C("SimpleStereo "); - if (id.Bit(VS_BIT_VERTEX_RANGE_CULLING)) desc.C("RangeCull "); + if (Bit(VS_BIT_SIMPLE_STEREO)) desc.C("SimpleStereo "); + if (Bit(VS_BIT_VERTEX_RANGE_CULLING)) desc.C("RangeCull "); return desc.as_string(); } @@ -176,15 +176,15 @@ static bool MatrixNeedsProjection(const float m[12], GETexProjMapMode mode) { return m[2] != 0.0f || m[5] != 0.0f || (m[8] != 0.0f && mode != GE_PROJMAP_UV) || m[11] != 1.0f; } -std::string FragmentShaderDesc(const FShaderID &id) { +std::string FShaderID::Description() const { char buffer[512]; StringWriter desc(buffer, sizeof(buffer)); - desc.W(id.ToDebugString()).C(" "); - if (id.Bit(FS_BIT_CLEARMODE)) desc.C("Clear "); - if (id.Bit(FS_BIT_DO_TEXTURE)) { - desc.W(id.Bit(FS_BIT_3D_TEXTURE) ? "Tex3D" : "Tex"); - switch (id.Bits(FS_BIT_TEXFUNC, 3)) { + desc.W(ToDebugString()).C(" "); + if (Bit(FS_BIT_CLEARMODE)) desc.C("Clear "); + if (Bit(FS_BIT_DO_TEXTURE)) { + desc.W(Bit(FS_BIT_3D_TEXTURE) ? "Tex3D" : "Tex"); + switch (Bits(FS_BIT_TEXFUNC, 3)) { case GE_TEXFUNC_ADD: desc.C("(TFuncAdd) "); break; case GE_TEXFUNC_BLEND: desc.C("(TFuncBlend) "); break; case GE_TEXFUNC_DECAL: desc.C("(TFuncDecal) "); break; @@ -193,41 +193,41 @@ std::string FragmentShaderDesc(const FShaderID &id) { default: desc.C("(TFuncUnk) "); break; } } - if (id.Bit(FS_BIT_LMODE)) desc.C("LM "); - if (id.Bit(FS_BIT_ENABLE_FOG)) desc.C("Fog "); - if (id.Bit(FS_BIT_FLATSHADE)) desc.C("Flat "); - if (id.Bit(FS_BIT_DEPTH_TEST_NEVER)) desc.C("DepthNever "); - if (id.Bit(FS_BIT_COLOR_WRITEMASK)) desc.C("WriteMask "); - if (id.Bit(FS_BIT_SHADER_TEX_CLAMP)) { + if (Bit(FS_BIT_LMODE)) desc.C("LM "); + if (Bit(FS_BIT_ENABLE_FOG)) desc.C("Fog "); + if (Bit(FS_BIT_FLATSHADE)) desc.C("Flat "); + if (Bit(FS_BIT_DEPTH_TEST_NEVER)) desc.C("DepthNever "); + if (Bit(FS_BIT_COLOR_WRITEMASK)) desc.C("WriteMask "); + if (Bit(FS_BIT_SHADER_TEX_CLAMP)) { desc.C("TClamp"); - if (id.Bit(FS_BIT_CLAMP_S)) desc.C("S"); - if (id.Bit(FS_BIT_CLAMP_T)) desc.C("T"); + if (Bit(FS_BIT_CLAMP_S)) desc.C("S"); + if (Bit(FS_BIT_CLAMP_T)) desc.C("T"); desc.C(" "); } - int blendBits = id.Bits(FS_BIT_REPLACE_BLEND, 3); + int blendBits = Bits(FS_BIT_REPLACE_BLEND, 3); if (blendBits) { switch (blendBits) { case ReplaceBlendType::REPLACE_BLEND_BLUE_TO_ALPHA: - desc.C("BlueToAlpha_" "A:").F("%d ", id.Bits(FS_BIT_BLENDFUNC_A, 4)); + desc.C("BlueToAlpha_" "A:").F("%d ", Bits(FS_BIT_BLENDFUNC_A, 4)); break; default: - desc.C("ReplaceBlend_").F("%d ", id.Bits(FS_BIT_REPLACE_BLEND, 3)) - .C("A:").F("%d ", id.Bits(FS_BIT_BLENDFUNC_A, 4)) - .C("_B:").F("%d ", id.Bits(FS_BIT_BLENDFUNC_B, 4)) - .C("_Eq:").F("%d ", id.Bits(FS_BIT_BLENDEQ, 3)); + desc.C("ReplaceBlend_").F("%d ", Bits(FS_BIT_REPLACE_BLEND, 3)) + .C("A:").F("%d ", Bits(FS_BIT_BLENDFUNC_A, 4)) + .C("_B:").F("%d ", Bits(FS_BIT_BLENDFUNC_B, 4)) + .C("_Eq:").F("%d ", Bits(FS_BIT_BLENDEQ, 3)); break; } } - switch (id.Bits(FS_BIT_STENCIL_TO_ALPHA, 2)) { + switch (Bits(FS_BIT_STENCIL_TO_ALPHA, 2)) { case REPLACE_ALPHA_NO: break; case REPLACE_ALPHA_YES: desc.C("StenToAlpha "); break; case REPLACE_ALPHA_DUALSOURCE: desc.C("StenToAlphaDual "); break; default: desc.C("StenToAlphaUnknown "); break; // bad } - if (id.Bits(FS_BIT_STENCIL_TO_ALPHA, 2) != REPLACE_ALPHA_NO) { - switch (id.Bits(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE, 4)) { + if (Bits(FS_BIT_STENCIL_TO_ALPHA, 2) != REPLACE_ALPHA_NO) { + switch (Bits(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE, 4)) { case STENCIL_VALUE_UNIFORM: desc.C("StenUniform "); break; case STENCIL_VALUE_ZERO: desc.C("Sten0 "); break; case STENCIL_VALUE_ONE: desc.C("Sten1 "); break; @@ -239,30 +239,30 @@ std::string FragmentShaderDesc(const FShaderID &id) { case STENCIL_VALUE_DECR_8BIT: desc.C("StenDecr8 "); break; default: desc.C("StenUnknown "); break; } - } else if (id.Bit(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE)) { + } else if (Bit(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE)) { desc.C("StenOff "); } - if (id.Bit(FS_BIT_ALPHA_AGAINST_ZERO)) desc.C("AlphaTest0 ").W(alphaTestFuncs[id.Bits(FS_BIT_ALPHA_TEST_FUNC, 3)]).C(" "); - else if (id.Bit(FS_BIT_ALPHA_TEST)) desc.C("AlphaTest ").W(alphaTestFuncs[id.Bits(FS_BIT_ALPHA_TEST_FUNC, 3)]).C(" "); - if (id.Bit(FS_BIT_COLOR_AGAINST_ZERO)) desc.C("ColorTest0 ").W(alphaTestFuncs[id.Bits(FS_BIT_COLOR_TEST_FUNC, 2)]).C(" "); // first 4 match; - else if (id.Bit(FS_BIT_COLOR_TEST)) desc.C("ColorTest ").W(alphaTestFuncs[id.Bits(FS_BIT_COLOR_TEST_FUNC, 2)]).C(" "); // first 4 match - if (id.Bit(FS_BIT_TEST_DISCARD_TO_ZERO)) desc.C("TestDiscardToZero "); - if (id.Bit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL)) desc.C("StencilDiscardWorkaround "); - int logicMode = id.Bits(FS_BIT_REPLACE_LOGIC_OP, 4); - if ((logicMode != GE_LOGIC_COPY) && !id.Bit(FS_BIT_CLEARMODE)) desc.C("RLogic(").W(logicFuncs[logicMode]).C(")"); - if (id.Bit(FS_BIT_SAMPLE_ARRAY_TEXTURE)) desc.C("TexArray "); - if (id.Bit(FS_BIT_STEREO)) desc.C("Stereo "); - if (id.Bit(FS_BIT_USE_FRAMEBUFFER_FETCH)) desc.C("(fetch)"); - if (id.Bit(FS_BIT_MINMAX_DISCARD)) desc.C("FragMinMaxDiscard "); - if (id.Bit(FS_BIT_DEPTH_CLAMP)) desc.C("FragDepthClamp "); + if (Bit(FS_BIT_ALPHA_AGAINST_ZERO)) desc.C("AlphaTest0 ").W(alphaTestFuncs[Bits(FS_BIT_ALPHA_TEST_FUNC, 3)]).C(" "); + else if (Bit(FS_BIT_ALPHA_TEST)) desc.C("AlphaTest ").W(alphaTestFuncs[Bits(FS_BIT_ALPHA_TEST_FUNC, 3)]).C(" "); + if (Bit(FS_BIT_COLOR_AGAINST_ZERO)) desc.C("ColorTest0 ").W(alphaTestFuncs[Bits(FS_BIT_COLOR_TEST_FUNC, 2)]).C(" "); // first 4 match; + else if (Bit(FS_BIT_COLOR_TEST)) desc.C("ColorTest ").W(alphaTestFuncs[Bits(FS_BIT_COLOR_TEST_FUNC, 2)]).C(" "); // first 4 match + if (Bit(FS_BIT_TEST_DISCARD_TO_ZERO)) desc.C("TestDiscardToZero "); + if (Bit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL)) desc.C("StencilDiscardWorkaround "); + int logicMode = Bits(FS_BIT_REPLACE_LOGIC_OP, 4); + if ((logicMode != GE_LOGIC_COPY) && !Bit(FS_BIT_CLEARMODE)) desc.C("RLogic(").W(logicFuncs[logicMode]).C(")"); + if (Bit(FS_BIT_SAMPLE_ARRAY_TEXTURE)) desc.C("TexArray "); + if (Bit(FS_BIT_STEREO)) desc.C("Stereo "); + if (Bit(FS_BIT_USE_FRAMEBUFFER_FETCH)) desc.C("(fetch)"); + if (Bit(FS_BIT_MINMAX_DISCARD)) desc.C("FragMinMaxDiscard "); + if (Bit(FS_BIT_DEPTH_CLAMP)) desc.C("FragDepthClamp "); - const ShaderDepalMode depalMode = (ShaderDepalMode)id.Bits(FS_BIT_SHADER_DEPAL_MODE, 2); + const ShaderDepalMode depalMode = (ShaderDepalMode)Bits(FS_BIT_SHADER_DEPAL_MODE, 2); switch (depalMode) { case ShaderDepalMode::OFF: break; case ShaderDepalMode::NORMAL: desc.C("Depal("); { - const GEBufferFormat shaderDepalFormat = (GEBufferFormat)id.Bits(FS_BIT_SHADER_DEPAL_FORMAT, 3); + const GEBufferFormat shaderDepalFormat = (GEBufferFormat)Bits(FS_BIT_SHADER_DEPAL_FORMAT, 3); desc.W(GeBufferFormatToString(shaderDepalFormat)).C(") "); break; } diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index 3aab8023a1..a3960acc30 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -205,6 +205,10 @@ struct VShaderID : public ShaderID { void SetBits(VShaderBit bit, int count, int value) { ShaderID::SetBits((int)bit, count, value); } + + // Generates a compact string that describes the shader. Useful in a list to get an overview + // of the current flora of shaders. + std::string Description() const; }; struct FShaderID : public ShaderID { @@ -230,20 +234,21 @@ struct FShaderID : public ShaderID { void SetBits(FShaderBit bit, int count, int value) { ShaderID::SetBits((int)bit, count, value); } + + std::string Description() const; }; +static_assert(sizeof(VShaderID) == sizeof(uint64_t), "VShaderID size mismatch"); +static_assert(sizeof(FShaderID) == sizeof(uint64_t), "FShaderID size mismatch"); + namespace Draw { class Bugs; } void ComputeVertexShaderID(VShaderID *id, u32 vertType, bool useHWTransform, bool weightsAsFloat, bool useSkinInDecode, ClipInfoFlags clipInfoFlags); -// Generates a compact string that describes the shader. Useful in a list to get an overview -// of the current flora of shaders. -std::string VertexShaderDesc(const VShaderID &id); struct ComputedPipelineState; void ComputeFragmentShaderID(FShaderID *id, const ComputedPipelineState &pipelineState, const Draw::Bugs &bugs, ClipInfoFlags clipInfoFlags); -std::string FragmentShaderDesc(const FShaderID &id); // For sanity checking. bool FragmentIdNeedsFramebufferRead(const FShaderID &id); diff --git a/GPU/Common/VertexShaderGenerator.cpp b/GPU/Common/VertexShaderGenerator.cpp index 57cfc0d8ba..8d49aa067a 100644 --- a/GPU/Common/VertexShaderGenerator.cpp +++ b/GPU/Common/VertexShaderGenerator.cpp @@ -169,7 +169,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag ShaderWriter p(buffer, compat, ShaderStage::Vertex, extensions); - p.F("// %s\n", VertexShaderDesc(id).c_str()); + p.C("// %").W(id.Description()).endl(); bool lmode = id.Bit(VS_BIT_LMODE); diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp index 2a80039c1a..f0a5233fc7 100644 --- a/GPU/D3D11/ShaderManagerD3D11.cpp +++ b/GPU/D3D11/ShaderManagerD3D11.cpp @@ -47,7 +47,7 @@ std::string D3D11FragmentShader::GetShaderString(DebugShaderStringType type) con case SHADER_STRING_SOURCE_CODE: return source_; case SHADER_STRING_SHORT_DESC: - return FragmentShaderDesc(id_); + return id_.Description(); default: return "N/A"; } @@ -69,7 +69,7 @@ std::string D3D11VertexShader::GetShaderString(DebugShaderStringType type) const case SHADER_STRING_SOURCE_CODE: return source_; case SHADER_STRING_SHORT_DESC: - return VertexShaderDesc(id_); + return id_.Description(); default: return "N/A"; } diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index d57965ca78..9d2ee2d09e 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -677,7 +677,7 @@ Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) { return nullptr; } _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "FS length error: %d", (int)strlen(codeBuffer_)); - std::string desc = FragmentShaderDesc(FSID); + std::string desc = FSID.Description(); ShaderDescGLES params{ GL_FRAGMENT_SHADER, 0, uniformMask }; return new Shader(render_, codeBuffer_, desc, params); } @@ -695,7 +695,7 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { return nullptr; } _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "VS length error: %d", (int)strlen(codeBuffer_)); - std::string desc = VertexShaderDesc(VSID); + std::string desc = VSID.Description(); ShaderDescGLES params{ GL_VERTEX_SHADER, attrMask, uniformMask }; params.useHWTransform = useHWTransform; return new Shader(render_, codeBuffer_, desc, params); @@ -826,7 +826,7 @@ std::string Shader::GetShaderString(DebugShaderStringType type, ShaderID id) con case SHADER_STRING_SOURCE_CODE: return source_; case SHADER_STRING_SHORT_DESC: - return isFragment_ ? FragmentShaderDesc(FShaderID(id)) : VertexShaderDesc(VShaderID(id)); + return isFragment_ ? FShaderID(id).Description() : VShaderID(id).Description(); default: return "N/A"; } diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 4a4614fa6f..21493fd1de 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -1,12 +1,11 @@ #include #include #include -#include - #include "Common/Profiler/Profiler.h" #include "Common/Log.h" #include "Common/StringUtils.h" +#include "Common/Data/Text/StringWriter.h" #include "Common/GPU/Vulkan/VulkanContext.h" #include "GPU/Vulkan/PipelineManagerVulkan.h" #include "GPU/Vulkan/ShaderManagerVulkan.h" @@ -30,7 +29,7 @@ PipelineManagerVulkan::~PipelineManagerVulkan() { // Block on all pipelines to make sure any background compiles are done. // This is very important to do before we start trying to tear down the shaders - otherwise, we might // be deleting shaders before queued pipeline creations that use them are performed. - pipelines_.Iterate([&](const VulkanPipelineKey &key, VulkanPipeline *value) { + pipelines_.Iterate([](const VulkanPipelineKey &key, VulkanPipeline *value) { if (value->pipeline) { value->pipeline->BlockUntilCompiled(); } @@ -327,7 +326,7 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, std::string tag = "game"; #ifdef _DEBUG - tag = FragmentShaderDesc(fs->GetID()) + " VS " + VertexShaderDesc(vs->GetID()); + tag = fs->GetID().Description() + " VS " + vs->GetID().Description(); #endif VKRGraphicsPipeline *pipeline = renderManager->CreateGraphicsPipeline(desc, pipelineFlags, variantBitmask, sampleCount, cacheLoad, tag.c_str()); @@ -509,64 +508,63 @@ std::string PipelineManagerVulkan::DebugGetObjectString(const std::string &id, D } std::string VulkanPipelineKey::GetRasterStateDesc(bool lineBreaks) const { - std::stringstream str; - str << topologies[raster.topology] << " "; + char temp[512]; + StringWriter str(temp); + str.W(topologies[raster.topology]).C(" "); if (useHWTransform) { - str << "HWX "; + str.C("HWX "); } if (vtxFmtId) { - str << "Vfmt(" << StringFromFormat("%08x", vtxFmtId) << ") "; // TODO: Format nicer. + str.F("Vfmt(%08x) ", vtxFmtId); // TODO: Format nicer. } else { - str << "SWX "; + str.C("SWX "); } - if (lineBreaks) str << std::endl; + if (lineBreaks) str.endl(); if (raster.blendEnable) { - str << "Blend(C:" << blendOps[raster.blendOpColor] << "/" - << blendFactors[raster.srcColor] << ":" << blendFactors[raster.destColor] << " "; + str.W("Blend(C:").W(blendOps[raster.blendOpColor]).W("/").W(blendFactors[raster.srcColor]).W(":").W(blendFactors[raster.destColor]).W(" "); if (raster.blendOpAlpha != VK_BLEND_OP_ADD || raster.srcAlpha != VK_BLEND_FACTOR_ONE || raster.destAlpha != VK_BLEND_FACTOR_ZERO) { - str << "A:" << blendOps[raster.blendOpAlpha] << "/" - << blendFactors[raster.srcColor] << ":" << blendFactors[raster.destColor] << " "; + str.C("A:").W(blendOps[raster.blendOpAlpha]).C("/").W(blendFactors[raster.srcColor]).C(":").W(blendFactors[raster.destColor]).W(" "); } - str << ") "; - if (lineBreaks) str << std::endl; + str.C(") "); + if (lineBreaks) str.endl(); } if (raster.colorWriteMask != 0xF) { - str << "Mask("; + str.C("Mask("); for (int i = 0; i < 4; i++) { if (raster.colorWriteMask & (1 << i)) { - str << "RGBA"[i]; + str.F("%c", "RGBA"[i]); } else { - str << "_"; + str.C("_"); } } - str << ") "; - if (lineBreaks) str << std::endl; + str.C(") "); + if (lineBreaks) str.endl(); } if (raster.depthTestEnable) { - str << "Z("; + str.C("Z("); if (raster.depthWriteEnable) - str << "W, "; + str.C("W, "); if (raster.depthCompareOp) - str << compareOps[raster.depthCompareOp & 7]; - str << ") "; - if (lineBreaks) str << std::endl; + str.W(compareOps[raster.depthCompareOp & 7]); + str.C(") "); + if (lineBreaks) str.endl(); } if (raster.stencilTestEnable) { - str << "Stenc("; - str << compareOps[raster.stencilCompareOp & 7] << " "; - str << stencilOps[raster.stencilPassOp & 7] << "/"; - str << stencilOps[raster.stencilFailOp & 7] << "/"; - str << stencilOps[raster.stencilDepthFailOp & 7]; - str << ") "; - if (lineBreaks) str << std::endl; + str.C("Stenc("); + str.W(compareOps[raster.stencilCompareOp & 7]).C(" "); + str.W(stencilOps[raster.stencilPassOp & 7]).C("/"); + str.W(stencilOps[raster.stencilFailOp & 7]).C("/"); + str.W(stencilOps[raster.stencilDepthFailOp & 7]); + str.C(") "); + if (lineBreaks) str.endl(); } if (raster.logicOpEnable) { - str << "Logic(" << logicOps[raster.logicOp & 15] << ") "; - if (lineBreaks) str << std::endl; + str.C("Logic(").W(logicOps[raster.logicOp & 15]).C(") "); + if (lineBreaks) str.endl(); } - return str.str(); + return str.as_string(); } std::string VulkanPipelineKey::GetDescription(DebugShaderStringType stringType, ShaderManagerVulkan *shaderManager) const { @@ -581,11 +579,11 @@ std::string VulkanPipelineKey::GetDescription(DebugShaderStringType stringType, VkShaderModule fsModule = this->fShader->BlockUntilReady(); VkShaderModule vsModule = this->vShader->BlockUntilReady(); - std::stringstream str; - str << "VS: " << VertexShaderDesc(shaderManager->GetVertexShaderFromModule(vsModule)->GetID()) << std::endl; - str << "FS: " << FragmentShaderDesc(shaderManager->GetFragmentShaderFromModule(fsModule)->GetID()) << std::endl; - str << GetRasterStateDesc(true); - return str.str(); + std::string str; + str += "VS: " + shaderManager->GetVertexShaderFromModule(vsModule)->GetID().Description() + "\n"; + str += "FS: " + shaderManager->GetFragmentShaderFromModule(fsModule)->GetID().Description() + "\n"; + str += GetRasterStateDesc(true); + return str; } default: diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index abf901fc5f..3dd3854790 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -106,7 +106,7 @@ VulkanFragmentShader::VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, : vulkan_(vulkan), id_(id), flags_(flags) { _assert_(!id.is_invalid()); source_ = code; - module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_FRAGMENT_BIT, source_.c_str(), new std::string(FragmentShaderDesc(id))); + module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_FRAGMENT_BIT, source_.c_str(), new std::string(id.Description())); VERBOSE_LOG(Log::G3D, "Compiled fragment shader:\n%s\n", (const char *)code); } @@ -127,7 +127,7 @@ std::string VulkanFragmentShader::GetShaderString(DebugShaderStringType type) co case SHADER_STRING_SOURCE_CODE: return source_; case SHADER_STRING_SHORT_DESC: - return FragmentShaderDesc(id_); + return id_.Description(); default: return "N/A"; } @@ -137,7 +137,7 @@ VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, VShaderID id, Vert : vulkan_(vulkan), useHWTransform_(useHWTransform), flags_(flags), id_(id) { _assert_(!id.is_invalid()); source_ = code; - module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_VERTEX_BIT, source_.c_str(), new std::string(VertexShaderDesc(id))); + module_ = CompileShaderModuleAsync(vulkan, VK_SHADER_STAGE_VERTEX_BIT, source_.c_str(), new std::string(id.Description())); VERBOSE_LOG(Log::G3D, "Compiled vertex shader:\n%s\n", (const char *)code); } @@ -158,7 +158,7 @@ std::string VulkanVertexShader::GetShaderString(DebugShaderStringType type) cons case SHADER_STRING_SOURCE_CODE: return source_; case SHADER_STRING_SHORT_DESC: - return VertexShaderDesc(id_); + return id_.Description(); default: return "N/A"; }