mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-10-07 10:53:31 +00:00
Vulkan: Basic geoshader code generation.
This commit is contained in:
parent
fbdb278168
commit
cdee10fe86
@ -1562,6 +1562,8 @@ 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
|
||||
|
@ -600,8 +600,6 @@ void VulkanContext::ChooseDevice(int physical_device) {
|
||||
deviceFeatures_.enabled.samplerAnisotropy = deviceFeatures_.available.samplerAnisotropy;
|
||||
deviceFeatures_.enabled.shaderClipDistance = deviceFeatures_.available.shaderClipDistance;
|
||||
deviceFeatures_.enabled.shaderCullDistance = deviceFeatures_.available.shaderCullDistance;
|
||||
// For easy wireframe mode, someday.
|
||||
deviceFeatures_.enabled.fillModeNonSolid = deviceFeatures_.available.fillModeNonSolid;
|
||||
deviceFeatures_.enabled.geometryShader = deviceFeatures_.available.geometryShader;
|
||||
|
||||
GetDeviceLayerExtensionList(nullptr, device_extension_properties_);
|
||||
|
79
GPU/Common/GeometryShaderGenerator.cpp
Normal file
79
GPU/Common/GeometryShaderGenerator.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
// 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 <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <locale.h>
|
||||
|
||||
#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__)
|
||||
|
||||
bool GenerateGeometryShader(const GShaderID &id, char *buffer, const ShaderLanguageDesc &compat, const Draw::Bugs bugs, std::string *errorString) {
|
||||
std::vector<const char*> gl_exts;
|
||||
if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) {
|
||||
if (gl_extensions.EXT_gpu_shader4) {
|
||||
gl_exts.push_back("#extension GL_EXT_gpu_shader4 : enable");
|
||||
}
|
||||
}
|
||||
|
||||
ShaderWriter p(buffer, compat, ShaderStage::Geometry, gl_exts.data(), gl_exts.size());
|
||||
p.C("layout(triangles) in;\n");
|
||||
p.C("layout(triangle_strip, max_vertices = 3) out;\n");
|
||||
|
||||
std::vector<VaryingDef> 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);
|
||||
|
||||
p.C(" for (int i = 0; i < gl_in.length(); i++) {\n");
|
||||
p.C(" gl_Position = gl_in[i].gl_Position;\n"); // copy attributes
|
||||
for (size_t i = 0; i < varyings.size(); i++) {
|
||||
VaryingDef &in = varyings[i];
|
||||
VaryingDef &out = outVaryings[i];
|
||||
p.F(" %s = %s[i];\n", outVaryings[i].name, varyings[i].name);
|
||||
}
|
||||
p.C(" EmitVertex();\n");
|
||||
p.C(" }\n");
|
||||
|
||||
p.EndGSMain();
|
||||
|
||||
return true;
|
||||
}
|
5
GPU/Common/GeometryShaderGenerator.h
Normal file
5
GPU/Common/GeometryShaderGenerator.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "GPU/Common/ShaderId.h"
|
||||
|
||||
bool GenerateGeometryShader(const GShaderID &id, char *buffer, const ShaderLanguageDesc &compat, const Draw::Bugs bugs, std::string *errorString);
|
@ -340,6 +340,7 @@
|
||||
<ClInclude Include="..\ext\xbrz\xbrz.h" />
|
||||
<ClInclude Include="Common\TextureShaderCommon.h" />
|
||||
<ClInclude Include="Common\Draw2D.h" />
|
||||
<ClInclude Include="Common\GeometryShaderGenerator.h" />
|
||||
<ClInclude Include="Common\ReinterpretFramebuffer.h" />
|
||||
<ClInclude Include="Common\DepalettizeShaderCommon.h" />
|
||||
<ClInclude Include="Common\DrawEngineCommon.h" />
|
||||
@ -455,6 +456,7 @@
|
||||
<ClCompile Include="..\ext\xbrz\xbrz.cpp" />
|
||||
<ClCompile Include="Common\TextureShaderCommon.cpp" />
|
||||
<ClCompile Include="Common\Draw2D.cpp" />
|
||||
<ClCompile Include="Common\GeometryShaderGenerator.cpp" />
|
||||
<ClCompile Include="Common\ReinterpretFramebuffer.cpp" />
|
||||
<ClCompile Include="Common\DepalettizeShaderCommon.cpp" />
|
||||
<ClCompile Include="Common\DrawEngineCommon.cpp" />
|
||||
|
@ -261,6 +261,9 @@
|
||||
<ClInclude Include="Debugger\GECommandTable.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\GeometryShaderGenerator.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Math3D.cpp">
|
||||
@ -512,6 +515,9 @@
|
||||
<ClCompile Include="Debugger\GECommandTable.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\GeometryShaderGenerator.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FxCompile Include="..\assets\shaders\tex_4xbrz.csh">
|
||||
|
@ -232,6 +232,14 @@ u32 GPU_Vulkan::CheckGPUFeatures() const {
|
||||
features |= GPU_SUPPORTS_DEPTH_CLAMP;
|
||||
}
|
||||
|
||||
if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) {
|
||||
const bool disabled = PSP_CoreParameter().compat.flags().DisableRangeCulling;
|
||||
// Fall back to geometry shader culling.
|
||||
if (enabledFeatures.geometryShader && !disabled && (features & GPU_SUPPORTS_VS_RANGE_CULLING) == 0) {
|
||||
features |= GPU_SUPPORTS_GS_CULLING;
|
||||
}
|
||||
}
|
||||
|
||||
// These are VULKAN_4444_FORMAT and friends.
|
||||
uint32_t fmt4444 = draw_->GetDataFormatSupport(Draw::DataFormat::B4G4R4A4_UNORM_PACK16);
|
||||
uint32_t fmt1555 = draw_->GetDataFormatSupport(Draw::DataFormat::A1R5G5B5_UNORM_PACK16);
|
||||
|
@ -716,7 +716,7 @@ bool PipelineManagerVulkan::LoadCache(FILE *file, bool loadRawPipelineCache, Sha
|
||||
VulkanVertexShader *vs = shaderManager->GetVertexShaderFromID(key.vShaderID);
|
||||
VulkanFragmentShader *fs = shaderManager->GetFragmentShaderFromID(key.fShaderID);
|
||||
VulkanGeometryShader *gs = shaderManager->GetGeometryShaderFromID(key.gShaderID);
|
||||
if (!vs || !fs) {
|
||||
if (!vs || !fs || (!gs && key.gShaderID.Bit(GS_BIT_ENABLED))) {
|
||||
failed = true;
|
||||
ERROR_LOG(G3D, "Failed to find vs or fs in of pipeline %d in cache", (int)i);
|
||||
continue;
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "GPU/ge_constants.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"
|
||||
#include "GPU/Vulkan/FramebufferManagerVulkan.h"
|
||||
@ -305,6 +306,11 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader
|
||||
_dbg_assert_(FSID.Bit(FS_BIT_DO_TEXTURE) == VSID.Bit(VS_BIT_DO_TEXTURE));
|
||||
_dbg_assert_(FSID.Bit(FS_BIT_FLATSHADE) == VSID.Bit(VS_BIT_FLATSHADE));
|
||||
|
||||
if (GSID.Bit(GS_BIT_ENABLED)) {
|
||||
_dbg_assert_(GSID.Bit(GS_BIT_LMODE) == VSID.Bit(VS_BIT_LMODE));
|
||||
_dbg_assert_(GSID.Bit(GS_BIT_DO_TEXTURE) == VSID.Bit(VS_BIT_DO_TEXTURE));
|
||||
}
|
||||
|
||||
// Just update uniforms if this is the same shader as last time.
|
||||
if (lastVShader_ != nullptr && lastFShader_ != nullptr && VSID == lastVSID_ && FSID == lastFSID_ && GSID == lastGSID_) {
|
||||
*vshader = lastVShader_;
|
||||
@ -345,7 +351,11 @@ void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader
|
||||
gs = gsCache_.Get(GSID);
|
||||
if (!gs) {
|
||||
// Geometry shader not in cache. Let's compile it.
|
||||
// TODO
|
||||
std::string genErrorString;
|
||||
bool success = GenerateGeometryShader(GSID, codeBuffer_, compat_, draw_->GetBugs(), &genErrorString);
|
||||
_assert_msg_(success, "GS gen error: %s", genErrorString.c_str());
|
||||
gs = new VulkanGeometryShader(vulkan, GSID, codeBuffer_);
|
||||
gsCache_.Insert(GSID, gs);
|
||||
}
|
||||
} else {
|
||||
gs = nullptr;
|
||||
@ -529,7 +539,12 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) {
|
||||
ERROR_LOG(G3D, "Vulkan shader cache truncated");
|
||||
break;
|
||||
}
|
||||
// TODO: Actually generate geometry shaders.
|
||||
std::string genErrorString;
|
||||
if (!GenerateGeometryShader(id, codeBuffer_, compat_, draw_->GetBugs(), &genErrorString)) {
|
||||
return false;
|
||||
}
|
||||
VulkanGeometryShader *gs = new VulkanGeometryShader(vulkan, id, codeBuffer_);
|
||||
gsCache_.Insert(id, gs);
|
||||
}
|
||||
|
||||
NOTICE_LOG(G3D, "Loaded %d vertex and %d fragment shaders", header.numVertexShaders, header.numFragmentShaders);
|
||||
|
@ -385,6 +385,7 @@
|
||||
<ClInclude Include="..\..\GPU\Common\DrawEngineCommon.h" />
|
||||
<ClInclude Include="..\..\GPU\Common\FragmentShaderGenerator.h" />
|
||||
<ClInclude Include="..\..\GPU\Common\FramebufferManagerCommon.h" />
|
||||
<ClInclude Include="..\..\GPU\Common\GeometryShaderGenerator.h" />
|
||||
<ClInclude Include="..\..\GPU\Common\PresentationCommon.h" />
|
||||
<ClInclude Include="..\..\GPU\Common\GPUDebugInterface.h" />
|
||||
<ClInclude Include="..\..\GPU\Common\GPUStateUtils.h" />
|
||||
@ -446,6 +447,7 @@
|
||||
<ClCompile Include="..\..\GPU\Common\DrawEngineCommon.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Common\FragmentShaderGenerator.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Common\FramebufferManagerCommon.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Common\GeometryShaderGenerator.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Common\PresentationCommon.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Common\GPUDebugInterface.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Common\GPUStateUtils.cpp" />
|
||||
|
@ -55,6 +55,7 @@
|
||||
<ClCompile Include="..\..\GPU\Software\RasterizerRectangle.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Software\RasterizerRegCache.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Common\FragmentShaderGenerator.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Common\GeometryShaderGenerator.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Common\VertexShaderGenerator.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Common\ReinterpretFramebuffer.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Common\Draw2D.cpp" />
|
||||
@ -116,6 +117,7 @@
|
||||
<ClInclude Include="..\..\GPU\Software\RasterizerRectangle.h" />
|
||||
<ClInclude Include="..\..\GPU\Software\RasterizerRegCache.h" />
|
||||
<ClInclude Include="..\..\GPU\Common\FragmentShaderGenerator.h" />
|
||||
<ClInclude Include="..\..\GPU\Common\GeometryShaderGenerator.h" />
|
||||
<ClInclude Include="..\..\GPU\Common\VertexShaderGenerator.h" />
|
||||
<ClInclude Include="..\..\GPU\Common\ReinterpretFramebuffer.h" />
|
||||
<ClInclude Include="..\..\GPU\Common\Draw2D.h" />
|
||||
|
@ -350,6 +350,7 @@ 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/Debugger/Breakpoints.cpp \
|
||||
$(SRC)/GPU/Debugger/Debugger.cpp \
|
||||
$(SRC)/GPU/Debugger/GECommandTable.cpp \
|
||||
|
@ -342,6 +342,7 @@ 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 \
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#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"
|
||||
@ -91,6 +92,32 @@ bool GenerateVShader(VShaderID id, char *buffer, ShaderLanguage lang, Draw::Bugs
|
||||
}
|
||||
}
|
||||
|
||||
bool GenerateGShader(GShaderID id, char *buffer, ShaderLanguage lang, Draw::Bugs bugs, std::string *errorString) {
|
||||
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;
|
||||
@ -369,6 +396,9 @@ bool TestVertexShaders() {
|
||||
if (!id.Bit(VS_BIT_USE_HW_TRANSFORM)) {
|
||||
id.SetBit(VS_BIT_ENABLE_BONES, 0);
|
||||
}
|
||||
if (id.Bit(VS_BIT_VERTEX_RANGE_CULLING)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool generateSuccess[numLanguages]{};
|
||||
std::string genErrorString[numLanguages];
|
||||
@ -463,6 +493,63 @@ 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++) {
|
||||
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.
|
||||
}
|
||||
|
||||
// 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());
|
||||
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();
|
||||
@ -476,6 +563,10 @@ bool TestShaderGenerators() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TestGeometryShaders()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TestReinterpretShaders()) {
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user