start implementing vulkan Shader type

This commit is contained in:
niki
2022-02-06 22:56:24 +01:00
parent 4692a0490c
commit 197dfb9738
9 changed files with 157 additions and 44 deletions
+2 -1
View File
@@ -342,7 +342,7 @@ ShaderStage *Graphics::newShaderStage(ShaderStageType stage, const std::string &
return s;
}
Shader *Graphics::newShader(const std::vector<std::string> &stagessource)
Shader *Graphics::newShader(const std::vector<std::string> &stagessource, bool vulkan)
{
StrongRef<ShaderStage> stages[SHADERSTAGE_MAX_ENUM] = {};
@@ -353,6 +353,7 @@ Shader *Graphics::newShader(const std::vector<std::string> &stagessource)
for (const std::string &source : stagessource)
{
Shader::SourceInfo info = Shader::getSourceInfo(source);
info.vulkan = vulkan;
bool isanystage = false;
for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++)
+1 -1
View File
@@ -449,7 +449,7 @@ public:
SpriteBatch *newSpriteBatch(Texture *texture, int size, BufferDataUsage usage);
ParticleSystem *newParticleSystem(Texture *texture, int size);
Shader *newShader(const std::vector<std::string> &stagessource);
Shader *newShader(const std::vector<std::string> &stagessource, bool vulkan = false);
Shader *newComputeShader(const std::string &source);
virtual Buffer *newBuffer(const Buffer::Settings &settings, const std::vector<Buffer::DataDeclaration> &format, const void *data, size_t size, size_t arraylength) = 0;
+38 -18
View File
@@ -83,13 +83,27 @@ static const char global_syntax[] = R"(
#ifdef GL_OES_standard_derivatives
#extension GL_OES_standard_derivatives : enable
#endif
#ifdef USE_VULKAN
#define VULKAN_LOCATION(x) layout(location=x)
#define VULKAN_BINDING(x) layout(binding=x)
#else
#define VULKAN_LOCATION(x)
#define VULKAN_BINDING(x)
#endif
)";
static const char render_uniforms[] = R"(
// According to the GLSL ES 1.0 spec, uniform precision must match between stages,
// but we can't guarantee that highp is always supported in fragment shaders...
// We *really* don't want to use mediump for these in vertex shaders though.
uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13];
#ifdef USE_VULKAN
VULKAN_BINDING(0) uniform LoveUniformsPerDraw {
vec4 uniformsPerDraw[13];
} udp;
#define love_UniformsPerDraw udp.uniformsPerDraw
#else
// According to the GLSL ES 1.0 spec, uniform precision must match between stages,
// but we can't guarantee that highp is always supported in fragment shaders...
// We *really* don't want to use mediump for these in vertex shaders though.
uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_UniformsPerDraw[13];
#endif
// These are initialized in love_initializeBuiltinUniforms below. GLSL ES can't
// do it as an initializer.
@@ -264,12 +278,12 @@ static const char vertex_header[] = R"(
static const char vertex_functions[] = R"()";
static const char vertex_main[] = R"(
attribute vec4 VertexPosition;
attribute vec4 VertexTexCoord;
attribute vec4 VertexColor;
VULKAN_LOCATION(0) attribute vec4 VertexPosition;
VULKAN_LOCATION(1) attribute vec4 VertexTexCoord;
VULKAN_LOCATION(2) attribute vec4 VertexColor;
varying vec4 VaryingTexCoord;
varying vec4 VaryingColor;
VULKAN_LOCATION(0) varying vec4 VaryingTexCoord;
VULKAN_LOCATION(1) varying vec4 VaryingColor;
vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition);
@@ -309,9 +323,9 @@ static const char pixel_header[] = R"(
)";
static const char pixel_functions[] = R"(
uniform sampler2D love_VideoYChannel;
uniform sampler2D love_VideoCbChannel;
uniform sampler2D love_VideoCrChannel;
VULKAN_BINDING(1) uniform sampler2D love_VideoYChannel;
VULKAN_BINDING(2) uniform sampler2D love_VideoCbChannel;
VULKAN_BINDING(3) uniform sampler2D love_VideoCrChannel;
vec4 VideoTexel(vec2 texcoords) {
vec3 yuv;
@@ -337,9 +351,9 @@ static const char pixel_main[] = R"(
#define love_PixelColor gl_FragColor
#endif
uniform sampler2D MainTex;
varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
varying mediump vec4 VaryingColor;
VULKAN_BINDING(4) uniform sampler2D MainTex;
VULKAN_LOCATION(0) varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
VULKAN_LOCATION(1) varying mediump vec4 VaryingColor;
vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord);
@@ -374,8 +388,8 @@ static const char pixel_main_custom[] = R"(
#define LOVE_MULTI_CANVASES 1
#endif
varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
varying mediump vec4 VaryingColor;
VULKAN_LOCATION(0) varying LOVE_HIGHP_OR_MEDIUMP vec4 VaryingTexCoord;
VULKAN_LOCATION(1) varying mediump vec4 VaryingColor;
void effect();
@@ -562,6 +576,9 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage,
if (glsl1on3)
lang = LANGUAGE_GLSL3;
if (info.vulkan)
lang = LANGUAGE_GLSL4;
glsl::StageInfo stageinfo = glsl::stageInfo[stage];
std::stringstream ss;
@@ -574,6 +591,8 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage,
ss << "#define LOVE_GAMMA_CORRECT 1\n";
if (info.usesMRT)
ss << "#define LOVE_MULTI_RENDER_TARGETS 1\n";
if (info.vulkan)
ss << "#define USE_VULKAN\n";
ss << glsl::global_syntax;
ss << stageinfo.header;
ss << stageinfo.uniforms;
@@ -893,7 +912,8 @@ bool Shader::validateInternal(StrongRef<ShaderStage> stages[], std::string &err,
{
LocalUniform u = {};
auto &values = u.initializerValues;
const glslang::TConstUnionArray *constarray = info.getConstArray();
// const glslang::TConstUnionArray *constarray = info.getConstArray(); was this function deprecated in a later version?
const glslang::TConstUnionArray* constarray = nullptr;
// Store initializer values for local uniforms. Some love graphics
// backends strip these out of the shader so we need to be able to
+1
View File
@@ -112,6 +112,7 @@ public:
Language language;
EntryPoint stages[SHADERSTAGE_MAX_ENUM];
bool usesMRT;
bool vulkan;
};
struct MatrixSize
+12 -1
View File
@@ -215,6 +215,17 @@ namespace love {
batchedDrawState.indexBuffer = new StreamBuffer(device, physicalDevice, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
}
for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++) {
auto stype = (Shader::StandardShader)i;
if (!Shader::standardShaders[i]) {
std::vector<std::string> stages;
stages.push_back(Shader::getDefaultCode(stype, SHADERSTAGE_VERTEX));
stages.push_back(Shader::getDefaultCode(stype, SHADERSTAGE_PIXEL));
Shader::standardShaders[i] = newShader(stages, true);
}
}
return true;
}
@@ -759,7 +770,7 @@ namespace love {
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f;
+10 -2
View File
@@ -3,6 +3,8 @@
#include "graphics/Graphics.h"
#include "StreamBuffer.h"
#include "ShaderStage.h"
#include "Shader.h"
#include <vulkan/vulkan.h>
#include <common/config.h>
@@ -66,8 +68,14 @@ namespace love {
void drawQuads(int start, int count, const VertexAttributes& attributes, const BufferBindings& buffers, Texture* texture) override { std::cout << "drawQuads "; }
protected:
graphics::ShaderStage* newShaderStageInternal(ShaderStageType stage, const std::string& cachekey, const std::string& source, bool gles) override { std::cout << "newShaderStageInternal "; return nullptr; }
graphics::Shader* newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override { std::cout << "newShaderInternal "; return nullptr; }
graphics::ShaderStage* newShaderStageInternal(ShaderStageType stage, const std::string& cachekey, const std::string& source, bool gles) override {
std::cout << "newShaderStageInternal ";
return new ShaderStage(this, stage, source, gles, cachekey);
}
graphics::Shader* newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override {
std::cout << "newShaderInternal ";
return new Shader(stages);
}
graphics::StreamBuffer* newStreamBuffer(BufferUsage type, size_t size) override;
bool dispatch(int x, int y, int z) override { std::cout << "dispatch "; return false; }
void initCapabilities() override { std::cout << "initCapabilities "; }
+15 -16
View File
@@ -1,7 +1,5 @@
#include "Shader.h"
#include "libraries/glslang/glslang/Public/ShaderLang.h"
#include "libraries/glslang/SPIRV/GlslangToSpv.h"
#include <vector>
namespace love {
@@ -21,24 +19,25 @@ namespace love {
Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[])
: graphics::Shader(stages) {
if (false) {
for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++) {
if (!stages[i])
continue;
for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++) {
if (!stages[i])
continue;
auto stage = dynamic_cast<ShaderStage*>(stages[i].get());
auto stage = dynamic_cast<ShaderStage*>(stages[i].get());
VkPipelineShaderStageCreateInfo shaderStageInfo{};
shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStageInfo.stage = getStageBit(stage->getStageType());
shaderStageInfo.module = stage->getShaderModule();
shaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStageInfo{};
shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStageInfo.stage = getStageBit(stage->getStageType());
shaderStageInfo.module = stage->getShaderModule();
shaderStageInfo.pName = "main";
shaderStages.push_back(shaderStageInfo);
}
shaderStages.push_back(shaderStageInfo);
}
}
int Shader::getVertexAttributeIndex(const std::string& name) {
return vertexAttributeIndices.at(name);
}
}
}
}
}
+25 -3
View File
@@ -3,10 +3,10 @@
#include <graphics/Shader.h>
#include <graphics/vulkan/ShaderStage.h>
#include "libraries/glslang/glslang/Public/ShaderLang.h"
#include "libraries/glslang/SPIRV/GlslangToSpv.h"
#include <vulkan/vulkan.h>
#include <map>
namespace love {
namespace graphics {
@@ -26,7 +26,7 @@ namespace love {
std::string getWarnings() const override { return ""; }
int getVertexAttributeIndex(const std::string& name) override { return 0; }
int getVertexAttributeIndex(const std::string& name) override;
const UniformInfo* getUniformInfo(const std::string& name) const override { return nullptr; }
const UniformInfo* getUniformInfo(BuiltinUniform builtin) const override { return nullptr; }
@@ -41,7 +41,29 @@ namespace love {
void setVideoTextures(Texture* ytexture, Texture* cbtexture, Texture* crtexture) override {}
private:
struct Vec4 {
float x, y, z, w;
};
struct LoveUniformsPerDraw {
Vec4 uniformsPerDraw[13];
};
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
std::map<std::string, int> vertexAttributeIndices = {
{ "VertexPosition", 0 },
{ "VertexTexCoord", 1 },
{ "VertexColor", 2 }
};
std::map<std::string, int> uniformBindings = {
{ "love_UniformsPerDraw", 0 },
{ "love_VideoYChannel", 1 },
{ "love_VideoCbChannel", 2 },
{ "love_VideoCrChannel", 3 },
{ "MainTex", 4 }
};
};
}
}
+53 -2
View File
@@ -9,12 +9,63 @@
namespace love {
namespace graphics {
namespace vulkan {
static int someIndex = 0;
static std::string getFileEnding(ShaderStageType type) {
switch (type) {
case SHADERSTAGE_VERTEX:
return ".vert";
case SHADERSTAGE_PIXEL:
return ".frag";
default:
throw love::Exception("unsupported shader stage type");
}
}
static std::vector<char> readFile(const std::string& filename) {
std::ifstream file(filename, std::ios::ate | std::ios::binary);
if (!file.is_open()) {
throw std::runtime_error("failed to open file!");
}
size_t fileSize = (size_t)file.tellg();
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), fileSize);
file.close();
return buffer;
}
static int shaderSourceId = 0;
std::vector<char> compileShader(const std::string& glsl, ShaderStageType stage) {
// fixme: use glslang or shaderc for this
std::string inputFileName = std::string("temp") + std::to_string(shaderSourceId++) + getFileEnding(stage);
std::string outputFileName = std::string("temp.spv");
std::ofstream out(inputFileName);
out << glsl;
out.close();
std::string command = std::string("glslc -fauto-bind-uniforms ") + inputFileName + " -o " + outputFileName;
system(command.c_str());
return readFile(outputFileName);
}
ShaderStage::ShaderStage(love::graphics::Graphics* gfx, ShaderStageType stage, const std::string& glsl, bool gles, const std::string& cachekey)
: love::graphics::ShaderStage(gfx, stage, glsl, gles, cachekey) {
auto code = compileShader(glsl, stage);
VkShaderModuleCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = 0;
createInfo.pCode = nullptr;
createInfo.codeSize = code.size();
createInfo.pCode = reinterpret_cast<uint32_t*>(code.data());
Graphics* vkGfx = (Graphics*)gfx;
device = vkGfx->getDevice();