vulkan material system
This commit is contained in:
parent
78f2aa18bf
commit
42bd8b06b5
@ -43,5 +43,30 @@ namespace api {
|
|||||||
Material* operator->() {
|
Material* operator->() {
|
||||||
return mMaterial.Ptr();
|
return mMaterial.Ptr();
|
||||||
}
|
}
|
||||||
|
template<typename T>
|
||||||
|
bool SetResource(MaterialResource* pResource, const T& t) {
|
||||||
|
if (!pResource) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto obj = pResource->obj;
|
||||||
|
#ifdef API_DEBUG
|
||||||
|
if (!obj.Check(meta_info<T>())) {
|
||||||
|
throw std::runtime_error("Error: SetResource with error class type");
|
||||||
|
}
|
||||||
|
#endif // API_DEBUG
|
||||||
|
*(obj.CastTo<T*>()) = t;
|
||||||
|
pResource->isDirty = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
bool SetStaticResource(Name name,const T& t) {
|
||||||
|
auto pResource = mInfo.staticBlock.FindMaterialResource(name);
|
||||||
|
return SetResource(pResource, t);
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
bool SetClassResource(Name name, const T& t) {
|
||||||
|
auto pResource = mInfo.classBlock.FindMaterialResource(name);
|
||||||
|
return SetResource(pResource, t);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -2,12 +2,19 @@
|
|||||||
#include "vertex.h"
|
#include "vertex.h"
|
||||||
namespace api{
|
namespace api{
|
||||||
struct ubMetaInfo {
|
struct ubMetaInfo {
|
||||||
uint32_t set;
|
uint32_t set{0};
|
||||||
uint32_t binding;
|
uint32_t binding{0};
|
||||||
bool isShared{false};
|
bool isUnique{false};
|
||||||
|
static ubMetaInfo FromField(const refl::FieldPtr& field) {
|
||||||
|
refl::Any meta = field.GetMeta();
|
||||||
|
if (meta) {
|
||||||
|
return meta.CastTo<ubMetaInfo>();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct ubSimple {
|
struct ubSimple {
|
||||||
UPROPERTY({}, api::ubMetaInfo{ .set = 0, .binding = 0 })
|
UPROPERTY({}, api::ubMetaInfo{ .set = 0, .binding = 0 , .isUnique = true})
|
||||||
Vector4 uColor;
|
Vector4 uColor;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "pmr/name.h"
|
#include "refl/pch.h"
|
||||||
#include "tinyimageformat/tinyimageformat_base.h"
|
#include "tinyimageformat/tinyimageformat_base.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
//#include <algorithm>
|
||||||
namespace api {
|
namespace api {
|
||||||
using pmr::Name;
|
using pmr::Name;
|
||||||
enum class GraphicsAPI
|
enum class GraphicsAPI
|
||||||
@ -97,16 +98,61 @@ namespace api {
|
|||||||
VERTEX = 0x1,
|
VERTEX = 0x1,
|
||||||
FRAGMENT = 0x2,
|
FRAGMENT = 0x2,
|
||||||
};
|
};
|
||||||
struct MaterialInfo {
|
struct MaterialResource {
|
||||||
|
Name name;
|
||||||
|
bool isDirty;
|
||||||
|
bool isUnique;
|
||||||
|
refl::Any obj;
|
||||||
|
void* Ptr()const {
|
||||||
|
return (void*)obj.ptr;
|
||||||
|
}
|
||||||
|
uint32_t Size()const {
|
||||||
|
return obj.cls ? obj.cls->size : 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct MaterialResourceBlock {
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
void* pHeader;
|
uint32_t blockSize;
|
||||||
char* pFlag;
|
MaterialResource* pResource;
|
||||||
struct Header {
|
static MaterialResourceBlock FromFields(std::span<const refl::FieldPtr> fields);
|
||||||
Name name;
|
operator bool() {
|
||||||
uint32_t size;
|
return pResource;
|
||||||
void* pCpuData;
|
}
|
||||||
void* pMappingData;
|
MaterialResource* FindMaterialResource(Name name) {
|
||||||
};
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
MaterialResource* res = (pResource + i);
|
||||||
|
if (res->name == name) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
void Upload(void** ppMappingAddr) {
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
auto res = pResource[i];
|
||||||
|
if (res.isDirty || res.isUnique) {
|
||||||
|
memcpy(*(ppMappingAddr + i), res.Ptr(), res.Size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct MaterialGpuResourceBlock {
|
||||||
|
uint16_t blockSize;
|
||||||
|
uint16_t bufferOffset;
|
||||||
|
bool isInit;
|
||||||
|
void** pMappingAddr;
|
||||||
|
operator bool() {
|
||||||
|
return isInit;
|
||||||
|
}
|
||||||
|
void* BufferPtr() {
|
||||||
|
return (char*)pMappingAddr + bufferOffset;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct MaterialInfo {
|
||||||
|
bool isInit = false;
|
||||||
|
MaterialGpuResourceBlock gpuBlock;
|
||||||
|
MaterialResourceBlock classBlock;
|
||||||
|
MaterialResourceBlock staticBlock;
|
||||||
};
|
};
|
||||||
struct ShaderDescriptorLayout {
|
struct ShaderDescriptorLayout {
|
||||||
Name name;
|
Name name;
|
||||||
|
|||||||
@ -46,9 +46,8 @@ namespace api {
|
|||||||
mesh->SetMaterial(material);
|
mesh->SetMaterial(material);
|
||||||
RenderAPI::Ptr()->SetStaticMesh(*mesh);
|
RenderAPI::Ptr()->SetStaticMesh(*mesh);
|
||||||
RenderAPI::Ptr()->SetUpMaterialInstance(mesh->GetMaterialInstance());
|
RenderAPI::Ptr()->SetUpMaterialInstance(mesh->GetMaterialInstance());
|
||||||
ResourceSystem::Ptr()->AddDirtyFile("/engine/assets/shader/simple.vert");
|
auto materialInstance = mesh->GetMaterialInstance();
|
||||||
ResourceSystem::Ptr()->AddDirtyFile("/engine/assets/shader/simple.frag");
|
materialInstance.SetClassResource(Name("uColor"), Vector4{1,0,0,1});
|
||||||
ResourceSystem::Ptr()->SaveDirtyFile();
|
|
||||||
}
|
}
|
||||||
auto& surface = graph.mSurface;
|
auto& surface = graph.mSurface;
|
||||||
ctx->SetViewport(0.0f, 0.0f,(float)surface.width,(float)surface.height, 0.f, 1.f);
|
ctx->SetViewport(0.0f, 0.0f,(float)surface.width,(float)surface.height, 0.f, 1.f);
|
||||||
|
|||||||
@ -1,3 +1,38 @@
|
|||||||
|
#include "render/type.h"
|
||||||
|
#include "render/asset/ubo.h"
|
||||||
|
#include <algorithm>
|
||||||
|
namespace api {
|
||||||
|
MaterialResourceBlock MaterialResourceBlock::FromFields(std::span<const refl::FieldPtr> fields)
|
||||||
|
{
|
||||||
|
uint32_t count = fields.size();
|
||||||
|
if (!count) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
uint32_t blockSize = meta_align_size(sizeof(MaterialResource) * count);
|
||||||
|
for (auto& field : fields) {
|
||||||
|
blockSize += meta_align_size(field.type->size);
|
||||||
|
}
|
||||||
|
MaterialResource* refResource = (MaterialResource*)xmalloc(blockSize);
|
||||||
|
char* pObj = (char*)refResource + meta_align_size(sizeof(MaterialResource) * count);
|
||||||
|
MaterialResource* pResource = refResource;
|
||||||
|
for (auto& field : fields) {
|
||||||
|
new(pResource)MaterialResource{};
|
||||||
|
pResource->name = field.name;
|
||||||
|
pResource->obj = field.Construct(pObj);
|
||||||
|
pResource->isDirty = false;
|
||||||
|
ubMetaInfo ub = ubMetaInfo::FromField(field);
|
||||||
|
pResource->isUnique = ub.isUnique;
|
||||||
|
pObj += meta_align_size(field.type->size);
|
||||||
|
pResource++;
|
||||||
|
}
|
||||||
|
if (count > 1) {
|
||||||
|
std::sort(refResource, refResource, [](const MaterialResource& res1, const MaterialResource& res2) {
|
||||||
|
return res1.name < res2.name;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return { count , blockSize , refResource };
|
||||||
|
}
|
||||||
|
}
|
||||||
#ifdef RENDER_API_VAL
|
#ifdef RENDER_API_VAL
|
||||||
#include "renderapi_impl.inl"
|
#include "renderapi_impl.inl"
|
||||||
#include "window_impl.inl"
|
#include "window_impl.inl"
|
||||||
|
|||||||
@ -67,7 +67,7 @@ namespace api
|
|||||||
};
|
};
|
||||||
auto FindFieldFn = [](FieldPtrSpan fieldList, uint32_t set, uint32_t binding) -> FindFieldResult{
|
auto FindFieldFn = [](FieldPtrSpan fieldList, uint32_t set, uint32_t binding) -> FindFieldResult{
|
||||||
for (auto& field : fieldList) {
|
for (auto& field : fieldList) {
|
||||||
ubMetaInfo info = field.GetMeta().CastTo<ubMetaInfo>();
|
ubMetaInfo info = ubMetaInfo::FromField(field);
|
||||||
if (info.set == set && info.binding == binding) {
|
if (info.set == set && info.binding == binding) {
|
||||||
return { &field , info};
|
return { &field , info};
|
||||||
}
|
}
|
||||||
@ -84,7 +84,6 @@ namespace api
|
|||||||
layout.stageFlags = stage;
|
layout.stageFlags = stage;
|
||||||
if (auto result = FindFieldFn(fieldList, layout.set, layout.binding)) {
|
if (auto result = FindFieldFn(fieldList, layout.set, layout.binding)) {
|
||||||
layout.name = result.field->name;
|
layout.name = result.field->name;
|
||||||
layout.isShared = result.info.isShared;
|
|
||||||
}
|
}
|
||||||
return layout;
|
return layout;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -144,4 +144,15 @@ namespace refl{
|
|||||||
memset(ptr, 0, size);
|
memset(ptr, 0, size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
inline Any FieldPtr::Construct(void* ptr) const
|
||||||
|
{
|
||||||
|
Any obj{ ptr, type };
|
||||||
|
if (data.member.value && flag & FIELD_MEMBER_FLAG) {
|
||||||
|
obj.Construct(data.member.value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj.Construct({});
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -22,9 +22,10 @@ namespace refl {
|
|||||||
enum FieldFlag :uint32_t {
|
enum FieldFlag :uint32_t {
|
||||||
FIELD_NONE_FLAG = 0,
|
FIELD_NONE_FLAG = 0,
|
||||||
FIELD_MEMBER_FLAG = 1 << 0,
|
FIELD_MEMBER_FLAG = 1 << 0,
|
||||||
FIELD_METHOD_FLAG = 1 << 1,
|
FIELD_STATIC_MEMBER_FLAG = 1 << 1,
|
||||||
FIELD_METHOD_VALUE_FLAG = 1 << 2,
|
FIELD_METHOD_FLAG = 1 << 2,
|
||||||
FIELD_CTOR_FLAG = 1 << 3,
|
FIELD_METHOD_VALUE_FLAG = 1 << 3,
|
||||||
|
FIELD_CTOR_FLAG = 1 << 4,
|
||||||
};
|
};
|
||||||
struct FieldPtr {
|
struct FieldPtr {
|
||||||
union Data
|
union Data
|
||||||
@ -42,12 +43,16 @@ namespace refl {
|
|||||||
const UClass* type{};
|
const UClass* type{};
|
||||||
Data data{};
|
Data data{};
|
||||||
uint32_t flag{};
|
uint32_t flag{};
|
||||||
|
bool IsStatic()const {
|
||||||
|
return flag & FIELD_STATIC_MEMBER_FLAG;
|
||||||
|
}
|
||||||
Offset GetOffset() const {
|
Offset GetOffset() const {
|
||||||
if (flag & FIELD_MEMBER_FLAG) {
|
if (flag & FIELD_MEMBER_FLAG) {
|
||||||
return data.member.offset;
|
return data.member.offset;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Any Construct(void* ptr)const;
|
||||||
Any GetValue()const {
|
Any GetValue()const {
|
||||||
if (flag & FIELD_MEMBER_FLAG)
|
if (flag & FIELD_MEMBER_FLAG)
|
||||||
return data.member.value;
|
return data.member.value;
|
||||||
|
|||||||
@ -35,6 +35,9 @@ namespace refl {
|
|||||||
template<typename T, typename Obj>
|
template<typename T, typename Obj>
|
||||||
static FieldPtr MemberField(T Obj::* ptr, std::string_view name, const MemberData& data = {});
|
static FieldPtr MemberField(T Obj::* ptr, std::string_view name, const MemberData& data = {});
|
||||||
|
|
||||||
|
template<typename T, typename Obj>
|
||||||
|
static FieldPtr MemberField(T* ptr, std::string_view name, const MemberData& data = {});
|
||||||
|
|
||||||
template<typename R, typename ...Args>
|
template<typename R, typename ...Args>
|
||||||
static FieldPtr MethodField(R(*ptr)(Args...), std::string_view name, const MethodData& data = {});
|
static FieldPtr MethodField(R(*ptr)(Args...), std::string_view name, const MethodData& data = {});
|
||||||
|
|
||||||
|
|||||||
@ -57,6 +57,21 @@ namespace refl {
|
|||||||
}
|
}
|
||||||
return FieldPtr{ name, cls, member, flag };
|
return FieldPtr{ name, cls, member, flag };
|
||||||
}
|
}
|
||||||
|
template<typename T, typename Obj>
|
||||||
|
inline FieldPtr MetaHelp::MemberField(T* ptr, std::string_view name, const MemberData& data)
|
||||||
|
{
|
||||||
|
const UClass* cls = meta_info<T>();
|
||||||
|
uint32_t flag = FIELD_STATIC_MEMBER_FLAG;
|
||||||
|
MemberData member;
|
||||||
|
member.offset = reinterpret_cast<std::size_t>(&(reinterpret_cast<const Obj*>(0)->*ptr));
|
||||||
|
if (data.value) {
|
||||||
|
member.value = data.value.New(MetaGlobalPool());
|
||||||
|
}
|
||||||
|
if (data.meta) {
|
||||||
|
member.meta = data.meta.New(MetaGlobalPool());
|
||||||
|
}
|
||||||
|
return FieldPtr{ name, cls, member, flag };
|
||||||
|
}
|
||||||
template<typename R, typename ...Args>
|
template<typename R, typename ...Args>
|
||||||
inline FieldPtr MetaHelp::MethodField(R(*ptr)(Args...), std::string_view name, const MethodData& data)
|
inline FieldPtr MetaHelp::MethodField(R(*ptr)(Args...), std::string_view name, const MethodData& data)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -17,6 +17,7 @@ namespace refl {
|
|||||||
enum EFieldFind :uint32_t {
|
enum EFieldFind :uint32_t {
|
||||||
FIND_ALL_FIELD = 0,
|
FIND_ALL_FIELD = 0,
|
||||||
FIND_ALL_MEMBER,
|
FIND_ALL_MEMBER,
|
||||||
|
FIND_ALL_MEMBER_WITH_STATIC,
|
||||||
FIND_ALL_METHOD,
|
FIND_ALL_METHOD,
|
||||||
FIND_FIELD,
|
FIND_FIELD,
|
||||||
FIND_CTOR,
|
FIND_CTOR,
|
||||||
|
|||||||
@ -178,16 +178,19 @@ namespace refl {
|
|||||||
span<const FieldPtr> GetFields(EFieldFind find, const Name& name) const {
|
span<const FieldPtr> GetFields(EFieldFind find, const Name& name) const {
|
||||||
constexpr int length = std::tuple_size<FieldsType>::value;
|
constexpr int length = std::tuple_size<FieldsType>::value;
|
||||||
constexpr int MemberCount = MetaImpl::MemberCount();
|
constexpr int MemberCount = MetaImpl::MemberCount();
|
||||||
|
constexpr int AllMemberCount = MemberCount + MetaImpl::StaticMemberCount();
|
||||||
constexpr int CtorCount = MetaImpl::CtorCount();
|
constexpr int CtorCount = MetaImpl::CtorCount();
|
||||||
switch (find) {
|
switch (find) {
|
||||||
case EFieldFind::FIND_ALL_FIELD:
|
case EFieldFind::FIND_ALL_FIELD:
|
||||||
return span<const FieldPtr>(&Fields[0], length);
|
return span<const FieldPtr>(&Fields[0], length);
|
||||||
case EFieldFind::FIND_ALL_MEMBER:
|
case EFieldFind::FIND_ALL_MEMBER:
|
||||||
return span<const FieldPtr>(&Fields[0], MemberCount);
|
return span<const FieldPtr>(&Fields[0], MemberCount);
|
||||||
|
case EFieldFind::FIND_ALL_MEMBER_WITH_STATIC:
|
||||||
|
return span<const FieldPtr>(&Fields[0], AllMemberCount);
|
||||||
case EFieldFind::FIND_ALL_METHOD:
|
case EFieldFind::FIND_ALL_METHOD:
|
||||||
return span<const FieldPtr>(&Fields[MemberCount + CtorCount], length - MemberCount - CtorCount);
|
return span<const FieldPtr>(&Fields[AllMemberCount + CtorCount], length - AllMemberCount - CtorCount);
|
||||||
case EFieldFind::FIND_CTOR:
|
case EFieldFind::FIND_CTOR:
|
||||||
return span<const FieldPtr>(&Fields[MemberCount], CtorCount);
|
return span<const FieldPtr>(&Fields[AllMemberCount], CtorCount);
|
||||||
case EFieldFind::FIND_FIELD:
|
case EFieldFind::FIND_FIELD:
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
if (name == Fields[i].name) {
|
if (name == Fields[i].name) {
|
||||||
@ -196,14 +199,14 @@ namespace refl {
|
|||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
case EFieldFind::FIND_MEMBER:
|
case EFieldFind::FIND_MEMBER:
|
||||||
for (int i = 0; i < MemberCount; i++) {
|
for (int i = 0; i < AllMemberCount; i++) {
|
||||||
if (name == Fields[i].name) {
|
if (name == Fields[i].name) {
|
||||||
return span<const FieldPtr>(&Fields[i], 1);
|
return span<const FieldPtr>(&Fields[i], 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
case EFieldFind::FIND_METHOD:
|
case EFieldFind::FIND_METHOD:
|
||||||
for (int i = MemberCount + CtorCount; i < length; i++) {
|
for (int i = AllMemberCount + CtorCount; i < length; i++) {
|
||||||
if (name == Fields[i].name) {
|
if (name == Fields[i].name) {
|
||||||
return span<const FieldPtr>(&Fields[i], 1);
|
return span<const FieldPtr>(&Fields[i], 1);
|
||||||
}
|
}
|
||||||
@ -212,7 +215,7 @@ namespace refl {
|
|||||||
case EFieldFind::FIND_METHODS:
|
case EFieldFind::FIND_METHODS:
|
||||||
{
|
{
|
||||||
int first = 0, count = 0;
|
int first = 0, count = 0;
|
||||||
for (int i = MemberCount + CtorCount; i < length; i++) {
|
for (int i = AllMemberCount + CtorCount; i < length; i++) {
|
||||||
if (name == Fields[i].name) {
|
if (name == Fields[i].name) {
|
||||||
if (!count) {
|
if (!count) {
|
||||||
first = i;
|
first = i;
|
||||||
|
|||||||
@ -21,6 +21,6 @@ namespace vkn {
|
|||||||
static void Init();
|
static void Init();
|
||||||
api::ResourceBundle LoadFile(api::PackagePath handle, const api::MetaBundle& meta) override;
|
api::ResourceBundle LoadFile(api::PackagePath handle, const api::MetaBundle& meta) override;
|
||||||
static uint32_t GetShaderLayout(VkDescriptorSetLayoutList& layoutList, pmr::vector<api::ShaderProgram*>& programList);
|
static uint32_t GetShaderLayout(VkDescriptorSetLayoutList& layoutList, pmr::vector<api::ShaderProgram*>& programList);
|
||||||
static void LoadShaderBuffer(pmr::vector<api::ShaderProgram*>& programList, MaterialInfo& info);
|
static void LoadShaderBuffer(VkDescriptorSetList& setList, pmr::vector<api::ShaderProgram*>& programList, MaterialInfo& info);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -6,10 +6,12 @@
|
|||||||
#include "render/asset/material.h"
|
#include "render/asset/material.h"
|
||||||
#include "render/tool/glsl_to_spirv.h"
|
#include "render/tool/glsl_to_spirv.h"
|
||||||
#include "render/asset/vertex.h"
|
#include "render/asset/vertex.h"
|
||||||
|
#include "render/asset/ubo.h"
|
||||||
#include "os/file_handle.h"
|
#include "os/file_handle.h"
|
||||||
#include ".render/vkmeta_vertex_gen.inl"
|
#include ".render/vkmeta_vertex_gen.inl"
|
||||||
using namespace api;
|
using namespace api;
|
||||||
namespace vkn {
|
namespace vkn {
|
||||||
|
table<Name, MaterialInfo> MaterialInfoTable;
|
||||||
void VulkanGlslLoader::Init()
|
void VulkanGlslLoader::Init()
|
||||||
{
|
{
|
||||||
refl::register_meta<PosVertex>();
|
refl::register_meta<PosVertex>();
|
||||||
@ -93,45 +95,91 @@ namespace vkn {
|
|||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
void VulkanGlslLoader::LoadShaderBuffer(pmr::vector<api::ShaderProgram*>& programList, MaterialInfo& info)
|
void InitMaterialGpuResourceBlock(MaterialGpuResourceBlock& block, std::span<const refl::FieldPtr> fields) {
|
||||||
{
|
block.isInit = true;
|
||||||
ShaderDescriptorSet descList{ FramePool() };
|
uint32_t count = fields.size();
|
||||||
GlslToSpirv::GetShaderLayout(descList, programList);
|
block.bufferOffset = meta_align_size(sizeof(void*) * count);
|
||||||
VulkanAPI* API = VulkanAPI::Ptr();
|
uint32_t blockSize = block.bufferOffset + meta_align_size(sizeof(Buffer) * count);
|
||||||
size_t count = descList.size();
|
block.pMappingAddr = (void**)BufferPool()->allocate(blockSize, 8);
|
||||||
if (!count) {
|
Buffer* pBuffer = (Buffer*)block.BufferPtr();
|
||||||
return;
|
void** ppMappingData = block.pMappingAddr;
|
||||||
}
|
for (auto& field : fields) {
|
||||||
size_t header_size = meta_align_size(sizeof(MaterialInfo::Header) * count) + meta_align_size(sizeof(Buffer) * count) + meta_align_size(count);
|
|
||||||
size_t size = header_size;
|
|
||||||
for (auto& desc : descList) {
|
|
||||||
size += meta_align_size(desc.size);
|
|
||||||
}
|
|
||||||
size += meta_align_size(sizeof(Buffer) * count);
|
|
||||||
MaterialInfo::Header* pHeader = (MaterialInfo::Header*)BufferPool()->allocate(size, 8);
|
|
||||||
Buffer* pBuffer = (Buffer*)((char*)pHeader + meta_align_size(sizeof(MaterialInfo::Header) * count));
|
|
||||||
info.count = count;
|
|
||||||
info.pHeader = pHeader;
|
|
||||||
info.pFlag = (char*)pBuffer + meta_align_size(sizeof(Buffer) * count);
|
|
||||||
char* pData = (char*)pHeader + header_size;
|
|
||||||
for (auto& desc : descList) {
|
|
||||||
new(pHeader)MaterialInfo::Header{};
|
|
||||||
new(pBuffer)Buffer{};
|
new(pBuffer)Buffer{};
|
||||||
pHeader->name = desc.name;
|
|
||||||
pHeader->size = desc.size;
|
|
||||||
pHeader->pCpuData = pData;
|
|
||||||
BufferCreator creatorInfo{};
|
BufferCreator creatorInfo{};
|
||||||
creatorInfo.pBuffer = &pBuffer->buffer;
|
creatorInfo.pBuffer = &pBuffer->buffer;
|
||||||
creatorInfo.pAllocation = &pBuffer->allocation;
|
creatorInfo.pAllocation = &pBuffer->allocation;
|
||||||
creatorInfo.ppCpuData = (void**) &pData;
|
creatorInfo.ppCpuData = ppMappingData;
|
||||||
creatorInfo.size = desc.size;
|
creatorInfo.size = field.type->size;
|
||||||
creatorInfo.memoryUsage = VMA_MEMORY_USAGE_AUTO;
|
creatorInfo.memoryUsage = VMA_MEMORY_USAGE_AUTO;
|
||||||
creatorInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
creatorInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||||
Backend::TransferWorker->Invoke(creatorInfo);
|
Backend::TransferWorker->CreateBuffer(creatorInfo);
|
||||||
pHeader++;
|
ppMappingData++;
|
||||||
pData += meta_align_size(desc.size);
|
pBuffer++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void BindDescriptorSetBuffer(MaterialGpuResourceBlock& block, const ShaderDescriptorSet& descList, const VkDescriptorSetList& setList) {
|
||||||
|
VkWriteDescriptorSet writeDescriptorSet[16] = {};
|
||||||
|
VkDescriptorBufferInfo bufferInfoList[16] = {};
|
||||||
|
uint32_t descCount = 0;
|
||||||
|
Buffer* buffer = (Buffer*)block.BufferPtr();
|
||||||
|
for (auto& desc : descList) {
|
||||||
|
auto& bufferInfo = bufferInfoList[descCount];
|
||||||
|
bufferInfo.offset = 0;
|
||||||
|
bufferInfo.range = desc.size;
|
||||||
|
bufferInfo.buffer = buffer->buffer;
|
||||||
|
auto& writeDesc = writeDescriptorSet[descCount];
|
||||||
|
writeDesc.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
|
writeDesc.dstSet = setList[desc.set];
|
||||||
|
writeDesc.dstBinding = desc.binding;
|
||||||
|
writeDesc.descriptorType = vkApiGetDescriptorType(desc.type);
|
||||||
|
writeDesc.descriptorCount = 1;
|
||||||
|
writeDesc.pBufferInfo = &bufferInfo;
|
||||||
|
descCount++;
|
||||||
|
}
|
||||||
|
vkUpdateDescriptorSets(VulkanAPI::Ptr()->GetBackend().GetDevice().Ptr(), descCount, writeDescriptorSet, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialInfo& FindMaterialStaticBlock(const refl::UClass* meta, std::span<const refl::FieldPtr> fields) {
|
||||||
|
auto it = MaterialInfoTable.find(meta->name);
|
||||||
|
if (it != MaterialInfoTable.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t classMember = 0, staticMember = 0;
|
||||||
|
for (auto& field : fields) {
|
||||||
|
if (field.IsStatic()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
classMember++;
|
||||||
|
}
|
||||||
|
MaterialResourceBlock staticBlock = MaterialResourceBlock::FromFields(fields.subspan(classMember, fields.size() - classMember));
|
||||||
|
MaterialInfo info{ {},{}, staticBlock };
|
||||||
|
MaterialInfoTable.emplace(meta->name, info);
|
||||||
|
return MaterialInfoTable[meta->name];
|
||||||
|
}
|
||||||
|
void VulkanGlslLoader::LoadShaderBuffer(VkDescriptorSetList& setList, pmr::vector<api::ShaderProgram*>& programList, MaterialInfo& material)
|
||||||
|
{
|
||||||
|
if (material.isInit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
material.isInit = true;
|
||||||
|
auto meta = refl::find_info(programList[0]->ubName());
|
||||||
|
if (!meta) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto fields = meta->GetFields(refl::FIND_ALL_MEMBER_WITH_STATIC, Name(""));
|
||||||
|
auto& info = FindMaterialStaticBlock(meta, fields);
|
||||||
|
MaterialResourceBlock classBlock = MaterialResourceBlock::FromFields(fields.subspan(0, fields.size() - info.staticBlock.count));
|
||||||
|
if (!info.gpuBlock) {
|
||||||
|
ShaderDescriptorSet descList{ FramePool() };
|
||||||
|
GlslToSpirv::GetShaderLayout(descList, programList);
|
||||||
|
InitMaterialGpuResourceBlock(info.gpuBlock, fields);
|
||||||
|
BindDescriptorSetBuffer(info.gpuBlock, descList, setList);
|
||||||
|
}
|
||||||
|
material.classBlock = classBlock;
|
||||||
|
material.gpuBlock = info.gpuBlock;
|
||||||
|
material.staticBlock = info.staticBlock;
|
||||||
|
}
|
||||||
void vkShaderProgram::Load(const pmr::vector<uint32_t>& spirv)
|
void vkShaderProgram::Load(const pmr::vector<uint32_t>& spirv)
|
||||||
{
|
{
|
||||||
VulkanAPI* API = VulkanAPI::Ptr();
|
VulkanAPI* API = VulkanAPI::Ptr();
|
||||||
|
|||||||
@ -73,17 +73,25 @@ namespace vkn {
|
|||||||
vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets);
|
vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets);
|
||||||
vkCmdBindIndexBuffer(ptr, vulkanVAO.indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
vkCmdBindIndexBuffer(ptr, vulkanVAO.indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||||
vkCmdBindPipeline(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline);
|
vkCmdBindPipeline(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline);
|
||||||
if(pipeline.descCount > 0)
|
if (pipeline.descCount > 0) {
|
||||||
|
auto& materialInst = mesh.GetMaterialInstance();
|
||||||
|
auto& materialInfo = materialInst.GetInfo();
|
||||||
|
auto& gpuBlock = materialInfo.gpuBlock;
|
||||||
|
uint32_t staticCount = materialInfo.staticBlock.count;
|
||||||
|
materialInfo.staticBlock.Upload(gpuBlock.pMappingAddr);
|
||||||
|
materialInfo.classBlock.Upload(gpuBlock.pMappingAddr + staticCount);
|
||||||
vkCmdBindDescriptorSets(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipelineLayout, 0, pipeline.descCount, pipeline.descList, 0, VK_NULL_HANDLE);
|
vkCmdBindDescriptorSets(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipelineLayout, 0, pipeline.descCount, pipeline.descList, 0, VK_NULL_HANDLE);
|
||||||
|
}
|
||||||
vkCmdDrawIndexed(ptr, vulkanVAO.indexCount, 1, 0, 0, 0);
|
vkCmdDrawIndexed(ptr, vulkanVAO.indexCount, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
void VulkanAPI::SetUpMaterialInstance(MaterialInstance& material)
|
void VulkanAPI::SetUpMaterialInstance(MaterialInstance& material)
|
||||||
{
|
{
|
||||||
Shader& shader = *material->GetShader();
|
Shader& shader = *material->GetShader();
|
||||||
|
VulkanPipeline& pipeline = PipelineTable[shader.GetGuid()];
|
||||||
pmr::vector<api::ShaderProgram*> programList{ FramePool() };
|
pmr::vector<api::ShaderProgram*> programList{ FramePool() };
|
||||||
programList.push_back(shader.GetVertHandle().Ptr());
|
programList.push_back(shader.GetVertHandle().Ptr());
|
||||||
programList.push_back(shader.GetFragHandle().Ptr());
|
programList.push_back(shader.GetFragHandle().Ptr());
|
||||||
VulkanGlslLoader::LoadShaderBuffer(programList, material.GetInfo());
|
VulkanGlslLoader::LoadShaderBuffer(pipeline.descList, programList, material.GetInfo());
|
||||||
}
|
}
|
||||||
void VulkanAPI::LoadShader(Shader& shader, size_t passKey)
|
void VulkanAPI::LoadShader(Shader& shader, size_t passKey)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -23,6 +23,10 @@ function _listen_gen_file(target, batch, template, macro, define)
|
|||||||
genfile, sourcefile = batch[1], batch[2]
|
genfile, sourcefile = batch[1], batch[2]
|
||||||
sourcefile = string.lower(sourcefile)
|
sourcefile = string.lower(sourcefile)
|
||||||
local dependfile = target:dependfile(genfile)
|
local dependfile = target:dependfile(genfile)
|
||||||
|
if false then
|
||||||
|
cmd_compile(batch[1], batch[2], template, macro, define)
|
||||||
|
return
|
||||||
|
end
|
||||||
depend.on_changed(
|
depend.on_changed(
|
||||||
function()
|
function()
|
||||||
cmd_compile(batch[1], batch[2], template, macro, define)
|
cmd_compile(batch[1], batch[2], template, macro, define)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user