mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
start implementing vulkan Shader type
This commit is contained in:
@@ -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++)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -112,6 +112,7 @@ public:
|
||||
Language language;
|
||||
EntryPoint stages[SHADERSTAGE_MAX_ENUM];
|
||||
bool usesMRT;
|
||||
bool vulkan;
|
||||
};
|
||||
|
||||
struct MatrixSize
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 "; }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user