implement custom uniforms for material shaders
This commit is contained in:
parent
d23c727350
commit
ea09ae1461
13 changed files with 406 additions and 299 deletions
|
|
@ -1142,7 +1142,7 @@ UniformField UserUniforms::GetField(const FString &name)
|
|||
return {field.Type, UniformStruct + field.Offset};
|
||||
}
|
||||
|
||||
void UserUniforms::WriteUniforms(UniformStructHolder &Uniforms)
|
||||
void UserUniforms::WriteUniforms(UniformStructHolder &Uniforms) const
|
||||
{
|
||||
Uniforms.Clear();
|
||||
Uniforms.addr = UniformStruct;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ enum class UniformType
|
|||
Mat4
|
||||
};
|
||||
|
||||
|
||||
const char* GetTypeStr(UniformType type);
|
||||
|
||||
struct UserUniformValue
|
||||
{
|
||||
UniformType Type = UniformType::Undefined;
|
||||
|
|
@ -136,7 +139,7 @@ public:
|
|||
|
||||
//must only be called once
|
||||
void LoadUniforms(const TMap<FString, UserUniformValue> &Uniforms);
|
||||
void WriteUniforms(UniformStructHolder &Data);
|
||||
void WriteUniforms(UniformStructHolder &Data) const;
|
||||
|
||||
|
||||
int UniformStructSize = 0;
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ VkVertexFormat *VkRenderPassManager::GetVertexFormat(int index)
|
|||
return &VertexFormats[index];
|
||||
}
|
||||
|
||||
VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(bool levelmesh)
|
||||
VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(bool levelmesh, int UserUniformSize)
|
||||
{
|
||||
auto &layout = PipelineLayouts[levelmesh];
|
||||
if (layout)
|
||||
|
|
@ -144,6 +144,12 @@ VulkanPipelineLayout* VkRenderPassManager::GetPipelineLayout(bool levelmesh)
|
|||
builder.AddSetLayout(levelmesh ? descriptors->GetLevelMeshLayout() : descriptors->GetRSBufferLayout());
|
||||
builder.AddSetLayout(descriptors->GetBindlessLayout());
|
||||
builder.AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants));
|
||||
|
||||
if(UserUniformSize > 0)
|
||||
{
|
||||
builder.AddPushConstantRange(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(PushConstants), UserUniformSize);
|
||||
}
|
||||
|
||||
builder.DebugName("VkRenderPassManager.PipelineLayout");
|
||||
layout = builder.Create(fb->GetDevice());
|
||||
return layout.get();
|
||||
|
|
@ -273,15 +279,25 @@ VulkanRenderPass *VkRenderPassSetup::GetRenderPass(int clearTargets)
|
|||
return RenderPasses[clearTargets].get();
|
||||
}
|
||||
|
||||
VulkanPipeline *VkRenderPassSetup::GetPipeline(const VkPipelineKey &key)
|
||||
VulkanPipeline *VkRenderPassSetup::GetPipeline(const VkPipelineKey &key, UniformStructHolder &Uniforms)
|
||||
{
|
||||
auto &item = Pipelines[key];
|
||||
if (!item)
|
||||
item = CreatePipeline(key);
|
||||
return item.get();
|
||||
auto item = Pipelines.find(key);
|
||||
if (item == Pipelines.end())
|
||||
{
|
||||
Uniforms.Clear();
|
||||
auto pipeline = CreatePipeline(key, Uniforms);
|
||||
auto ptr = pipeline.get();
|
||||
Pipelines.insert(std::pair<VkPipelineKey, PipelineData>{key, PipelineData{std::move(pipeline), Uniforms}});
|
||||
return ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
Uniforms = item->second.Uniforms;
|
||||
return item->second.pipeline.get();
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipelineKey &key)
|
||||
std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipelineKey &key, UniformStructHolder &Uniforms)
|
||||
{
|
||||
GraphicsPipelineBuilder builder;
|
||||
builder.Cache(fb->GetRenderPassManager()->GetCache());
|
||||
|
|
@ -365,10 +381,12 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
|
|||
|
||||
builder.RasterizationSamples((VkSampleCountFlagBits)PassKey.Samples);
|
||||
|
||||
builder.Layout(fb->GetRenderPassManager()->GetPipelineLayout(key.ShaderKey.UseLevelMesh));
|
||||
builder.Layout(fb->GetRenderPassManager()->GetPipelineLayout(key.ShaderKey.UseLevelMesh, program->Uniforms.sz));
|
||||
builder.RenderPass(GetRenderPass(0));
|
||||
builder.DebugName("VkRenderPassSetup.Pipeline");
|
||||
|
||||
Uniforms = program->Uniforms;
|
||||
|
||||
return builder.Create(fb->GetDevice());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,21 +69,27 @@ public:
|
|||
bool operator!=(const VkRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkRenderPassKey)) != 0; }
|
||||
};
|
||||
|
||||
struct PipelineData
|
||||
{
|
||||
std::unique_ptr<VulkanPipeline> pipeline;
|
||||
UniformStructHolder Uniforms;
|
||||
};
|
||||
|
||||
class VkRenderPassSetup
|
||||
{
|
||||
public:
|
||||
VkRenderPassSetup(VulkanRenderDevice* fb, const VkRenderPassKey &key);
|
||||
|
||||
VulkanRenderPass *GetRenderPass(int clearTargets);
|
||||
VulkanPipeline *GetPipeline(const VkPipelineKey &key);
|
||||
VulkanPipeline *GetPipeline(const VkPipelineKey &key, UniformStructHolder &Uniforms);
|
||||
|
||||
VkRenderPassKey PassKey;
|
||||
std::unique_ptr<VulkanRenderPass> RenderPasses[8];
|
||||
std::map<VkPipelineKey, std::unique_ptr<VulkanPipeline>> Pipelines;
|
||||
std::map<VkPipelineKey, PipelineData> Pipelines;
|
||||
|
||||
private:
|
||||
std::unique_ptr<VulkanRenderPass> CreateRenderPass(int clearTargets);
|
||||
std::unique_ptr<VulkanPipeline> CreatePipeline(const VkPipelineKey &key);
|
||||
std::unique_ptr<VulkanPipeline> CreatePipeline(const VkPipelineKey &key, UniformStructHolder &Uniforms);
|
||||
|
||||
VulkanRenderDevice* fb = nullptr;
|
||||
};
|
||||
|
|
@ -109,7 +115,7 @@ public:
|
|||
VkRenderPassSetup *GetRenderPass(const VkRenderPassKey &key);
|
||||
int GetVertexFormat(const std::vector<size_t>& bufferStrides, const std::vector<FVertexBufferAttribute>& attrs);
|
||||
VkVertexFormat *GetVertexFormat(int index);
|
||||
VulkanPipelineLayout* GetPipelineLayout(bool levelmesh);
|
||||
VulkanPipelineLayout* GetPipelineLayout(bool levelmesh, int UserUniformSize);
|
||||
|
||||
VkPPRenderPassSetup* GetPPRenderPass(const VkPPRenderPassKey& key);
|
||||
|
||||
|
|
|
|||
|
|
@ -138,14 +138,14 @@ FString VkPPShader::CreateUniformBlockDecl(const char* name, const std::vector<U
|
|||
decl.Format("layout(%s) uniform %s\n{\n", layout.GetChars(), name);
|
||||
for (size_t i = 0; i < fields.size(); i++)
|
||||
{
|
||||
decl.AppendFormat("\t%s %s;\n", GetTypeStr(fields[i].Type), fields[i].Name);
|
||||
decl.AppendFormat("\t%s %s;\n", GetTypeStr(fields[i].Type), fields[i].Name.GetChars());
|
||||
}
|
||||
decl += "};\n";
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
const char* VkPPShader::GetTypeStr(UniformType type)
|
||||
const char* GetTypeStr(UniformType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ public:
|
|||
private:
|
||||
FString LoadShaderCode(const FString &lumpname, const FString &defines, int version);
|
||||
static FString CreateUniformBlockDecl(const char* name, const std::vector<UniformFieldDesc>& fields, int bindingpoint);
|
||||
static const char* GetTypeStr(UniformType type);
|
||||
|
||||
ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system);
|
||||
FString LoadPublicShaderLump(const char* lumpname);
|
||||
|
|
|
|||
|
|
@ -113,9 +113,9 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key)
|
|||
};
|
||||
|
||||
const auto& desc = effectshaders[key.SpecialEffect];
|
||||
program.vert = LoadVertShader(desc.ShaderName, mainvp, vert_nocustom, desc.defines, key);
|
||||
program.vert = LoadVertShader(desc.ShaderName, mainvp, vert_nocustom, desc.defines, key, nullptr);
|
||||
if (!key.NoFragmentShader)
|
||||
program.frag = LoadFragShader(desc.ShaderName, desc.fp1, desc.fp2, desc.fp3, desc.fp4, desc.fp5, desc.defines, key);
|
||||
program.frag = LoadFragShader(desc.ShaderName, desc.fp1, desc.fp2, desc.fp3, desc.fp4, desc.fp5, desc.defines, key, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -153,9 +153,9 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key)
|
|||
if (key.EffectState < FIRST_USER_SHADER)
|
||||
{
|
||||
const auto& desc = defaultshaders[key.EffectState];
|
||||
program.vert = LoadVertShader(desc.ShaderName, mainvp, vert_nocustom, desc.Defines, key);
|
||||
program.vert = LoadVertShader(desc.ShaderName, mainvp, vert_nocustom, desc.Defines, key, nullptr);
|
||||
if (!key.NoFragmentShader)
|
||||
program.frag = LoadFragShader(desc.ShaderName, mainfp, desc.material_lump, desc.mateffect_lump, desc.lightmodel_lump_shared, desc.lightmodel_lump, desc.Defines, key);
|
||||
program.frag = LoadFragShader(desc.ShaderName, mainfp, desc.material_lump, desc.mateffect_lump, desc.lightmodel_lump_shared, desc.lightmodel_lump, desc.Defines, key, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -163,15 +163,45 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key)
|
|||
const FString& name = ExtractFileBase(desc.shader.GetChars());
|
||||
FString defines = defaultshaders[desc.shaderType].Defines + desc.defines;
|
||||
|
||||
program.vert = LoadVertShader(name, mainvp, desc.vertshader.IsEmpty() ? vert_nocustom : desc.vertshader.GetChars(), defines.GetChars(), key);
|
||||
program.vert = LoadVertShader(name, mainvp, desc.vertshader.IsEmpty() ? vert_nocustom : desc.vertshader.GetChars(), defines.GetChars(), key, &desc.Uniforms);
|
||||
if (!key.NoFragmentShader)
|
||||
program.frag = LoadFragShader(name, mainfp, desc.shader.GetChars(), defaultshaders[desc.shaderType].mateffect_lump, defaultshaders[desc.shaderType].lightmodel_lump_shared, defaultshaders[desc.shaderType].lightmodel_lump, defines.GetChars(), key);
|
||||
program.frag = LoadFragShader(name, mainfp, desc.shader.GetChars(), defaultshaders[desc.shaderType].mateffect_lump, defaultshaders[desc.shaderType].lightmodel_lump_shared, defaultshaders[desc.shaderType].lightmodel_lump, defines.GetChars(), key, &desc.Uniforms);
|
||||
|
||||
desc.Uniforms.WriteUniforms(program.Uniforms);
|
||||
}
|
||||
}
|
||||
return &program;
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanShader> VkShaderManager::LoadVertShader(FString shadername, const char *vert_lump, const char *vert_lump_custom, const char *defines, const VkShaderKey& key)
|
||||
static void addPushConstants(FString &layoutBlock, const UserUniforms *uniforms)
|
||||
{
|
||||
|
||||
layoutBlock << "// This must match the PushConstants struct\n";
|
||||
layoutBlock << "layout(push_constant) uniform PushConstants\n";
|
||||
layoutBlock << "{\n";
|
||||
layoutBlock << "#if defined(USE_LEVELMESH)\n";
|
||||
layoutBlock << " int unused0;\n";
|
||||
layoutBlock << " int unused1;\n";
|
||||
layoutBlock << "#else\n";
|
||||
layoutBlock << " int uDataIndex; // surfaceuniforms index\n";
|
||||
layoutBlock << " int uLightIndex; // dynamic lights\n";
|
||||
layoutBlock << "#endif\n";
|
||||
layoutBlock << " int uBoneIndexBase; // bone animation\n";
|
||||
layoutBlock << " int uFogballIndex; // fog balls\n";
|
||||
|
||||
if(uniforms && uniforms->UniformStructSize)
|
||||
{
|
||||
for(auto &field : uniforms->Fields)
|
||||
{
|
||||
//layoutBlock.AppendFormat(" layout(offset = %d) %s %s;\n", (field.Offset + sizeof(PushConstants)), GetTypeStr(field.Type), field.Name.GetChars());
|
||||
layoutBlock.AppendFormat(" %s %s;\n", GetTypeStr(field.Type), field.Name.GetChars());
|
||||
}
|
||||
}
|
||||
layoutBlock << "};\n";
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanShader> VkShaderManager::LoadVertShader(FString shadername, const char *vert_lump, const char *vert_lump_custom, const char *defines, const VkShaderKey& key, const UserUniforms *uniforms)
|
||||
{
|
||||
FString definesBlock;
|
||||
definesBlock << defines;
|
||||
|
|
@ -192,9 +222,11 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadVertShader(FString shadername
|
|||
definesBlock << "#define USE_LEVELMESH\n";
|
||||
|
||||
FString layoutBlock;
|
||||
addPushConstants(layoutBlock, uniforms);
|
||||
layoutBlock << LoadPrivateShaderLump("shaders/scene/layout_shared.glsl").GetChars() << "\n";
|
||||
layoutBlock << LoadPrivateShaderLump("shaders/scene/layout_vert.glsl").GetChars() << "\n";
|
||||
|
||||
|
||||
FString codeBlock;
|
||||
codeBlock << LoadPrivateShaderLump(vert_lump).GetChars() << "\n";
|
||||
codeBlock << LoadPublicShaderLump(vert_lump_custom).GetChars() << "\n";
|
||||
|
|
@ -211,7 +243,7 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadVertShader(FString shadername
|
|||
.Create(shadername.GetChars(), fb->GetDevice());
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char* mateffect_lump, const char *light_lump_shared, const char *light_lump, const char *defines, const VkShaderKey& key)
|
||||
std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char* mateffect_lump, const char *light_lump_shared, const char *light_lump, const char *defines, const VkShaderKey& key, const UserUniforms *uniforms)
|
||||
{
|
||||
FString definesBlock;
|
||||
if (fb->IsRayQueryEnabled()) definesBlock << "\n#define SUPPORTS_RAYQUERY\n";
|
||||
|
|
@ -299,9 +331,11 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
|
|||
else definesBlock << "#define uFogEnabled 0\n";
|
||||
|
||||
FString layoutBlock;
|
||||
addPushConstants(layoutBlock, uniforms);
|
||||
layoutBlock << LoadPrivateShaderLump("shaders/scene/layout_shared.glsl").GetChars() << "\n";
|
||||
layoutBlock << LoadPrivateShaderLump("shaders/scene/layout_frag.glsl").GetChars() << "\n";
|
||||
|
||||
|
||||
FString codeBlock;
|
||||
codeBlock << LoadPrivateShaderLump(frag_lump).GetChars() << "\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "hwrenderer/postprocessing/hw_useruniforms.h"
|
||||
|
||||
class ShaderIncludeResult;
|
||||
class VulkanRenderDevice;
|
||||
class VulkanDevice;
|
||||
|
|
@ -122,6 +124,8 @@ class VkShaderProgram
|
|||
public:
|
||||
std::unique_ptr<VulkanShader> vert;
|
||||
std::unique_ptr<VulkanShader> frag;
|
||||
|
||||
UniformStructHolder Uniforms;
|
||||
};
|
||||
|
||||
class VkShaderManager
|
||||
|
|
@ -146,8 +150,8 @@ public:
|
|||
VulkanShader* GetLightTilesShader() { return LightTiles.get(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<VulkanShader> LoadVertShader(FString shadername, const char *vert_lump, const char *vert_lump_custom, const char *defines, const VkShaderKey& key);
|
||||
std::unique_ptr<VulkanShader> LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char* mateffect_lump, const char *light_lump_shared, const char *lightmodel_lump, const char *defines, const VkShaderKey& key);
|
||||
std::unique_ptr<VulkanShader> LoadVertShader(FString shadername, const char *vert_lump, const char *vert_lump_custom, const char *defines, const VkShaderKey& key, const UserUniforms *uniforms);
|
||||
std::unique_ptr<VulkanShader> LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char* mateffect_lump, const char *light_lump_shared, const char *lightmodel_lump, const char *defines, const VkShaderKey& key, const UserUniforms *uniforms);
|
||||
|
||||
ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system);
|
||||
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ void VkRenderState::ApplyRenderPass(int dt)
|
|||
|
||||
if (changingPipeline)
|
||||
{
|
||||
mCommandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mPassSetup->GetPipeline(pipelineKey));
|
||||
mCommandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mPassSetup->GetPipeline(pipelineKey, mUniforms));
|
||||
mPipelineKey = pipelineKey;
|
||||
}
|
||||
}
|
||||
|
|
@ -444,7 +444,12 @@ void VkRenderState::ApplyPushConstants()
|
|||
mPushConstants.uBoneIndexBase = mBoneIndexBase;
|
||||
mPushConstants.uFogballIndex = mFogballIndex >= 0 ? (mFogballIndex % MAX_FOGBALL_DATA) : -1;
|
||||
|
||||
mCommandBuffer->pushConstants(fb->GetRenderPassManager()->GetPipelineLayout(mPipelineKey.ShaderKey.UseLevelMesh), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants);
|
||||
mCommandBuffer->pushConstants(fb->GetRenderPassManager()->GetPipelineLayout(mPipelineKey.ShaderKey.UseLevelMesh, mUniforms.sz), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants);
|
||||
|
||||
if(mUniforms.sz > 0)
|
||||
{
|
||||
mCommandBuffer->pushConstants(fb->GetRenderPassManager()->GetPipelineLayout(mPipelineKey.ShaderKey.UseLevelMesh, mUniforms.sz), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, (uint32_t)sizeof(PushConstants), (uint32_t)mUniforms.sz, mUniforms.addr);
|
||||
}
|
||||
}
|
||||
|
||||
void VkRenderState::ApplyMatrices()
|
||||
|
|
@ -510,7 +515,7 @@ void VkRenderState::ApplyBufferSets()
|
|||
if (mViewpointOffset != mLastViewpointOffset || matrixOffset != mLastMatricesOffset || surfaceUniformsOffset != mLastSurfaceUniformsOffset || lightsOffset != mLastLightsOffset || fogballsOffset != mLastFogballsOffset)
|
||||
{
|
||||
auto descriptors = fb->GetDescriptorSetManager();
|
||||
VulkanPipelineLayout* layout = fb->GetRenderPassManager()->GetPipelineLayout(mPipelineKey.ShaderKey.UseLevelMesh);
|
||||
VulkanPipelineLayout* layout = fb->GetRenderPassManager()->GetPipelineLayout(mPipelineKey.ShaderKey.UseLevelMesh, mUniforms.sz);
|
||||
|
||||
uint32_t offsets[5] = { mViewpointOffset, matrixOffset, surfaceUniformsOffset, lightsOffset, fogballsOffset };
|
||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet());
|
||||
|
|
@ -1092,14 +1097,14 @@ void VkRenderState::ApplyLevelMeshPipeline(VulkanCommandBuffer* cmdbuffer, VkPip
|
|||
pushConstants.uBoneIndexBase = -1;
|
||||
pushConstants.uFogballIndex = -1;
|
||||
|
||||
VulkanPipelineLayout* layout = fb->GetRenderPassManager()->GetPipelineLayout(pipelineKey.ShaderKey.UseLevelMesh);
|
||||
VulkanPipelineLayout* layout = fb->GetRenderPassManager()->GetPipelineLayout(pipelineKey.ShaderKey.UseLevelMesh, mUniforms.sz);
|
||||
uint32_t viewpointOffset = mViewpointOffset;
|
||||
uint32_t matrixOffset = mRSBuffers->MatrixBuffer->Offset();
|
||||
uint32_t fogballsOffset = 0;
|
||||
uint32_t offsets[] = { viewpointOffset, matrixOffset, fogballsOffset };
|
||||
|
||||
auto descriptors = fb->GetDescriptorSetManager();
|
||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mPassSetup->GetPipeline(pipelineKey));
|
||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mPassSetup->GetPipeline(pipelineKey, mUniforms));
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet());
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetLevelMeshSet(), 3, offsets);
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptors->GetBindlessSet());
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ protected:
|
|||
bool mDepthClamp = true;
|
||||
VulkanCommandBuffer *mCommandBuffer = nullptr;
|
||||
VkPipelineKey mPipelineKey = {};
|
||||
UniformStructHolder mUniforms;
|
||||
VkRenderPassSetup* mPassSetup = nullptr;
|
||||
int mClearTargets = 0;
|
||||
bool mNeedApply = true;
|
||||
|
|
|
|||
|
|
@ -114,8 +114,7 @@ struct UserShaderDesc
|
|||
bool disablealphatest = false;
|
||||
uint8_t shaderFlags = 0;
|
||||
|
||||
TMap<FString, UserUniformValue> Uniforms;
|
||||
UserUniforms UniformData;
|
||||
UserUniforms Uniforms;
|
||||
};
|
||||
|
||||
extern TArray<UserShaderDesc> usershaders;
|
||||
|
|
|
|||
|
|
@ -63,31 +63,34 @@ GlobalShaderDesc globalshaders[NUM_BUILTIN_SHADERS];
|
|||
|
||||
struct ExtraUniformCVARData
|
||||
{
|
||||
FString Shader;
|
||||
bool isPP;
|
||||
int ShaderIndex;
|
||||
FString Uniform;
|
||||
void * data = nullptr;
|
||||
ExtraUniformCVARData* Next = nullptr;
|
||||
void (*OldCallback)(FBaseCVar &);
|
||||
};
|
||||
|
||||
void pp_uniform_get_data(ExtraUniformCVARData* data)
|
||||
void uniform_get_data(ExtraUniformCVARData* data)
|
||||
{
|
||||
if (!(data->data))
|
||||
{
|
||||
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
||||
if(data->isPP)
|
||||
{
|
||||
PostProcessShader& shader = PostProcessShaders[i];
|
||||
if (strcmp(shader.Name.GetChars(), data->Shader.GetChars()) == 0)
|
||||
{
|
||||
data->data = shader.Uniforms.GetField(data->Uniform).Value;
|
||||
}
|
||||
PostProcessShader& shader = PostProcessShaders[data->ShaderIndex];
|
||||
data->data = shader.Uniforms.GetField(data->Uniform).Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
UserShaderDesc& shader = usershaders[data->ShaderIndex];
|
||||
data->data = shader.Uniforms.GetField(data->Uniform).Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void do_pp_uniform_set1i(int value, ExtraUniformCVARData* data)
|
||||
static void do_uniform_set1i(int value, ExtraUniformCVARData* data)
|
||||
{
|
||||
pp_uniform_get_data(data);
|
||||
uniform_get_data(data);
|
||||
|
||||
int * i1 = (int *)data->data;
|
||||
if (i1)
|
||||
|
|
@ -96,12 +99,12 @@ static void do_pp_uniform_set1i(int value, ExtraUniformCVARData* data)
|
|||
}
|
||||
|
||||
if (data->Next)
|
||||
do_pp_uniform_set1i(value, data->Next);
|
||||
do_uniform_set1i(value, data->Next);
|
||||
}
|
||||
|
||||
static void do_pp_uniform_set1f(float value, ExtraUniformCVARData* data)
|
||||
static void do_uniform_set1f(float value, ExtraUniformCVARData* data)
|
||||
{
|
||||
pp_uniform_get_data(data);
|
||||
uniform_get_data(data);
|
||||
|
||||
float * f1 = (float *)data->data;
|
||||
if (f1)
|
||||
|
|
@ -110,12 +113,12 @@ static void do_pp_uniform_set1f(float value, ExtraUniformCVARData* data)
|
|||
}
|
||||
|
||||
if (data->Next)
|
||||
do_pp_uniform_set1f(value, data->Next);
|
||||
do_uniform_set1f(value, data->Next);
|
||||
}
|
||||
|
||||
static void do_pp_uniform_set2f(float x, float y, ExtraUniformCVARData* data)
|
||||
static void do_uniform_set2f(float x, float y, ExtraUniformCVARData* data)
|
||||
{
|
||||
pp_uniform_get_data(data);
|
||||
uniform_get_data(data);
|
||||
|
||||
float * f2 = (float *)data->data;
|
||||
if (f2)
|
||||
|
|
@ -125,12 +128,12 @@ static void do_pp_uniform_set2f(float x, float y, ExtraUniformCVARData* data)
|
|||
}
|
||||
|
||||
if (data->Next)
|
||||
do_pp_uniform_set2f(x, y, data->Next);
|
||||
do_uniform_set2f(x, y, data->Next);
|
||||
}
|
||||
|
||||
static void do_pp_uniform_set3f(float x, float y, float z, ExtraUniformCVARData* data)
|
||||
static void do_uniform_set3f(float x, float y, float z, ExtraUniformCVARData* data)
|
||||
{
|
||||
pp_uniform_get_data(data);
|
||||
uniform_get_data(data);
|
||||
|
||||
float * f3 = (float *)data->data;
|
||||
if (f3)
|
||||
|
|
@ -141,12 +144,12 @@ static void do_pp_uniform_set3f(float x, float y, float z, ExtraUniformCVARData*
|
|||
}
|
||||
|
||||
if (data->Next)
|
||||
do_pp_uniform_set3f(x, y, z, data->Next);
|
||||
do_uniform_set3f(x, y, z, data->Next);
|
||||
}
|
||||
|
||||
static void do_pp_uniform_set4f(float x, float y, float z, float w, ExtraUniformCVARData* data)
|
||||
static void do_uniform_set4f(float x, float y, float z, float w, ExtraUniformCVARData* data)
|
||||
{
|
||||
pp_uniform_get_data(data);
|
||||
uniform_get_data(data);
|
||||
|
||||
float * f4 = (float *)data->data;
|
||||
if (f4)
|
||||
|
|
@ -158,28 +161,28 @@ static void do_pp_uniform_set4f(float x, float y, float z, float w, ExtraUniform
|
|||
}
|
||||
|
||||
if (data->Next)
|
||||
do_pp_uniform_set4f(x, y, z, w, data->Next);
|
||||
do_uniform_set4f(x, y, z, w, data->Next);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void pp_uniform_callback1i(T &self)
|
||||
void uniform_callback1i(T &self)
|
||||
{
|
||||
auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2();
|
||||
if(data->OldCallback) data->OldCallback(self);
|
||||
|
||||
do_pp_uniform_set1i(*self, data);
|
||||
do_uniform_set1i(*self, data);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void pp_uniform_callback1f(T &self)
|
||||
void uniform_callback1f(T &self)
|
||||
{
|
||||
auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2();
|
||||
if(data->OldCallback) data->OldCallback(self);
|
||||
|
||||
do_pp_uniform_set1f(*self, data);
|
||||
do_uniform_set1f(*self, data);
|
||||
}
|
||||
|
||||
void pp_uniform_callback_color3f(FColorCVar &self)
|
||||
void uniform_callback_color3f(FColorCVar &self)
|
||||
{
|
||||
auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2();
|
||||
if(data->OldCallback) data->OldCallback(self);
|
||||
|
|
@ -187,10 +190,10 @@ void pp_uniform_callback_color3f(FColorCVar &self)
|
|||
PalEntry col;
|
||||
col.d = *self;
|
||||
|
||||
do_pp_uniform_set3f(col.r / 255.0, col.g / 255.0, col.b / 255.0, data);
|
||||
do_uniform_set3f(col.r / 255.0, col.g / 255.0, col.b / 255.0, data);
|
||||
}
|
||||
|
||||
void pp_uniform_callback_color4f(FColorCVar &self)
|
||||
void uniform_callback_color4f(FColorCVar &self)
|
||||
{
|
||||
auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2();
|
||||
if(data->OldCallback) data->OldCallback(self);
|
||||
|
|
@ -198,7 +201,7 @@ void pp_uniform_callback_color4f(FColorCVar &self)
|
|||
PalEntry col;
|
||||
col.d = *self;
|
||||
|
||||
do_pp_uniform_set4f(col.r / 255.0, col.g / 255.0, col.b / 255.0, col.a / 255.0, data);
|
||||
do_uniform_set4f(col.r / 255.0, col.g / 255.0, col.b / 255.0, col.a / 255.0, data);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1403,6 +1406,9 @@ class GLDefsParser
|
|||
bool iwad = false;
|
||||
bool no_mipmap = false;
|
||||
|
||||
bool hasUniforms = false;
|
||||
TMap<FString, UserUniformValue> Uniforms;
|
||||
|
||||
bool is_globalshader = false;
|
||||
TArray<int> globaltargets;
|
||||
FString str_globaltargets;
|
||||
|
|
@ -1612,6 +1618,12 @@ class GLDefsParser
|
|||
sc.MustGetString();
|
||||
usershader.vertshader = sc.String;
|
||||
}
|
||||
else if (sc.Compare("uniform"))
|
||||
{
|
||||
isProperty = true;
|
||||
hasUniforms = true;
|
||||
ParseShaderUniform(Uniforms, usershaders.Size(), false);
|
||||
}
|
||||
else if (sc.Compare("texture"))
|
||||
{
|
||||
isProperty = true;
|
||||
|
|
@ -1822,6 +1834,11 @@ class GLDefsParser
|
|||
|
||||
globalshaders[target].shaderindex = usershaders.Push(usershader) + FIRST_USER_SHADER;
|
||||
|
||||
if(hasUniforms)
|
||||
{
|
||||
usershaders.Last().Uniforms.LoadUniforms(Uniforms);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_CUSTOM_HW_SHADER_TEXTURES; i++)
|
||||
{
|
||||
if (mlay.CustomShaderTextures[i])
|
||||
|
|
@ -1927,20 +1944,29 @@ class GLDefsParser
|
|||
}
|
||||
tex->SetShaderSpeed(speed);
|
||||
|
||||
for (unsigned i = 0; i < usershaders.Size(); i++)
|
||||
{
|
||||
if (!usershaders[i].shader.CompareNoCase(usershader.shader) &&
|
||||
usershaders[i].shaderType == usershader.shaderType &&
|
||||
usershaders[i].shaderFlags == usershader.shaderFlags &&
|
||||
!usershaders[i].defines.Compare(usershader.defines))
|
||||
if(!hasUniforms)
|
||||
{ // shaders with uniforms are never reused
|
||||
for (unsigned i = 0; i < usershaders.Size(); i++)
|
||||
{
|
||||
SetShaderIndex(tex, i + FIRST_USER_SHADER);
|
||||
tex->SetShaderLayers(mlay);
|
||||
return;
|
||||
if (!usershaders[i].shader.CompareNoCase(usershader.shader) &&
|
||||
usershaders[i].shaderType == usershader.shaderType &&
|
||||
usershaders[i].shaderFlags == usershader.shaderFlags &&
|
||||
!usershaders[i].defines.Compare(usershader.defines) &&
|
||||
usershaders[i].Uniforms.UniformStructSize == 0)
|
||||
{
|
||||
SetShaderIndex(tex, i + FIRST_USER_SHADER);
|
||||
tex->SetShaderLayers(mlay);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetShaderIndex(tex, usershaders.Push(usershader) + FIRST_USER_SHADER);
|
||||
|
||||
if(hasUniforms)
|
||||
{
|
||||
usershaders.Last().Uniforms.LoadUniforms(Uniforms);
|
||||
}
|
||||
}
|
||||
tex->SetShaderLayers(mlay);
|
||||
}
|
||||
|
|
@ -1953,18 +1979,247 @@ class GLDefsParser
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void ParseShaderUniform(TMap<FString, UserUniformValue> &Uniforms, int ShaderIndex, bool isPP)
|
||||
{
|
||||
bool is_cvar = false;
|
||||
bool ok = true;
|
||||
|
||||
sc.MustGetString();
|
||||
FString uniformType = sc.String;
|
||||
uniformType.ToLower();
|
||||
|
||||
sc.MustGetString();
|
||||
FString uniformName = sc.String;
|
||||
|
||||
UniformType parsedType = UniformType::Undefined;
|
||||
|
||||
if (uniformType.Compare("int") == 0)
|
||||
{
|
||||
parsedType = UniformType::Int;
|
||||
}
|
||||
else if (uniformType.Compare("float") == 0)
|
||||
{
|
||||
parsedType = UniformType::Float;
|
||||
}
|
||||
else if (uniformType.Compare("vec2") == 0)
|
||||
{
|
||||
parsedType = UniformType::Vec2;
|
||||
}
|
||||
else if (uniformType.Compare("vec3") == 0)
|
||||
{
|
||||
parsedType = UniformType::Vec3;
|
||||
}
|
||||
else if (uniformType.Compare("vec4") == 0)
|
||||
{
|
||||
parsedType = UniformType::Vec4;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unrecognized uniform type '%s'", sc.String);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
double Values[4] = {0.0, 0.0, 0.0, 1.0};
|
||||
|
||||
if(ok && sc.CheckToken('='))
|
||||
{
|
||||
if(sc.CheckString("cvar"))
|
||||
{
|
||||
is_cvar = true;
|
||||
}
|
||||
else switch(parsedType)
|
||||
{
|
||||
case UniformType::Int:
|
||||
sc.MustGetNumber();
|
||||
Values[0] = sc.BigNumber;
|
||||
break;
|
||||
case UniformType::Float:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
break;
|
||||
case UniformType::Vec2:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[1] = sc.Float;
|
||||
break;
|
||||
case UniformType::Vec3:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[1] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[2] = sc.Float;
|
||||
break;
|
||||
case UniformType::Vec4:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[1] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[2] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[3] = sc.Float;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (ok && !is_cvar)
|
||||
{
|
||||
Uniforms[uniformName].Type = parsedType;
|
||||
Uniforms[uniformName].Values[0] = Values[0];
|
||||
Uniforms[uniformName].Values[1] = Values[1];
|
||||
Uniforms[uniformName].Values[2] = Values[2];
|
||||
Uniforms[uniformName].Values[3] = Values[3];
|
||||
}
|
||||
|
||||
if (ok && is_cvar)
|
||||
{
|
||||
FBaseCVar *cvar;
|
||||
FString cvarname;
|
||||
void (*callback)(FBaseCVar&) = nullptr;
|
||||
|
||||
if(ok)
|
||||
{
|
||||
sc.MustGetString();
|
||||
cvarname = sc.String;
|
||||
cvar = FindCVar(cvarname.GetChars(), NULL);
|
||||
|
||||
if (!cvar)
|
||||
{
|
||||
sc.ScriptMessage("Unknown cvar passed to cvar_uniform");
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(ok)
|
||||
{
|
||||
switch (cvar->GetRealType())
|
||||
{
|
||||
case CVAR_Bool:
|
||||
if(parsedType == UniformType::Int)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&uniform_callback1i<FBoolCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
}
|
||||
else if(parsedType == UniformType::Float)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&uniform_callback1f<FBoolCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("CVar '%s' type (bool) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars());
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
case CVAR_Int:
|
||||
if(parsedType == UniformType::Int)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&uniform_callback1i<FIntCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
}
|
||||
else if(parsedType == UniformType::Float)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&uniform_callback1f<FIntCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("CVar '%s' type (int) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars());
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
case CVAR_Float:
|
||||
if(parsedType == UniformType::Int)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&uniform_callback1i<FFloatCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Float).Float;
|
||||
}
|
||||
else if(parsedType == UniformType::Float)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&uniform_callback1f<FFloatCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Float).Float;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("CVar '%s' type (float) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars());
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
case CVAR_Color:
|
||||
if(parsedType == UniformType::Vec3)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&uniform_callback_color3f);
|
||||
|
||||
PalEntry col;
|
||||
col.d = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
Values[0] = col.r / 255.0;
|
||||
Values[1] = col.g / 255.0;
|
||||
Values[2] = col.b / 255.0;
|
||||
}
|
||||
else if(parsedType == UniformType::Vec4)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&uniform_callback_color4f);
|
||||
|
||||
PalEntry col;
|
||||
col.d = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
Values[0] = col.r / 255.0;
|
||||
Values[1] = col.g / 255.0;
|
||||
Values[2] = col.b / 255.0;
|
||||
Values[3] = col.a / 255.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("CVar '%s' type (color) is not convertible to uniform type (%s), must be vec3 or vec4", cvarname.GetChars(), uniformType.GetChars());
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc.ScriptError("CVar '%s' type not supported for uniforms!", cvarname.GetChars());
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ok)
|
||||
{
|
||||
ExtraUniformCVARData* oldextra = (ExtraUniformCVARData*) cvar->GetExtraDataPointer2();
|
||||
|
||||
ExtraUniformCVARData* extra = new ExtraUniformCVARData;
|
||||
extra->isPP = isPP;
|
||||
extra->ShaderIndex = ShaderIndex;
|
||||
extra->Uniform = uniformName.GetChars();
|
||||
extra->OldCallback = oldextra ? oldextra->OldCallback : cvar->m_Callback;
|
||||
extra->Next = oldextra;
|
||||
|
||||
cvar->SetCallback(callback);
|
||||
cvar->SetExtraDataPointer2(extra);
|
||||
|
||||
Uniforms[uniformName].Type = parsedType;
|
||||
Uniforms[uniformName].Values[0] = Values[0];
|
||||
Uniforms[uniformName].Values[1] = Values[1];
|
||||
Uniforms[uniformName].Values[2] = Values[2];
|
||||
Uniforms[uniformName].Values[3] = Values[3];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ParseHardwareShader()
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("postprocess"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
|
||||
|
||||
PostProcessShader shaderdesc;
|
||||
TMap<FString, UserUniformValue> Uniforms;
|
||||
shaderdesc.Target = sc.String;
|
||||
shaderdesc.Target.ToLower();
|
||||
|
||||
bool hasUniforms = false;
|
||||
bool validTarget = false;
|
||||
if (sc.Compare("beforebloom")) validTarget = true;
|
||||
if (sc.Compare("scene")) validTarget = true;
|
||||
|
|
@ -1993,215 +2248,8 @@ class GLDefsParser
|
|||
}
|
||||
else if (sc.Compare("uniform"))
|
||||
{
|
||||
bool is_cvar = false;
|
||||
bool ok = true;
|
||||
|
||||
sc.MustGetString();
|
||||
FString uniformType = sc.String;
|
||||
uniformType.ToLower();
|
||||
|
||||
sc.MustGetString();
|
||||
FString uniformName = sc.String;
|
||||
|
||||
UniformType parsedType = UniformType::Undefined;
|
||||
|
||||
if (uniformType.Compare("int") == 0)
|
||||
{
|
||||
parsedType = UniformType::Int;
|
||||
}
|
||||
else if (uniformType.Compare("float") == 0)
|
||||
{
|
||||
parsedType = UniformType::Float;
|
||||
}
|
||||
else if (uniformType.Compare("vec2") == 0)
|
||||
{
|
||||
parsedType = UniformType::Vec2;
|
||||
}
|
||||
else if (uniformType.Compare("vec3") == 0)
|
||||
{
|
||||
parsedType = UniformType::Vec3;
|
||||
}
|
||||
else if (uniformType.Compare("vec4") == 0)
|
||||
{
|
||||
parsedType = UniformType::Vec4;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unrecognized uniform type '%s'", sc.String);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
double Values[4] = {0.0, 0.0, 0.0, 1.0};
|
||||
|
||||
if(ok && sc.CheckToken('='))
|
||||
{
|
||||
if(sc.CheckString("cvar"))
|
||||
{
|
||||
is_cvar = true;
|
||||
}
|
||||
else switch(parsedType)
|
||||
{
|
||||
case UniformType::Int:
|
||||
sc.MustGetNumber();
|
||||
Values[0] = sc.BigNumber;
|
||||
break;
|
||||
case UniformType::Float:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
break;
|
||||
case UniformType::Vec2:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[1] = sc.Float;
|
||||
break;
|
||||
case UniformType::Vec3:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[1] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[2] = sc.Float;
|
||||
break;
|
||||
case UniformType::Vec4:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[1] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[2] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[3] = sc.Float;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (ok && !is_cvar)
|
||||
{
|
||||
Uniforms[uniformName].Type = parsedType;
|
||||
Uniforms[uniformName].Values[0] = Values[0];
|
||||
Uniforms[uniformName].Values[1] = Values[1];
|
||||
Uniforms[uniformName].Values[2] = Values[2];
|
||||
Uniforms[uniformName].Values[3] = Values[3];
|
||||
}
|
||||
|
||||
if (ok && is_cvar)
|
||||
{
|
||||
if (shaderdesc.Name.IsEmpty())
|
||||
sc.ScriptError("Shader must have a name to use cvar uniforms");
|
||||
|
||||
int cvarflags = CVAR_MOD|CVAR_ARCHIVE|CVAR_VIRTUAL;
|
||||
FBaseCVar *cvar;
|
||||
FString cvarname;
|
||||
void (*callback)(FBaseCVar&) = nullptr;
|
||||
|
||||
if(ok)
|
||||
{
|
||||
sc.MustGetString();
|
||||
cvarname = sc.String;
|
||||
cvar = FindCVar(cvarname.GetChars(), NULL);
|
||||
|
||||
if (!cvar)
|
||||
{
|
||||
sc.ScriptMessage("Unknown cvar passed to cvar_uniform");
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(ok)
|
||||
{
|
||||
switch (cvar->GetRealType())
|
||||
{
|
||||
case CVAR_Int:
|
||||
if(parsedType == UniformType::Int)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1i<FIntCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
}
|
||||
else if(parsedType == UniformType::Float)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1f<FIntCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("CVar '%s' type (int) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars());
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
case CVAR_Float:
|
||||
if(parsedType == UniformType::Int)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1i<FFloatCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Float).Float;
|
||||
}
|
||||
else if(parsedType == UniformType::Float)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1f<FFloatCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Float).Float;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("CVar '%s' type (float) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars());
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
case CVAR_Color:
|
||||
if(parsedType == UniformType::Vec3)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback_color3f);
|
||||
|
||||
PalEntry col;
|
||||
col.d = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
Values[0] = col.r / 255.0;
|
||||
Values[1] = col.g / 255.0;
|
||||
Values[2] = col.b / 255.0;
|
||||
}
|
||||
else if(parsedType == UniformType::Vec4)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback_color4f);
|
||||
|
||||
PalEntry col;
|
||||
col.d = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
Values[0] = col.r / 255.0;
|
||||
Values[1] = col.g / 255.0;
|
||||
Values[2] = col.b / 255.0;
|
||||
Values[3] = col.a / 255.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("CVar '%s' type (color) is not convertible to uniform type (%s), must be vec3 or vec4", cvarname.GetChars(), uniformType.GetChars());
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc.ScriptError("CVar '%s' type not supported for uniforms!", cvarname.GetChars());
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ok)
|
||||
{
|
||||
ExtraUniformCVARData* oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer2();
|
||||
|
||||
ExtraUniformCVARData* extra = new ExtraUniformCVARData;
|
||||
extra->Shader = shaderdesc.Name.GetChars();
|
||||
extra->Uniform = uniformName.GetChars();
|
||||
extra->OldCallback = oldextra ? oldextra->OldCallback : cvar->m_Callback;
|
||||
extra->Next = oldextra;
|
||||
|
||||
cvar->SetCallback(callback);
|
||||
cvar->SetExtraDataPointer2(extra);
|
||||
|
||||
Uniforms[uniformName].Type = parsedType;
|
||||
Uniforms[uniformName].Values[0] = Values[0];
|
||||
Uniforms[uniformName].Values[1] = Values[1];
|
||||
Uniforms[uniformName].Values[2] = Values[2];
|
||||
Uniforms[uniformName].Values[3] = Values[3];
|
||||
}
|
||||
}
|
||||
hasUniforms = true;
|
||||
ParseShaderUniform(Uniforms, PostProcessShaders.Size(), true);
|
||||
}
|
||||
else if (sc.Compare("texture"))
|
||||
{
|
||||
|
|
@ -2224,7 +2272,11 @@ class GLDefsParser
|
|||
}
|
||||
|
||||
auto index = PostProcessShaders.Push(shaderdesc);
|
||||
PostProcessShaders[index].Uniforms.LoadUniforms(Uniforms);
|
||||
|
||||
if(hasUniforms)
|
||||
{
|
||||
PostProcessShaders.Last().Uniforms.LoadUniforms(Uniforms);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,20 +3,6 @@
|
|||
#include "shaders/scene/binding_rsbuffers.glsl"
|
||||
#include "shaders/scene/binding_textures.glsl"
|
||||
|
||||
// This must match the PushConstants struct
|
||||
layout(push_constant) uniform PushConstants
|
||||
{
|
||||
#if defined(USE_LEVELMESH)
|
||||
int unused0;
|
||||
int unused1;
|
||||
#else
|
||||
int uDataIndex; // surfaceuniforms index
|
||||
int uLightIndex; // dynamic lights
|
||||
#endif
|
||||
int uBoneIndexBase; // bone animation
|
||||
int uFogballIndex; // fog balls
|
||||
};
|
||||
|
||||
// material types
|
||||
#if defined(SPECULAR)
|
||||
#define normaltexture texture2
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue