mirror of https://github.com/bjornbytes/lovr.git
commit
73eae189ae
|
@ -261,7 +261,6 @@ if config.modules.graphics and config.glslang then
|
|||
glslang_cflags += '-fno-rtti'
|
||||
glslang_cflags += '-Ideps/glslang'
|
||||
glslang_lflags += '-shared'
|
||||
glslang_src += 'deps/glslang/OGLCompilersDLL/*.cpp'
|
||||
glslang_src += 'deps/glslang/glslang/CInterface/*.cpp'
|
||||
glslang_src += 'deps/glslang/glslang/MachineIndependent/*.cpp'
|
||||
glslang_src += 'deps/glslang/glslang/MachineIndependent/preprocessor/*.cpp'
|
||||
|
@ -468,11 +467,12 @@ vert = 'etc/shaders/*.vert'
|
|||
frag = 'etc/shaders/*.frag'
|
||||
comp = 'etc/shaders/*.comp'
|
||||
|
||||
glslang_flags += '--quiet'
|
||||
glslang_flags += config.debug and '-gVS' or ''
|
||||
glslang_flags += '--target-env vulkan1.1'
|
||||
|
||||
function compileShaders(stage)
|
||||
pattern = 'etc/shaders/*.' .. stage
|
||||
glslang_flags += '--quiet'
|
||||
glslang_flags += config.debug and '-gVS' or ''
|
||||
glslang_flags += '--target-env vulkan1.1'
|
||||
tup.foreach_rule(pattern, 'glslangValidator $(glslang_flags) --vn lovr_shader_%B_' .. stage .. ' -o %o %f', '%f.h')
|
||||
end
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e7d1279bc02891585c96479987c0f3a11cc042b9
|
||||
Subproject commit 545226e46f85f24d3d447a812d3156787ca879d7
|
|
@ -2,7 +2,7 @@
|
|||
#extension GL_EXT_multiview : require
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
|
||||
#include "lovr.glsl"
|
||||
#include "shaders/lovr.glsl"
|
||||
|
||||
vec4 lovrmain() {
|
||||
float y = UV.y;
|
Binary file not shown.
|
@ -9,7 +9,7 @@ function lovr.load()
|
|||
lovr.graphics.setBackgroundColor(0x20232c)
|
||||
end
|
||||
|
||||
logo = lovr.graphics.newShader('unlit', 'logo')
|
||||
logo = lovr.graphics.newShader('unlit', 'logo.spv')
|
||||
end
|
||||
|
||||
function lovr.draw(pass)
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "shaders/animator.comp.h"
|
||||
#include "shaders/blender.comp.h"
|
||||
#include "shaders/tallymerge.comp.h"
|
||||
#include "shaders/logo.frag.h"
|
||||
|
||||
#include "shaders/lovr.glsl.h"
|
||||
|
||||
|
@ -19,3 +18,5 @@
|
|||
#define LOCATION_UV 12
|
||||
#define LOCATION_COLOR 13
|
||||
#define LOCATION_TANGENT 14
|
||||
|
||||
#define LAST_BUILTIN_BINDING 3
|
||||
|
|
|
@ -63,6 +63,10 @@ layout(set = 1, binding = 4) uniform texture2D RoughnessTexture;
|
|||
layout(set = 1, binding = 5) uniform texture2D ClearcoatTexture;
|
||||
layout(set = 1, binding = 6) uniform texture2D OcclusionTexture;
|
||||
layout(set = 1, binding = 7) uniform texture2D NormalTexture;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
uint DrawID;
|
||||
};
|
||||
#endif
|
||||
|
||||
// Attributes
|
||||
|
@ -116,7 +120,7 @@ layout(location = 14) in vec4 Tangent;
|
|||
#define BaseInstance gl_BaseInstance
|
||||
#define BaseVertex gl_BaseVertex
|
||||
#define DrawIndex gl_DrawIndex
|
||||
#define InstanceIndex (gl_InstanceIndex - gl_BaseInstance)
|
||||
#define InstanceIndex gl_InstanceIndex
|
||||
#define PointSize gl_PointSize
|
||||
#define Position gl_Position
|
||||
#define VertexIndex gl_VertexIndex
|
||||
|
@ -140,12 +144,7 @@ layout(location = 14) in vec4 Tangent;
|
|||
|
||||
// Helpers
|
||||
|
||||
#define Constants layout(push_constant) uniform PushConstants
|
||||
#ifdef GL_COMPUTE_SHADER
|
||||
#define var(x) layout(set = 0, binding = x)
|
||||
#else
|
||||
#define var(x) layout(set = 2, binding = x)
|
||||
#endif
|
||||
#define Constants uniform DefaultUniformBlock
|
||||
|
||||
#ifndef GL_COMPUTE_SHADER
|
||||
#define Projection Cameras[ViewIndex].projection
|
||||
|
@ -156,7 +155,6 @@ layout(location = 14) in vec4 Tangent;
|
|||
#endif
|
||||
|
||||
#ifdef GL_VERTEX_SHADER
|
||||
#define DrawID gl_BaseInstance
|
||||
#define Transform mat4(Draws[DrawID].transform)
|
||||
#define NormalMatrix (cofactor3(Draws[DrawID].transform))
|
||||
#define PassColor Draws[DrawID].color
|
||||
|
|
|
@ -51,6 +51,7 @@ extern StringEntry lovrPassType[];
|
|||
extern StringEntry lovrPermission[];
|
||||
extern StringEntry lovrSampleFormat[];
|
||||
extern StringEntry lovrShaderStage[];
|
||||
extern StringEntry lovrShaderType[];
|
||||
extern StringEntry lovrShapeType[];
|
||||
extern StringEntry lovrSmoothMode[];
|
||||
extern StringEntry lovrStackType[];
|
||||
|
|
|
@ -58,7 +58,6 @@ StringEntry lovrDefaultShader[] = {
|
|||
[SHADER_EQUIRECT] = ENTRY("equirect"),
|
||||
[SHADER_FILL_2D] = ENTRY("fill"),
|
||||
[SHADER_FILL_ARRAY] = ENTRY("fillarray"),
|
||||
[SHADER_LOGO] = ENTRY("logo"),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -146,6 +145,12 @@ StringEntry lovrShaderStage[] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
StringEntry lovrShaderType[] = {
|
||||
[SHADER_GRAPHICS] = ENTRY("graphics"),
|
||||
[SHADER_COMPUTE] = ENTRY("compute"),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
StringEntry lovrStackType[] = {
|
||||
[STACK_TRANSFORM] = ENTRY("transform"),
|
||||
[STACK_STATE] = ENTRY("state"),
|
||||
|
@ -978,94 +983,88 @@ static int l_lovrGraphicsNewSampler(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static ShaderSource luax_checkshadersource(lua_State* L, int index, ShaderStage stage, bool* allocated) {
|
||||
ShaderSource source;
|
||||
static ShaderSource luax_checkshadersource(lua_State* L, int index, ShaderStage stage, bool* shouldFree) {
|
||||
*shouldFree = false;
|
||||
|
||||
if (lua_isstring(L, index)) {
|
||||
size_t length;
|
||||
const char* string = lua_tolstring(L, index, &length);
|
||||
|
||||
if (memchr(string, '\n', MIN(256, length))) {
|
||||
source.code = string;
|
||||
source.size = length;
|
||||
*allocated = false;
|
||||
return (ShaderSource) { stage, string, length };
|
||||
} else {
|
||||
for (int i = 0; lovrDefaultShader[i].length; i++) {
|
||||
if (lovrDefaultShader[i].length == length && !memcmp(lovrDefaultShader[i].string, string, length)) {
|
||||
*allocated = false;
|
||||
return lovrGraphicsGetDefaultShaderSource(i, stage);
|
||||
}
|
||||
}
|
||||
|
||||
source.code = luax_readfile(string, &source.size);
|
||||
size_t size;
|
||||
void* code = luax_readfile(string, &size);
|
||||
|
||||
if (source.code) {
|
||||
*allocated = true;
|
||||
if (code) {
|
||||
*shouldFree = true;
|
||||
return (ShaderSource) { stage, code, size };
|
||||
} else {
|
||||
luaL_argerror(L, index, "single-line string was not filename or DefaultShader");
|
||||
}
|
||||
}
|
||||
} else if (lua_isuserdata(L, index)) {
|
||||
Blob* blob = luax_checktype(L, index, Blob);
|
||||
source.code = blob->data;
|
||||
source.size = blob->size;
|
||||
*allocated = false;
|
||||
return (ShaderSource) { stage, blob->data, blob->size };
|
||||
} else {
|
||||
*allocated = false;
|
||||
return lovrGraphicsGetDefaultShaderSource(SHADER_UNLIT, stage);
|
||||
luax_typeerror(L, index, "string, Blob, or DefaultShader");
|
||||
}
|
||||
|
||||
ShaderSource bytecode = lovrGraphicsCompileShader(stage, &source, luax_readfile);
|
||||
|
||||
if (bytecode.code != source.code) {
|
||||
if (*allocated) free((void*) source.code);
|
||||
*allocated = true;
|
||||
return bytecode;
|
||||
}
|
||||
|
||||
return source;
|
||||
return (ShaderSource) { 0 };
|
||||
}
|
||||
|
||||
static int l_lovrGraphicsCompileShader(lua_State* L) {
|
||||
ShaderStage stage = luax_checkenum(L, 1, ShaderStage, NULL);
|
||||
bool allocated;
|
||||
ShaderSource spirv = luax_checkshadersource(L, 2, stage, &allocated);
|
||||
Blob* blob = lovrBlobCreate((void*) spirv.code, spirv.size, "Compiled Shader Code");
|
||||
luax_pushtype(L, Blob, blob);
|
||||
lovrRelease(blob, lovrBlobDestroy);
|
||||
return 1;
|
||||
ShaderSource inputs[2], outputs[2];
|
||||
bool shouldFree[2];
|
||||
uint32_t count;
|
||||
|
||||
if (lua_gettop(L) == 1) {
|
||||
inputs[0] = luax_checkshadersource(L, 1, STAGE_COMPUTE, &shouldFree[0]);
|
||||
count = 1;
|
||||
} else {
|
||||
inputs[0] = luax_checkshadersource(L, 1, STAGE_VERTEX, &shouldFree[0]);
|
||||
inputs[1] = luax_checkshadersource(L, 2, STAGE_FRAGMENT, &shouldFree[1]);
|
||||
count = 2;
|
||||
}
|
||||
|
||||
lovrGraphicsCompileShader(inputs, outputs, count, luax_readfile);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if (shouldFree[i] && outputs[i].code != inputs[i].code) free((void*) inputs[i].code);
|
||||
Blob* blob = lovrBlobCreate((void*) outputs[i].code, outputs[i].size, "Shader code");
|
||||
luax_pushtype(L, Blob, blob);
|
||||
lovrRelease(blob, lovrBlobDestroy);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int l_lovrGraphicsNewShader(lua_State* L) {
|
||||
ShaderInfo info = { 0 };
|
||||
bool allocated[2];
|
||||
ShaderSource source[2], compiled[2];
|
||||
ShaderInfo info = { .stages = compiled };
|
||||
bool shouldFree[2] = { 0 };
|
||||
int index;
|
||||
|
||||
// If there's only one source given, it could be a DefaultShader or a compute shader
|
||||
if (lua_gettop(L) == 1 || (lua_istable(L, 2) && luax_len(L, 2) == 0)) {
|
||||
if (lua_type(L, 1) == LUA_TSTRING) {
|
||||
size_t length;
|
||||
const char* string = lua_tolstring(L, 1, &length);
|
||||
for (int i = 0; lovrDefaultShader[i].length; i++) {
|
||||
if (lovrDefaultShader[i].length == length && !memcmp(lovrDefaultShader[i].string, string, length)) {
|
||||
info.source[STAGE_VERTEX] = lovrGraphicsGetDefaultShaderSource(i, STAGE_VERTEX);
|
||||
info.source[STAGE_FRAGMENT] = lovrGraphicsGetDefaultShaderSource(i, STAGE_FRAGMENT);
|
||||
allocated[0] = false;
|
||||
allocated[1] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!info.source[0].code) {
|
||||
info.source[STAGE_COMPUTE] = luax_checkshadersource(L, 1, STAGE_COMPUTE, &allocated[0]);
|
||||
}
|
||||
|
||||
if (lua_gettop(L) == 1 || lua_istable(L, 2)) {
|
||||
info.type = SHADER_COMPUTE;
|
||||
source[0] = luax_checkshadersource(L, 1, STAGE_COMPUTE, &shouldFree[0]);
|
||||
info.stageCount = 1;
|
||||
index = 2;
|
||||
} else {
|
||||
info.source[STAGE_VERTEX] = luax_checkshadersource(L, 1, STAGE_VERTEX, &allocated[0]);
|
||||
info.source[STAGE_FRAGMENT] = luax_checkshadersource(L, 2, STAGE_FRAGMENT, &allocated[1]);
|
||||
info.type = SHADER_GRAPHICS;
|
||||
source[0] = luax_checkshadersource(L, 1, STAGE_VERTEX, &shouldFree[0]);
|
||||
source[1] = luax_checkshadersource(L, 2, STAGE_FRAGMENT, &shouldFree[1]);
|
||||
info.stageCount = 2;
|
||||
index = 3;
|
||||
}
|
||||
|
||||
lovrGraphicsCompileShader(source, compiled, info.stageCount, luax_readfile);
|
||||
|
||||
arr_t(ShaderFlag) flags;
|
||||
arr_init(&flags, realloc);
|
||||
|
||||
|
@ -1088,6 +1087,10 @@ static int l_lovrGraphicsNewShader(lua_State* L) {
|
|||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "type");
|
||||
info.type = lua_isnil(L, -1) ? info.type : luax_checkenum(L, -1, ShaderType, NULL);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "label");
|
||||
info.label = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
@ -1101,8 +1104,12 @@ static int l_lovrGraphicsNewShader(lua_State* L) {
|
|||
Shader* shader = lovrShaderCreate(&info);
|
||||
luax_pushtype(L, Shader, shader);
|
||||
lovrRelease(shader, lovrShaderDestroy);
|
||||
if (allocated[0]) free((void*) info.source[0].code);
|
||||
if (allocated[1]) free((void*) info.source[1].code);
|
||||
|
||||
for (uint32_t i = 0; i < info.stageCount; i++) {
|
||||
if (shouldFree[i]) free((void*) source[i].code);
|
||||
if (source[i].code != compiled[i].code) free((void*) compiled[i].code);
|
||||
}
|
||||
|
||||
arr_free(&flags);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -643,15 +643,9 @@ static int l_lovrPassSetWireframe(lua_State* L) {
|
|||
|
||||
static int l_lovrPassSend(lua_State* L) {
|
||||
Pass* pass = luax_checktype(L, 1, Pass);
|
||||
const char* name = NULL;
|
||||
size_t length = 0;
|
||||
uint32_t slot = ~0u;
|
||||
|
||||
switch (lua_type(L, 2)) {
|
||||
case LUA_TSTRING: name = lua_tolstring(L, 2, &length); break;
|
||||
case LUA_TNUMBER: slot = lua_tointeger(L, 2) - 1; break;
|
||||
default: return luax_typeerror(L, 2, "string or number");
|
||||
}
|
||||
size_t length;
|
||||
const char* name = lua_tolstring(L, 2, &length);
|
||||
|
||||
if (lua_isnoneornil(L, 3)) {
|
||||
return luax_typeerror(L, 3, "Buffer, Texture, Sampler, number, vector, table, or boolean");
|
||||
|
@ -662,27 +656,27 @@ static int l_lovrPassSend(lua_State* L) {
|
|||
if (buffer) {
|
||||
uint32_t offset = lua_tointeger(L, 4);
|
||||
uint32_t extent = lua_tointeger(L, 5);
|
||||
lovrPassSendBuffer(pass, name, length, slot, buffer, offset, extent);
|
||||
lovrPassSendBuffer(pass, name, length, buffer, offset, extent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Texture* texture = luax_totype(L, 3, Texture);
|
||||
|
||||
if (texture) {
|
||||
lovrPassSendTexture(pass, name, length, slot, texture);
|
||||
lovrPassSendTexture(pass, name, length, texture);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Sampler* sampler = luax_totype(L, 3, Sampler);
|
||||
|
||||
if (sampler) {
|
||||
lovrPassSendSampler(pass, name, length, slot, sampler);
|
||||
lovrPassSendSampler(pass, name, length, sampler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* pointer;
|
||||
DataField* format;
|
||||
lovrPassSendData(pass, name, length, slot, &pointer, &format);
|
||||
lovrPassSendData(pass, name, length, &pointer, &format);
|
||||
char* data = pointer;
|
||||
|
||||
// Coerce booleans since they aren't supported in buffer formats
|
||||
|
|
|
@ -33,6 +33,13 @@ static int l_lovrShaderClone(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrShaderGetType(lua_State* L) {
|
||||
Shader* shader = luax_checktype(L, 1, Shader);
|
||||
const ShaderInfo* info = lovrShaderGetInfo(shader);
|
||||
luax_pushenum(L, ShaderType, info->type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrShaderHasStage(lua_State* L) {
|
||||
Shader* shader = luax_checktype(L, 1, Shader);
|
||||
ShaderStage stage = luax_checkenum(L, 2, ShaderStage, NULL);
|
||||
|
@ -86,18 +93,12 @@ static int l_lovrShaderGetBufferFormat(lua_State* L) {
|
|||
return 2;
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
static int l_lovrShaderGetType(lua_State* L) {
|
||||
lua_pushstring(L, lovrShaderHasStage(luax_checktype(L, 1, Shader), STAGE_COMPUTE) ? "compute" : "graphics");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrShader[] = {
|
||||
{ "clone", l_lovrShaderClone },
|
||||
{ "getType", l_lovrShaderGetType },
|
||||
{ "hasStage", l_lovrShaderHasStage },
|
||||
{ "hasAttribute", l_lovrShaderHasAttribute },
|
||||
{ "getWorkgroupSize", l_lovrShaderGetWorkgroupSize },
|
||||
{ "getBufferFormat", l_lovrShaderGetBufferFormat },
|
||||
{ "getType", l_lovrShaderGetType }, // Deprecated
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -246,16 +246,16 @@ void gpu_layout_destroy(gpu_layout* layout);
|
|||
// Shader
|
||||
|
||||
typedef struct {
|
||||
uint32_t stage;
|
||||
const void* code;
|
||||
size_t length;
|
||||
} gpu_shader_stage;
|
||||
} gpu_shader_source;
|
||||
|
||||
typedef struct {
|
||||
gpu_shader_stage vertex;
|
||||
gpu_shader_stage fragment;
|
||||
gpu_shader_stage compute;
|
||||
gpu_layout* layouts[4];
|
||||
uint32_t stageCount;
|
||||
gpu_shader_source* stages;
|
||||
uint32_t pushConstantSize;
|
||||
gpu_layout* layouts[4];
|
||||
const char* label;
|
||||
} gpu_shader_info;
|
||||
|
||||
|
|
|
@ -991,31 +991,28 @@ void gpu_layout_destroy(gpu_layout* layout) {
|
|||
// Shader
|
||||
|
||||
bool gpu_shader_init(gpu_shader* shader, gpu_shader_info* info) {
|
||||
struct { VkShaderStageFlags flags; gpu_shader_stage* source; } stages[] = {
|
||||
{ VK_SHADER_STAGE_VERTEX_BIT, &info->vertex },
|
||||
{ VK_SHADER_STAGE_FRAGMENT_BIT, &info->fragment },
|
||||
{ VK_SHADER_STAGE_COMPUTE_BIT, &info->compute }
|
||||
};
|
||||
|
||||
uint32_t stageCount = 0;
|
||||
VkShaderStageFlags stageFlags = 0;
|
||||
for (uint32_t i = 0; i < COUNTOF(stages); i++) {
|
||||
if (!stages[i].source->code) continue;
|
||||
for (uint32_t i = 0; i < info->stageCount; i++) {
|
||||
switch (info->stages[i].stage) {
|
||||
case GPU_STAGE_VERTEX: stageFlags |= VK_SHADER_STAGE_VERTEX_BIT; break;
|
||||
case GPU_STAGE_FRAGMENT: stageFlags |= VK_SHADER_STAGE_FRAGMENT_BIT; break;
|
||||
case GPU_STAGE_COMPUTE: stageFlags |= VK_SHADER_STAGE_COMPUTE_BIT; break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < info->stageCount; i++) {
|
||||
VkShaderModuleCreateInfo moduleInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.codeSize = stages[i].source->length,
|
||||
.pCode = stages[i].source->code
|
||||
.codeSize = info->stages[i].length,
|
||||
.pCode = info->stages[i].code
|
||||
};
|
||||
|
||||
VK(vkCreateShaderModule(state.device, &moduleInfo, NULL, &shader->handles[stageCount]), "Failed to load shader") {
|
||||
VK(vkCreateShaderModule(state.device, &moduleInfo, NULL, &shader->handles[i]), "Failed to load shader") {
|
||||
return false;
|
||||
}
|
||||
|
||||
nickname(shader->handles[i], VK_OBJECT_TYPE_SHADER_MODULE, info->label);
|
||||
|
||||
stageFlags |= stages[i].flags;
|
||||
stageCount++;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout layouts[4];
|
||||
|
@ -1594,7 +1591,7 @@ bool gpu_pipeline_init_graphics(gpu_pipeline* pipeline, gpu_pipeline_info* info)
|
|||
.pData = (const void*) constants
|
||||
};
|
||||
|
||||
uint32_t stageCount = info->shader->handles[1] && info->pass->colorCount > 0 ? 2 : 1;
|
||||
uint32_t stageCount = info->shader->handles[1] ? 2 : 1;
|
||||
|
||||
VkPipelineShaderStageCreateInfo shaders[2] = {
|
||||
{
|
||||
|
|
|
@ -20,8 +20,7 @@ typedef union {
|
|||
uint16_t name;
|
||||
} attribute;
|
||||
struct {
|
||||
uint8_t set;
|
||||
uint8_t binding;
|
||||
uint16_t decoration;
|
||||
uint16_t name;
|
||||
} variable;
|
||||
struct {
|
||||
|
@ -220,8 +219,12 @@ static spv_result spv_parse_decoration(spv_context* spv, const uint32_t* op, spv
|
|||
case 1: spv->cache[id].flag.number = op[3]; break; // SpecID
|
||||
case 6: spv->cache[id].type.arrayStride = op[3]; break; // ArrayStride (overrides name)
|
||||
case 30: spv->cache[id].attribute.location = op[3]; break; // Location
|
||||
case 33: spv->cache[id].variable.binding = op[3]; break; // Binding
|
||||
case 34: spv->cache[id].variable.set = op[3]; break; // Set
|
||||
case 33:
|
||||
case 34:
|
||||
if (spv->cache[id].variable.decoration == 0xffff) {
|
||||
spv->cache[id].variable.decoration = op - spv->words;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -352,11 +355,8 @@ static spv_result spv_parse_variable(spv_context* spv, const uint32_t* op, spv_i
|
|||
return spv_parse_field(spv, type, info->pushConstants, info);
|
||||
}
|
||||
|
||||
uint32_t set = spv->cache[variableId].variable.set;
|
||||
uint32_t binding = spv->cache[variableId].variable.binding;
|
||||
|
||||
// Ignore output variables (storageClass 3) and anything without a set/binding decoration
|
||||
if (storageClass == 3 || set == 0xff || binding == 0xff) {
|
||||
if (storageClass == 3 || spv->cache[variableId].variable.decoration == 0xffff) {
|
||||
return SPV_OK;
|
||||
}
|
||||
|
||||
|
@ -374,8 +374,38 @@ static spv_result spv_parse_variable(spv_context* spv, const uint32_t* op, spv_i
|
|||
|
||||
spv_resource* resource = &info->resources[info->resourceCount++];
|
||||
|
||||
resource->set = set;
|
||||
resource->binding = binding;
|
||||
// Resolve the set/binding pointers. The cache stores the index of the first set/binding
|
||||
// decoration word, we need to search for the "other" one.
|
||||
const uint32_t* word = spv->words + spv->cache[variableId].variable.decoration;
|
||||
bool set = word[2] == 34;
|
||||
uint32_t other = set ? 33 : 34;
|
||||
|
||||
if (set) {
|
||||
resource->set = &word[3];
|
||||
resource->binding = NULL;
|
||||
} else {
|
||||
resource->set = NULL;
|
||||
resource->binding = &word[3];
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
const uint32_t* next = word + OP_LENGTH(word);
|
||||
|
||||
if (word == next || next > spv->edge || (OP_CODE(next) != 71 && OP_CODE(next) != 72)) {
|
||||
break;
|
||||
}
|
||||
|
||||
word = next;
|
||||
|
||||
if (OP_CODE(word) == 71 && word[1] == variableId && word[2] == other) {
|
||||
if (set) {
|
||||
resource->binding = &word[3];
|
||||
} else {
|
||||
resource->set = &word[3];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If it's an array, read the array size and unwrap the inner type
|
||||
if (OP_CODE(type) == 28) { // OpTypeArray
|
||||
|
|
|
@ -79,10 +79,10 @@ enum {
|
|||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t set;
|
||||
uint32_t binding;
|
||||
uint32_t arraySize;
|
||||
const uint32_t* set;
|
||||
const uint32_t* binding;
|
||||
const char* name;
|
||||
uint32_t arraySize;
|
||||
spv_resource_type type;
|
||||
spv_texture_dimension dimension;
|
||||
uint32_t textureFlags;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -285,21 +285,25 @@ typedef enum {
|
|||
SHADER_EQUIRECT,
|
||||
SHADER_FILL_2D,
|
||||
SHADER_FILL_ARRAY,
|
||||
SHADER_LOGO,
|
||||
SHADER_ANIMATOR,
|
||||
SHADER_BLENDER,
|
||||
SHADER_TALLY_MERGE,
|
||||
DEFAULT_SHADER_COUNT
|
||||
} DefaultShader;
|
||||
|
||||
typedef enum {
|
||||
SHADER_GRAPHICS,
|
||||
SHADER_COMPUTE
|
||||
} ShaderType;
|
||||
|
||||
typedef enum {
|
||||
STAGE_VERTEX,
|
||||
STAGE_FRAGMENT,
|
||||
STAGE_COMPUTE,
|
||||
STAGE_COUNT
|
||||
STAGE_COMPUTE
|
||||
} ShaderStage;
|
||||
|
||||
typedef struct {
|
||||
ShaderStage stage;
|
||||
const void* code;
|
||||
size_t size;
|
||||
} ShaderSource;
|
||||
|
@ -311,15 +315,18 @@ typedef struct {
|
|||
} ShaderFlag;
|
||||
|
||||
typedef struct {
|
||||
ShaderSource source[STAGE_COUNT];
|
||||
uint32_t flagCount;
|
||||
ShaderType type;
|
||||
ShaderSource* stages;
|
||||
uint32_t stageCount;
|
||||
ShaderFlag* flags;
|
||||
uint32_t flagCount;
|
||||
const char* label;
|
||||
bool isDefault;
|
||||
} ShaderInfo;
|
||||
|
||||
typedef void* ShaderIncluder(const char* filename, size_t* bytesRead);
|
||||
|
||||
ShaderSource lovrGraphicsCompileShader(ShaderStage stage, ShaderSource* source, ShaderIncluder* includer);
|
||||
void lovrGraphicsCompileShader(ShaderSource* stages, ShaderSource* outputs, uint32_t count, ShaderIncluder* includer);
|
||||
ShaderSource lovrGraphicsGetDefaultShaderSource(DefaultShader type, ShaderStage stage);
|
||||
Shader* lovrGraphicsGetDefaultShader(DefaultShader type);
|
||||
Shader* lovrShaderCreate(const ShaderInfo* info);
|
||||
|
@ -606,10 +613,10 @@ void lovrPassSetViewCull(Pass* pass, bool enable);
|
|||
void lovrPassSetWinding(Pass* pass, Winding winding);
|
||||
void lovrPassSetWireframe(Pass* pass, bool wireframe);
|
||||
|
||||
void lovrPassSendBuffer(Pass* pass, const char* name, size_t length, uint32_t slot, Buffer* buffer, uint32_t offset, uint32_t extent);
|
||||
void lovrPassSendTexture(Pass* pass, const char* name, size_t length, uint32_t slot, Texture* texture);
|
||||
void lovrPassSendSampler(Pass* pass, const char* name, size_t length, uint32_t slot, Sampler* sampler);
|
||||
void lovrPassSendData(Pass* pass, const char* name, size_t length, uint32_t slot, void** data, DataField** format);
|
||||
void lovrPassSendBuffer(Pass* pass, const char* name, size_t length, Buffer* buffer, uint32_t offset, uint32_t extent);
|
||||
void lovrPassSendTexture(Pass* pass, const char* name, size_t length, Texture* texture);
|
||||
void lovrPassSendSampler(Pass* pass, const char* name, size_t length, Sampler* sampler);
|
||||
void lovrPassSendData(Pass* pass, const char* name, size_t length, void** data, DataField** format);
|
||||
|
||||
void lovrPassPoints(Pass* pass, uint32_t count, float** vertices);
|
||||
void lovrPassLine(Pass* pass, uint32_t count, float** vertices);
|
||||
|
|
Loading…
Reference in New Issue