Commit for 2021.07.10 23-11-15.7z

This commit is contained in:
mrq 2021-07-10 23:11:00 -05:00
parent bb85db104f
commit 5d9de97436
60 changed files with 2285 additions and 2235 deletions

View File

@ -37,7 +37,7 @@
"ext": {
"vulkan": {
"validation": {
"enabled": false,
"enabled": true,
"filters": [
"MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps)
"MessageID = 0x71500fba", // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
@ -66,7 +66,7 @@
"deferred alias output to swapchain": true,
"vsync": true,
"hdr": false,
"vxgi": true,
"vxgi": false,
"deferred sampling": false
},
"formats": {

View File

@ -36,12 +36,24 @@ bool validCubemapIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < CUBEMAPS;
}
#if DEFERRED || COMPUTE
bool validTextureIndex( uint id ) {
return 0 <= id && id < MAX_TEXTURES;
}
bool validTextureIndex( uint start, int offset ) {
return 0 <= offset && start + offset < MAX_TEXTURES;
}
uint textureIndex( uint start, int offset ) {
return start + offset;
}
vec4 sampleTexture( uint id ) {
const Texture t = textures[id];
return texture( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, surface.uv ) );
}
vec4 sampleTexture( uint id, float mip ) {
const Texture t = textures[id];
return textureLod( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, surface.uv ), mip );
}
#if 0
vec4 sampleTexture( uint start, uint slot, int offset, int atlas ) {
Texture a;
const bool useAtlas = 0 <= atlas && validTextureIndex( start, atlas );
@ -61,6 +73,7 @@ vec4 sampleTexture( uint start, uint slot, int offset, int atlas, float mip ) {
return textureLod( samplerTextures[nonuniformEXT(i)], uv, mip );
}
#endif
#endif
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, in Ray ray ) {
const vec3 t0 = (boundsMin - ray.origin) / ray.direction;
const vec3 t1 = (boundsMax - ray.origin) / ray.direction;

View File

@ -56,6 +56,9 @@ struct Mode {
};
struct Light {
mat4 view;
mat4 projection;
vec3 position;
float radius;
@ -66,9 +69,6 @@ struct Light {
int typeMap;
int indexMap;
float depthBias;
mat4 view;
mat4 projection;
};
struct Material {
@ -100,11 +100,16 @@ struct Texture {
vec4 lerp;
};
struct DrawCall {
int materialIndex;
int textureIndex;
uint textureSlot;
uint padding;
struct DrawCommand {
uint indices; // triangle count
uint instances; // instance count
uint indexID; // starting triangle position
int vertexID; // starting vertex position
uint instanceID; // starting instance position
uint materialID; // material used for draw
uint objectID; //
uint vertices; //
};
struct SurfaceMaterial {

View File

@ -9,7 +9,7 @@
#if DEFERRED_SAMPLING
layout (binding = 3) uniform sampler2D samplerUvs;
#else
layout (binding = 3) uniform sampler2D samplerAlbedo;
layout (binding = 4) uniform sampler2D samplerAlbedo;
#endif
#else
layout (binding = 1) uniform usampler2DMS samplerId;
@ -17,7 +17,7 @@
#if DEFERRED_SAMPLING
layout (binding = 3) uniform sampler2DMS samplerUvs;
#else
layout (binding = 3) uniform sampler2DMS samplerAlbedo;
layout (binding = 4) uniform sampler2DMS samplerAlbedo;
#endif
#endif

View File

@ -43,7 +43,7 @@ layout (binding = 4) uniform UBO {
uint lights;
uint materials;
uint textures;
uint drawCalls;
uint drawCommands;
vec3 ambient;
float gamma;
@ -63,8 +63,8 @@ layout (std140, binding = 6) readonly buffer Materials {
layout (std140, binding = 7) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 8) readonly buffer DrawCalls {
DrawCall drawCalls[];
layout (std140, binding = 8) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (binding = 9) uniform sampler2D samplerTextures[TEXTURES];
@ -168,8 +168,8 @@ void populateSurface() {
return;
}
const uint drawId = ID.x - 1;
const DrawCall drawCall = drawCalls[drawId];
surface.material.id = ID.y + drawCall.materialIndex - 1;
const DrawCommand drawCommand = drawCommands[drawId];
surface.material.id = ID.y + drawCommand.materialID - 1;
const Material material = materials[surface.material.id];
surface.material.albedo = material.colorBase;
surface.fragment = material.colorEmissive;
@ -180,8 +180,10 @@ void populateSurface() {
surface.uv = resolve(samplerUv, ubo.msaa).xy;
#endif
const float mip = mipLevel(inUv.xy);
if ( validTextureIndex( drawCall.textureIndex, material.indexAlbedo ) ) {
surface.material.albedo = sampleTexture( drawCall.textureIndex, drawCall.textureSlot, material.indexAlbedo, material.indexAtlas, mip );
// if ( validTextureIndex( drawCommand.textureIndex, material.indexAlbedo ) ) {
// surface.material.albedo = sampleTexture( drawCommand.textureIndex, drawCommand.textureSlot, material.indexAlbedo, material.indexAtlas, mip );
if ( validTextureIndex( material.indexAlbedo ) ) {
surface.material.albedo = sampleTexture( material.indexAlbedo, mip );
}
// OPAQUE
if ( material.modeAlpha == 0 ) {
@ -194,8 +196,10 @@ void populateSurface() {
}
// Emissive textures
if ( validTextureIndex( drawCall.textureIndex, material.indexEmissive ) ) {
surface.fragment += sampleTexture( drawCall.textureIndex, drawCall.textureSlot, material.indexEmissive, material.indexAtlas, mip );
// if ( validTextureIndex( drawCommand.textureIndex, material.indexEmissive ) ) {
// surface.fragment += sampleTexture( drawCommand.textureIndex, drawCommand.textureSlot, material.indexEmissive, material.indexAtlas, mip );
if ( validTextureIndex( material.indexEmissive ) ) {
surface.fragment += sampleTexture( material.indexEmissive, mip );
}
#else
#if !MULTISAMPLING

View File

@ -26,7 +26,7 @@ layout (binding = 4) uniform UBO {
uint lights;
uint materials;
uint textures;
uint drawCalls;
uint drawCommands;
vec3 ambient;
float gamma;
@ -46,8 +46,8 @@ layout (std140, binding = 6) readonly buffer Materials {
layout (std140, binding = 7) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 8) readonly buffer DrawCalls {
DrawCall drawCalls[];
layout (std140, binding = 8) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (binding = 9) uniform sampler2D samplerTextures[TEXTURES];
@ -81,16 +81,18 @@ void main() {
continue;
}
const uint drawId = ID.x - 1;
const DrawCall drawCall = drawCalls[drawId];
surface.material.id = ID.y + drawCall.materialIndex - 1;
const DrawCommand drawCommand = drawCommands[drawId];
surface.material.id = ID.y + drawCommand.materialID - 1;
const Material material = materials[surface.material.id];
surface.material.albedo = material.colorBase;
surface.fragment = material.colorEmissive;
#if DEFERRED_SAMPLING
surface.uv = imageLoad(voxelUv[CASCADE], ivec3(tUvw) ).xy;
if ( validTextureIndex( drawCall.textureIndex, material.indexAlbedo ) ) {
surface.material.albedo = sampleTexture( drawCall.textureIndex, drawCall.textureSlot, material.indexAlbedo, material.indexAtlas );
// if ( validTextureIndex( drawCommand.textureIndex, material.indexAlbedo ) ) {
// surface.material.albedo = sampleTexture( drawCommand.textureIndex, drawCommand.textureSlot, material.indexAlbedo, material.indexAtlas );
if ( validTextureIndex( material.indexAlbedo ) ) {
surface.material.albedo = sampleTexture( material.indexAlbedo );
}
// OPAQUE
@ -104,8 +106,10 @@ void main() {
}
// Emissive textures
if ( validTextureIndex( drawCall.textureIndex, material.indexEmissive ) ) {
surface.fragment += sampleTexture( drawCall.textureIndex, drawCall.textureSlot, material.indexEmissive, material.indexAtlas );
// if ( validTextureIndex( drawCommand.textureIndex, material.indexEmissive ) ) {
// surface.fragment += sampleTexture( drawCommand.textureIndex, drawCommand.textureSlot, material.indexEmissive, material.indexAtlas );
if ( validTextureIndex( material.indexEmissive ) ) {
surface.fragment += sampleTexture( material.indexEmissive );
}
#else
surface.material.albedo = imageLoad(voxelRadiance[CASCADE], ivec3(tUvw) );

View File

@ -57,7 +57,7 @@ void main() {
if ( useAtlas ) textureAtlas = textures[material.indexAtlas];
if ( !validTextureIndex( material.indexAlbedo ) ) discard; {
Texture t = textures[material.indexAlbedo];
A = textureLod( samplerTextures[nonuniformEXT((useAtlas) ? textureAtlas.index : t.index)], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip );
A = textureLod( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
// alpha mode OPAQUE
if ( material.modeAlpha == 0 ) {
A.a = 1;
@ -88,7 +88,7 @@ void main() {
// sample normal
if ( validTextureIndex( material.indexNormal ) ) {
Texture t = textures[material.indexNormal];
N = inTBN * normalize( textureLod( samplerTextures[nonuniformEXT((useAtlas)?textureAtlas.index:t.index)], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ).xyz * 2.0 - vec3(1.0));
N = inTBN * normalize( textureLod( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ), mip ).xyz * 2.0 - vec3(1.0));
}
#if 0
// sample metallic/roughness

View File

@ -46,7 +46,7 @@ namespace {
}
}
}
#include <uf/utils/mesh/mesh.h>
int main(int argc, char** argv){
for ( size_t i = 0; i < argc; ++i ) {
char* c_str = argv[i];
@ -58,6 +58,46 @@ int main(int argc, char** argv){
signal(SIGABRT, ::handlers::abrt);
signal(SIGSEGV, ::handlers::segv);
{
uf::Mesh mesh;
mesh.bind<pod::Vertex_2F2F, uint16_t>();
mesh.insertVertices<pod::Vertex_2F2F>({
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
{ {-1.0f, -1.0f}, {0.0f, 0.0f}, },
{ {1.0f, -1.0f}, {1.0f, 0.0f}, },
{ {1.0f, 1.0f}, {1.0f, 1.0f}, }
});
mesh.insertIndices<uint16_t>({
0, 1, 2, 2, 3, 0
});
/*
mesh.bind<pod::Vertex_3F2F3F>();
mesh.insertVertices<pod::Vertex_3F2F3F>({
{{0.0f, 1.0f, 2.0f}, {3.0f, 4.0f}, {5.0f, 6.0f, 7.0f}},
{{8.0f, 9.0f, 10.0f}, {11.0f, 12.0f}, {13.0f, 14.0f, 15.0f}},
{{16.0f, 17.0f, 18.0f}, {19.0f, 20.0f}, {21.0f, 22.0f, 23.0f}},
});
mesh.insertIndices<uint32_t>({
0, 1, 2
});
*/
mesh.print();
/*
auto& buffer = mesh.buffers[0 <= mesh.vertex.interleaved && mesh.vertex.interleaved < mesh.buffers.size() ? mesh.vertex.interleaved :];
uint8_t* pointer = (uint8_t*) buffer.data();
while ( pointer < (uint8_t*) buffer.data() + buffer.size() ) {
for ( auto& attribute : mesh.vertex.attributes ) {
float* vector = pointer + attrribute.descriptor.offset;
for ( auto i = 0; i < attribute.descriptor.components; ++i ) {
UF_MSG_DEBUG( attribute.descriptor.name << ": " << vector[i] );
}
pointer += attribute.descriptor.size;
}
}
*/
}
client::initialize();
ext::initialize();

View File

@ -4,82 +4,48 @@
#include <uf/engine/object/object.h>
#include <uf/utils/math/transform.h>
#include <uf/utils/mesh/mesh.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/utils/math/collision.h>
#include "mesh.h"
#include "pod.h"
#include <uf/utils/memory/fifo_map.h>
#include <queue>
#define UF_GRAPH_EXPERIMENTAL 1
#define UF_GRAPH_VARYING_MESH 1
#define UF_GRAPH_INDIRECT_DRAW 1
#include "pod.inl"
#include "mesh.inl"
#include "scene.inl"
namespace pod {
struct UF_API Texture {
struct Storage {
/*alignas(4)*/ int32_t index = -1;
/*alignas(4)*/ int32_t sampler = -1;
/*alignas(4)*/ int32_t remap = -1;
/*alignas(4)*/ float blend = 0;
/*alignas(16)*/ pod::Vector4f lerp = {0, 0, 1, 1};
} storage;
uf::stl::string name = "";
uf::renderer::Texture2D texture;
bool bind = false;
};
struct UF_API Node {
uf::stl::string name = "";
int32_t index = -1;
int32_t skin = -1;
int32_t parent = -1;
int32_t mesh = -1;
pod::Transform<> transform;
uf::stl::vector<int32_t> children;
uf::Object* entity = NULL;
struct {
int32_t material = -1;
int32_t texture = -1;
int32_t joint = -1;
} buffers;
};
struct UF_API Graph {
#if UF_GRAPH_EXPERIMENTAL
typedef pod::VaryingMesh Mesh;
#else
typedef uf::graph::skinned_mesh_t Mesh;
#endif
// Node* node = NULL;
pod::Node root;
uf::stl::vector<pod::Node> nodes;
uf::Object* entity = NULL;
struct {
int32_t instance = -1;
} buffers;
uf::stl::string name = "";
uf::graph::load_mode_t mode;
uf::Serializer metadata;
uf::Atlas atlas;
uf::stl::vector<uf::Image> images;
uf::stl::vector<uf::renderer::Sampler> samplers;
uf::stl::vector<pod::Texture> textures;
uf::stl::vector<pod::Material> materials;
uf::stl::vector<pod::Light> lights;
uf::stl::vector<pod::DrawCall> drawCalls;
pod::Node root;
uf::stl::vector<pod::Node> nodes; // node's position corresponds to its drawCommand and instance
// Render information
uf::stl::vector<uf::stl::vector<pod::DrawCommand>> drawCommands; // draws to dispatch, one per primitive, gets copied per rendermode
uf::stl::vector<pod::Instance> instances; // instance data to use, gets copied per rendermode
uf::stl::vector<uf::stl::string> meshes; // collection of primitives (stored as meshes, by material)
uf::stl::vector<uf::stl::string> images; // references global pool of images
uf::stl::vector<uf::stl::string> materials; // references global pool of materials
uf::stl::vector<uf::stl::string> textures; // references global pool of textures
uf::stl::vector<uf::stl::string> texture2Ds; // references global pool of texture2Ds
uf::stl::vector<uf::stl::string> samplers; // references global pool of samplers
// Lighting information
uf::stl::unordered_map<uf::stl::string, pod::Light> lights;
// Animations
uf::stl::vector<Skin> skins;
uf::stl::vector<Mesh> meshes;
uf::stl::unordered_map<uf::stl::string, Animation> animations;
// Animation queue
std::queue<uf::stl::string> sequence;
struct {
struct {
@ -92,22 +58,29 @@ namespace pod {
} override;
} animations;
} settings;
// Local storage, used for save/load
struct Storage {
uf::stl::fifo_map<uf::stl::string, uf::Atlas> atlases;
uf::stl::fifo_map<uf::stl::string, uf::Image> images;
uf::stl::fifo_map<uf::stl::string, pod::Mesh> meshes;
uf::stl::fifo_map<uf::stl::string, pod::Material> materials;
uf::stl::fifo_map<uf::stl::string, pod::Texture> textures;
uf::stl::fifo_map<uf::stl::string, uf::renderer::Texture2D> texture2Ds;
uf::stl::fifo_map<uf::stl::string, uf::renderer::Sampler> samplers;
};
};
}
namespace uf {
namespace graph {
/*
namespace {
extern UF_API uf::stl::vector<pod::Material::Storage> storage;
extern UF_API uf::stl::vector<uf::stl::string> indices;
} materials;
namespace {
extern UF_API uf::stl::vector<pod::Texture::Storage> storage;
extern UF_API uf::stl::vector<uf::stl::string> indices;
} textures;
*/
extern UF_API pod::Graph::Storage storage;
}
}
namespace uf {
namespace graph {
pod::Node* UF_API find( pod::Graph& graph, int32_t index );
pod::Node* UF_API find( pod::Graph& graph, const uf::stl::string& name );
@ -128,7 +101,7 @@ namespace uf {
void UF_API destroy( pod::Graph& );
pod::Graph UF_API load( const uf::stl::string&, uf::graph::load_mode_t = 0, const uf::Serializer& = ext::json::null() );
pod::Graph UF_API load( const uf::stl::string&, const uf::Serializer& = ext::json::null() );
void UF_API save( const pod::Graph&, const uf::stl::string& );
uf::stl::string UF_API print( const pod::Graph& graph );

View File

@ -1,52 +0,0 @@
#pragma once
#include <uf/utils/mesh/mesh.h>
namespace uf {
namespace graph {
enum LoadMode {
ATLAS = 0x1 << 1,
INVERT = 0x1 << 2,
TRANSFORM = 0x1 << 3,
SKINNED = 0x1 << 4,
};
typedef uint16_t load_mode_t;
typedef uint16_t id_t;
namespace mesh {
struct Base {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(8)*/ pod::Vector2f uv;
/*alignas(8)*/ pod::Vector2f st;
/*alignas(4)*/ pod::Vector<id_t, 2> id;
static UF_API uf::stl::vector<uf::renderer::VertexDescriptor> descriptor;
};
struct ID {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(8)*/ pod::Vector2f uv;
/*alignas(8)*/ pod::Vector2f st;
/*alignas(16)*/ pod::Vector3f normal;
/*alignas(16)*/ pod::Vector3f tangent;
/*alignas(4)*/ pod::Vector<id_t, 2> id;
static UF_API uf::stl::vector<uf::renderer::VertexDescriptor> descriptor;
};
struct Skinned {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(8)*/ pod::Vector2f uv;
/*alignas(8)*/ pod::Vector2f st;
/*alignas(16)*/ pod::Vector3f normal;
/*alignas(16)*/ pod::Vector3f tangent;
/*alignas(4)*/ pod::Vector<id_t, 2> id;
/*alignas(8)*/ pod::Vector<id_t, 4> joints;
/*alignas(16)*/ pod::Vector4f weights;
static UF_API uf::stl::vector<uf::renderer::VertexDescriptor> descriptor;
};
}
typedef uf::Mesh<uf::graph::mesh::Base> base_mesh_t;
typedef uf::Mesh<uf::graph::mesh::ID> id_mesh_t;
typedef uf::Mesh<uf::graph::mesh::Skinned> skinned_mesh_t;
}
}

View File

@ -0,0 +1,40 @@
namespace uf {
namespace graph {
namespace mesh {
typedef uint16_t id_t;
struct Base {
pod::Vector3f position;
pod::Vector2f uv;
pod::Vector2f st;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct ID {
pod::Vector3f position;
pod::Vector2f uv;
pod::Vector2f st;
pod::Vector3f normal;
pod::Vector3f tangent;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct Skinned {
pod::Vector3f position;
pod::Vector2f uv;
pod::Vector2f st;
pod::Vector3f normal;
pod::Vector3f tangent;
pod::Vector<id_t, 4> joints;
pod::Vector4f weights;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
}
/*
typedef uf::Mesh<uf::graph::mesh::Base> base_mesh_t;
typedef uf::Mesh<uf::graph::mesh::ID> id_mesh_t;
typedef uf::Mesh<uf::graph::mesh::Skinned> skinned_mesh_t;
*/
}
}

View File

@ -1,99 +0,0 @@
#pragma once
#include <uf/config.h>
#include <uf/utils/memory/string.h>
#include <uf/utils/math/vector.h>
#include <uf/utils/math/transform.h>
namespace pod {
struct UF_API SceneTextures {
uf::renderer::Texture3D noise;
uf::renderer::TextureCube skybox;
struct {
uf::stl::vector<uf::renderer::Texture3D> id;
uf::stl::vector<uf::renderer::Texture3D> uv;
uf::stl::vector<uf::renderer::Texture3D> normal;
uf::stl::vector<uf::renderer::Texture3D> radiance;
uf::stl::vector<uf::renderer::Texture3D> depth;
} voxels;
};
struct UF_API DrawCall {
struct Storage {
/*alignas(4)*/ int32_t materialIndex = -1;
/*alignas(4)*/ int32_t textureIndex = -1;
/*alignas(4)*/ uint32_t textureSlot = 0;
/*alignas(4)*/ uint32_t padding = 0;
} storage;
uf::stl::string name = "";
size_t verticesIndex = 0;
size_t vertices = 0;
size_t indicesIndex = 0;
size_t indices = 0;
};
struct UF_API Light {
struct UF_API Storage {
/*alignas(16)*/ pod::Vector4f position;
/*alignas(16)*/ pod::Vector4f color;
/*alignas(4)*/ int32_t type = 0;
/*alignas(4)*/ int32_t typeMap = 0;
/*alignas(4)*/ int32_t indexMap = -1;
/*alignas(4)*/ float depthBias = 0;
/*alignas(16)*/ pod::Matrix4f view;
/*alignas(16)*/ pod::Matrix4f projection;
};
uf::stl::string name = "";
pod::Vector3f color = { 1, 1, 1 };
float intensity = 1.0f;
float range = 0.0f;
};
struct UF_API Material {
struct Storage {
/*alignas(16)*/ pod::Vector4f colorBase = { 0, 0, 0, 0 };
/*alignas(16)*/ pod::Vector4f colorEmissive = { 0, 0, 0, 0 };
/*alignas(4)*/ float factorMetallic = 0.0f;
/*alignas(4)*/ float factorRoughness = 0.0f;
/*alignas(4)*/ float factorOcclusion = 0.0f;
/*alignas(4)*/ float factorAlphaCutoff = 1.0f;
/*alignas(4)*/ int32_t indexAlbedo = -1;
/*alignas(4)*/ int32_t indexNormal = -1;
/*alignas(4)*/ int32_t indexEmissive = -1;
/*alignas(4)*/ int32_t indexOcclusion = -1;
/*alignas(4)*/ int32_t indexMetallicRoughness = -1;
/*alignas(4)*/ int32_t indexAtlas = -1;
/*alignas(4)*/ int32_t indexLightmap = -1;
/*alignas(4)*/ int32_t modeAlpha = -1;
} storage;
uf::stl::string name = "";
uf::stl::string alphaMode = "";
};
struct UF_API Skin {
uf::stl::string name = "";
uf::stl::vector<int32_t> joints;
uf::stl::vector<pod::Matrix4f> inverseBindMatrices;
};
struct UF_API Animation {
struct Sampler {
uf::stl::string interpolator;
uf::stl::vector<float> inputs;
uf::stl::vector<pod::Vector4f> outputs;
};
struct Channel {
uf::stl::string path;
int32_t node;
uint32_t sampler;
};
uf::stl::string name = "";
uf::stl::vector<Sampler> samplers;
uf::stl::vector<Channel> channels;
float start = std::numeric_limits<float>::max();
float end = std::numeric_limits<float>::min();
float cur = 0;
};
}

View File

@ -0,0 +1,121 @@
namespace pod {
struct UF_API DrawCommand {
uint32_t indices = 0; // triangle count
uint32_t instances = 0; // instance count
uint32_t indexID = 0; // starting triangle position
int32_t vertexID = 0; // starting vertex position
uint32_t instanceID = 0; // starting instance position
uint32_t materialID = 0;
uint32_t objectID = 0;
uint32_t vertices = 0;
};
struct UF_API Instance {
pod::Matrix4f model;
pod::Vector4f color = {1,1,1,1};
alignas(4) uint32_t materialID = 0;
alignas(4) uint32_t padding1 = 0;
alignas(4) uint32_t padding2 = 0;
alignas(4) uint32_t padding3 = 0;
struct {
pod::Vector3f min = {};
alignas(4) float padding1 = 0;
pod::Vector3f max = {};
alignas(4) float padding2 = 0;
} bounds;
};
struct UF_API Material {
pod::Vector4f colorBase = { 0, 0, 0, 0 };
pod::Vector4f colorEmissive = { 0, 0, 0, 0 };
float factorMetallic = 0.0f;
float factorRoughness = 0.0f;
float factorOcclusion = 0.0f;
float factorAlphaCutoff = 1.0f;
int32_t indexAlbedo = -1;
int32_t indexNormal = -1;
int32_t indexEmissive = -1;
int32_t indexOcclusion = -1;
int32_t indexMetallicRoughness = -1;
int32_t indexAtlas = -1;
int32_t indexLightmap = -1;
int32_t modeAlpha = -1;
};
struct UF_API Texture {
int32_t index = -1;
int32_t sampler = -1;
int32_t remap = -1;
float blend = 0;
pod::Vector4f lerp = {0, 0, 1, 1};
};
struct UF_API Light {
pod::Matrix4f view;
pod::Matrix4f projection;
pod::Vector3f position;
alignas(4) float range = 0.0f;
pod::Vector3f color;
alignas(4) float intensity = 0.0f;
int32_t type = 0;
int32_t typeMap = 0;
int32_t indexMap = -1;
float depthBias = 0;
};
//
struct UF_API Mesh {
uf::stl::vector<pod::DrawCommand> drawCommands;
uf::Mesh mesh;
};
//
struct UF_API Skin {
uf::stl::string name = "";
uf::stl::vector<int32_t> joints;
uf::stl::vector<pod::Matrix4f> inverseBindMatrices;
};
struct UF_API Animation {
struct Sampler {
uf::stl::string interpolator;
uf::stl::vector<float> inputs;
uf::stl::vector<pod::Vector4f> outputs;
};
struct Channel {
uf::stl::string path;
int32_t node;
uint32_t sampler;
};
uf::stl::string name = "";
uf::stl::vector<Sampler> samplers;
uf::stl::vector<Channel> channels;
float start = std::numeric_limits<float>::max();
float end = std::numeric_limits<float>::min();
float cur = 0;
};
//
struct UF_API Node {
uf::stl::string name = "";
int32_t index = -1;
int32_t parent = -1;
int32_t mesh = -1;
int32_t skin = -1;
uf::stl::vector<int32_t> children;
uf::Object* entity = NULL;
pod::Transform<> transform;
};
}

View File

@ -0,0 +1,15 @@
// Doesn't have a home
namespace pod {
struct UF_API SceneTextures {
uf::renderer::Texture3D noise;
uf::renderer::TextureCube skybox;
struct {
uf::stl::vector<uf::renderer::Texture3D> id;
uf::stl::vector<uf::renderer::Texture3D> uv;
uf::stl::vector<uf::renderer::Texture3D> normal;
uf::stl::vector<uf::renderer::Texture3D> radiance;
uf::stl::vector<uf::renderer::Texture3D> depth;
} voxels;
};
}

View File

@ -57,7 +57,7 @@ namespace ext {
#endif
// collider for mesh (static or dynamic)
pod::Bullet& create( uf::Object&, const pod::Mesh&, bool );
pod::Bullet& create( uf::Object&, const uf::Mesh&, bool );
// collider for boundingbox
pod::Bullet& UF_API create( uf::Object&, const pod::Vector3f&, float );
// collider for capsule

View File

@ -1,12 +1,11 @@
#pragma once
#include <uf/engine/graph/mesh.h>
#include <uf/engine/graph/graph.h>
#include <uf/engine/object/object.h>
namespace ext {
namespace gltf {
pod::Graph UF_API load( const uf::stl::string&, uf::graph::load_mode_t = 0, const uf::Serializer& = {} );
pod::Graph UF_API load( const uf::stl::string&, const uf::Serializer& = {} );
void UF_API save( const uf::stl::string&, const pod::Graph& );
}
}

View File

@ -1,54 +0,0 @@
#pragma once
#include <uf/config.h>
#include <json/json.h>
namespace ext {
namespace json {
class UF_API Value;
typedef Json::Value base_value;
typedef Value Document;
class UF_API Value : public base_value {
public:
Value( Json::ValueType type = Json::objectValue ) : base_value(type) {}
Value& operator=( const Value& );
template<typename... Args> Value& operator[]( Args... args );
template<typename... Args> const Value& operator[]( Args... args ) const;
template<typename... Args> Value& operator=( Args... args );
template<typename T>
Value& emplace_back( const T& );
};
inline bool isTable( const Value& v ) { return v.isArray() || v.isObject(); }
inline bool isObject( const Value& v ) { return v.isObject(); }
inline bool isArray( const Value& v ) { return v.isArray(); }
inline bool isNull( const Value& v ) { return v.isNull(); }
inline Value array() { return Value(Json::arrayValue); }
inline Value object() { return Value(Json::objectValue); }
inline Value null() { return Value(Json::nullValue); }
inline uf::stl::vector<uf::stl::string> keys( const Value& v ) { return v.getMemberNames(); }
}
}
template<typename... Args> ext::json::Value& ext::json::Value::operator[]( Args... args ) {
return (ext::json::Value&) ext::json::base_value::operator[](args...);
}
template<typename... Args> const ext::json::Value& ext::json::Value::operator[]( Args... args ) const {
return (const ext::json::Value&) ext::json::base_value::operator[](args...);
}
template<typename... Args> ext::json::Value& ext::json::Value::operator=( Args... args ) {
ext::json::base_value::operator=(args...);
return *this;
}
template<typename T>
ext::json::Value& ext::json::Value::emplace_back( const T& v ) {
ext::json::base_value::append( v );
return *this;
}

View File

@ -1,56 +0,0 @@
#pragma once
#include <uf/config.h>
#include <uf/ext/lua/lua.h>
namespace ext {
namespace json {
class UF_API Value;
typedef sol::table base_value;
typedef Value Document;
class UF_API Value : public base_value {
public:
Value& operator=( const Value& );
template<typename... Args> Value& operator[]( Args... args );
template<typename... Args> const Value& operator[]( Args... args ) const;
template<typename... Args> Value& operator=( Args... args );
};
inline bool isTable( sol::object v ) { return v.is<sol::table>(); }
inline bool isObject( sol::object v ) { return v.is<sol::table>(); }
inline bool isArray( sol::object v ) { return v.is<sol::table>(); }
inline bool isNull( sol::object v ) { return v == sol::lua_nil; }
template<typename T> inline bool isTable( T v );
template<typename T> inline bool isObject( T v );
template<typename T> inline bool isArray( T v );
template<typename T> inline bool isNull( T v );
}
}
template<typename... Args> ext::json::Value& ext::json::Value::operator[]( Args... args ) {
return (ext::json::Value&) ext::json::base_value::operator[](args...);
}
template<typename... Args> const ext::json::Value& ext::json::Value::operator[]( Args... args ) const {
return (const ext::json::Value&) ext::json::base_value::operator[](args...);
}
template<typename... Args> ext::json::Value& ext::json::Value::operator=( Args... args ) {
ext::json::base_value::operator=(args...);
return *this;
}
template<typename T>
inline bool ext::json::isTable( T v ) { return v.get_type() == sol::type::table; }
template<typename T>
inline bool ext::json::isObject( T v ) { return v.get_type() == sol::type::table; }
template<typename T>
inline bool ext::json::isArray( T v ) { return v.get_type() == sol::type::table; }
template<typename T>
inline bool ext::json::isNull( T v ) { return v.get_type() == sol::type::nil; }

View File

@ -1,147 +0,0 @@
#pragma once
#include <uf/config.h>
#include <rapidjson/document.h>
namespace ext {
namespace json {
class UF_API Value;
typedef rapidjson::Value base_value;
struct UF_API Document;
// typedef rapidjson::Document Document
class UF_API Value : public base_value {
public:
Value& operator=( const Value& );
template<typename... Args> Value& operator[]( Args... args );
template<typename... Args> const Value& operator[]( Args... args ) const;
inline size_t size() const { return Size(); }
inline decltype(auto) begin() { return Begin(); }
inline decltype(auto) end() { return End(); }
template<typename T> inline T get() const = delete;
template<typename T> inline Value& operator=( T v ) = delete;
};
inline bool isTable( const Value& v ) { return v.IsArray() || v.IsObject(); }
inline bool isObject( const Value& v ) { return v.IsObject(); }
inline bool isArray( const Value& v ) { return v.IsArray(); }
inline bool isNull( const Value& v ) { return v.IsNull(); }
inline decltype(auto) array() {
return ext::json::base_value(rapidjson::kArrayType).Move();
}
inline decltype(auto) object() {
return ext::json::base_value(rapidjson::kObjectType).Move();
}
inline Value null() { return Value(); }
uf::stl::vector<uf::stl::string> UF_API keys( const Value& v );
static rapidjson::Document::AllocatorType allocator;
struct Document : public rapidjson::Document {
public:
Document() : rapidjson::Document(&ext::json::allocator) {}
template<typename... Args> Value& operator[]( Args... args );
template<typename... Args> const Value& operator[]( Args... args ) const;
};
}
}
template<typename... Args> ext::json::Value& ext::json::Value::operator[]( Args... args ) {
const uf::stl::string k(args...);
auto key = rapidjson::StringRef(k.c_str());
auto it = ext::json::base_value::FindMember(key);
if ( it != ext::json::base_value::MemberEnd() )
return (ext::json::Value&) it->value;
// member doesn't exist, make empty object
ext::json::base_value::AddMember(key, ext::json::object(), ext::json::allocator);
return this->operator[](args...);
}
template<typename... Args> const ext::json::Value& ext::json::Value::operator[]( Args... args ) const {
const uf::stl::string k(args...);
auto key = rapidjson::StringRef(k.c_str());
auto it = ext::json::base_value::FindMember(key);
if ( it != ext::json::base_value::MemberEnd() )
return (const ext::json::Value&) it->value;
return ext::json::base_value();
}
template<> inline ext::json::Value& ext::json::Value::operator=<uf::stl::string>( uf::stl::string v ) {
ext::json::base_value::SetString( v.c_str(), ext::json::allocator );
return *this;
}
template<> inline ext::json::Value& ext::json::Value::operator=<bool>( bool v ) {
ext::json::base_value::SetBool(v);
return *this;
}
template<> inline ext::json::Value& ext::json::Value::operator=<int>( int v ) {
ext::json::base_value::SetInt(v);
return *this;
}
template<> inline ext::json::Value& ext::json::Value::operator=<size_t>( size_t v ) {
ext::json::base_value::SetUint64(v);
return *this;
}
template<> inline ext::json::Value& ext::json::Value::operator=<float>( float v ) {
ext::json::base_value::SetFloat(v);
return *this;
}
template<> inline ext::json::Value& ext::json::Value::operator=<double>( double v ) {
ext::json::base_value::SetDouble(v);
return *this;
}
template<typename... Args> ext::json::Value& ext::json::Document::operator[]( Args... args ) {
const uf::stl::string k(args...);
auto key = rapidjson::StringRef(k.c_str());
auto it = rapidjson::Document::FindMember(key);
if ( it != rapidjson::Document::MemberEnd() )
return (ext::json::Value&) it->value;
// member doesn't exist, make empty object
rapidjson::Document::AddMember(key, ext::json::object(), ext::json::allocator);
return this->operator[](args...);
}
template<typename... Args> const ext::json::Value& ext::json::Document::operator[]( Args... args ) const {
const uf::stl::string k(args...);
auto key = rapidjson::StringRef(k.c_str());
auto it = rapidjson::Document::FindMember(key);
if ( it != rapidjson::Document::MemberEnd() )
return (const ext::json::Value&) it->value;
return ext::json::base_value();
}
template<> inline bool ext::json::Value::is<bool>() const { return IsBool(); }
template<> inline bool ext::json::Value::is<int>() const { return IsInt64(); }
template<> inline bool ext::json::Value::is<size_t>() const { return IsUint64(); }
template<> inline bool ext::json::Value::is<float>() const { return IsDouble(); }
template<> inline bool ext::json::Value::is<double>() const { return IsDouble(); }
template<> inline bool ext::json::Value::is<uf::stl::string>() const { return IsString(); }
template<> inline bool ext::json::Value::get<bool>() const { return GetBool(); }
template<> inline int ext::json::Value::get<int>() const { return GetInt(); }
template<> inline size_t ext::json::Value::get<size_t>() const { return GetUint64(); }
template<> inline float ext::json::Value::get<float>() const { return GetDouble(); }
template<> inline double ext::json::Value::get<double>() const { return GetDouble(); }
template<> inline uf::stl::string ext::json::Value::get<uf::stl::string>() const { return GetString(); }
template<typename T> inline T ext::json::Value::as() const {
if ( !is<T>() ) return T();
return get<T>();
}
template<> inline bool ext::json::Value::as<bool>() const {
if ( is<bool>() ) return get<bool>();
if ( IsNull() ) return false;
if ( IsNumber() ) return get<int>() != 0;
if ( IsString() ) return get<uf::stl::string>() != "";
if ( IsObject() ) return !ext::json::keys( *this ).empty();
if ( IsArray() ) return size() > 0;
return false;
}

View File

@ -5,6 +5,6 @@
namespace ext {
namespace meshopt {
void UF_API optimize( pod::Mesh&, size_t = SIZE_MAX );
void UF_API optimize( uf::Mesh&, size_t = SIZE_MAX );
}
}

View File

@ -80,10 +80,10 @@ namespace ext {
void initialize( const uf::stl::string& = "" );
void destroy();
template<typename T, typename U>
void initializeMesh( uf::Mesh<T, U>& mesh, size_t = SIZE_MAX );
void initializeAttributes( const pod::Mesh::Attributes& mesh );
// template<typename T, typename U>
// void initializeMesh( uf::Mesh<T, U>& mesh, size_t = SIZE_MAX );
// void initializeAttributes( const uf::Mesh::Attributes& mesh );
void initializeMesh( uf::Mesh& mesh );
bool hasPipeline( const GraphicDescriptor& descriptor ) const;
void initializePipeline();

View File

@ -1,6 +1,8 @@
#if 0
template<typename T, typename U>
void ext::opengl::Graphic::initializeMesh( uf::Mesh<T, U>& mesh, size_t o ) {
if ( mesh.indices.empty() ) mesh.initialize( o );
mesh.updateDescriptor();
initializeAttributes( mesh.attributes );
}
}
#endif

View File

@ -8,7 +8,7 @@ namespace ext {
struct Device;
struct UF_API Buffer {
VkDevice device;
ext::vulkan::Device* device = NULL;
VkBuffer buffer = VK_NULL_HANDLE;
VkDeviceMemory memory = VK_NULL_HANDLE;
VkDescriptorBufferInfo descriptor = {
@ -40,7 +40,9 @@ namespace ext {
// RAII
~Buffer();
void initialize( VkDevice device );
void initialize( ext::vulkan::Device& device );
void initialize( const void*, VkDeviceSize, VkBufferUsageFlags, VkMemoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, bool = VK_DEFAULT_STAGE_BUFFERS );
void update( const void*, VkDeviceSize, bool = VK_DEFAULT_STAGE_BUFFERS ) const;
void destroy();
void aliasBuffer( const Buffer& );

View File

@ -10,6 +10,7 @@
namespace ext {
namespace vulkan {
struct Graphic;
struct UF_API Pipeline {
bool aliased = false;
@ -39,6 +40,7 @@ namespace ext {
uf::stl::vector<Shader*> getShaders( uf::stl::vector<Shader>& );
uf::stl::vector<const Shader*> getShaders( const uf::stl::vector<Shader>& ) const;
};
struct UF_API Material {
bool aliased = false;
Device* device;
@ -64,6 +66,7 @@ namespace ext {
bool validate();
};
struct UF_API Graphic : public Buffers {
GraphicDescriptor descriptor;
@ -76,14 +79,28 @@ namespace ext {
uf::stl::unordered_map<uf::stl::string, size_t> buffers;
} metadata;
struct Layout {
uf::stl::vector<VkDescriptorBufferInfo> uniform;
uf::stl::vector<VkDescriptorBufferInfo> storage;
uf::stl::vector<VkDescriptorImageInfo> image;
uf::stl::vector<VkDescriptorImageInfo> image2D;
uf::stl::vector<VkDescriptorImageInfo> imageCube;
uf::stl::vector<VkDescriptorImageInfo> image3D;
uf::stl::vector<VkDescriptorImageInfo> sampler;
uf::stl::vector<VkDescriptorImageInfo> input;
} layout;
~Graphic();
void initialize( const uf::stl::string& = "" );
void destroy();
template<typename T, typename U>
void initializeMesh( uf::Mesh<T, U>& mesh, size_t = SIZE_MAX );
void initializeAttributes( const pod::Mesh::Attributes& mesh );
// template<typename T, typename U>
// void initializeMesh( uf::Mesh<T, U>& mesh );
// void initializeAttributes( const uf::Mesh::Attributes& mesh );
void initializeMesh( uf::Mesh& mesh, bool buffer = true );
bool hasPipeline( const GraphicDescriptor& descriptor ) const;
void initializePipeline();
@ -99,13 +116,6 @@ namespace ext {
void record( VkCommandBuffer commandBuffer, size_t pass = 0, size_t draw = 0 ) const;
void record( VkCommandBuffer commandBuffer, const GraphicDescriptor& descriptor, size_t pass = 0, size_t draw = 0 ) const;
bool hasStorage( const uf::stl::string& name ) const;
Buffer& getStorageBuffer( const uf::stl::string& name );
const Buffer& getStorageBuffer( const uf::stl::string& name ) const;
uf::Serializer getStorageJson( const uf::stl::string& name, bool cache = true );
ext::vulkan::userdata_t getStorageUserdata( const uf::stl::string& name, const ext::json::Value& payload );
};
}
}

View File

@ -1,6 +1,8 @@
#if 0
template<typename T, typename U>
void ext::vulkan::Graphic::initializeMesh( uf::Mesh<T, U>& mesh, size_t o ) {
if ( mesh.indices.empty() ) mesh.initialize( o );
mesh.updateDescriptor();
initializeAttributes( mesh.attributes );
}
}
#endif

View File

@ -38,6 +38,14 @@ namespace ext {
uf::stl::string type = "";
struct Definition {
struct InOut {
uf::stl::string name = "";
uint32_t index = 0;
uint32_t binding = 0;
uint32_t size = 0;
// int32_t buffer = -1;
ext::vulkan::enums::Image::viewType_t type{};
};
struct Texture {
uf::stl::string name = "";
uint32_t index = 0;
@ -50,12 +58,14 @@ namespace ext {
uint32_t index = 0;
uint32_t binding = 0;
uint32_t size = 0;
// int32_t buffer = -1;
};
struct Storage {
uf::stl::string name = "";
uint32_t index = 0;
uint32_t binding = 0;
uint32_t size = 0;
// int32_t buffer = -1;
};
struct PushConstant {
uf::stl::string name = "";
@ -75,6 +85,8 @@ namespace ext {
} value;
};
uf::stl::unordered_map<size_t, Texture> textures;
uf::stl::unordered_map<uf::stl::string, InOut> inputs;
uf::stl::unordered_map<uf::stl::string, InOut> outputs;
uf::stl::unordered_map<uf::stl::string, Uniform> uniforms;
uf::stl::unordered_map<uf::stl::string, Storage> storage;
uf::stl::unordered_map<uf::stl::string, PushConstant> pushConstants;
@ -106,16 +118,25 @@ namespace ext {
inline bool updateUniform( const uf::stl::string& name, const ext::vulkan::userdata_t& userdata ) const {
return updateUniform(name, (const void*) userdata, userdata.size() );
}
bool hasStorage( const uf::stl::string& name ) const;
Buffer& getStorageBuffer( const uf::stl::string& name );
const Buffer& getStorageBuffer( const uf::stl::string& name ) const;
bool updateStorage( const uf::stl::string& name, const void*, size_t ) const;
inline bool updateStorage( const uf::stl::string& name, const ext::vulkan::userdata_t& userdata ) const {
return updateStorage(name, (const void*) userdata, userdata.size() );
}
/*
uf::Serializer getUniformJson( const uf::stl::string& name, bool cache = true );
bool updateUniform( const uf::stl::string& name, const ext::json::Value& payload );
ext::vulkan::userdata_t getUniformUserdata( const uf::stl::string& name, const ext::json::Value& payload );
uf::Serializer getStorageJson( const uf::stl::string& name, bool cache = true );
ext::vulkan::userdata_t getStorageUserdata( const uf::stl::string& name, const ext::json::Value& payload );
*/
};
}
}

View File

@ -15,6 +15,7 @@ namespace uf {
void setPositions( const uf::stl::vector<pod::Vector3>& );
#if 0
template<typename T, typename U>
void setPositions( const uf::Mesh<T, U>& mesh ) {
this->m_positions.clear();
@ -25,6 +26,7 @@ namespace uf {
for ( auto& vertex : mesh.vertices ) this->m_positions.push_back( vertex.position );
}
}
#endif
virtual uf::stl::string type() const;
virtual pod::Vector3* expand() const;

View File

@ -0,0 +1,22 @@
#pragma once
#include <uf/config.h>
#include "./allocator.h"
#include <nlohmann/fifo_map.hpp>
namespace uf {
namespace stl {
template<
class Key,
class T,
class Compare = nlohmann::fifo_map_compare<Key>,
#if UF_MEMORYPOOL_USE_STL_ALLOCATOR
class Allocator = std::allocator<std::pair<const Key, T>>
#else
class Allocator = uf::Allocator<std::pair<const Key, T>>
#endif
>
using fifo_map = nlohmann::fifo_map<Key, T, Compare, Allocator>;
}
}

View File

@ -1,3 +1,4 @@
#if 0
#pragma once
#include <uf/config.h>
@ -36,7 +37,6 @@ namespace uf {
void insert( uint32_t, uint32_t, uint32_t, const pod::Vector3f&, const pod::Vector3f&, const pod::Vector3f& );
public:
~MeshGrid();
template<typename T, typename U>
void initialize( const uf::Mesh<T,U>& mesh, size_t = 1 );
@ -56,4 +56,5 @@ namespace uf {
};
};
#include "grid.inl"
#include "grid.inl"
#endif

View File

@ -21,40 +21,159 @@ namespace ext {
#else
typedef uint32_t index_t;
#endif
struct /*UF_API*/ VertexDescriptor {
ext::RENDERER::enums::Format::type_t format = ext::RENDERER::enums::Format::UNDEFINED; // VK_FORMAT_R32G32B32_SFLOAT
size_t offset = 0; // offsetof(Vertex, position)
size_t size = 0; // sizeof(Vertex::position::type_t)
size_t components = 0; // Vertex::position::size
ext::RENDERER::enums::Type::type_t type = 0; // ext::RENDERER::typeToEnum<Vertex::position::type_t>()
struct UF_API AttributeDescriptor {
// essential for vertex input
size_t offset = 0;
size_t size = 0;
ext::RENDERER::enums::Format::type_t format = ext::RENDERER::enums::Format::UNDEFINED;
// not as essential
uf::stl::string name = "";
bool operator==( const VertexDescriptor& right ) const { return format == right.format && offset == right.offset && size == right.size && components == right.components && type == right.type && name == right.name; }
bool operator!=( const VertexDescriptor& right ) const { return !(*this == right); };
ext::RENDERER::enums::Type::type_t type = 0;
size_t components = 0;
// somewhat essential
size_t length = 0;
void* pointer = NULL;
bool operator==( const AttributeDescriptor& right ) const { return
offset == right.offset &&
size == right.size &&
format == right.format &&
name == right.name &&
type == right.type &&
components == right.components;
}
bool operator!=( const AttributeDescriptor& right ) const { return !(*this == right); };
};
}
}
namespace pod {
namespace uf {
struct UF_API Mesh {
public:
struct Attributes {
struct {
size_t size = 0;
size_t length = 0;
void* pointer = NULL;
} vertex, index;
static bool defaultInterleaved;
typedef uf::stl::vector<uint8_t> buffer_t;
struct Attribute {
ext::RENDERER::AttributeDescriptor descriptor;
int32_t buffer = -1;
size_t offset = 0;
};
struct Input {
uf::stl::vector<Attribute> attributes;
size_t count = 0; // how many elements is the input using
size_t first = 0; // base index to start from
size_t stride = 0; // size of one element in the input's buffer
size_t offset = 0; // bytes to offset from within the associated buffer
int32_t interleaved = -1; // index to interleaved buffer if in bounds
typedef uf::stl::vector<ext::RENDERER::VertexDescriptor> descriptors_t;
descriptors_t descriptor;
} attributes;
struct Settings {
bool interleaved = false;
} settings;
} vertex, index, instance, indirect;
uf::stl::vector<buffer_t> buffers;
protected:
void _destroy( uf::Mesh::Input& input );
void _bind( bool interleaved = uf::Mesh::defaultInterleaved );
void _updateDescriptor( uf::Mesh::Input& input );
bool _hasV( const uf::Mesh::Input& input, const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) const;
bool _hasV( const uf::Mesh::Input& input, const uf::Mesh::Input& src ) const;
void _bindV( uf::Mesh::Input& input, const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors );
void _resizeVs( uf::Mesh::Input& input, size_t count );
void _reserveVs( uf::Mesh::Input& input, size_t count );
void _insertV( uf::Mesh::Input& input, const void* data );
void _insertV( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput );
void _insertVs( uf::Mesh::Input& input, const void* data, size_t size );
template<typename T> inline bool _hasV( const uf::Mesh::Input& input ) const { return _hasV( input, T::descriptors ); }
template<typename T> inline void _bindV( uf::Mesh::Input& input ) { return _bindV( input, T::descriptor ); }
template<typename T> inline void _insertV( uf::Mesh::Input& input, const T& vertex ) { return _insertV( input, (const void*) &vertex ); }
template<typename T> inline void _insertVs( uf::Mesh::Input& input, const uf::stl::vector<T>& vs ) { return _insertVs( input, (const void*) vs.data(), vs.size() ); }
void _bindI( uf::Mesh::Input& input, size_t size, ext::RENDERER::enums::Type::type_t type, size_t count = 1 );
void _reserveIs( uf::Mesh::Input& input, size_t count, size_t i = 0 );
void _resizeIs( uf::Mesh::Input& input, size_t count, size_t i = 0 );
void _insertI( uf::Mesh::Input& input, const void* data, size_t i );
void _insertI( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput );
void _insertIs( uf::Mesh::Input& input, const void* data, size_t size, size_t i );
template<typename U> inline void _bindI( uf::Mesh::Input& input, size_t indices = 1 ) { return _bindI( input, sizeof(U), ext::RENDERER::typeToEnum<U>(), indices ); }
template<typename U> inline void _insertI( uf::Mesh::Input& input, U index, size_t i = 0 ) { return _insertI( input, (const void*) &index, i ); }
template<typename U> inline void _insertIs( uf::Mesh::Input& input, const uf::stl::vector<U>& is, size_t i = 0 ) { return _insertIs( input, (const void*) is.data(), is.size(), i ); }
public:
void initialize();
void destroy();
uf::Mesh interleave() const;
void updateDescriptor();
void insert( const uf::Mesh& );
void generateIndices();
virtual ~Mesh();
virtual void updateDescriptor();
virtual void resizeVertices( size_t );
virtual void resizeIndices( size_t );
void generateIndirect();
bool isInterleaved( size_t ) const;
void print() const;
inline bool hasVertex( const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) const { return _hasV( vertex, descriptors ); }
inline bool hasVertex( const uf::Mesh& mesh ) const { return _hasV( vertex, mesh.vertex ); }
inline void bindVertex( const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) { return _bindV( vertex, descriptors ); }
inline void resizeVertices( size_t count ) { return _resizeVs( vertex, count ); }
inline void reserveVertices( size_t count ) { return _reserveVs( vertex, count ); }
inline void insertVertex( const void* data ) { return _insertV( vertex, data ); }
inline void insertVertices( const void* data, size_t size ) { return _insertVs( vertex, data, size ); }
inline void insertVertices( const uf::Mesh& mesh ) { return _insertV( vertex, mesh, mesh.vertex ); }
inline void updateVertexDescriptor() { return _updateDescriptor( vertex ); }
template<typename T> inline bool hasVertex() const { return _hasV( vertex, T::descriptors ); }
template<typename T> inline void bindVertex() { return _bindV( vertex, T::descriptor ); }
template<typename T> inline void insertVertex( const T& v ) { return _insertV( vertex, (const void*) &v ); }
template<typename T> inline void insertVertices( const uf::stl::vector<T>& vertices ) { return _insertVs( vertex, (const void*) vertices.data(), vertices.size() ); }
inline void bindIndex( size_t size, ext::RENDERER::enums::Type::type_t type, size_t count = 1 ) { return _bindI( index, size, type, count ); }
inline void reserveIndices( size_t count, size_t i = 0 ) { return _reserveIs( index, count, i ); }
inline void resizeIndices( size_t count, size_t i = 0 ) { return _resizeIs( index, count, i ); }
inline void insertIndex( const void* data, size_t i = 0 ) { return _insertI( index, data, i ); }
inline void insertIndices( const void* data, size_t size, size_t i = 0 ) { return _insertIs( index, data, size, i ); }
inline void insertIndices( const uf::Mesh& mesh ) { return _insertI( index, mesh, mesh.index ); }
inline void updateIndexDescriptor() { return _updateDescriptor( index ); }
template<typename U> inline void bindIndex( size_t count = 1 ) { return _bindI( index, sizeof(U), ext::RENDERER::typeToEnum<U>(), count ); }
template<typename U> inline void insertIndex( U I, size_t i = 0 ) { return _insertI( index, (const void*) &I, i ); }
template<typename U> inline void insertIndices( const uf::stl::vector<U>& indices, size_t i = 0 ) { return _insertIs( index, (const void*) indices.data(), indices.size(), i ); }
inline bool hasInstance( const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) const { return _hasV( instance, descriptors ); }
inline bool hasInstance( const uf::Mesh& mesh ) const { return _hasV( instance, mesh.instance ); }
inline void bindInstance( const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) { return _bindV( instance, descriptors ); }
inline void resizeInstances( size_t count ) { return _resizeVs( instance, count ); }
inline void reserveInstances( size_t count ) { return _reserveVs( instance, count ); }
inline void insertInstance( const void* data ) { return _insertV( instance, data ); }
inline void insertInstances( const void* data, size_t size ) { return _insertVs( instance, data, size ); }
inline void insertInstances( const uf::Mesh& mesh ) { return _insertV( instance, mesh, mesh.instance ); }
inline void updateInstanceDescriptor() { return _updateDescriptor( instance ); }
template<typename T> inline bool hasInstance() const { return _hasV( instance, T::descriptors ); }
template<typename T> inline void bindInstance() { return _bindV( instance, T::descriptor ); }
template<typename T> inline void insertInstance( const T& v ) { return _insertV( instance, (const void*) &v ); }
template<typename T> inline void insertInstances( const uf::stl::vector<T>& instances ) { return _insertVs( instance, (const void*) instances.data(), instances.size() ); }
inline void bindIndirect( size_t size, ext::RENDERER::enums::Type::type_t type, size_t count = 1 ) { return _bindI( indirect, size, type, count ); }
inline void reserveIndirects( size_t count, size_t i = 0 ) { return _reserveIs( indirect, count, i ); }
inline void resizeIndirects( size_t count, size_t i = 0 ) { return _resizeIs( indirect, count, i ); }
inline void insertIndirect( const void* data, size_t i = 0 ) { return _insertI( indirect, data, i ); }
inline void insertIndirects( const void* data, size_t size, size_t i = 0 ) { return _insertIs( indirect, data, size, i ); }
inline void insertIndirects( const uf::Mesh& mesh ) { return _insertI( indirect, mesh, mesh.indirect ); }
inline void updateIndirectDescriptor() { return _updateDescriptor( indirect ); }
template<typename U> inline void bindIndirect( size_t i = 1 ) { return _bindI( indirect, sizeof(U), ext::RENDERER::typeToEnum<U>(), i ); }
template<typename U> inline void insertIndirect( U v, size_t i = 0 ) { return _insertI( indirect, (const void*) &v, i ); }
template<typename U> inline void insertIndirects( const uf::stl::vector<U>& indirects, size_t i = 0 ) { return _insertIs( indirect, (const void*) indirects.data(), indirects.size(), i ); }
template<typename T, typename U = ext::RENDERER::index_t>
void bind( bool interleave = uf::Mesh::defaultInterleaved, size_t indices = 1 ) {
bindVertex<T>();
bindIndex<U>( indices );
_bind( interleave );
}
};
}
@ -73,13 +192,10 @@ namespace ext {
uint32_t renderTarget = 0;
uint32_t subpass = 0;
pod::Mesh::Attributes attributes;
size_t indices = 0;
struct {
size_t vertex = 0;
size_t index = 0;
} offsets;
uf::Mesh::Input vertex, index, instance, indirect;
size_t bufferOffset = 0;
} inputs;
ext::RENDERER::enums::PrimitiveTopology::type_t topology = ext::RENDERER::enums::PrimitiveTopology::TRIANGLE_LIST;
ext::RENDERER::enums::PolygonMode::type_t fill = ext::RENDERER::enums::PolygonMode::FILL;
@ -98,7 +214,9 @@ namespace ext {
float clamp = 0;
} bias;
} depth;
bool invalidated = false;
hash_t hash() const;
void parse( ext::json::Value& );
bool operator==( const GraphicDescriptor& right ) const { return this->hash() == right.hash(); }
@ -109,16 +227,16 @@ namespace ext {
#undef UF_RENDERER
#define UF_VERTEX_DESCRIPTION( TYPE, FORMAT, ATTRIBUTE ) {\
uf::renderer::enums::Format::FORMAT,\
offsetof(TYPE, ATTRIBUTE),\
sizeof(decltype(TYPE::ATTRIBUTE)::type_t),\
decltype(TYPE::ATTRIBUTE)::size,\
ext::RENDERER::typeToEnum<decltype(TYPE::ATTRIBUTE)::type_t>(),\
#ATTRIBUTE\
.offset = offsetof(TYPE, ATTRIBUTE),\
.size = sizeof(decltype(TYPE::ATTRIBUTE)),\
.format = uf::renderer::enums::Format::FORMAT,\
.name = #ATTRIBUTE,\
.type = ext::RENDERER::typeToEnum<decltype(TYPE::ATTRIBUTE)::type_t>(),\
.components = decltype(TYPE::ATTRIBUTE)::size,\
},
#define UF_VERTEX_DESCRIPTOR( TYPE, ... )\
uf::stl::vector<uf::renderer::VertexDescriptor> TYPE::descriptor = { __VA_ARGS__ };
uf::stl::vector<uf::renderer::AttributeDescriptor> TYPE::descriptor = { __VA_ARGS__ };
#if UF_USE_VULKAN
@ -131,31 +249,6 @@ namespace ext {
}
#endif
namespace uf {
template<typename T, typename U = uf::renderer::index_t>
class /*UF_API*/ Mesh : public pod::Mesh {
public:
typedef T vertex_t;
typedef U index_t;
typedef vertex_t vertices_t;
typedef index_t indices_t;
uf::stl::vector<vertex_t> vertices;
uf::stl::vector<index_t> indices;
void initialize( size_t = SIZE_MAX );
void destroy();
void expand( bool = true );
uf::Mesh<T,U> simplify( float = 0.2f );
void optimize( size_t = SIZE_MAX );
void insert( const uf::Mesh<T,U>& mesh );
virtual void updateDescriptor();
virtual void resizeVertices( size_t );
virtual void resizeIndices( size_t );
};
}
namespace pod {
struct /*UF_API*/ Vertex_3F2F3F4F {
/*alignas(16)*/ pod::Vector3f position;
@ -163,7 +256,7 @@ namespace pod {
/*alignas(16)*/ pod::Vector3f normal;
/*alignas(16)*/ pod::Vector4f color;
static UF_API uf::stl::vector<uf::renderer::VertexDescriptor> descriptor;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F2F3F32B {
/*alignas(16)*/ pod::Vector3f position;
@ -171,14 +264,14 @@ namespace pod {
/*alignas(16)*/ pod::Vector3f normal;
/*alignas(16)*/ pod::Vector4t<uint8_t> color;
static UF_API uf::stl::vector<uf::renderer::VertexDescriptor> descriptor;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F3F3F {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(16)*/ pod::Vector3f uv;
/*alignas(16)*/ pod::Vector3f normal;
static UF_API uf::stl::vector<uf::renderer::VertexDescriptor> descriptor;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F2F3F1UI {
/*alignas(16)*/ pod::Vector3f position;
@ -186,83 +279,34 @@ namespace pod {
/*alignas(16)*/ pod::Vector3f normal;
/*alignas(4)*/ pod::Vector1ui id;
static UF_API uf::stl::vector<uf::renderer::VertexDescriptor> descriptor;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F2F3F {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(8)*/ pod::Vector2f uv;
/*alignas(16)*/ pod::Vector3f normal;
static UF_API uf::stl::vector<uf::renderer::VertexDescriptor> descriptor;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F2F {
/*alignas(16)*/ pod::Vector3f position;
/*alignas(8)*/ pod::Vector2f uv;
static UF_API uf::stl::vector<uf::renderer::VertexDescriptor> descriptor;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_2F2F {
/*alignas(8)*/ pod::Vector2f position;
/*alignas(8)*/ pod::Vector2f uv;
static UF_API uf::stl::vector<uf::renderer::VertexDescriptor> descriptor;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
struct /*UF_API*/ Vertex_3F {
/*alignas(16)*/ pod::Vector3f position;
static UF_API uf::stl::vector<uf::renderer::VertexDescriptor> descriptor;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
}
#if 0
namespace uf {
typedef BaseMesh<pod::Vertex_3F2F3F32B> ColoredMesh;
typedef BaseMesh<pod::Vertex_3F2F3F> Mesh;
typedef BaseMesh<pod::Vertex_3F> LineMesh;
template<size_t N = 6>
struct MeshDescriptor {
struct {
/*alignas(16)*/ pod::Matrix4f model;
/*alignas(16)*/ pod::Matrix4f view[N];
/*alignas(16)*/ pod::Matrix4f projection[N];
} matrices;
/*alignas(16)*/ pod::Vector4f color = { 1, 1, 1, 0 };
};
}
#endif
#include <uf/utils/userdata/userdata.h>
namespace pod {
struct UF_API VaryingMesh : public pod::Mesh {
pod::PointeredUserdata userdata;
pod::Mesh& get();
const pod::Mesh& get() const;
void destroy();
virtual void updateDescriptor();
virtual void resizeVertices( size_t );
virtual void resizeIndices( size_t );
template<typename T, typename U = uf::renderer::index_t>
bool is() const;
template<typename T, typename U = uf::renderer::index_t>
uf::Mesh<T,U>& get();
template<typename T, typename U = uf::renderer::index_t>
const uf::Mesh<T,U>& get() const;
template<typename T, typename U = uf::renderer::index_t>
void set( const uf::Mesh<T, U>& = {} );
template<typename T, typename U = uf::renderer::index_t>
void insert( const pod::VaryingMesh& mesh );
template<typename T, typename U = uf::renderer::index_t>
void insert( const uf::Mesh<T, U>& mesh );
};
}
#include <uf/ext/meshopt/meshopt.h>
#include "mesh.inl"

View File

@ -1,3 +1,4 @@
#if 0
template<typename T, typename U>
void uf::Mesh<T, U>::initialize( size_t o ) {
this->optimize(o);
@ -44,12 +45,13 @@ void uf::Mesh<T, U>::expand( bool check ) {
template<typename T, typename U>
void uf::Mesh<T, U>::updateDescriptor() {
attributes.vertex.size = sizeof(vertex_t);
attributes.index.size = sizeof(indices_t);
attributes.vertex.pointer = &this->vertices[0];
attributes.index.pointer = &this->indices[0];
attributes.vertex.length = this->vertices.size();
attributes.vertex.pointer = &this->vertices[0];
attributes.vertex.descriptor = vertex_t::descriptor;
attributes.index.size = sizeof(indices_t);
attributes.index.length = this->indices.size();
attributes.descriptor = vertex_t::descriptor;
attributes.index.pointer = &this->indices[0];
}
template<typename T, typename U>
void uf::Mesh<T, U>::destroy() {
@ -105,26 +107,26 @@ bool pod::VaryingMesh::is() const {
#if 0
return uf::pointeredUserdata::is<uf::Mesh<T,U>>();
#else
if ( attributes.descriptor.size() != T::descriptor.size() ||
if ( attributes.vertex.descriptor.size() != T::descriptor.size() ||
// vertex types are the same size
attributes.vertex.size != sizeof(T) ||
// index types are the same size
attributes.index.size != sizeof(U) ) return false;
for ( size_t i = 0; i < attributes.descriptor.size(); ++i ) {
if ( attributes.descriptor[i].offset != attributes.descriptor[i].offset || attributes.descriptor[i].size != attributes.descriptor[i].size || attributes.descriptor[i].components != attributes.descriptor[i].components ) return false;
for ( size_t i = 0; i < attributes.vertex.descriptor.size(); ++i ) {
if ( attributes.vertex.descriptor[i].offset != attributes.vertex.descriptor[i].offset || attributes.vertex.descriptor[i].size != attributes.vertex.descriptor[i].size || attributes.vertex.descriptor[i].components != attributes.vertex.descriptor[i].components ) return false;
}
return true;
#if 0
return
// descriptors are the same size
attributes.descriptor.size() == T::descriptor.size() &&
attributes.vertex.descriptor.size() == T::descriptor.size() &&
// vertex types are the same size
attributes.vertex.size == sizeof(T) &&
// index types are the same size
attributes.index.size == sizeof(U) &&
// attributes are the same
std::equal( attributes.descriptor.begin(), attributes.descriptor.end(), T::descriptor.begin() );
std::equal( attributes.vertex.descriptor.begin(), attributes.vertex.descriptor.end(), T::descriptor.begin() );
#endif
#endif
}
@ -157,4 +159,5 @@ template<typename T, typename U>
void pod::VaryingMesh::insert( const uf::Mesh<T, U>& mesh ) {
get<T,U>().insert( mesh );
updateDescriptor();
}
}
#endif

View File

@ -139,6 +139,7 @@ uf::stl::string uf::Asset::load( const uf::stl::string& uri, const uf::stl::stri
UF_MSG_ERROR("Failed to load `" << filename << "`: Hash mismatch; expected " << hash << ", got " << actual);
return "";
}
#define UF_ASSET_REGISTER(type)\
auto& container = this->getContainer<type>();\
if ( !ext::json::isNull( map[extension][uri]["index"] ) ) return filename;\
@ -172,29 +173,17 @@ uf::stl::string uf::Asset::load( const uf::stl::string& uri, const uf::stl::stri
auto& metadata = this->getComponent<uf::Serializer>();
#if UF_USE_OPENGL_FIXED_FUNCTION
// force disable use of a texture atlas, for now
metadata[uri]["flags"]["ATLAS"] = false;
metadata[uri]["flags"]["SEPARATE"] = true;
// metadata[uri]["flags"]["NORMALS"] = true;
#else
// metadata[uri]["flags"]["ATLAS"] = true;
#elif UF_GRAPH_INDIRECT_DRAW
metadata[uri]["flags"]["ATLAS"] = false;
metadata[uri]["flags"]["SEPARATE"] = false;
#endif
uf::graph::load_mode_t LOAD_FLAGS = 0;
#define LOAD_FLAG(name)\
if ( metadata[uri]["flags"][#name].as<bool>() )\
LOAD_FLAGS |= uf::graph::LoadMode::name;
LOAD_FLAG(ATLAS) // = 0x1 << 1,
LOAD_FLAG(INVERT) // = 0x1 << 2,
LOAD_FLAG(TRANSFORM) // = 0x1 << 3,
LOAD_FLAG(SKINNED) // = 0x1 << 4,
asset = uf::graph::load( filename, LOAD_FLAGS, metadata[uri] );
asset = uf::graph::load( filename, metadata[uri] );
uf::graph::process( asset );
if ( asset.metadata["debug"]["print stats"].as<bool>() ) UF_MSG_INFO(uf::graph::stats( asset ).dump(1,'\t'));
if ( asset.metadata["debug"]["print tree"].as<bool>() ) UF_MSG_INFO(uf::graph::print( asset ));
if ( !asset.metadata["debug"]["no cleanup"].as<bool>() ) uf::graph::cleanup( asset );
//uf::graph::process( asset );
} else {
UF_MSG_ERROR("Failed to parse `" + filename + "`: Unimplemented extension: " + extension + " or category: " + category );
}

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +0,0 @@
#include <uf/engine/graph/mesh.h>
UF_VERTEX_DESCRIPTOR(uf::graph::mesh::Base,
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32B32_SFLOAT, position)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32_SFLOAT, uv)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32_SFLOAT, st)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R16G16_SINT, id)
);
UF_VERTEX_DESCRIPTOR(uf::graph::mesh::ID,
UF_VERTEX_DESCRIPTION(uf::graph::mesh::ID, R32G32B32_SFLOAT, position)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::ID, R32G32_SFLOAT, uv)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::ID, R32G32_SFLOAT, st)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::ID, R32G32B32_SFLOAT, normal)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::ID, R32G32B32_SFLOAT, tangent)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::ID, R16G16_SINT, id)
);
UF_VERTEX_DESCRIPTOR(uf::graph::mesh::Skinned,
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32_SFLOAT, position)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32_SFLOAT, uv)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32_SFLOAT, st)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32_SFLOAT, normal)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32_SFLOAT, tangent)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R16G16_SINT, id)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R16G16B16A16_SINT, joints)
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32A32_SFLOAT, weights)
);

View File

@ -66,6 +66,7 @@ void uf::GraphBehavior::initialize( uf::Object& self ) {
}
void uf::GraphBehavior::destroy( uf::Object& self ) {}
void uf::GraphBehavior::tick( uf::Object& self ) {
#if 0
/* Update animations */ if ( this->hasComponent<pod::Graph>() ) {
auto& graph = this->getComponent<pod::Graph>();
// if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) uf::graph::update( graph );
@ -101,7 +102,7 @@ void uf::GraphBehavior::tick( uf::Object& self ) {
auto& node = graph.nodes[i];
instances[i] = uf::transform::model( node.entity ? node.entity->getComponent<pod::Transform<>>() : node.transform );
}
graphic.updateBuffer( (const void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.buffers.instance );
shader.updateBuffer( (const void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.buffers.instance );
shader.execute( graphic, mesh.attributes.vertex.pointer );
} else if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) {
shader.execute( graphic, mesh.attributes.vertex.pointer );
@ -117,7 +118,7 @@ void uf::GraphBehavior::tick( uf::Object& self ) {
auto& node = graph.nodes[i];
instances[i] = uf::transform::model( node.entity ? node.entity->getComponent<pod::Transform<>>() : node.transform );
}
graphic.updateBuffer( (const void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.buffers.instance /*storageBuffer*/ );
shader.updateBuffer( (const void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.buffers.instance /*storageBuffer*/ );
} else {
struct UniformDescriptor {
/*alignas(16)*/ pod::Matrix4f model;
@ -135,7 +136,7 @@ void uf::GraphBehavior::tick( uf::Object& self ) {
.model = uf::transform::model( transform ),
// .color = uf::vector::decode( metadata["color"], pod::Vector4f{1,1,1,1} ),
};
graphic.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
#endif
}
}
@ -148,12 +149,14 @@ void uf::GraphBehavior::tick( uf::Object& self ) {
instances[i] = node.entity ? uf::transform::model( node.entity->getComponent<pod::Transform<>>() ) : uf::transform::model( node.transform );
}
auto& storageBuffer = *graphic.getStorageBuffer("Models");
graphic.updateBuffer( (const void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.buffers.instance /*storageBuffer*/ );
shader.updateBuffer( (const void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.buffers.instance /*storageBuffer*/ );
}
#endif
#endif
#endif
}
void uf::GraphBehavior::render( uf::Object& self ) {
#if 0
/* Update uniforms */
if ( !this->hasComponent<uf::Graphic>() ) return;
@ -199,10 +202,11 @@ void uf::GraphBehavior::render( uf::Object& self ) {
shader.updateUniform("Camera", uniform);
#else
pod::Camera::Viewports uniforms = camera.data().viewport;
graphic.updateBuffer( uniforms, shader.getUniformBuffer("Camera") );
shader.updateBuffer( uniforms, shader.getUniformBuffer("Camera") );
#endif
}
#endif
#endif
}
void uf::GraphBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {}
void uf::GraphBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) {}

View File

@ -62,7 +62,7 @@ void uf::RenderBehavior::tick( uf::Object& self ) {
.model = uf::transform::model( transform ),
// .color = uf::vector::decode( metadata["color"], pod::Vector4f{ 1, 1, 1, 1 } ),
};
graphic.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
#endif
#endif
}
@ -115,7 +115,7 @@ void uf::RenderBehavior::render( uf::Object& self ) {
shader.updateUniform("Camera", uniform);
#else
pod::Camera::Viewports uniforms = camera.data().viewport;
graphic.updateBuffer( uniforms, shader.getUniformBuffer("Camera") );
shader.updateBuffer( uniforms, shader.getUniformBuffer("Camera") );
#endif
#endif
}

View File

@ -10,28 +10,27 @@
class BulletDebugDrawer : public btIDebugDraw {
protected:
int m;
uf::Mesh<pod::Vertex_3F2F3F4F> mesh;
uf::Mesh mesh;
public:
virtual void drawLine( const btVector3& from, const btVector3& to, const btVector3& color ) {
drawLine( from, to, color, color );
}
virtual void drawLine( const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor ) {
auto& A = mesh.vertices.emplace_back();
A.position = { from.getX(), from.getY(), from.getZ() };
//{0.0f, 0.0f},
//{0.0f, 0.0f, 0.0f},
A.color = { fromColor.getX(), fromColor.getY(), fromColor.getZ(), 1.0f };
auto& B = mesh.vertices.emplace_back();
B.position = { to.getX(), to.getY(), to.getZ() };
//{0.0f, 0.0f},
//{0.0f, 0.0f, 0.0f},
B.color = { toColor.getX(), toColor.getY(), toColor.getZ(), 1.0f };
pod::Vertex_3F2F3F4F vertex;
vertex.position = { from.getX(), from.getY(), from.getZ() };
vertex.color = { fromColor.getX(), fromColor.getY(), fromColor.getZ(), 1.0f };
mesh.insertVertex(vertex);
vertex.position = { to.getX(), to.getY(), to.getZ() };
vertex.color = { toColor.getX(), toColor.getY(), toColor.getZ(), 1.0f };
mesh.insertVertex(vertex);
}
virtual void drawContactPoint(const btVector3&, const btVector3&, btScalar, int, const btVector3&) {
}
virtual void reportErrorWarning(const char* str ) {
uf::iostream << "[Bullet] " << str << "\n";
UF_MSG_WARNING("[Bullet] " << str);
}
virtual void draw3dText(const btVector3& , const char* str ) {
@ -48,8 +47,8 @@ public:
}
int getDebugMode(void) const { return m; }
uf::Mesh<pod::Vertex_3F2F3F4F>& getMesh() { return mesh; }
const uf::Mesh<pod::Vertex_3F2F3F4F>& getMesh() const { return mesh; }
uf::Mesh& getMesh() { return mesh; }
const uf::Mesh& getMesh() const { return mesh; }
};
bool ext::bullet::debugDrawEnabled = false;
@ -112,7 +111,7 @@ void ext::bullet::initialize() {
ext::bullet::dynamicsWorld->setGravity(btVector3(0, -9.81, 0));
ext::bullet::debugDrawer.setDebugMode(btIDebugDraw::DBG_DrawWireframe);
ext::bullet::dynamicsWorld->setDebugDrawer(&ext::bullet::debugDrawer);
ext::bullet::dynamicsWorld->setDebugDrawer(&ext::bullet::debugDrawer);
#if !UF_ENV_DREAMCAST
gContactAddedCallback = contactCallback;
@ -276,46 +275,38 @@ void ext::bullet::detach( pod::Bullet& collider ) {
ext::bullet::dynamicsWorld->removeCollisionObject( collider.body );
}
pod::Bullet& ext::bullet::create( uf::Object& object, const pod::Mesh& mesh, bool dynamic ) {
pod::Bullet& ext::bullet::create( uf::Object& object, const uf::Mesh& mesh, bool dynamic ) {
auto& transform = object.getComponent<pod::Transform<>>();
auto& collider = ext::bullet::create( object );
auto model = uf::transform::model( collider.transform );
size_t indices = mesh.attributes.index.length;
size_t indexStride = mesh.attributes.index.size;
uint8_t* indexPointer = (uint8_t*) mesh.attributes.index.pointer;
size_t vertices = mesh.attributes.vertex.length;
size_t vertexStride = mesh.attributes.vertex.size;
uint8_t* vertexPointer = (uint8_t*) mesh.attributes.vertex.pointer;
uf::renderer::VertexDescriptor vertexAttributePosition;
for ( auto& attribute : mesh.attributes.descriptor ) {
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
}
if ( vertexAttributePosition.name == "" ) return collider;
btTriangleMesh* bMesh = new btTriangleMesh( true, false );
bMesh->preallocateVertices( vertices );
for ( size_t currentIndex = 0; currentIndex < vertices; ++currentIndex ) {
uint8_t* vertexSrc = vertexPointer + (currentIndex * vertexStride);
const pod::Vector3f& position = *((pod::Vector3f*) (vertexSrc + vertexAttributePosition.offset));
bMesh->findOrAddVertex( btVector3( position.x, position.y, position.z ), false );
}
if ( mesh.attributes.index.pointer ) {
bMesh->preallocateIndices( indices );
for ( size_t currentIndex = 0; currentIndex < indices; ++currentIndex ) {
uint32_t index = 0;
uint8_t* indexSrc = indexPointer + (currentIndex * indexStride);
switch ( indexStride ) {
case sizeof( uint8_t): index = *(( uint8_t*) indexSrc); break;
case sizeof(uint16_t): index = *((uint16_t*) indexSrc); break;
case sizeof(uint32_t): index = *((uint32_t*) indexSrc); break;
}
bMesh->addIndex( index );
for ( auto& attribute : mesh.vertex.attributes ) {
if ( attribute.descriptor.name != "position" ) continue;
const pod::Vector3f* pointer = (const pod::Vector3f*) attribute.descriptor.pointer;
bMesh->preallocateVertices( mesh.vertex.count );
for ( auto i = 0; i < mesh.vertex.count; ++i ) {
bMesh->findOrAddVertex( btVector3( pointer[i].x, pointer[i].y, pointer[i].z ), false );
}
break;
}
if ( mesh.index.count ) {
bMesh->preallocateIndices( mesh.index.count );
for ( auto& attribute : mesh.index.attributes ) {
size_t count = attribute.descriptor.length / attribute.descriptor.size;
const uint8_t* pointer = (const uint8_t*) attribute.descriptor.pointer;
for ( auto i = 0; i < count; ++i ) {
uint32_t index = 0;
switch ( attribute.descriptor.size ) {
case sizeof( uint8_t): index = (( uint8_t*) pointer)[i]; break;
case sizeof(uint16_t): index = ((uint16_t*) pointer)[i]; break;
case sizeof(uint32_t): index = ((uint32_t*) pointer)[i]; break;
}
bMesh->addIndex( index );
}
}
bMesh->getIndexedMeshArray()[0].m_numTriangles = indices / 3;
}
collider.shape = new btBvhTriangleMeshShape(bMesh, true);
@ -332,7 +323,6 @@ pod::Bullet& ext::bullet::create( uf::Object& object, const pod::Mesh& mesh, boo
triangleInfoMap->m_maxEdgeAngleThreshold = SIMD_HALF_PI*0.25;
if ( !false ) btGenerateInternalEdgeInfo( triangleMeshShape, triangleInfoMap );
collider.body->setCollisionFlags(collider.body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
return collider;
}
pod::Bullet& ext::bullet::create( uf::Object& object, const pod::Vector3f& corner, float mass ) {
@ -453,7 +443,10 @@ void UF_API ext::bullet::activateCollision( pod::Bullet& collider, bool enabled
void UF_API ext::bullet::debugDraw( uf::Object& object ) {
auto& mesh = ext::bullet::debugDrawer.getMesh();
if ( mesh.vertices.empty() ) return;
mesh.bind<pod::Vertex_3F2F3F4F>();
if ( !mesh.vertex.count ) return;
bool create = !object.hasComponent<uf::Graphic>();
auto& graphic = object.getComponent<uf::Graphic>();
graphic.process = false;
@ -468,14 +461,14 @@ void UF_API ext::bullet::debugDraw( uf::Object& object ) {
graphic.material.attachShader(uf::io::root + "/shaders/base/base.frag.spv", uf::renderer::enums::Shader::FRAGMENT);
graphic.initialize();
graphic.initializeMesh( mesh, 0 );
graphic.initializeMesh( mesh );
graphic.descriptor.topology = uf::renderer::enums::PrimitiveTopology::LINE_LIST;
graphic.descriptor.fill = uf::renderer::enums::PolygonMode::LINE;
graphic.descriptor.lineWidth = 8.0f;
} else {
graphic.process = true;
graphic.initializeMesh( mesh, 0 );
graphic.initializeMesh( mesh );
graphic.getPipeline().update( graphic );
}
}

View File

@ -75,7 +75,7 @@ namespace {
} else {
transform.position = { 0, 0, 0 };
}
if ( !(graph.mode & uf::graph::LoadMode::INVERT) ) {
if ( !(graph.metadata["flags"]["INVERT"].as<bool>()) ) {
transform.position.x *= -1;
}
if ( node.rotation.size() == 4 ) {
@ -111,10 +111,10 @@ namespace {
}
}
pod::Graph ext::gltf::load( const uf::stl::string& filename, uf::graph::load_mode_t mode, const uf::Serializer& metadata ) {
pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serializer& metadata ) {
uf::stl::string extension = uf::io::extension( filename );
if ( extension != "glb" && extension != "gltf" ) {
return uf::graph::load( filename, mode, metadata );
return uf::graph::load( filename, metadata );
}
tinygltf::Model model;
@ -125,7 +125,6 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, uf::graph::load_mod
pod::Graph graph;
graph.name = filename;
graph.mode = mode;
graph.metadata = metadata;
if ( !warn.empty() ) UF_MSG_WARNING("glTF warning: " << warn);
@ -136,9 +135,9 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, uf::graph::load_mod
// load samplers
{
graph.samplers.reserve(model.samplers.size());
uf::graph::storage.samplers.reserve(model.samplers.size());
for ( auto& s : model.samplers ) {
auto& sampler = graph.samplers.emplace_back();
auto& sampler = uf::graph::storage.samplers[graph.samplers.emplace_back(s.name)];
sampler.descriptor.filter.min = getFilterMode( s.minFilter );
sampler.descriptor.filter.mag = getFilterMode( s.magFilter );
sampler.descriptor.addressMode.u = getWrapMode( s.wrapS );
@ -149,84 +148,69 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, uf::graph::load_mod
// load images
{
graph.images.reserve(model.images.size());
uf::graph::storage.images.reserve(model.images.size());
for ( auto& i : model.images ) {
size_t index = graph.images.size();
auto& image = graph.images.emplace_back();
auto& image = uf::graph::storage.images[graph.images.emplace_back(i.name)];
image.loadFromBuffer( &i.image[0], {i.width, i.height}, 8, i.component, true );
}
}
// generate atlas
if ( mode & uf::graph::LoadMode::ATLAS ) {
graph.atlas.generate( graph.images );
if ( graph.metadata["flags"]["ATLAS"].as<bool>() ) {
// uf::graph::storage.atlases[filename].generate();
}
// load textures
{
graph.textures.reserve(model.textures.size());
uf::graph::storage.textures.reserve(model.textures.size());
for ( auto& t : model.textures ) {
auto& texture = graph.textures.emplace_back();
texture.name = t.name;
texture.storage.index = t.source;
texture.storage.sampler = t.sampler;
if ( 0 <= t.source && graph.atlas.generated() ) {
size_t index = t.source;
const auto& hash = graph.images[index].getHash();
auto atlasMin = graph.atlas.mapUv( {0, 0}, hash );
auto atlasMax = graph.atlas.mapUv( {1, 1}, hash );
texture.storage.lerp = {
atlasMin.x,
atlasMin.y,
atlasMax.x,
atlasMax.y,
};
auto& texture = uf::graph::storage.textures[graph.textures.emplace_back(t.name)];
texture.index = t.source;
texture.sampler = t.sampler;
if ( 0 <= t.source && uf::graph::storage.atlases[filename].generated() ) {
auto& image = graph.images[t.source];
const auto& hash = uf::graph::storage.images[image].getHash();
auto atlasMin = uf::graph::storage.atlases[filename].mapUv( {0, 0}, hash );
auto atlasMax = uf::graph::storage.atlases[filename].mapUv( {1, 1}, hash );
texture.lerp = { atlasMin.x, atlasMin.y, atlasMax.x, atlasMax.y, };
}
}
}
if ( graph.atlas.generated() ) {
graph.atlas.clear(false);
// clear source images
if ( uf::graph::storage.atlases[filename].generated() ) {
uf::graph::storage.atlases[filename].clear(false);
}
// load materials
{
graph.materials.reserve(model.materials.size());
uf::graph::storage.materials.reserve(model.materials.size());
for ( auto& m : model.materials ) {
auto& material = graph.materials.emplace_back();
material.name = m.name;
material.storage.indexAlbedo = m.pbrMetallicRoughness.baseColorTexture.index;
material.storage.indexNormal = m.normalTexture.index;
material.storage.indexEmissive = m.emissiveTexture.index;
material.storage.indexOcclusion = m.occlusionTexture.index;
material.storage.indexMetallicRoughness = m.pbrMetallicRoughness.metallicRoughnessTexture.index;
material.storage.colorBase = {
auto& material = uf::graph::storage.materials[graph.materials.emplace_back(m.name)];
material.indexAlbedo = m.pbrMetallicRoughness.baseColorTexture.index;
material.indexNormal = m.normalTexture.index;
material.indexEmissive = m.emissiveTexture.index;
material.indexOcclusion = m.occlusionTexture.index;
material.indexMetallicRoughness = m.pbrMetallicRoughness.metallicRoughnessTexture.index;
material.colorBase = {
m.pbrMetallicRoughness.baseColorFactor[0],
m.pbrMetallicRoughness.baseColorFactor[1],
m.pbrMetallicRoughness.baseColorFactor[2],
m.pbrMetallicRoughness.baseColorFactor[3],
};
material.storage.colorEmissive = {
material.colorEmissive = {
m.emissiveFactor[0],
m.emissiveFactor[1],
m.emissiveFactor[2],
0
};
material.storage.factorMetallic = m.pbrMetallicRoughness.metallicFactor;
material.storage.factorRoughness = m.pbrMetallicRoughness.roughnessFactor;
material.storage.factorOcclusion = m.occlusionTexture.strength;
material.storage.factorAlphaCutoff = m.alphaCutoff;
material.factorMetallic = m.pbrMetallicRoughness.metallicFactor;
material.factorRoughness = m.pbrMetallicRoughness.roughnessFactor;
material.factorOcclusion = m.occlusionTexture.strength;
material.factorAlphaCutoff = m.alphaCutoff;
if ( m.alphaMode == "OPAQUE" ) material.modeAlpha = 0;
else if ( m.alphaMode == "BLEND" ) material.modeAlpha = 1;
else if ( m.alphaMode == "MASK" ) material.modeAlpha = 2;
else UF_MSG_WARNING("Unhandled alpha mode: " << m.alphaMode);
material.alphaMode = m.alphaMode;
if ( material.alphaMode == "OPAQUE" ) {
material.storage.modeAlpha = 0;
} else if ( material.alphaMode == "BLEND" ) {
material.storage.modeAlpha = 1;
} else if ( material.alphaMode == "MASK" ) {
material.storage.modeAlpha = 2;
} else {
UF_MSG_WARNING("Unhandled alpha mode: " << material.alphaMode)
}
if ( m.doubleSided && graph.metadata["cull mode"].as<uf::stl::string>() == "auto" ) {
graph.metadata["cull mode"] = "none";
}
@ -236,54 +220,19 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, uf::graph::load_mod
{
graph.meshes.reserve(model.meshes.size());
for ( auto& m : model.meshes ) {
// auto& mesh = graph.meshes.emplace_back();
auto& pair = uf::graph::storage.meshes[graph.meshes.emplace_back(m.name)];
auto& mesh = pair.mesh;
mesh.bind<uf::graph::mesh::Skinned, uint32_t>();
/*
struct {
uf::Mesh<uf::graph::mesh::Base> base;
uf::Mesh<uf::graph::mesh::ID> id;
uf::Mesh<uf::graph::mesh::Skinned> skinned;
} meshes;
*/
/*
// use skinned mesh
if ( mode & uf::graph::LoadMode::SKINNED ) {
mesh.set<uf::graph::mesh::Skinned>();
// use ID'd mesh
} else {
mesh.set<uf::graph::mesh::ID>();
}
*/
// we'll fill up the most feature complete mesh (skinned) and then convert down to what we need
// this is fine since we only really ever load gltf files once, and parse to an internal format for reuse
/*
uf::Mesh<uf::graph::mesh::Skinned, uint32_t> storageMesh;
// already here, just move it over
auto& MESH = graph.meshes.emplace_back();
auto& mesh = ( mode & uf::graph::LoadMode::SKINNED ) ? MESH.get<uf::graph::mesh::Skinned>() : storageMesh;
*/
#if UF_GRAPH_EXPERIMENTAL
uf::Mesh<uf::graph::mesh::Skinned, uint32_t> mesh;
auto& varyingMesh = graph.meshes.emplace_back();
#else
auto& mesh = graph.meshes.emplace_back();
#endif
pod::DrawCall drawCall;
drawCall.verticesIndex = mesh.vertices.size();
drawCall.indicesIndex = mesh.indices.size();
drawCall.vertices = 0;
drawCall.indices = 0;
for ( auto& primitive : m.primitives ) {
pod::DrawCall dc;
dc.verticesIndex = mesh.vertices.size();
dc.indicesIndex = mesh.indices.size();
for ( auto& p : m.primitives ) {
uf::stl::vector<uf::graph::mesh::Skinned> vertices;
uf::stl::vector<uint32_t> indices;
struct Attribute {
uf::stl::string name = "";
size_t components = 1;
uf::stl::vector<float> buffer;
uf::stl::vector<uint16_t> indices;
uf::stl::vector<float> floats;
uf::stl::vector<uint16_t> ints;
};
uf::stl::unordered_map<uf::stl::string, Attribute> attributes = {
{"POSITION", {}},
@ -297,14 +246,14 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, uf::graph::load_mod
for ( auto& kv : attributes ) {
auto& attribute = kv.second;
attribute.name = kv.first;
auto it = primitive.attributes.find(attribute.name);
if ( it == primitive.attributes.end() ) continue;
auto it = p.attributes.find(attribute.name);
if ( it == p.attributes.end() ) continue;
auto& accessor = model.accessors[it->second];
auto& view = model.bufferViews[accessor.bufferView];
if ( attribute.name == "POSITION" ) {
dc.vertices = accessor.count;
vertices.resize(accessor.count);
pod::Vector3f minCorner = { accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] };
pod::Vector3f maxCorner = { accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] };
@ -315,34 +264,30 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, uf::graph::load_mod
auto* buffer = reinterpret_cast<const uint16_t*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(uint16_t);
size_t len = accessor.count * attribute.components;
attribute.indices.reserve( len );
attribute.indices.insert( attribute.indices.end(), &buffer[0], &buffer[len] );
attribute.ints.assign( &buffer[0], &buffer[len] );
} else {
auto* buffer = reinterpret_cast<const float*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
attribute.components = accessor.ByteStride(view) / sizeof(float);
size_t len = accessor.count * attribute.components;
attribute.buffer.reserve( len );
attribute.buffer.insert( attribute.buffer.end(), &buffer[0], &buffer[len] );
attribute.floats.assign( &buffer[0], &buffer[len] );
}
}
mesh.vertices.reserve( dc.vertices + dc.verticesIndex );
for ( size_t i = 0; i < dc.vertices; ++i ) {
for ( size_t i = 0; i < vertices.size(); ++i ) {
#define ITERATE_ATTRIBUTE( name, member )\
if ( !attributes[name].indices.empty() ) { \
if ( !attributes[name].ints.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].indices[i * attributes[name].components + j];\
} else if ( !attributes[name].buffer.empty() ) { \
vertex.member[j] = attributes[name].ints[i * attributes[name].components + j];\
} else if ( !attributes[name].floats.empty() ) { \
for ( size_t j = 0; j < attributes[name].components; ++j )\
vertex.member[j] = attributes[name].buffer[i * attributes[name].components + j];\
vertex.member[j] = attributes[name].floats[i * attributes[name].components + j];\
}
auto& vertex = mesh.vertices.emplace_back();
auto& vertex = vertices[i];
ITERATE_ATTRIBUTE("POSITION", position);
ITERATE_ATTRIBUTE("TEXCOORD_0", uv);
ITERATE_ATTRIBUTE("NORMAL", normal);
ITERATE_ATTRIBUTE("TANGENT", tangent);
vertex.id = { 0, primitive.material };
ITERATE_ATTRIBUTE("JOINTS_0", joints);
ITERATE_ATTRIBUTE("WEIGHTS_0", weights);
@ -350,26 +295,27 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, uf::graph::load_mod
// required due to reverse-Z projection matrix flipping the X axis as well
// default is to proceed with this
if ( !(graph.mode & uf::graph::LoadMode::INVERT) ){
if ( !(graph.metadata["flags"]["INVERT"].as<bool>()) ){
vertex.position.x *= -1;
vertex.normal.x *= -1;
vertex.tangent.x *= -1;
}
}
if ( primitive.indices > -1 ) {
auto& accessor = model.accessors[primitive.indices];
if ( p.indices > -1 ) {
auto& accessor = model.accessors[p.indices];
auto& view = model.bufferViews[accessor.bufferView];
auto& buffer = model.buffers[view.buffer];
dc.indices = static_cast<uint32_t>(accessor.count);
mesh.indices.reserve( dc.indices + dc.indicesIndex );
const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]);
indices.reserve( static_cast<uint32_t>(accessor.count) );
#define COPY_INDICES()\
for (size_t index = 0; index < dc.indices; index++)\
mesh.indices.emplace_back(buf[index] + dc.verticesIndex);
for (size_t index = 0; index < indices.size(); index++)\
indices.emplace_back(buf[index]);
const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]);
switch (accessor.componentType) {
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: {
auto* buf = static_cast<const uint32_t*>( pointer );
@ -390,49 +336,22 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, uf::graph::load_mod
#undef COPY_INDICES
}
drawCall.vertices += dc.vertices;
drawCall.indices += dc.indices;
pair.drawCommands.emplace_back(pod::DrawCommand{
.indices = indices.size(),
.instances = 1,
.indexID = mesh.index.count,
.vertexID = mesh.vertex.count,
.instanceID = mesh.instance.count,
.materialID = p.material,
.objectID = 0,
.vertices = vertices.size(),
});
mesh.insertVertices(vertices);
mesh.insertIndices(indices);
}
mesh.updateDescriptor();
// convert to a more optimal format
#if UF_GRAPH_EXPERIMENTAL
bool override = graph.metadata["debug"]["override varying mesh"].as<bool>();
// use skinned mesh
if ( override || (mode & uf::graph::LoadMode::SKINNED) ) {
auto& m = varyingMesh.get<uf::graph::mesh::Skinned>();
m.indices = std::move( mesh.indices );
m.vertices = std::move( mesh.vertices );
#if 0
// use barebone mesh
} else if ( UF_ENV_DREAMCAST ) {
auto& m = varyingMesh.get<uf::graph::mesh::Base>();
m.indices = std::move( mesh.indices );
m.vertices.reserve( mesh.vertices.size() );
for ( auto& v : mesh.vertices ) m.vertices.emplace_back(uf::graph::mesh::Base{
.position = v.position,
.uv = v.uv,
.st = v.st,
.normal = v.normal,
});
#endif
// use ID'd mesh
} else {
auto& m = varyingMesh.get<uf::graph::mesh::ID>();
m.indices = std::move( mesh.indices );
m.vertices.reserve( mesh.vertices.size() );
for ( auto& v : mesh.vertices ) m.vertices.emplace_back(uf::graph::mesh::ID{
.position = v.position,
.uv = v.uv,
.st = v.st,
.normal = v.normal,
.tangent = v.tangent,
.id = v.id,
});
}
varyingMesh.updateDescriptor();
#else
#endif
}
}
// load node information/meshes
@ -449,8 +368,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, uf::graph::load_mod
// load lights
{
for ( auto& l : model.lights ) {
auto& light = graph.lights.emplace_back();
light.name = l.name;
auto& light = graph.lights[l.name];
light.color = { l.color[0], l.color[1], l.color[2], };
light.intensity = l.intensity;
light.range = l.range;
@ -542,19 +460,6 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, uf::graph::load_mod
}
}
}
{
if ( graph.metadata["export"]["should"].as<bool>() ) uf::graph::save( graph, filename );
/*
bool shouldExport = false;
if ( graph.metadata["debug"]["export"].is<bool>() ) shouldExport = graph.metadata["debug"]["export"].as<bool>();
else if ( ext::json::isObject( graph.metadata["debug"]["export"] ) ) {
if ( graph.metadata["debug"]["export"]["should"].is<bool>() )
shouldExport = graph.metadata["debug"]["export"]["should"].as<bool>();
else
shouldExport = true;
}
if ( shouldExport ) uf::graph::save( graph, filename );
*/
}
if ( graph.metadata["export"]["should"].as<bool>() ) uf::graph::save( graph, filename );
return graph;
}

View File

@ -3,7 +3,7 @@
#include <meshoptimizer.h>
#endif
void ext::meshopt::optimize( pod::Mesh& mesh, size_t o ) {
void ext::meshopt::optimize( uf::Mesh& mesh, size_t o ) {
#if 0
mesh.updateDescriptor();

View File

@ -8,7 +8,7 @@
#include <bitset>
#include <uf/utils/mesh/mesh.h>
#include <uf/engine/graph/mesh.h>
#include <uf/engine/graph/graph.h>
#define VERBOSE false
#define VERBOSE_SUBMIT false
@ -397,14 +397,14 @@ void ext::opengl::CommandBuffer::draw( const ext::opengl::CommandBuffer::InfoDra
size_t vertexStride = drawInfo.descriptor.attributes.vertex.size;
size_t vertices = vertexBuffer.range / vertexStride;
uf::renderer::VertexDescriptor vertexAttributePosition,
uf::renderer::AttributeDescriptor vertexAttributePosition,
vertexAttributeNormal,
vertexAttributeColor,
vertexAttributeUv,
vertexAttributeSt,
vertexAttributeId;
for ( auto& attribute : drawInfo.descriptor.attributes.descriptor ) {
for ( auto& attribute : drawInfo.descriptor.attributes.vertex.descriptor ) {
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute;
else if ( attribute.name == "color" ) vertexAttributeColor = attribute;
@ -701,14 +701,14 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
size_t vertexStride = drawInfo.descriptor.attributes.vertex.size;
size_t vertices = vertexBuffer.range / vertexStride;
uf::renderer::VertexDescriptor vertexAttributePosition,
uf::renderer::AttributeDescriptor vertexAttributePosition,
vertexAttributeNormal,
vertexAttributeColor,
vertexAttributeUv,
vertexAttributeSt,
vertexAttributeId;
for ( auto& attribute : drawInfo.descriptor.attributes.descriptor ) {
for ( auto& attribute : drawInfo.descriptor.attributes.vertex.descriptor ) {
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute;
else if ( attribute.name == "color" ) vertexAttributeColor = attribute;

View File

@ -38,8 +38,8 @@ void ext::opengl::Pipeline::initialize( const Graphic& graphic, const GraphicDes
{
GL_ERROR_CHECK(glGenVertexArrays(1, &vertexArray));
GL_ERROR_CHECK(glBindVertexArray(vertexArray));
for ( size_t i = 0; i < descriptor.attributes.descriptor.size(); ++i ) {
auto& attribute = descriptor.attributes.descriptor[i];
for ( size_t i = 0; i < descriptor.attributes.vertex.descriptor.size(); ++i ) {
auto& attribute = descriptor.attributes.vertex.descriptor[i];
GL_ERROR_CHECK(glEnableVertexAttribArray(i));
GL_ERROR_CHECK(glVertexAttribPointer(0, attribute.components, attribute.type, false, descriptor.attributes.vertex.size, attribute.offset));
@ -183,7 +183,7 @@ ext::opengl::Pipeline& ext::opengl::Graphic::initializePipeline( const GraphicDe
return pipeline;
}
void ext::opengl::Graphic::initializeAttributes( const pod::Mesh::Attributes& attributes ) {
void ext::opengl::Graphic::initializeAttributes( const uf::Mesh::Attributes& attributes ) {
// already generated, check if we can just update
if ( descriptor.indices > 0 ) {
if ( descriptor.attributes.vertex.size == attributes.vertex.size && descriptor.attributes.index.size == attributes.index.size && descriptor.indices == attributes.index.length ) {
@ -266,14 +266,14 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
}
if ( !vertexBuffer.buffer || !indexBuffer.buffer ) return;
uf::renderer::VertexDescriptor vertexAttributePosition,
uf::renderer::AttributeDescriptor vertexAttributePosition,
vertexAttributeNormal,
vertexAttributeColor,
vertexAttributeUv,
vertexAttributeSt,
vertexAttributeId;
for ( auto& attribute : descriptor.attributes.descriptor ) {
for ( auto& attribute : descriptor.attributes.vertex.descriptor ) {
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
// else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute;
// else if ( attribute.name == "color" ) vertexAttributeColor = attribute;
@ -524,9 +524,9 @@ ext::opengl::GraphicDescriptor::hash_t ext::opengl::GraphicDescriptor::hash() co
serializer["offsets"]["vertex"] = offsets.vertex;
serializer["offsets"]["index"] = offsets.index;
for ( uint8_t i = 0; i < attributes.descriptor.size(); ++i ) {
serializer["geometry"]["attributes"][i]["format"] = attributes.descriptor[i].format;
serializer["geometry"]["attributes"][i]["offset"] = attributes.descriptor[i].offset;
for ( uint8_t i = 0; i < attributes.vertex.descriptor.size(); ++i ) {
serializer["geometry"]["attributes"][i]["format"] = attributes.vertex.descriptor[i].format;
serializer["geometry"]["attributes"][i]["offset"] = attributes.vertex.descriptor[i].offset;
}
serializer["topology"] = topology;
@ -558,9 +558,9 @@ ext::opengl::GraphicDescriptor::hash_t ext::opengl::GraphicDescriptor::hash() co
hash += std::hash<decltype(offsets.vertex)>{}(offsets.vertex);
hash += std::hash<decltype(offsets.index)>{}(offsets.index);
for ( uint8_t i = 0; i < attributes.descriptor.size(); ++i ) {
hash += std::hash<decltype(attributes.descriptor[i].format)>{}(attributes.descriptor[i].format);
hash += std::hash<decltype(attributes.descriptor[i].offset)>{}(attributes.descriptor[i].offset);
for ( uint8_t i = 0; i < attributes.vertex.descriptor.size(); ++i ) {
hash += std::hash<decltype(attributes.vertex.descriptor[i].format)>{}(attributes.vertex.descriptor[i].format);
hash += std::hash<decltype(attributes.vertex.descriptor[i].offset)>{}(attributes.vertex.descriptor[i].offset);
}
hash += std::hash<decltype(topology)>{}(topology);

View File

@ -189,12 +189,12 @@ void UF_API ext::opengl::initialize() {
size_t vertexStride = graphic.descriptor.attributes.vertex.size;
size_t vertices = vertexBuffer.range / vertexStride;
uf::renderer::VertexDescriptor vertexAttributePosition,
uf::renderer::AttributeDescriptor vertexAttributePosition,
vertexAttributeUv,
vertexAttributeNormal,
vertexAttributeId;
for ( auto& attribute : graphic.descriptor.attributes.descriptor ) {
for ( auto& attribute : graphic.descriptor.attributes.vertex.descriptor ) {
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute;
else if ( attribute.name == "uv" ) vertexAttributeUv = attribute;
@ -255,12 +255,12 @@ void UF_API ext::opengl::initialize() {
size_t vertexStride = graphic.descriptor.attributes.vertex.size;
size_t vertices = vertexBuffer.range / vertexStride;
uf::renderer::VertexDescriptor vertexAttributePosition,
uf::renderer::AttributeDescriptor vertexAttributePosition,
vertexAttributeNormal,
vertexAttributeJoints,
vertexAttributeWeights;
for ( auto& attribute : graphic.descriptor.attributes.descriptor ) {
for ( auto& attribute : graphic.descriptor.attributes.vertex.descriptor ) {
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute;
else if ( attribute.name == "joints" ) vertexAttributeJoints = attribute;

View File

@ -99,8 +99,8 @@ void ext::vulkan::Buffer::allocate( VkBufferCreateInfo bufferCreateInfo ) {
ext::vulkan::Buffer::~Buffer() {
// this->destroy();
}
void ext::vulkan::Buffer::initialize( VkDevice device ) {
this->device = device;
void ext::vulkan::Buffer::initialize( ext::vulkan::Device& device ) {
this->device = &device;
}
void ext::vulkan::Buffer::destroy() {
if ( !device ) return;
@ -114,6 +114,50 @@ void ext::vulkan::Buffer::destroy() {
buffer = nullptr;
memory = nullptr;
}
void ext::vulkan::Buffer::initialize( const void* data, VkDeviceSize length, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties, bool stage ) {
if ( stage ) usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; // implicitly set properties
VK_CHECK_RESULT(device->createBuffer(
usage,
memoryProperties,
*this,
length
));
if ( data ) update( data, length, stage );
}
void ext::vulkan::Buffer::update( const void* data, VkDeviceSize length, bool stage ) const {
if ( length > allocationInfo.size ) {
UF_MSG_DEBUG("LENGTH OF " << length << " EXCEEDS BUFFER SIZE " << allocationInfo.size );
Buffer& b = *const_cast<Buffer*>(this);
b.destroy();
b.initialize( data, length, usage, memoryProperties, stage );
return;
}
if ( !stage ) {
void* map = this->map();
memcpy(map, data, length);
if ((this->memoryProperties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0) this->flush();
this->unmap();
return;
}
Buffer staging;
device->createBuffer(
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
staging,
length,
data
);
// Copy to staging buffer
VkCommandBuffer copyCommand = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
VkBufferCopy region = {};
region.size = length;
vkCmdCopyBuffer(copyCommand, staging.buffer, buffer, 1, &region);
device->flushCommandBuffer(copyCommand, true);
staging.destroy();
}
//
// Buffers
@ -133,93 +177,13 @@ void ext::vulkan::Buffers::destroy() {
size_t ext::vulkan::Buffers::initializeBuffer( const void* data, VkDeviceSize length, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties, bool stage ) {
size_t index = buffers.size();
Buffer& buffer = buffers.emplace_back();
// Stage
if ( !stage ) {
VK_CHECK_RESULT(device->createBuffer(
usage,
memoryProperties,
buffer,
length
));
this->updateBuffer( data, length, buffer, stage );
return index;
}
// implicitly set properties
usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
Buffer staging;
VkDeviceSize storageBufferSize = length;
device->createBuffer(
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
staging,
storageBufferSize,
data
);
device->createBuffer(
usage,
memoryProperties,
buffer,
storageBufferSize
);
// Copy to staging buffer
VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
VkBufferCopy copyRegion = {};
copyRegion.size = storageBufferSize;
vkCmdCopyBuffer(copyCmd, staging.buffer, buffer.buffer, 1, &copyRegion);
device->flushCommandBuffer(copyCmd, true);
staging.destroy();
auto& buffer = buffers.emplace_back();
buffer.initialize( *device );
buffer.initialize( data, length, usage, memoryProperties, stage );
return index;
}
void ext::vulkan::Buffers::updateBuffer( const void* data, VkDeviceSize length, const Buffer& buffer, bool stage ) const {
// assert(buffer.allocationInfo.size == length);
if ( length > buffer.allocationInfo.size ) {
if ( !true ) {
VK_VALIDATION_MESSAGE("Mismatch buffer update: Requesting " << buffer.allocationInfo.size << ", got " << length << "; Userdata might've been corrupted, please try validating with shader.validate() before updating buffer");
} else {
VK_VALIDATION_MESSAGE("Mismatch buffer update: Requesting " << buffer.allocationInfo.size << ", got " << length << ", resetting for safety");
length = buffer.allocationInfo.size;
}
// assert(buffer.allocationInfo.size > length);
}
if ( !stage ) {
#if UF_TESTING
void* map = buffer.map();
memcpy(map, data, length);
if ((buffer.memoryProperties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0) buffer.flush();
buffer.unmap();
#else
void* map = buffer.map();
memcpy(map, data, length);
if ((buffer.memoryProperties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0) buffer.flush();
buffer.unmap();
#endif
return;
}
Buffer staging;
device->createBuffer(
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
staging,
length,
data
);
// Copy to staging buffer
VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
VkBufferCopy copyRegion = {};
copyRegion.size = length;
vkCmdCopyBuffer(copyCmd, staging.buffer, buffer.buffer, 1, &copyRegion);
device->flushCommandBuffer(copyCmd, true);
staging.destroy();
buffer.update( data, length, stage );
}
#endif

View File

@ -394,7 +394,7 @@ VkResult ext::vulkan::Device::createBuffer(
VkDeviceSize size,
const void* data
) {
buffer.device = logicalDevice;
buffer.device = this;
buffer.usage = usage;
buffer.memoryProperties = memoryProperties;

View File

@ -42,8 +42,8 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
uf::stl::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
uf::stl::vector<VkPipelineShaderStageCreateInfo> shaderDescriptors;
uf::stl::vector<VkVertexInputAttributeDescription> vertexAttributeDescriptions;
uf::stl::vector<VkVertexInputBindingDescription> inputBindingDescriptions;
uf::stl::vector<VkVertexInputAttributeDescription> attributeDescriptions;
{
for ( auto* shaderPointer : shaders ) {
@ -209,30 +209,46 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
0
);
// Binding description
uf::stl::vector<VkVertexInputBindingDescription> vertexBindingDescriptions = {
ext::vulkan::initializers::vertexInputBindingDescription(
VERTEX_BUFFER_BIND_ID,
descriptor.attributes.vertex.size,
VK_VERTEX_INPUT_RATE_VERTEX
)
};
// Attribute descriptions
// Describes memory layout and shader positions
for ( auto& attribute : descriptor.attributes.descriptor ) {
vertexAttributeDescriptions.emplace_back(ext::vulkan::initializers::vertexInputAttributeDescription(
VERTEX_BUFFER_BIND_ID,
vertexAttributeDescriptions.size(),
attribute.format,
attribute.offset
));
// Vertex binding description
size_t vertexBindID = 0;
size_t vertexLocationID = 0;
if ( !descriptor.inputs.vertex.attributes.empty() ) {
if ( 0 <= descriptor.inputs.vertex.interleaved ) {
inputBindingDescriptions.emplace_back(ext::vulkan::initializers::vertexInputBindingDescription(
vertexBindID, // descriptor.inputs.vertex.interleaved,
descriptor.inputs.vertex.stride,
VK_VERTEX_INPUT_RATE_VERTEX
));
for ( auto& attribute : descriptor.inputs.vertex.attributes ) {
attributeDescriptions.emplace_back(ext::vulkan::initializers::vertexInputAttributeDescription(
vertexBindID,
vertexLocationID++,
attribute.descriptor.format,
attribute.descriptor.offset
));
}
++vertexBindID;
} else for ( auto& attribute : descriptor.inputs.vertex.attributes ) {
inputBindingDescriptions.emplace_back(ext::vulkan::initializers::vertexInputBindingDescription(
vertexBindID, // attribute.buffer,
attribute.descriptor.size,
VK_VERTEX_INPUT_RATE_VERTEX
));
attributeDescriptions.emplace_back(ext::vulkan::initializers::vertexInputAttributeDescription(
vertexBindID,
vertexLocationID++,
attribute.descriptor.format,
0 // attribute.descriptor.offset
));
++vertexBindID;
}
}
VkPipelineVertexInputStateCreateInfo vertexInputState = ext::vulkan::initializers::pipelineVertexInputStateCreateInfo();
vertexInputState.vertexBindingDescriptionCount = vertexBindingDescriptions.size();
vertexInputState.pVertexBindingDescriptions = vertexBindingDescriptions.data();
vertexInputState.vertexAttributeDescriptionCount = vertexAttributeDescriptions.size();
vertexInputState.pVertexAttributeDescriptions = vertexAttributeDescriptions.data();
vertexInputState.vertexBindingDescriptionCount = inputBindingDescriptions.size();
vertexInputState.pVertexBindingDescriptions = inputBindingDescriptions.data();
vertexInputState.vertexAttributeDescriptionCount = attributeDescriptions.size();
vertexInputState.pVertexAttributeDescriptions = attributeDescriptions.data();
for ( auto* shader : shaders ) shaderDescriptors.emplace_back(shader->descriptor);
@ -257,11 +273,9 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
VK_CHECK_RESULT(vkCreateGraphicsPipelines( device, device.pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline));
}
// graphic.process = true;
return;
PIPELINE_INITIALIZATION_INVALID:
// graphic.process = false;
VK_DEBUG_VALIDATION_MESSAGE("Pipeline initialization invalid, updating next tick...");
uf::thread::add( uf::thread::get("Main"), [&]() -> int {
this->initialize( graphic, descriptor );
@ -271,32 +285,47 @@ PIPELINE_INITIALIZATION_INVALID:
void ext::vulkan::Pipeline::record( const Graphic& graphic, VkCommandBuffer commandBuffer, size_t pass, size_t draw ) const {
auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
auto shaders = getShaders( graphic.material.shaders );
for ( auto* shaderPointer : shaders ) {
auto& shader = *shaderPointer;
if ( shader.descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) {
bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
}
size_t offset = 0;
for ( auto& pushConstant : shader.pushConstants ) {
//
// if ( ext::json::isObject( shader.metadata.json["definitions"]["pushConstants"]["PushConstant"] ) ) {
if ( shader.metadata.definitions.pushConstants.count("PushConstant") > 0 ) {
if ( shader.descriptor.stage == VK_SHADER_STAGE_VERTEX_BIT ) {
for ( auto* shader : shaders ) {
if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
#if 0
if ( shader->metadata.definitions.pushConstants.count("PushConstant") > 0 ) {
if ( shader->descriptor.stage == VK_SHADER_STAGE_VERTEX_BIT ) {
struct PushConstant {
uint32_t pass;
uint32_t draw;
} pushConstant = { pass, draw };
vkCmdPushConstants( commandBuffer, pipelineLayout, shader.descriptor.stage, 0, sizeof(pushConstant), &pushConstant );
( commandBuffer, pipelineLayout, shader->descriptor.stage, 0, sizeof(pushConstant), &pushConstant );
}
} else
#endif
if ( !shader->pushConstants.empty() ) {
auto& pushConstant = shader->pushConstants.front();
size_t size = pushConstant.size();
void* data = pushConstant.data().data;
if ( size && data ) {
vkCmdPushConstants( commandBuffer, pipelineLayout, shader->descriptor.stage, 0, size, data );
}
}
/*
size_t offset = 0;
for ( auto& pushConstant : shader->pushConstants ) {
if ( shader->metadata.definitions.pushConstants.count("PushConstant") > 0 ) {
if ( shader->descriptor.stage == VK_SHADER_STAGE_VERTEX_BIT ) {
struct PushConstant {
uint32_t pass;
uint32_t draw;
} pushConstant = { pass, draw };
( commandBuffer, pipelineLayout, shader->descriptor.stage, 0, sizeof(pushConstant), &pushConstant );
}
} else {
size_t len = pushConstant.data().len;
void* pointer = pushConstant.data().data;
if ( len > 0 && pointer ) {
vkCmdPushConstants( commandBuffer, pipelineLayout, shader.descriptor.stage, 0, len, pointer );
vkCmdPushConstants( commandBuffer, pipelineLayout, shader->descriptor.stage, 0, len, pointer );
}
}
}
*/
}
// Bind descriptor sets describing shader binding points
vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
@ -312,16 +341,12 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
if ( descriptorSet == VK_NULL_HANDLE ) return;
this->descriptor = descriptor;
//descriptor = d;
RenderMode& renderMode = ext::vulkan::getRenderMode(descriptor.renderMode, true);
auto& renderTarget = renderMode.getRenderTarget(descriptor.renderTarget );
uf::stl::vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings;
auto shaders = getShaders( graphic.material.shaders );
for ( auto* shaderPointer : shaders ) {
auto& shader = *shaderPointer;
descriptorSetLayoutBindings.insert( descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.end() );
}
uf::stl::vector<VkWriteDescriptorSet> writeDescriptorSets;
struct {
uf::stl::vector<VkDescriptorBufferInfo> uniform;
@ -337,6 +362,8 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
uf::stl::vector<VkDescriptorImageInfo> input;
} infos;
uf::stl::vector<ext::vulkan::enums::Image::viewType_t> types;
if ( descriptor.subpass < renderTarget.passes.size() ) {
auto& subpass = renderTarget.passes[descriptor.subpass];
for ( auto& input : subpass.inputs ) {
@ -347,56 +374,35 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
}
}
{
for ( auto& texture : graphic.material.textures ) {
infos.image.emplace_back(texture.descriptor);
switch ( texture.viewType ) {
case VK_IMAGE_VIEW_TYPE_2D:
infos.image2D.emplace_back(texture.descriptor);
break;
case VK_IMAGE_VIEW_TYPE_CUBE:
infos.imageCube.emplace_back(texture.descriptor);
break;
case VK_IMAGE_VIEW_TYPE_3D:
infos.image3D.emplace_back(texture.descriptor);
break;
default:
infos.imageUnknown.emplace_back(texture.descriptor);
break;
}
for ( auto& texture : graphic.material.textures ) {
infos.image.emplace_back(texture.descriptor);
switch ( texture.viewType ) {
case VK_IMAGE_VIEW_TYPE_2D: infos.image2D.emplace_back(texture.descriptor); break;
case VK_IMAGE_VIEW_TYPE_CUBE: infos.imageCube.emplace_back(texture.descriptor); break;
case VK_IMAGE_VIEW_TYPE_3D: infos.image3D.emplace_back(texture.descriptor); break;
default: infos.imageUnknown.emplace_back(texture.descriptor); break;
}
for ( auto& sampler : graphic.material.samplers ) infos.sampler.emplace_back(sampler.descriptor.info);
}
for ( auto& sampler : graphic.material.samplers ) {
infos.sampler.emplace_back(sampler.descriptor.info);
}
size_t consumes = 0;
// uf::stl::vector<uf::stl::string> types;
uf::stl::vector<ext::vulkan::enums::Image::viewType_t> types;
for ( auto* shaderPointer : shaders ) {
auto& shader = *shaderPointer;
#define PARSE_BUFFER( buffers ) for ( auto& buffer : buffers ) {\
if ( buffer.usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ) {\
infos.uniform.emplace_back(buffer.descriptor);\
}\
if ( buffer.usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ) {\
infos.storage.emplace_back(buffer.descriptor);\
}\
for ( auto* shader : shaders ) {
for ( auto& buffer : shader->buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
}
PARSE_BUFFER(shader.buffers)
PARSE_BUFFER(graphic.buffers)
// check if we can even consume that many infos
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
for ( auto& layout : shader->descriptorSetLayoutBindings ) {
switch ( layout.descriptorType ) {
// consume an texture image info
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
consumes += layout.descriptorCount;
// uf::stl::string binding = std::to_string(layout.binding);
// uf::stl::string imageType = shader.metadata.json["definitions"]["textures"][binding]["type"].as<uf::stl::string>();
ext::vulkan::enums::Image::viewType_t imageType = shader.metadata.definitions.textures.at(layout.binding).type;
consumes += layout.descriptorCount;
ext::vulkan::enums::Image::viewType_t imageType = shader->metadata.definitions.textures.at(layout.binding).type;
types.reserve(consumes);
for ( size_t i = 0; i < layout.descriptorCount; ++i ) types.emplace_back(imageType);
} break;
@ -421,7 +427,6 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
while ( infos.imageUnknown.size() < maxTexturesUnknown ) infos.imageUnknown.emplace_back(Texture2D::empty.descriptor);
for ( size_t i = infos.image.size(); i < consumes; ++i ) {
// uf::stl::string type = i < types.size() ? types[i] : "";
ext::vulkan::enums::Image::viewType_t type = i < types.size() ? types[i] : ext::vulkan::enums::Image::viewType_t{};
if ( type == ext::vulkan::enums::Image::VIEW_TYPE_3D ) infos.image.emplace_back(Texture3D::empty.descriptor);
else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_CUBE ) infos.image.emplace_back(TextureCube::empty.descriptor);
@ -441,33 +446,16 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
auto samplerInfo = infos.sampler.begin();
auto inputInfo = infos.input.begin();
uf::stl::vector<VkWriteDescriptorSet> writeDescriptorSets;
for ( auto* shaderPointer : shaders ) {
auto& shader = *shaderPointer;
// UF_MSG_DEBUG(shader.filename << ": ");
// UF_MSG_DEBUG("\tAVAILABLE UNIFORM BUFFERS: " << infos.uniform.size());
// UF_MSG_DEBUG("\tAVAILABLE STORAGE BUFFERS: " << infos.storage.size());
// UF_MSG_DEBUG("\tCONSUMING : " << shader.descriptorSetLayoutBindings.size());
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
// VK_VALIDATION_MESSAGE(shader.filename << "\tType: " << layout.descriptorType << "\tConsuming: " << layout.descriptorCount);
for ( auto* shader : shaders ) {
for ( auto& layout : shader->descriptorSetLayoutBindings ) {
switch ( layout.descriptorType ) {
// consume an texture image info
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
// UF_MSG_DEBUG("\t["<< layout.binding << "] INSERTING " << layout.descriptorCount << " IMAGE");
// if ( layout.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ) UF_MSG_DEBUG("\t\tCOMBINED_IMAGE_SAMPLER");
// if ( layout.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ) UF_MSG_DEBUG("\t\tSAMPLED_IMAGE");
// if ( layout.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ) UF_MSG_DEBUG("\t\tSTORAGE_IMAGE");
// if ( layout.descriptorCount == 1 ) UF_MSG_DEBUG(i.imageView << "\t" << (*imageInfo).imageLayout);
#if 1
ext::vulkan::enums::Image::viewType_t imageType = shader.metadata.definitions.textures.at(layout.binding).type;
ext::vulkan::enums::Image::viewType_t imageType = shader->metadata.definitions.textures.at(layout.binding).type;
if ( imageType == ext::vulkan::enums::Image::VIEW_TYPE_2D ) {
UF_ASSERT_BREAK_MSG( image2DInfo != infos.image2D.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
UF_ASSERT_BREAK_MSG( image2DInfo != infos.image2D.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
@ -477,7 +465,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
));
image2DInfo += layout.descriptorCount;
} else if ( imageType == ext::vulkan::enums::Image::VIEW_TYPE_CUBE ) {
UF_ASSERT_BREAK_MSG( imageCubeInfo != infos.imageCube.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
UF_ASSERT_BREAK_MSG( imageCubeInfo != infos.imageCube.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
@ -487,7 +475,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
));
imageCubeInfo += layout.descriptorCount;
} else if ( imageType == ext::vulkan::enums::Image::VIEW_TYPE_3D ) {
UF_ASSERT_BREAK_MSG( image3DInfo != infos.image3D.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
UF_ASSERT_BREAK_MSG( image3DInfo != infos.image3D.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
@ -497,7 +485,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
));
image3DInfo += layout.descriptorCount;
} else {
UF_ASSERT_BREAK_MSG( imageUnknownInfo != infos.imageUnknown.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
UF_ASSERT_BREAK_MSG( imageUnknownInfo != infos.imageUnknown.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
@ -507,21 +495,9 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
));
imageUnknownInfo += layout.descriptorCount;
}
#else
UF_ASSERT_BREAK_MSG( imageInfo != infos.image.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
layout.binding,
&(*imageInfo),
layout.descriptorCount
));
imageInfo += layout.descriptorCount;
#endif
} break;
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
// UF_MSG_DEBUG("\t["<< layout.binding << "] INSERTING " << layout.descriptorCount << " INPUT_ATTACHMENT");
UF_ASSERT_BREAK_MSG( inputInfo != infos.input.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
UF_ASSERT_BREAK_MSG( inputInfo != infos.input.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
@ -532,8 +508,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
inputInfo += layout.descriptorCount;
} break;
case VK_DESCRIPTOR_TYPE_SAMPLER: {
// UF_MSG_DEBUG("\t["<< layout.binding << "] INSERTING " << layout.descriptorCount << " SAMPLER");
UF_ASSERT_BREAK_MSG( samplerInfo != infos.sampler.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
UF_ASSERT_BREAK_MSG( samplerInfo != infos.sampler.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
@ -544,8 +519,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
samplerInfo += layout.descriptorCount;
} break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {
// UF_MSG_DEBUG("\t["<< layout.binding << "] INSERTING " << layout.descriptorCount << " UNIFORM_BUFFER");
UF_ASSERT_BREAK_MSG( uniformBufferInfo != infos.uniform.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
UF_ASSERT_BREAK_MSG( uniformBufferInfo != infos.uniform.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
@ -556,8 +530,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
uniformBufferInfo += layout.descriptorCount;
} break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: {
// UF_MSG_DEBUG("\t["<< layout.binding << "] INSERTING " << layout.descriptorCount << " STORAGE_BUFFER");
UF_ASSERT_BREAK_MSG( storageBufferInfo != infos.storage.end(), "Filename: " << shader.filename << "\tCount: " << layout.descriptorCount )
UF_ASSERT_BREAK_MSG( storageBufferInfo != infos.storage.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount )
writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet(
descriptorSet,
layout.descriptorType,
@ -571,6 +544,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
}
}
// validate writeDescriptorSets
for ( auto& descriptor : writeDescriptorSets ) {
for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) {
if ( descriptor.pBufferInfo ) {
@ -588,17 +562,10 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
if ( descriptor.pImageInfo[i].imageView == VK_NULL_HANDLE || descriptor.pImageInfo[i].imageLayout == VK_IMAGE_LAYOUT_UNDEFINED ) {
VK_DEBUG_VALIDATION_MESSAGE("Null image view or layout is undefined, replacing with fallback texture...");
auto pointer = const_cast<VkDescriptorImageInfo*>(&descriptor.pImageInfo[i]);
// uf::stl::string binding = std::to_string(descriptor.dstBinding);
// uf::stl::string imageType = "";
ext::vulkan::enums::Image::viewType_t imageType{};
for ( auto* shaderPointer : shaders ) {
auto& shader = *shaderPointer;
if ( shader.metadata.definitions.textures.count(descriptor.dstBinding) == 0 ) continue;
imageType = shader.metadata.definitions.textures.at(descriptor.dstBinding).type;
// auto& info = shader.metadata.json["definitions"]["textures"][binding];
// if ( ext::json::isNull(info) ) continue;
// imageType = info["type"].as<uf::stl::string>();
for ( auto* shader : shaders ) {
if ( shader->metadata.definitions.textures.count(descriptor.dstBinding) == 0 ) continue;
imageType = shader->metadata.definitions.textures.at(descriptor.dstBinding).type;
break;
}
if ( imageType == ext::vulkan::enums::Image::VIEW_TYPE_3D ) {
@ -615,9 +582,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
pointer->imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
}
}
if ( descriptor.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
descriptor.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
) {
if ( descriptor.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || descriptor.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ) {
if ( !descriptor.pImageInfo[i].sampler ) {
VK_DEBUG_VALIDATION_MESSAGE("Image descriptor type is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, yet lacks a sampler, adding default sampler...");
auto pointer = const_cast<VkDescriptorImageInfo*>(&descriptor.pImageInfo[i]);
@ -629,7 +594,6 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
}
renderMode.rebuild = true;
// graphic.process = true;
vkUpdateDescriptorSets(
*device,
@ -797,49 +761,55 @@ ext::vulkan::Pipeline& ext::vulkan::Graphic::initializePipeline( const GraphicDe
return pipeline;
}
void ext::vulkan::Graphic::initializeAttributes( const pod::Mesh::Attributes& attributes ) {
// already generated, check if we can just update
if ( descriptor.indices > 0 ) {
if ( descriptor.attributes.vertex.size == attributes.vertex.size && descriptor.attributes.index.size == attributes.index.size && descriptor.indices == attributes.index.length ) {
// too lazy to check if this equals, only matters in pipeline creation anyways
descriptor.attributes = attributes;
void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
// generate indices if not found
if ( mesh.index.count == 0 ) mesh.generateIndices();
// generate indirect data if not found
if ( mesh.indirect.count == 0 ) mesh.generateIndirect();
// ensure our descriptors are proper
mesh.updateDescriptor();
int32_t vertexBuffer = -1;
int32_t indexBuffer = -1;
for ( size_t i = 0; i < buffers.size(); ++i ) {
if ( buffers[i].usage & uf::renderer::enums::Buffer::VERTEX ) vertexBuffer = i;
if ( buffers[i].usage & uf::renderer::enums::Buffer::INDEX ) indexBuffer = i;
}
// copy descriptors
descriptor.inputs.vertex = mesh.vertex;
descriptor.inputs.index = mesh.index;
descriptor.inputs.instance = mesh.instance;
descriptor.inputs.indirect = mesh.indirect;
if ( vertexBuffer > 0 && indexBuffer > 0 ) {
updateBuffer(
(const void*) attributes.vertex.pointer,
attributes.vertex.size * attributes.vertex.length,
vertexBuffer
);
updateBuffer(
(const void*) attributes.index.pointer,
attributes.index.size * attributes.index.length,
indexBuffer
);
return;
}
// create buffer if not set and requested
if ( !initialized && buffer ) {
// ensures each buffer index reflects nicely
struct Queue {
void* data;
size_t size;
uf::renderer::enums::Buffer::type_t usage;
};
uf::stl::vector<Queue> queue;
descriptor.inputs.bufferOffset = buffers.empty() ? 0 : buffers.size() - 1;
#define PARSE_ATTRIBUTE(i, usage) {\
auto& buffer = mesh.buffers[i];\
if ( queue.size() <= i ) queue.resize( i );\
if ( !buffer.empty() ) queue.emplace_back(Queue{ (void*) buffer.data(), buffer.size(), usage });\
}
#define PARSE_INPUT(name, usage){\
if ( mesh.isInterleaved( mesh.name.interleaved ) ) PARSE_ATTRIBUTE(descriptor.inputs.name.interleaved, usage)\
else for ( auto& attribute : descriptor.inputs.name.attributes ) PARSE_ATTRIBUTE(attribute.buffer, usage)\
}
PARSE_INPUT(vertex, uf::renderer::enums::Buffer::VERTEX)
PARSE_INPUT(index, uf::renderer::enums::Buffer::INDEX)
PARSE_INPUT(instance, uf::renderer::enums::Buffer::VERTEX)
PARSE_INPUT(indirect, uf::renderer::enums::Buffer::INDIRECT)
// allocate buffers
for ( auto& q : queue ) {
initializeBuffer( q.data, q.size, q.usage );
}
}
descriptor.attributes = attributes;
descriptor.indices = attributes.index.length;
initializeBuffer(
(const void*) attributes.vertex.pointer,
attributes.vertex.size * attributes.vertex.length,
uf::renderer::enums::Buffer::VERTEX
);
initializeBuffer(
(const void*) attributes.index.pointer,
attributes.index.size * attributes.index.length,
uf::renderer::enums::Buffer::INDEX
);
if ( mesh.instance.count == 0 && mesh.instance.attributes.empty() ) {
descriptor.inputs.instance.count = 1;
}
}
bool ext::vulkan::Graphic::hasPipeline( const GraphicDescriptor& descriptor ) const {
return pipelines.count( descriptor.hash() ) > 0;
@ -877,118 +847,150 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD
return;
}
if ( !pipeline.metadata.process ) return;
const Buffer* vertexBuffer = NULL;
const Buffer* indexBuffer = NULL;
for ( auto& buffer : buffers ) {
if ( buffer.usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ) vertexBuffer = &buffer;
if ( buffer.usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT ) indexBuffer = &buffer;
}
assert( vertexBuffer && indexBuffer );
pipeline.record(*this, commandBuffer, pass, draw);
// Bind triangle vertex buffer (contains position and colors)
VkDeviceSize offsets[1] = { descriptor.offsets.vertex };
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer->buffer, offsets);
// Bind triangle index buffer
VkIndexType indicesType = VK_INDEX_TYPE_UINT32;
switch ( descriptor.attributes.index.size ) {
case 1: indicesType = VK_INDEX_TYPE_UINT8_EXT; break;
case 2: indicesType = VK_INDEX_TYPE_UINT16; break;
case 4: indicesType = VK_INDEX_TYPE_UINT32; break;
default:
UF_EXCEPTION("Vulkan error: invalid indices size of " << (int) descriptor.attributes.index.size);
break;
/*
struct VertexInstance {
VkBuffer buffer;
VkDeviceSize offset;
};
struct {
struct {
size_t min;
size_t max;
} binding;
uf::stl::vector<VkBuffer> buffer;
uf::stl::vector<VkDeviceSize> offset;
} vertexInstance;
uf::stl::unordered_map<size_t, VertexInstance> vertexInstanceRemap;
for ( auto& attribute : descriptor.inputs.vertex.attributes ) {
vertexInstanceRemap[attribute.binding] = {
.buffer = buffers.at(attribute.buffer).buffer,
.offset = attribute.offset,
};
vertexInstance.binding.min = MIN(vertexInstance.binding.min, attribute.binding);
vertexInstance.binding.max = MAX(vertexInstance.binding.max, attribute.binding);
}
for ( auto& attribute : descriptor.inputs.instance.attributes ) {
vertexInstanceRemap[attribute.binding] = {
.buffer = buffers.at(attribute.buffer).buffer,
.offset = attribute.offset,
};
vertexInstance.binding.min = MIN(vertexInstance.binding.min, attribute.binding);
vertexInstance.binding.max = MAX(vertexInstance.binding.max, attribute.binding);
}
vertexInstance.buffer.resize( vertexInstanceRemap.size() );
vertexInstance.offset.resize( vertexInstanceRemap.size() );
for ( auto i = vertexInstance.binding.min; i <= vertexInstance.binding.max; ++i ) {
vertexInstance.buffer.emplace_back(vertexInstanceRemap[i].buffer);
vertexInstance.offset.emplace_back(vertexInstanceRemap[i].offset);
}
*/
struct {
uf::stl::vector<VkBuffer> buffer;
uf::stl::vector<VkDeviceSize> offset;
} vertexInstance;
for ( auto& attribute : descriptor.inputs.vertex.attributes ) {
vertexInstance.buffer.emplace_back( buffers.at((0 <= descriptor.inputs.vertex.interleaved ? descriptor.inputs.vertex.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer );
vertexInstance.offset.emplace_back( 0 <= descriptor.inputs.vertex.interleaved ? descriptor.inputs.vertex.offset : attribute.offset );
}
for ( auto& attribute : descriptor.inputs.instance.attributes ) {
vertexInstance.buffer.emplace_back( buffers.at((0 <= descriptor.inputs.instance.interleaved ? descriptor.inputs.instance.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer );
vertexInstance.offset.emplace_back( 0 <= descriptor.inputs.instance.interleaved ? descriptor.inputs.instance.offset : attribute.offset );
}
struct {
VkBuffer buffer = NULL;
VkDeviceSize offset = 0;
size_t binding = 0;
size_t index = 0;
} index, indirect;
if ( descriptor.inputs.index.count && !descriptor.inputs.index.attributes.empty() ) {
auto& attribute = descriptor.inputs.index.attributes.front();
index.buffer = buffers.at((0 <= descriptor.inputs.index.interleaved ? descriptor.inputs.index.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer;
index.offset = 0 <= descriptor.inputs.index.interleaved ? descriptor.inputs.index.offset : attribute.offset;
}
if ( descriptor.inputs.indirect.count && !descriptor.inputs.indirect.attributes.empty() ) {
auto& attribute = descriptor.inputs.indirect.attributes.front();
indirect.buffer = buffers.at((0 <= descriptor.inputs.indirect.interleaved ? descriptor.inputs.indirect.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer;
indirect.offset = 0 <= descriptor.inputs.indirect.interleaved ? descriptor.inputs.indirect.offset : attribute.offset;
}
for ( auto& buffer : buffers ) {
if ( !index.buffer && buffer.usage & uf::renderer::enums::Buffer::INDEX ) index.buffer = buffer.buffer;
if ( !indirect.buffer && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect.buffer = buffer.buffer;
}
if ( !vertexInstance.buffer.empty() ) {
vkCmdBindVertexBuffers( commandBuffer, 0, vertexInstance.buffer.size(), vertexInstance.buffer.data(), vertexInstance.offset.data() );
}
if ( index.buffer ) {
VkIndexType indicesType = VK_INDEX_TYPE_UINT32;
switch ( descriptor.inputs.index.stride ) {
case 1: indicesType = VK_INDEX_TYPE_UINT8_EXT; break;
case 2: indicesType = VK_INDEX_TYPE_UINT16; break;
case 4: indicesType = VK_INDEX_TYPE_UINT32; break;
default:
UF_EXCEPTION("invalid indices size of " << (int) descriptor.inputs.index.stride);
break;
}
vkCmdBindIndexBuffer(commandBuffer, index.buffer, index.offset, indicesType);
}
if ( index.buffer && indirect.buffer ) {
vkCmdDrawIndexedIndirect(commandBuffer, indirect.buffer,
descriptor.inputs.indirect.offset, // offset
descriptor.inputs.indirect.count, // drawCount
descriptor.inputs.indirect.stride // stride
);
} else if ( index.buffer && !indirect.buffer ) {
vkCmdDrawIndexed(commandBuffer,
descriptor.inputs.index.count, // indexCount
descriptor.inputs.instance.count, // instanceCount
descriptor.inputs.index.first, // firstIndex
descriptor.inputs.vertex.first, // vertexOffset
descriptor.inputs.instance.first // firstInstance
);
} else if ( !vertexInstance.buffer.empty() && indirect.buffer ) {
vkCmdDrawIndexedIndirect(commandBuffer, indirect.buffer,
descriptor.inputs.indirect.offset, // offset
descriptor.inputs.indirect.count, // drawCount
descriptor.inputs.indirect.stride // stride
);
} else/* if ( !vertexInstance.buffer.empty() && !indirect.buffer ) */{
vkCmdDraw(commandBuffer,
descriptor.inputs.vertex.count, // vertexCount
descriptor.inputs.instance.count, // instanceCount
descriptor.inputs.vertex.first, // firstVertex
descriptor.inputs.instance.first // firstInstance
);
}
vkCmdBindIndexBuffer(commandBuffer, indexBuffer->buffer, descriptor.offsets.index, indicesType);
vkCmdDrawIndexed(commandBuffer, descriptor.indices, 1, 0, 0, 1);
}
void ext::vulkan::Graphic::destroy() {
for ( auto& pair : pipelines ) pair.second.destroy();
pipelines.clear();
material.destroy();
ext::vulkan::Buffers::destroy();
ext::vulkan::states::rebuild = true;
}
bool ext::vulkan::Graphic::hasStorage( const uf::stl::string& name ) const {
for ( auto& shader : material.shaders ) if ( shader.hasStorage(name) ) return true;
return false;
}
ext::vulkan::Buffer& ext::vulkan::Graphic::getStorageBuffer( const uf::stl::string& name ) {
size_t storageIndex = -1;
for ( auto& shader : material.shaders ) {
if ( !shader.hasStorage(name) ) continue;
storageIndex = shader.metadata.definitions.storage[name].index;
break;
}
for ( size_t bufferIndex = 0, storageCounter = 0; bufferIndex < buffers.size(); ++bufferIndex ) {
if ( !(buffers[bufferIndex].usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) ) continue;
if ( storageCounter++ != storageIndex ) continue;
return buffers[bufferIndex];
}
UF_EXCEPTION("buffer not found: " << name);
}
const ext::vulkan::Buffer& ext::vulkan::Graphic::getStorageBuffer( const uf::stl::string& name ) const {
size_t storageIndex = -1;
for ( auto& shader : material.shaders ) {
if ( !shader.hasStorage(name) ) continue;
storageIndex = shader.metadata.definitions.storage.at(name).index;
break;
}
for ( size_t bufferIndex = 0, storageCounter = 0; bufferIndex < buffers.size(); ++bufferIndex ) {
if ( !(buffers[bufferIndex].usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) ) continue;
if ( storageCounter++ != storageIndex ) continue;
return buffers[bufferIndex];
}
UF_EXCEPTION("buffer not found: " << name);
}
// JSON shit
uf::Serializer ext::vulkan::Graphic::getStorageJson( const uf::stl::string& name, bool cache ) {
for ( auto& shader : material.shaders ) {
if ( !shader.hasStorage(name) ) continue;
return shader.getStorageJson(name, cache);
}
return ext::json::null();
}
ext::vulkan::userdata_t ext::vulkan::Graphic::getStorageUserdata( const uf::stl::string& name, const ext::json::Value& payload ) {
for ( auto& shader : material.shaders ) {
if ( !shader.hasStorage(name) ) continue;
return shader.getStorageUserdata(name, payload);
}
return ext::vulkan::userdata_t();
}
#include <uf/utils/string/hash.h>
void ext::vulkan::GraphicDescriptor::parse( ext::json::Value& metadata ) {
if ( metadata["front face"].is<uf::stl::string>() ) {
if ( metadata["front face"].as<uf::stl::string>() == "ccw" ) {
frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
} else if ( metadata["front face"].as<uf::stl::string>() == "cw" ) {
frontFace = VK_FRONT_FACE_CLOCKWISE;
}
if ( metadata["front face"].as<uf::stl::string>() == "ccw" ) frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
else if ( metadata["front face"].as<uf::stl::string>() == "cw" ) frontFace = VK_FRONT_FACE_CLOCKWISE;
}
if ( metadata["cull mode"].is<uf::stl::string>() ) {
if ( metadata["cull mode"].as<uf::stl::string>() == "back" ) {
cullMode = VK_CULL_MODE_BACK_BIT;
} else if ( metadata["cull mode"].as<uf::stl::string>() == "front" ) {
cullMode = VK_CULL_MODE_FRONT_BIT;
} else if ( metadata["cull mode"].as<uf::stl::string>() == "none" ) {
cullMode = VK_CULL_MODE_NONE;
} else if ( metadata["cull mode"].as<uf::stl::string>() == "both" ) {
cullMode = VK_CULL_MODE_FRONT_AND_BACK;
}
}
if ( metadata["indices"].is<size_t>() ) {
indices = metadata["indices"].as<size_t>();
}
if ( ext::json::isObject( metadata["offsets"] ) ) {
offsets.vertex = metadata["offsets"]["vertex"].as<size_t>();
offsets.index = metadata["offsets"]["index"].as<size_t>();
if ( metadata["cull mode"].as<uf::stl::string>() == "back" ) cullMode = VK_CULL_MODE_BACK_BIT;
else if ( metadata["cull mode"].as<uf::stl::string>() == "front" ) cullMode = VK_CULL_MODE_FRONT_BIT;
else if ( metadata["cull mode"].as<uf::stl::string>() == "none" ) cullMode = VK_CULL_MODE_NONE;
else if ( metadata["cull mode"].as<uf::stl::string>() == "both" ) cullMode = VK_CULL_MODE_FRONT_AND_BACK;
}
if ( ext::json::isObject(metadata["depth bias"]) ) {
depth.bias.enable = VK_TRUE;
depth.bias.constant = metadata["depth bias"]["constant"].as<float>();
@ -997,41 +999,6 @@ void ext::vulkan::GraphicDescriptor::parse( ext::json::Value& metadata ) {
}
}
ext::vulkan::GraphicDescriptor::hash_t ext::vulkan::GraphicDescriptor::hash() const {
#if UF_GRAPHIC_DESCRIPTOR_USE_STRING
uf::Serializer serializer;
serializer["subpass"] = subpass;
if ( settings::experimental::individualPipelines )
serializer["renderMode"] = renderMode;
serializer["renderTarget"] = renderTarget;
serializer["geometry"]["sizes"]["vertex"] = attributes.vertex.size;
serializer["geometry"]["sizes"]["indices"] = attributes.index.size;
serializer["indices"] = indices;
serializer["offsets"]["vertex"] = offsets.vertex;
serializer["offsets"]["index"] = offsets.index;
for ( uint8_t i = 0; i < attributes.descriptor.size(); ++i ) {
serializer["geometry"]["attributes"][i]["format"] = attributes.descriptor[i].format;
serializer["geometry"]["attributes"][i]["offset"] = attributes.descriptor[i].offset;
}
serializer["topology"] = topology;
serializer["cullMode"] = cullMode;
serializer["fill"] = fill;
serializer["lineWidth"] = lineWidth;
serializer["frontFace"] = frontFace;
serializer["depth"]["test"] = depth.test;
serializer["depth"]["write"] = depth.write;
serializer["depth"]["operation"] = depth.operation;
serializer["depth"]["bias"]["enable"] = depth.bias.enable;
serializer["depth"]["bias"]["constant"] = depth.bias.constant;
serializer["depth"]["bias"]["slope"] = depth.bias.slope;
serializer["depth"]["bias"]["clamp"] = depth.bias.clamp;
return uf::string::sha256( serializer.serialize() );
// return serializer.dump();
#else
size_t hash{};
hash += std::hash<decltype(subpass)>{}(subpass);
@ -1039,15 +1006,23 @@ ext::vulkan::GraphicDescriptor::hash_t ext::vulkan::GraphicDescriptor::hash() co
hash += std::hash<decltype(renderMode)>{}(renderMode);
hash += std::hash<decltype(renderTarget)>{}(renderTarget);
hash += std::hash<decltype(attributes.vertex.size)>{}(attributes.vertex.size);
hash += std::hash<decltype(attributes.index.size)>{}(attributes.index.size);
hash += std::hash<decltype(indices)>{}(indices);
hash += std::hash<decltype(offsets.vertex)>{}(offsets.vertex);
hash += std::hash<decltype(offsets.index)>{}(offsets.index);
for ( uint8_t i = 0; i < attributes.descriptor.size(); ++i ) {
hash += std::hash<decltype(attributes.descriptor[i].format)>{}(attributes.descriptor[i].format);
hash += std::hash<decltype(attributes.descriptor[i].offset)>{}(attributes.descriptor[i].offset);
/*
hash += std::hash<decltype(vertex.attributes.size)>{}(vertex.attributes.size);
hash += std::hash<decltype(vertex.attributes.length)>{}(vertex.attributes.length);
hash += std::hash<decltype(index.attributes.size)>{}(index.attributes.size);
hash += std::hash<decltype(index.attributes.length)>{}(index.attributes.length);
hash += std::hash<decltype(instance.attributes.size)>{}(instance.attributes.size);
hash += std::hash<decltype(instance.attributes.length)>{}(instance.attributes.length);
*/
for ( uint8_t i = 0; i < inputs.vertex.attributes.size(); ++i ) {
hash += std::hash<decltype(inputs.vertex.attributes[i].descriptor.format)>{}(inputs.vertex.attributes[i].descriptor.format);
hash += std::hash<decltype(inputs.vertex.attributes[i].descriptor.offset)>{}(inputs.vertex.attributes[i].descriptor.offset);
}
for ( uint8_t i = 0; i < inputs.index.attributes.size(); ++i ) {
hash += std::hash<decltype(inputs.index.attributes[i].descriptor.format)>{}(inputs.index.attributes[i].descriptor.format);
hash += std::hash<decltype(inputs.index.attributes[i].descriptor.offset)>{}(inputs.index.attributes[i].descriptor.offset);
}
hash += std::hash<decltype(topology)>{}(topology);
@ -1064,7 +1039,6 @@ ext::vulkan::GraphicDescriptor::hash_t ext::vulkan::GraphicDescriptor::hash() co
hash += std::hash<decltype(depth.bias.clamp)>{}(depth.bias.clamp);
return hash;
#endif
}
#endif

View File

@ -81,6 +81,18 @@ void ext::vulkan::ComputeRenderMode::initialize( Device& device ) {
}
}
{
uf::Mesh mesh;
mesh.bind<pod::Vertex_2F2F, uint16_t>();
mesh.insertVertices<pod::Vertex_2F2F>({
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
{ {-1.0f, -1.0f}, {0.0f, 0.0f}, },
{ {1.0f, -1.0f}, {1.0f, 0.0f}, },
{ {1.0f, 1.0f}, {1.0f, 1.0f}, }
});
mesh.insertIndices<uint16_t>({
0, 1, 2, 2, 3, 0
});
/*
uf::Mesh<pod::Vertex_2F2F, uint16_t> mesh;
mesh.vertices = {
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
@ -91,6 +103,7 @@ void ext::vulkan::ComputeRenderMode::initialize( Device& device ) {
mesh.indices = {
0, 1, 2, 2, 3, 0
};
*/
blitter.device = &device;
blitter.material.device = &device;
blitter.descriptor.subpass = 1;

View File

@ -192,6 +192,18 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
renderTarget.initialize( device );
{
uf::Mesh mesh;
mesh.bind<pod::Vertex_2F2F, uint16_t>();
mesh.insertVertices<pod::Vertex_2F2F>({
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
{ {-1.0f, -1.0f}, {0.0f, 0.0f}, },
{ {1.0f, -1.0f}, {1.0f, 0.0f}, },
{ {1.0f, 1.0f}, {1.0f, 1.0f}, }
});
mesh.insertIndices<uint16_t>({
0, 1, 2, 2, 3, 0
});
/*
uf::Mesh<pod::Vertex_2F2F, uint16_t> mesh;
mesh.vertices = {
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
@ -202,6 +214,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
mesh.indices = {
0, 1, 2, 0, 2, 3
};
*/
blitter.descriptor.subpass = 1;
blitter.descriptor.depth.test = false;
blitter.descriptor.depth.write = false;
@ -305,33 +318,33 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
});
}
uf::stl::vector<pod::Light::Storage> lights(maxLights);
uf::stl::vector<pod::Material::Storage> materials(maxTextures2D);
uf::stl::vector<pod::Texture::Storage> textures(maxTextures2D);
uf::stl::vector<pod::DrawCall::Storage> drawCalls(maxTextures2D);
uf::stl::vector<pod::Light> lights(maxLights);
uf::stl::vector<pod::Material> materials(maxTextures2D);
uf::stl::vector<pod::Texture> textures(maxTextures2D);
uf::stl::vector<pod::DrawCommand> drawCommands(maxTextures2D);
for ( auto& material : materials ) material.colorBase = {0,0,0,0};
metadata.lightBufferIndex = blitter.initializeBuffer(
metadata.lightBufferIndex = shader.initializeBuffer(
(const void*) lights.data(),
lights.size() * sizeof(pod::Light::Storage),
lights.size() * sizeof(pod::Light),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
metadata.materialBufferIndex = blitter.initializeBuffer(
metadata.materialBufferIndex = shader.initializeBuffer(
(const void*) materials.data(),
materials.size() * sizeof(pod::Material::Storage),
materials.size() * sizeof(pod::Material),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
metadata.textureBufferIndex = blitter.initializeBuffer(
metadata.textureBufferIndex = shader.initializeBuffer(
(const void*) textures.data(),
textures.size() * sizeof(pod::Texture::Storage),
textures.size() * sizeof(pod::Texture),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
metadata.drawCallBufferIndex = blitter.initializeBuffer(
(const void*) drawCalls.data(),
drawCalls.size() * sizeof(pod::DrawCall::Storage),
metadata.drawCallBufferIndex = shader.initializeBuffer(
(const void*) drawCommands.data(),
drawCommands.size() * sizeof(pod::DrawCommand),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
}

View File

@ -303,16 +303,17 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
renderTarget.initialize( device );
if ( blitter.process ) {
uf::Mesh<pod::Vertex_2F2F, uint16_t> mesh;
mesh.vertices = {
uf::Mesh mesh;
mesh.bind<pod::Vertex_2F2F, uint16_t>();
mesh.insertVertices<pod::Vertex_2F2F>({
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
{ {-1.0f, -1.0f}, {0.0f, 0.0f}, },
{ {1.0f, -1.0f}, {1.0f, 0.0f}, },
{ {1.0f, 1.0f}, {1.0f, 1.0f}, }
};
mesh.indices = {
});
mesh.insertIndices<uint16_t>({
0, 1, 2, 2, 3, 0
};
});
blitter.device = &device;
blitter.material.device = &device;
@ -434,33 +435,33 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
}
});
uf::stl::vector<pod::Light::Storage> lights(maxLights);
uf::stl::vector<pod::Material::Storage> materials(maxTextures2D);
uf::stl::vector<pod::Texture::Storage> textures(maxTextures2D);
uf::stl::vector<pod::DrawCall::Storage> drawCalls(maxTextures2D);
uf::stl::vector<pod::Light> lights(maxLights);
uf::stl::vector<pod::Material> materials(maxTextures2D);
uf::stl::vector<pod::Texture> textures(maxTextures2D);
uf::stl::vector<pod::DrawCommand> drawCalls(maxTextures2D);
for ( auto& material : materials ) material.colorBase = {0,0,0,0};
metadata.lightBufferIndex = blitter.initializeBuffer(
metadata.lightBufferIndex = shader.initializeBuffer(
(const void*) lights.data(),
lights.size() * sizeof(pod::Light::Storage),
lights.size() * sizeof(pod::Light),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
metadata.materialBufferIndex = blitter.initializeBuffer(
metadata.materialBufferIndex = shader.initializeBuffer(
(const void*) materials.data(),
materials.size() * sizeof(pod::Material::Storage),
materials.size() * sizeof(pod::Material),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
metadata.textureBufferIndex = blitter.initializeBuffer(
metadata.textureBufferIndex = shader.initializeBuffer(
(const void*) textures.data(),
textures.size() * sizeof(pod::Texture::Storage),
textures.size() * sizeof(pod::Texture),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
metadata.drawCallBufferIndex = blitter.initializeBuffer(
metadata.drawCallBufferIndex = shader.initializeBuffer(
(const void*) drawCalls.data(),
drawCalls.size() * sizeof(pod::DrawCall::Storage),
drawCalls.size() * sizeof(pod::DrawCommand),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
} else {

View File

@ -399,7 +399,9 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
};
uf::Serializer payload = ext::json::array();
const auto& type = comp.get_type(type_id);
for ( auto& member_type_id : type.member_types ) {
if ( type.member_types.empty() ) {
payload = parseMember( type_id );
} else for ( auto& member_type_id : type.member_types ) {
const auto& member_type = comp.get_type(member_type_id);
uf::stl::string name = comp.get_member_name(type.type_alias, payload.size());
if ( name == "" ) name = comp.get_member_name(type.parent_type, payload.size());
@ -545,16 +547,74 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
{
uniforms.reserve( metadata.definitions.uniforms.size() );
uf::stl::vector<size_t> sizes( metadata.definitions.uniforms.size() );
uf::stl::vector<uf::stl::string> remap( metadata.definitions.uniforms.size() );
for ( auto pair : metadata.definitions.uniforms ) {
sizes[pair.second.index] = pair.second.size;
remap[pair.second.index] = pair.second.name;
}
for ( auto size : sizes ) {
auto& uniform = uniforms.emplace_back();
uniform.create( size );
for ( auto& name : remap ) {
auto& definition = metadata.definitions.uniforms[name];
auto& userdata = uniforms.emplace_back();
userdata.create( definition.size, nullptr );
initializeBuffer(
(const void*) userdata.data().data,
userdata.data().len,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
);
}
}
for ( auto i = 0; i < res.stage_inputs.size(); ++i ) {
const auto& resource = res.stage_inputs[i];
const auto& type = comp.get_type(resource.type_id);
const auto& base_type = comp.get_type(resource.base_type_id);
const size_t binding = comp.get_decoration(resource.id, spv::DecorationBinding);
const uf::stl::string name = resource.name;
size_t size = 0; // comp.get_declared_struct_size(type);
// generate definition to JSON
{
metadata.json["definitions"]["inputs"][name]["name"] = name;
metadata.json["definitions"]["inputs"][name]["index"] = i;
metadata.json["definitions"]["inputs"][name]["binding"] = binding;
metadata.json["definitions"]["inputs"][name]["size"] = size;
metadata.json["definitions"]["inputs"][name]["members"] = parseMembers(resource.type_id);
}
// generate definition to unordered_map
{
metadata.definitions.inputs[name] = Shader::Metadata::Definition::InOut{
name,
i,
binding,
size,
};
}
}
for ( auto i = 0; i < res.stage_outputs.size(); ++i ) {
const auto& resource = res.stage_outputs[i];
const auto& type = comp.get_type(resource.type_id);
const auto& base_type = comp.get_type(resource.base_type_id);
const size_t binding = comp.get_decoration(resource.id, spv::DecorationBinding);
const uf::stl::string name = resource.name;
size_t size = 0; // comp.get_declared_struct_size(type);
// generate definition to JSON
{
metadata.json["definitions"]["outputs"][name]["name"] = name;
metadata.json["definitions"]["outputs"][name]["index"] = i;
metadata.json["definitions"]["outputs"][name]["binding"] = binding;
metadata.json["definitions"]["outputs"][name]["size"] = size;
metadata.json["definitions"]["outputs"][name]["members"] = parseMembers(resource.type_id);
}
// generate definition to unordered_map
{
metadata.definitions.outputs[name] = Shader::Metadata::Definition::InOut{
name,
i,
binding,
size
};
}
}
for ( const auto& resource : res.push_constant_buffers ) {
const auto& type = comp.get_type(resource.type_id);
const auto& base_type = comp.get_type(resource.base_type_id);
@ -701,21 +761,9 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
}
// organize layouts
{
std::sort( descriptorSetLayoutBindings.begin(), descriptorSetLayoutBindings.end(), [&]( const VkDescriptorSetLayoutBinding& l, const VkDescriptorSetLayoutBinding& r ){
return l.binding < r.binding;
} );
}
// update uniform buffers
for ( auto& uniform : uniforms ) {
auto& userdata = uniform.data();
initializeBuffer(
(const void*) userdata.data,
userdata.len,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
);
}
std::sort( descriptorSetLayoutBindings.begin(), descriptorSetLayoutBindings.end(), [&]( const VkDescriptorSetLayoutBinding& l, const VkDescriptorSetLayoutBinding& r ){
return l.binding < r.binding;
} );
}
void ext::vulkan::Shader::destroy() {
@ -739,7 +787,7 @@ bool ext::vulkan::Shader::validate() {
bool valid = true;
auto it = uniforms.begin();
for ( auto& buffer : buffers ) {
if ( !(buffer.usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue;
if ( !(buffer.usage & uf::renderer::enums::Buffer::UNIFORM) ) continue;
if ( it == uniforms.end() ) break;
auto& uniform = *(it++);
if ( uniform.data().len != buffer.allocationInfo.size ) {
@ -758,7 +806,7 @@ ext::vulkan::Buffer& ext::vulkan::Shader::getUniformBuffer( const uf::stl::strin
UF_ASSERT( hasUniform(name) );
size_t uniformIndex = metadata.definitions.uniforms[name].index;
for ( size_t bufferIndex = 0, uniformCounter = 0; bufferIndex < buffers.size(); ++bufferIndex ) {
if ( !(buffers[bufferIndex].usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue;
if ( !(buffers[bufferIndex].usage & uf::renderer::enums::Buffer::UNIFORM) ) continue;
if ( uniformCounter++ != uniformIndex ) continue;
return buffers[bufferIndex];
}
@ -768,7 +816,7 @@ const ext::vulkan::Buffer& ext::vulkan::Shader::getUniformBuffer( const uf::stl:
UF_ASSERT( hasUniform(name) );
size_t uniformIndex = metadata.definitions.uniforms.at(name).index;
for ( size_t bufferIndex = 0, uniformCounter = 0; bufferIndex < buffers.size(); ++bufferIndex ) {
if ( !(buffers.at(bufferIndex).usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ) continue;
if ( !(buffers.at(bufferIndex).usage & uf::renderer::enums::Buffer::UNIFORM) ) continue;
if ( uniformCounter++ != uniformIndex ) continue;
return buffers.at(bufferIndex);
}
@ -787,7 +835,7 @@ bool ext::vulkan::Shader::updateUniform( const uf::stl::string& name, const void
updateBuffer( data, size, getUniformBuffer(name) );
return true;
}
//
bool ext::vulkan::Shader::hasStorage( const uf::stl::string& name ) const {
return metadata.definitions.storage.count(name) > 0;
}
@ -795,7 +843,7 @@ ext::vulkan::Buffer& ext::vulkan::Shader::getStorageBuffer( const uf::stl::strin
UF_ASSERT( hasStorage(name) );
size_t storageIndex = metadata.definitions.storage[name].index;
for ( size_t bufferIndex = 0, storageCounter = 0; bufferIndex < buffers.size(); ++bufferIndex ) {
if ( !(buffers[bufferIndex].usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) ) continue;
if ( !(buffers[bufferIndex].usage & uf::renderer::enums::Buffer::STORAGE) ) continue;
if ( storageCounter++ != storageIndex ) continue;
return buffers[bufferIndex];
}
@ -805,13 +853,19 @@ const ext::vulkan::Buffer& ext::vulkan::Shader::getStorageBuffer( const uf::stl:
UF_ASSERT( hasStorage(name) );
size_t storageIndex = metadata.definitions.storage.at(name).index;
for ( size_t bufferIndex = 0, storageCounter = 0; bufferIndex < buffers.size(); ++bufferIndex ) {
if ( !(buffers.at(bufferIndex).usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) ) continue;
if ( !(buffers.at(bufferIndex).usage & uf::renderer::enums::Buffer::STORAGE) ) continue;
if ( storageCounter++ != storageIndex ) continue;
return buffers.at(bufferIndex);
}
UF_EXCEPTION("buffer not found: " << name);
}
bool ext::vulkan::Shader::updateStorage( const uf::stl::string& name, const void* data, size_t size ) const {
if ( !hasStorage(name) ) return false;
updateBuffer( data, size, getStorageBuffer(name) );
return true;
}
// JSON shit
/*
uf::Serializer ext::vulkan::Shader::getUniformJson( const uf::stl::string& name, bool cache ) {
if ( !hasUniform(name) ) return ext::json::null();
if ( cache && !ext::json::isNull(metadata.json["uniforms"][name]) ) return metadata.json["uniforms"][name];
@ -839,5 +893,5 @@ ext::vulkan::userdata_t ext::vulkan::Shader::getStorageUserdata( const uf::stl::
if ( !hasStorage(name) ) return false;
return jsonToUserdata(payload, metadata.json["definitions"]["storage"][name]);
}
*/
#endif

View File

@ -5,7 +5,9 @@
pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
#if UF_USE_XATLAS
::xatlas::Atlas* atlas = ::xatlas::Create();
for ( auto& mesh : graph.meshes ) {
#if 0
for ( auto& name : graph.meshes ) {
auto& mesh = uf::graph::storage.meshes[name];
mesh.updateDescriptor();
size_t indices = mesh.attributes.index.length;
@ -16,13 +18,13 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
size_t vertexStride = mesh.attributes.vertex.size;
uint8_t* vertexPointer = (uint8_t*) mesh.attributes.vertex.pointer;
uf::renderer::VertexDescriptor vertexAttributePosition,
uf::renderer::AttributeDescriptor vertexAttributePosition,
vertexAttributeNormal,
vertexAttributeUv,
vertexAttributeSt,
vertexAttributeId;
for ( auto& attribute : mesh.attributes.descriptor ) {
for ( auto& attribute : mesh.attributes.vertex.descriptor ) {
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute;
else if ( attribute.name == "uv" ) vertexAttributeUv = attribute;
@ -68,10 +70,9 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
::xatlas::Generate(atlas, chartOptions, packOptions);
#if UF_GRAPH_EXPERIMENTAL
for ( size_t i = 0; i < atlas->meshCount; i++ ) {
auto& xmesh = atlas->meshes[i];
auto& mesh = graph.meshes[i];
auto& mesh = uf::graph::storage.meshes[graph.meshes[i]];
size_t indices = mesh.attributes.index.length;
size_t indexStride = mesh.attributes.index.size;
@ -87,18 +88,16 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
uint8_t* oldVertexPointer = oldVertexBuffer.data();
uint8_t* newvertexPointer = (uint8_t*) mesh.attributes.vertex.pointer;
uf::renderer::VertexDescriptor vertexAttributePosition,
uf::renderer::AttributeDescriptor vertexAttributePosition,
vertexAttributeNormal,
vertexAttributeUv,
vertexAttributeSt,
vertexAttributeId;
vertexAttributeSt;
for ( auto& attribute : mesh.attributes.descriptor ) {
for ( auto& attribute : mesh.attributes.vertex.descriptor ) {
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute;
else if ( attribute.name == "uv" ) vertexAttributeUv = attribute;
else if ( attribute.name == "st" ) vertexAttributeSt = attribute;
else if ( attribute.name == "id" ) vertexAttributeId = attribute;
}
UF_ASSERT( vertexAttributePosition.name != "" );
@ -126,58 +125,8 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
pod::Vector2ui size = pod::Vector2ui{ atlas->width, atlas->height };
::xatlas::Destroy(atlas);
#else
#if 0
for (size_t i = 0; i < atlas->meshCount; i++) {
auto& mesh = graph.meshes[i];
auto& xmesh = atlas->meshes[i];
for ( size_t v = 0; v < xmesh.vertexCount; v++) {
auto& xvertex = xmesh.vertexArray[v];
auto& vertex = mesh.vertices[xvertex.xref];
vertex.st = { xvertex.uv[0] / atlas->width, xvertex.uv[1] / atlas->height };
}
}
#else
auto oldMeshes = std::move( graph.meshes );
graph.meshes.resize( oldMeshes.size() );
for (size_t i = 0; i < atlas->meshCount; i++) {
auto& xmesh = atlas->meshes[i];
auto& oldMesh = oldMeshes[i];
auto& newMesh = graph.meshes[i];
newMesh.vertices.reserve( xmesh.vertexCount );
newMesh.indices.reserve( xmesh.indexCount );
for ( size_t v = 0; v < xmesh.vertexCount; v++) {
auto& xvertex = xmesh.vertexArray[v];
auto& oldVertex = oldMesh.vertices[xvertex.xref];
auto& newVertex = newMesh.vertices.emplace_back(oldVertex);
newVertex.st = { xvertex.uv[0] / atlas->width, xvertex.uv[1] / atlas->height };
}
for ( size_t i = 0; i < xmesh.indexCount; ++i ) newMesh.indices.emplace_back( xmesh.indexArray[i] );
newMesh.updateDescriptor();
}
#endif
pod::Vector2ui size = pod::Vector2ui{ atlas->width, atlas->height };
::xatlas::Destroy(atlas);
for ( auto& node : graph.nodes ) {
if ( !(0 <= node.mesh && node.mesh < graph.meshes.size()) ) continue;
auto& nodeMesh = graph.meshes[node.mesh];
for ( auto& vertex : nodeMesh.vertices ) {
vertex.id.x = node.index;
// in almost-software mode, material ID is actually its albedo ID, as we can't use any other forms of mapping
#if UF_USE_OPENGL_FIXED_FUNCTION
if ( !(graph.mode & uf::graph::LoadMode::ATLAS) ) {
auto& material = graph.materials[vertex.id.y];
auto& texture = graph.textures[material.storage.indexAlbedo];
vertex.id.y = texture.storage.index;
}
#endif
}
}
#endif
return size;
#else
return pod::Vector2ui{};
#endif
#endif
}

View File

@ -2,7 +2,7 @@
#include <uf/utils/mesh/grid.h>
#include <uf/utils/math/collision/mesh.h>
#include <uf/utils/math/collision/boundingbox.h>
#if 0
uf::MeshGrid::~MeshGrid() {
this->destroy();
}
@ -271,4 +271,5 @@ pod::Vector3i uf::MeshGrid::unwrapIndex( size_t i ) {
break;
}
}
#endif
#endif

View File

@ -1,4 +1,5 @@
#include <uf/utils/mesh/mesh.h>
#include <uf/engine/graph/graph.h>
// Used for per-vertex colors
UF_VERTEX_DESCRIPTOR(pod::Vertex_3F2F3F4F,
@ -46,48 +47,394 @@ UF_VERTEX_DESCRIPTOR(pod::Vertex_3F,
UF_VERTEX_DESCRIPTION(pod::Vertex_3F, R32G32B32_SFLOAT, position)
)
pod::Mesh::~Mesh() {}
void pod::Mesh::generateIndices() {
this->resizeIndices(this->attributes.vertex.length);
switch ( this->attributes.index.size ) {
case sizeof(uint32_t):
for ( size_t i = 0; i < this->attributes.vertex.length; ++i ) ((uint32_t*) this->attributes.index.pointer)[i] = i;
break;
case sizeof(uint16_t):
for ( size_t i = 0; i < this->attributes.vertex.length; ++i ) ((uint16_t*) this->attributes.index.pointer)[i] = i;
break;
case sizeof(uint8_t):
for ( size_t i = 0; i < this->attributes.vertex.length; ++i ) ((uint8_t*) this->attributes.index.pointer)[i] = i;
break;
bool uf::Mesh::defaultInterleaved = false;
void uf::Mesh::initialize() {
}
void uf::Mesh::destroy() {
_destroy(vertex);
_destroy(index);
_destroy(instance);
_destroy(indirect);
buffers.clear();
}
uf::Mesh uf::Mesh::interleave() const {
uf::Mesh interleaved;
auto& buffer = interleaved.buffers.emplace_back();
#define PARSE_INPUT_INTERLEAVED(name) {\
interleaved.name = name;\
interleaved.name.offset = buffer.size();\
if ( isInterleaved( name.interleaved ) ) buffer.insert( buffer.end(), buffers[name.interleaved].begin(), buffers[name.interleaved].end() );\
else for ( auto& attribute : name.attributes ) buffer.insert( buffer.end(), buffers[attribute.buffer].begin(), buffers[attribute.buffer].end() );\
}
PARSE_INPUT_INTERLEAVED(vertex);
PARSE_INPUT_INTERLEAVED(index);
PARSE_INPUT_INTERLEAVED(instance);
PARSE_INPUT_INTERLEAVED(indirect);
return interleaved;
}
void uf::Mesh::updateDescriptor() {
_updateDescriptor(vertex);
_updateDescriptor(index);
_updateDescriptor(instance);
_updateDescriptor(indirect);
}
void uf::Mesh::insert( const uf::Mesh& mesh ) {
insertVertex(mesh);
insertIndex(mesh);
insertInstance(mesh);
insertIndirect(mesh);
}
/*
uint32_t indices = 0; // triangle count
uint32_t instances = 0; // instance count
uint32_t indexID = 0; // starting triangle position
int32_t vertexID = 0; // starting vertex position
uint32_t instanceID = 0; // starting instance position
uint32_t materialID = 0;
uint32_t objectID = 0;
uint32_t vertices = 0;
*/
void uf::Mesh::generateIndices() {
// deduce type
size_t size = sizeof(uint32_t);
uf::renderer::enums::Type::type_t type;
/*if ( vertex.count <= std::numeric_limits<uint8_t>::max() ) { size = sizeof(uint8_t); type = uf::renderer::typeToEnum<uint8_t>(); }
else*/ if ( vertex.count <= std::numeric_limits<uint16_t>::max() ) { size = sizeof(uint16_t); type = uf::renderer::typeToEnum<uint16_t>(); }
else if ( vertex.count <= std::numeric_limits<uint32_t>::max() ) { size = sizeof(uint32_t); type = uf::renderer::typeToEnum<uint32_t>(); }
if ( !index.attributes.empty() ) {
_destroy( index );
}
_bindI( index, size, type );
_bind( isInterleaved( vertex.interleaved ) );
switch ( size ) {
case 1: { uf::stl::vector<uint8_t> indices( vertex.count ); std::iota( indices.begin(), indices.end(), 0 ); insertIndices( indices ); } break;
case 2: { uf::stl::vector<uint16_t> indices( vertex.count ); std::iota( indices.begin(), indices.end(), 0 ); insertIndices( indices ); } break;
case 4: { uf::stl::vector<uint32_t> indices( vertex.count ); std::iota( indices.begin(), indices.end(), 0 ); insertIndices( indices ); } break;
}
}
void pod::Mesh::updateDescriptor() {}
void pod::Mesh::resizeVertices( size_t n ) {}
void pod::Mesh::resizeIndices( size_t n ) {}
void uf::Mesh::generateIndirect() {
if ( index.count == 0 ) generateIndices();
pod::Mesh& pod::VaryingMesh::get() {
return uf::pointeredUserdata::get<pod::Mesh>( userdata, false );
}
const pod::Mesh& pod::VaryingMesh::get() const {
return uf::pointeredUserdata::get<pod::Mesh>( userdata, false );
}
uf::stl::vector<pod::DrawCommand> commands;
for ( auto& attribute : index.attributes ) {
auto& buffer = buffers[isInterleaved(index.interleaved) ? index.interleaved : attribute.buffer];
auto& command = commands.emplace_back();
command.indices = buffer.size() / attribute.descriptor.size;
command.instances = instance.count == 0 && instance.attributes.empty() ? 1 : instance.count;
command.indexID = 0;
command.vertexID = 0;
command.instanceID = 0;
command.objectID = 0;
command.vertices = vertex.count;
}
void pod::VaryingMesh::destroy() {
uf::pointeredUserdata::destroy( userdata );
_destroy( indirect );
bindIndirect<pod::DrawCommand>();
_bind();
insertIndirects( commands );
}
void pod::VaryingMesh::updateDescriptor() {
auto& mesh = get();
mesh.updateDescriptor();
attributes = mesh.attributes;
bool uf::Mesh::isInterleaved( size_t i ) const { return 0 <= i && i < buffers.size(); }
void uf::Mesh::print() const {
std::stringstream str;
str << "Buffers: " << buffers.size() << "\n";
str << "Vertices: " << vertex.count << " | " << (isInterleaved(vertex.interleaved) ? "interleaved" : "deinterleaved") << "\n";
for ( auto i = 0; i < vertex.count; ++i ) {
if ( isInterleaved(vertex.interleaved) ) {
auto& buffer = buffers[vertex.interleaved];
uint8_t* e = (uint8_t*) &buffer[i * vertex.stride];
for ( auto& attribute : vertex.attributes ) {
str << "[" << i << "][" << attribute.descriptor.name << "]: ( ";
switch ( attribute.descriptor.type ) {
case uf::renderer::enums::Type::FLOAT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::UINT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint32_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::INT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int32_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::USHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint16_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::SHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int16_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::UBYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint8_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::BYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int8_t*) (e + attribute.descriptor.offset))[j] << " "; break;
}
str << ")\n";
}
} else for ( auto& attribute : vertex.attributes ) {
auto& buffer = buffers[attribute.buffer];
str << "[" << i << "][" << attribute.descriptor.name << "]: ( ";
switch ( attribute.descriptor.type ) {
case uf::renderer::enums::Type::FLOAT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::UINT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint32_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::INT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int32_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::USHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint16_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::SHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int16_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::UBYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint8_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::BYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int8_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
}
str << ")\n";
}
}
str << "Indices: " << index.count << " | " << (isInterleaved(index.interleaved) ? "interleaved" : "deinterleaved") << "\n";
for ( auto i = 0; i < index.count; ++i ) {
if ( isInterleaved(index.interleaved) ) {
auto& buffer = buffers[index.interleaved];
switch ( index.stride ) {
case 1: str << "[" << i << "]: " << *(( uint8_t*) &buffer[i * index.stride]) << "\n"; break;
case 2: str << "[" << i << "]: " << *((uint16_t*) &buffer[i * index.stride]) << "\n"; break;
case 4: str << "[" << i << "]: " << *((uint32_t*) &buffer[i * index.stride]) << "\n"; break;
}
} else for ( auto& attribute : index.attributes ) {
auto& buffer = buffers[attribute.buffer];
switch ( attribute.descriptor.size ) {
case 1: str << "[" << i << "]: " << *(( uint8_t*) &buffer[i * attribute.descriptor.size]) << "\n"; break;
case 2: str << "[" << i << "]: " << *((uint16_t*) &buffer[i * attribute.descriptor.size]) << "\n"; break;
case 4: str << "[" << i << "]: " << *((uint32_t*) &buffer[i * attribute.descriptor.size]) << "\n"; break;
}
}
}
str << "Instances: " << instance.count << " | " << (isInterleaved(instance.interleaved) ? "interleaved" : "deinterleaved") << "\n";
for ( auto i = 0; i < instance.count; ++i ) {
if ( isInterleaved(instance.interleaved) ) {
auto& buffer = buffers[instance.interleaved];
uint8_t* e = (uint8_t*) &buffer[i * instance.stride];
for ( auto& attribute : instance.attributes ) {
str << "[" << i << "][" << attribute.descriptor.name << "]: ( ";
switch ( attribute.descriptor.type ) {
case uf::renderer::enums::Type::FLOAT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::UINT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint32_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::INT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int32_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::USHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint16_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::SHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int16_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::UBYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint8_t*) (e + attribute.descriptor.offset))[j] << " "; break;
case uf::renderer::enums::Type::BYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int8_t*) (e + attribute.descriptor.offset))[j] << " "; break;
}
str << ")\n";
}
} else for ( auto& attribute : instance.attributes ) {
auto& buffer = buffers[attribute.buffer];
str << "[" << i << "][" << attribute.descriptor.name << "]: ( ";
switch ( attribute.descriptor.type ) {
case uf::renderer::enums::Type::FLOAT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((float*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::UINT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint32_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::INT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int32_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::USHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint16_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::SHORT: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int16_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::UBYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((uint8_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
case uf::renderer::enums::Type::BYTE: for ( auto j = 0; j < attribute.descriptor.components; ++j ) str << ((int8_t*) &buffer[i * attribute.descriptor.size])[j] << " "; break;
}
str << ")\n";
}
}
str << "Indirect: " << indirect.count << " | " << (isInterleaved(indirect.interleaved) ? "interleaved" : "deinterleaved");
std::cout << str.str() << std::endl;
}
//
void uf::Mesh::_destroy( uf::Mesh::Input& input ) {
for ( auto& attribute : input.attributes ) {
attribute.descriptor.length = 0;
attribute.descriptor.pointer = NULL;
attribute.buffer = 0;
}
input.attributes.clear();
}
void uf::Mesh::_bind( bool interleave ) {
size_t buffer = 0;
#define PARSE_INPUT(INPUT, INTERLEAVED){\
if ( INTERLEAVED ) INPUT.interleaved = buffer;\
for ( auto i = 0; i < INPUT.attributes.size(); ++i ) INPUT.attributes[i].buffer = !INTERLEAVED ? buffer++ : buffer;\
if ( !INPUT.attributes.empty() && INTERLEAVED ) ++buffer;\
}
PARSE_INPUT(vertex, interleave)
PARSE_INPUT(index, false)
PARSE_INPUT(instance, interleave)
PARSE_INPUT(indirect, false)
void pod::VaryingMesh::resizeVertices( size_t n ) {
auto& mesh = get();
mesh.resizeVertices( n );
attributes = mesh.attributes;
buffers.resize( buffer );
updateDescriptor();
// for ( auto& attribute : vertex.attributes ) UF_MSG_DEBUG( attribute.descriptor.name << "[" << attribute.descriptor.offset << "]: " << attribute.descriptor.size );
#undef PARSE_INPUT
}
void pod::VaryingMesh::resizeIndices( size_t n ) {
auto& mesh = get();
mesh.resizeIndices( n );
attributes = mesh.attributes;
void uf::Mesh::_updateDescriptor( uf::Mesh::Input& input ) {
input.stride = 0;
for ( auto& attribute : input.attributes ) {
auto& buffer = buffers[isInterleaved(input.interleaved) ? input.interleaved : attribute.buffer];
attribute.descriptor.length = buffer.size();
attribute.descriptor.pointer = (void*) (buffer.data());
input.stride += attribute.descriptor.size;
}
}
void uf::Mesh::_insertV( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput ) {
if ( !_hasV( input, srcInput ) ) return;
_reserveVs( input, input.count += srcInput.count );
// both meshes are interleaved, just copy directly
if ( isInterleaved(input.interleaved) && isInterleaved(srcInput.interleaved) ) {
auto& src = mesh.buffers[srcInput.interleaved];
auto& dst = buffers[input.interleaved];
dst.insert( dst.end(), src.begin(), src.end() );
// both meshes are de-interleaved, just copy directly
} else if ( !isInterleaved(input.interleaved) && !isInterleaved(srcInput.interleaved) ) {
for ( auto i = 0; i < input.attributes.size(); ++i ) {
auto& srcAttribute = srcInput.attributes[i];
auto& dstAttribute = input.attributes[i];
auto& src = mesh.buffers[srcAttribute.buffer];
auto& dst = buffers[dstAttribute.buffer];
dst.insert( dst.end(), src.begin(), src.end() );
}
// not easy to convert, will implement later
} else {
UF_EXCEPTION("to be implemented");
}
_updateDescriptor( input );
}
void uf::Mesh::_insertI( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput ) {
// if ( !_hasI( source ) ) return;
_reserveIs( input, input.count += srcInput.count );
// both meshes are interleaved, just copy directly
if ( isInterleaved(input.interleaved) && isInterleaved(srcInput.interleaved) ) {
auto& src = mesh.buffers[srcInput.interleaved];
auto& dst = buffers[input.interleaved];
dst.insert( dst.end(), src.begin(), src.end() );
// both meshes are de-interleaved, just copy directly
} else if ( !isInterleaved(input.interleaved) && !isInterleaved(srcInput.interleaved) ) {
for ( auto i = 0; i < input.attributes.size(); ++i ) {
auto& srcAttribute = srcInput.attributes[i];
auto& dstAttribute = input.attributes[i];
auto& src = mesh.buffers[srcAttribute.buffer];
auto& dst = buffers[dstAttribute.buffer];
dst.insert( dst.end(), src.begin(), src.end() );
}
// not easy to convert, will implement later
} else {
UF_EXCEPTION("to be implemented");
}
_updateDescriptor( input );
}
// Vertices
bool uf::Mesh::_hasV( const uf::Mesh::Input& input, const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) const {
if ( input.attributes.size() != descriptors.size() ) return false;
for ( auto i = 0; i < input.attributes.size(); ++i ) if ( input.attributes[i].descriptor != descriptors[i] ) return false;
return true;
}
bool uf::Mesh::_hasV( const uf::Mesh::Input& input, const uf::Mesh::Input& srcInput ) const {
if ( input.attributes.size() != srcInput.attributes.size() || input.stride != srcInput.stride ) return false;
for ( auto i = 0; i < input.attributes.size(); ++i ) if ( input.attributes[i].descriptor != srcInput.attributes[i].descriptor ) return false;
return true;
}
void uf::Mesh::_bindV( uf::Mesh::Input& input, const uf::stl::vector<uf::renderer::AttributeDescriptor>& descriptors ) {
input.attributes.resize( descriptors.size() );
for ( auto i = 0; i < descriptors.size(); ++i ) {
auto& attribute = input.attributes[i];
attribute.descriptor = descriptors[i];
input.stride += attribute.descriptor.size;
}
}
void uf::Mesh::_reserveVs( uf::Mesh::Input& input, size_t count ) {
if ( isInterleaved(input.interleaved) ) {
buffers[input.interleaved].reserve( count * input.stride );
for ( auto& attribute : input.attributes ) {
attribute.descriptor.length = buffers[input.interleaved].size();
attribute.descriptor.pointer = (void*) (buffers[input.interleaved].data());
}
} else for ( auto& attribute : input.attributes ) {
buffers[attribute.buffer].reserve( count * attribute.descriptor.size );
attribute.descriptor.length = buffers[attribute.buffer].size();
attribute.descriptor.pointer = (void*) (buffers[attribute.buffer].data());
}
}
void uf::Mesh::_resizeVs( uf::Mesh::Input& input, size_t count ) {
if ( isInterleaved(input.interleaved) ) {
buffers[input.interleaved].resize( count * input.stride );
for ( auto& attribute : input.attributes ) {
attribute.descriptor.length = buffers[input.interleaved].size();
attribute.descriptor.pointer = (void*) (buffers[input.interleaved].data());
}
} else for ( auto& attribute : input.attributes ) {
buffers[attribute.buffer].resize( count * attribute.descriptor.size );
attribute.descriptor.length = buffers[attribute.buffer].size();
attribute.descriptor.pointer = (void*) (buffers[attribute.buffer].data());
}
}
void uf::Mesh::_insertV( uf::Mesh::Input& input, const void* data ) {
_reserveVs( input, ++input.count );
const uint8_t* pointer = (const uint8_t*) data;
if ( isInterleaved(input.interleaved) ) {
buffers[input.interleaved].insert( buffers[input.interleaved].end(), pointer, pointer + input.stride );
} else for ( auto& attribute : input.attributes ) {
buffers[attribute.buffer].insert( buffers[attribute.buffer].end(), pointer + attribute.descriptor.offset, pointer + attribute.descriptor.offset + attribute.descriptor.size );
}
}
void uf::Mesh::_insertVs( uf::Mesh::Input& input, const void* data, size_t size ) {
#if 0
const uint8_t* pointer = (const uint8_t*) data;
for ( auto i = 0; i < size; ++i ) insertV( pointer + i * input.stride );
#else
_reserveVs( input, input.count += size );
const uint8_t* pointer = (const uint8_t*) data;
if ( isInterleaved(input.interleaved) ) {
buffers[input.interleaved].insert( buffers[input.interleaved].end(), pointer, pointer + size * input.stride );
} else for ( const uint8_t* p = pointer; p < pointer + size * input.stride; p += input.stride ) {
for ( auto& attribute : input.attributes )
buffers[attribute.buffer].insert( buffers[attribute.buffer].end(), p + attribute.descriptor.offset, p + attribute.descriptor.offset + attribute.descriptor.size );
}
#endif
}
// Indices
void uf::Mesh::_bindI( uf::Mesh::Input& input, size_t size, ext::RENDERER::enums::Type::type_t type, size_t count ) {
input.attributes.resize( count );
input.stride = size;
for ( auto i = 0; i < count; ++i ) {
auto& attribute = input.attributes[i];
attribute.descriptor.offset = 0;
attribute.descriptor.size = size;
attribute.descriptor.components = 1;
attribute.descriptor.type = type;
}
}
void uf::Mesh::_reserveIs( uf::Mesh::Input& input, size_t count, size_t i ) {
auto& attribute = input.attributes[i];
buffers[attribute.buffer].reserve( count * attribute.descriptor.size );
attribute.descriptor.length = buffers[attribute.buffer].size();
attribute.descriptor.pointer = (void*) (buffers[attribute.buffer].data());
}
void uf::Mesh::_resizeIs( uf::Mesh::Input& input, size_t count, size_t i ) {
auto& attribute = input.attributes[i];
buffers[attribute.buffer].resize( count * attribute.descriptor.size );
attribute.descriptor.length = buffers[attribute.buffer].size();
attribute.descriptor.pointer = (void*) (buffers[attribute.buffer].data());
}
void uf::Mesh::_insertI( uf::Mesh::Input& input, const void* data, size_t i ) {
auto& attribute = input.attributes[i];
_reserveIs( input, ++input.count );
const uint8_t* pointer = (const uint8_t*) data;
#if 1
buffers[attribute.buffer].insert( buffers[attribute.buffer].end(), pointer, pointer + attribute.descriptor.size );
#else
if ( isInterleaved(input.interleaved) ) {
buffers[input.interleaved].insert( buffers[input.interleaved].end(), pointer, pointer + attribute.descriptor.size );
} else {
buffers[attribute.buffer].insert( buffers[attribute.buffer].end(), pointer, pointer + attribute.descriptor.size );
}
#endif
}
void uf::Mesh::_insertIs( uf::Mesh::Input& input, const void* data, size_t size, size_t i ) {
auto& attribute = input.attributes[i];
_reserveIs( input, input.count += size );
const uint8_t* pointer = (const uint8_t*) data;
#if 1
for ( const uint8_t* p = pointer; p < pointer + size * attribute.descriptor.size; p += attribute.descriptor.size )
buffers[attribute.buffer].insert( buffers[attribute.buffer].end(), p + attribute.descriptor.offset, p + attribute.descriptor.offset + attribute.descriptor.size );
#else
if ( isInterleaved(input.interleaved) ) {
buffers[input.interleaved].insert( buffers[input.interleaved].end(), pointer, pointer + size * attribute.descriptor.size );
} else for ( const uint8_t* p = pointer; p < pointer + size * attribute.descriptor.size; p += attribute.descriptor.size ) {
buffers[attribute.buffer].insert( buffers[attribute.buffer].end(), p + attribute.descriptor.offset, p + attribute.descriptor.offset + attribute.descriptor.size );
}
#endif
}

View File

@ -61,7 +61,7 @@ void UF_API uf::userdata::destroy( uf::MemoryPool& requestedMemoryPool, pod::Use
}
pod::Userdata* UF_API uf::userdata::copy( uf::MemoryPool& requestedMemoryPool, const pod::Userdata* userdata ) {
if ( !userdata || userdata->len <= 0 ) return NULL;
auto* copied = uf::userdata::create( userdata->len, const_cast<void*>((const void*) userdata->data[0]) );
auto* copied = uf::userdata::create( userdata->len, const_cast<void*>((const void*) &userdata->data[0]) );
copied->type = userdata->type;
return copied;
}

View File

@ -7,7 +7,7 @@
#include <uf/utils/camera/camera.h>
#include <uf/ext/gltf/gltf.h>
#include <uf/engine/asset/asset.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/ext/xatlas/xatlas.h>
#include "../light/behavior.h"
@ -17,6 +17,7 @@ UF_BEHAVIOR_REGISTER_CPP(ext::BakingBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::BakingBehavior, ticks = true, renders = false, multithread = false)
#define this (&self)
void ext::BakingBehavior::initialize( uf::Object& self ) {
#if 0
#if UF_USE_VULKAN
UF_MSG_DEBUG("Ping");
@ -316,7 +317,7 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
for ( auto& node : graph.nodes ) {
instances.emplace_back( uf::transform::model( node.transform ) );
}
metadata.buffers.instance = graphic.initializeBuffer(
metadata.buffers.instance = shader.initializeBuffer(
(const void*) instances.data(),
instances.size() * sizeof(pod::Matrix4f),
uf::renderer::enums::Buffer::STORAGE
@ -326,7 +327,7 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
for ( size_t i = 0; i < graph.materials.size(); ++i ) {
materials[i] = graph.materials[i].storage;
}
metadata.buffers.material = graphic.initializeBuffer(
metadata.buffers.material = shader.initializeBuffer(
(const void*) materials.data(),
materials.size() * sizeof(pod::Material::Storage),
uf::renderer::enums::Buffer::STORAGE
@ -336,13 +337,13 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
for ( size_t i = 0; i < graph.textures.size(); ++i ) {
textures[i] = graph.textures[i].storage;
}
metadata.buffers.texture = graphic.initializeBuffer(
metadata.buffers.texture = shader.initializeBuffer(
(const void*) textures.data(),
textures.size() * sizeof(pod::Texture::Storage),
uf::renderer::enums::Buffer::STORAGE
);
// Light storage buffer
metadata.buffers.light = graphic.initializeBuffer(
metadata.buffers.light = shader.initializeBuffer(
(const void*) lights.data(),
lights.size() * sizeof(pod::Light::Storage),
uf::renderer::enums::Buffer::STORAGE
@ -431,8 +432,10 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
this->queueHook( "entity:PostInitialization.%UID%", ext::json::null(), 1 );
#endif
#endif
}
void ext::BakingBehavior::tick( uf::Object& self ) {
#if 0
#if UF_USE_VULKAN
if ( !this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) return;
auto& metadata = this->getComponent<ext::BakingBehavior::Metadata>();
@ -483,6 +486,7 @@ SAVE: {
return;
}
#endif
#endif
}
void ext::BakingBehavior::render( uf::Object& self ){}
void ext::BakingBehavior::destroy( uf::Object& self ){

View File

@ -523,7 +523,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
alignas(4) uint32_t lights = 0;
alignas(4) uint32_t materials = 0;
alignas(4) uint32_t textures = 0;
alignas(4) uint32_t drawCalls = 0;
alignas(4) uint32_t drawCommands = 0;
} lengths;
pod::Vector3f ambient;
@ -559,41 +559,59 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
texturesCube.reserve( metadata.max.texturesCube );
// lighting information
uf::stl::vector<pod::Light::Storage> lights;
uf::stl::vector<pod::Light> lights;
lights.reserve( metadata.max.lights );
// material information
uf::stl::vector<pod::Material::Storage> materials;
uf::stl::vector<pod::Material> materials;
materials.reserve( metadata.max.textures2D );
materials.emplace_back().colorBase = {0,0,0,0}; // setup our fallback material information
// texture information
uf::stl::vector<pod::Texture::Storage> textures;
uf::stl::vector<pod::Texture> textures;
textures.reserve( metadata.max.textures2D );
// drawcall information
uf::stl::vector<pod::DrawCall::Storage> drawCalls;
drawCalls.reserve( metadata.max.textures2D );
uf::stl::vector<pod::DrawCommand> drawCommands;
drawCommands.reserve( metadata.max.textures2D );
// bind materials
for ( auto pair : uf::graph::storage.materials ) materials.emplace_back(pair.second);
for ( auto pair : uf::graph::storage.textures ) textures.emplace_back(pair.second);
// bind textures
// bind texture2Ds
for ( auto pair : uf::graph::storage.images ) {
auto& image = pair.second;
auto& texture2D = uf::graph::storage.texture2Ds[pair.first];
if ( !texture2D.generated() ) texture2D.loadFromImage( pair.second );
textures2D.emplace_back().aliasTexture(texture2D);
}
// traverse scene graph
for ( auto entity : graph ) {
// needed to grab our necessary materials/texture information, until i add it globally
#if 0
if ( entity->hasComponent<pod::Graph>() ) {
auto& graph = entity->getComponent<pod::Graph>();
// pass our draw call information, necessary in shader
drawCalls.emplace_back(pod::DrawCall::Storage{
/*
drawCommands.emplace_back(pod::DrawCall{
materials.size(),
textures.size(),
textures2D.size(),
0,
});
*/
// pass material information
for ( auto& material : graph.materials ) materials.emplace_back( material.storage );
for ( auto& material : graph.materials ) {
materials.emplace_back( uf::graph::storage.materials[material] );
}
// pass texture information
for ( auto& texture : graph.textures ) {
textures.emplace_back( texture.storage );
textures.emplace_back( uf::graph::storage.textures[texture] );
// attach the actual texture if the texture information requests it
if ( texture.bind ) textures2D.emplace_back().aliasTexture(texture.texture);
// if ( texture.bind ) textures2D.emplace_back().aliasTexture(texture.texture);
}
}
#endif
// ignore this scene, our controller, and anything that isn't actually a light
if ( entity == this || entity == &controller || !entity->hasComponent<ext::LightBehavior::Metadata>() ) continue;
auto& metadata = entity->getComponent<ext::LightBehavior::Metadata>();
@ -637,15 +655,15 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
uf::Entity* entity = info.entity;
if ( !info.shadows ) {
lights.emplace_back(pod::Light::Storage{
lights.emplace_back(pod::Light{
.view = uf::matrix::identity(),
.projection = uf::matrix::identity(),
.position = info.position,
.color = info.color,
.type = info.type,
.typeMap = 0,
.indexMap = -1,
.depthBias = info.bias,
.view = uf::matrix::identity(),
.projection = uf::matrix::identity(),
});
} else {
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
@ -676,15 +694,15 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
break;
}
}
lights.emplace_back(pod::Light::Storage{
lights.emplace_back(pod::Light{
.view = lightCamera.getView(0),
.projection = lightCamera.getProjection(0),
.position = info.position,
.color = info.color,
.type = info.type,
.typeMap = metadata.shadow.experimentalMode,
.indexMap = index,
.depthBias = info.bias,
.view = lightCamera.getView(0),
.projection = lightCamera.getProjection(0),
});
// any other shadowing light, even point lights, are split by shadow maps
} else {
@ -692,15 +710,15 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
if ( attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) continue;
for ( size_t view = 0; view < renderMode.renderTarget.views; ++view ) {
lights.emplace_back(pod::Light::Storage{
lights.emplace_back(pod::Light{
.view = lightCamera.getView(view),
.projection = lightCamera.getProjection(view),
.position = info.position,
.color = info.color,
.type = info.type,
.typeMap = 0,
.indexMap = textures2D.size(),
.depthBias = info.bias,
.view = lightCamera.getView(view),
.projection = lightCamera.getProjection(view),
});
textures2D.emplace_back().aliasAttachment(attachment, view);
}
@ -766,7 +784,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
.lights = MIN( lights.size(), metadata.max.lights ),
.materials = MIN( materials.size(), metadata.max.textures2D ),
.textures = MIN( textures.size(), metadata.max.textures2D ),
.drawCalls = MIN( drawCalls.size(), metadata.max.textures2D ),
// .drawCommands = MIN( drawCommands.size(), metadata.max.textures2D ),
};
uniforms.ambient = metadata.light.ambient;
@ -801,24 +819,24 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
}
// update lighting buffer
graphic.updateBuffer( (const void*) lights.data(), uniforms.lengths.lights * sizeof(pod::Light::Storage), renderMode.metadata.lightBufferIndex, false );
shader.updateBuffer( (const void*) lights.data(), uniforms.lengths.lights * sizeof(pod::Light), renderMode.metadata.lightBufferIndex, false );
//
if ( shouldUpdate ) {
graphic.updateBuffer( (const void*) materials.data(), uniforms.lengths.materials * sizeof(pod::Material::Storage), renderMode.metadata.materialBufferIndex, false );
graphic.updateBuffer( (const void*) textures.data(), uniforms.lengths.textures * sizeof(pod::Texture::Storage), renderMode.metadata.textureBufferIndex, false );
graphic.updateBuffer( (const void*) drawCalls.data(), uniforms.lengths.drawCalls * sizeof(pod::DrawCall::Storage), renderMode.metadata.drawCallBufferIndex, false );
shader.updateBuffer( (const void*) materials.data(), uniforms.lengths.materials * sizeof(pod::Material), renderMode.metadata.materialBufferIndex, false );
shader.updateBuffer( (const void*) textures.data(), uniforms.lengths.textures * sizeof(pod::Texture), renderMode.metadata.textureBufferIndex, false );
shader.updateBuffer( (const void*) drawCommands.data(), uniforms.lengths.drawCommands * sizeof(pod::DrawCommand), renderMode.metadata.drawCallBufferIndex, false );
graphic.updatePipelines();
}
// graphic.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
graphic.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
// shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
/*
auto& uniform = shader.getUniform("UBO");
memcpy( (void*) uniform, &uniforms, sizeof(uniforms) );
shader.updateUniform( "UBO", uniform );
*/
}
#endif
}
#endif
#undef this

View File

@ -5,6 +5,7 @@
#include <uf/utils/math/transform.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/camera/camera.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/ext/gltf/gltf.h>
#include <uf/engine/asset/asset.h>
@ -234,7 +235,7 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) {
.matrix = metadata.extents.matrix,
.cascadePower = metadata.cascadePower,
};
graphic.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
#endif
}
}

View File

@ -317,9 +317,9 @@ void ext::Gui::load( const uf::Image& image ) {
auto& texture = graphic.material.textures.emplace_back();
texture.loadFromImage( image );
auto& mesh = this->getComponent<ext::Gui::mesh_t>();
// auto& mesh = this->getComponent<ext::Gui::mesh_t>();
auto& transform = this->getComponent<pod::Transform<>>();
mesh.vertices = {
uf::stl::vector<pod::Vertex_3F2F3F> vertices = {
{ pod::Vector3f{ 1.0f, -1.0f, 0.0f}, pod::Vector2f{1.0f, 0.0f}, metadata.color },
{ pod::Vector3f{-1.0f, -1.0f, 0.0f}, pod::Vector2f{0.0f, 0.0f}, metadata.color },
{ pod::Vector3f{-1.0f, 1.0f, 0.0f}, pod::Vector2f{0.0f, 1.0f}, metadata.color },
@ -350,11 +350,9 @@ void ext::Gui::load( const uf::Image& image ) {
metadataJson["cull mode"] = "none";
graphic.descriptor.parse( metadataJson );
if ( metadataJson["flip uv"].as<bool>() ) {
for ( auto& v : mesh.vertices ) v.uv.y = 1 - v.uv.y;
}
if ( metadata.depth != 0.0f )
for ( auto& v : mesh.vertices ) v.position.z = metadata.depth;
if ( metadataJson["flip uv"].as<bool>() ) for ( auto& v : vertices ) v.uv.y = 1 - v.uv.y;
if ( metadata.depth != 0.0f ) for ( auto& v : vertices ) v.position.z = metadata.depth;
if ( metadataJson["scaling"].is<uf::stl::string>() ) {
uf::stl::string mode = metadataJson["scaling"].as<uf::stl::string>();
if ( mode == "mesh" ) {
@ -379,7 +377,13 @@ void ext::Gui::load( const uf::Image& image ) {
} else {
graphic.initialize( ::defaultRenderMode );
}
auto& mesh = this->getComponent<uf::Mesh>();
mesh.bind<pod::Vertex_3F2F3F>();
mesh.insertVertices( vertices );
graphic.initializeMesh( mesh );
struct {
uf::stl::string vertex = uf::io::root+"/shaders/gui/base.vert.spv";
uf::stl::string fragment = uf::io::root+"/shaders/gui/base.frag.spv";
@ -524,7 +528,7 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
});
this->addHook( "window:Mouse.Moved", [&](ext::json::Value& json){
if ( this->getUid() == 0 ) return;
if ( !this->hasComponent<ext::Gui::mesh_t>() ) return;
if ( !this->hasComponent<uf::Mesh>() ) return;
if ( metadata.world ) return;
if ( !metadata.box.min && !metadata.box.max ) return;
@ -596,19 +600,17 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
key += std::to_string(metadataGlyph.sdf);
}
auto& scene = uf::scene::getCurrentScene();
auto& mesh = this->getComponent<ext::Gui::glyph_mesh_t>();
auto& mesh = this->getComponent<uf::Mesh>();
auto& graphic = this->getComponent<uf::Graphic>();
auto& atlas = this->getComponent<uf::Atlas>();
auto& images = atlas.getImages();
if ( !first ) {
atlas.clear();
mesh.vertices.clear();
mesh.indices.clear();
mesh.destroy();
for ( auto& texture : graphic.material.textures ) texture.destroy();
graphic.material.textures.clear();
}
mesh.vertices.reserve( glyphs.size() * 6 );
uf::stl::unordered_map<uf::stl::string, uf::stl::string> glyphHashMap;
for ( auto& g : glyphs ) {
@ -637,26 +639,31 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
transform.scale.x = scale;
transform.scale.y = scale;
uf::stl::vector<pod::Vertex_3F2F3F> vertices;
vertices.reserve( glyphs.size() * 6 );
for ( auto& g : glyphs ) {
auto glyphKey = std::to_string((uint64_t) g.code) + ";"+key;
auto& glyph = ::glyphs.cache[font][glyphKey];
auto hash = glyphHashMap[glyphKey];
// add vertices
mesh.vertices.push_back({pod::Vector3f{ g.box.x, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 0.0f }, hash ), g.color});
mesh.vertices.push_back({pod::Vector3f{ g.box.x, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 1.0f }, hash ), g.color});
mesh.vertices.push_back({pod::Vector3f{ g.box.x + g.box.w, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 1.0f }, hash ), g.color});
mesh.vertices.push_back({pod::Vector3f{ g.box.x, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 0.0f }, hash ), g.color});
mesh.vertices.push_back({pod::Vector3f{ g.box.x + g.box.w, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 1.0f }, hash ), g.color});
mesh.vertices.push_back({pod::Vector3f{ g.box.x + g.box.w, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 0.0f }, hash ), g.color});
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 0.0f }, hash ), g.color});
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 1.0f }, hash ), g.color});
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x + g.box.w, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 1.0f }, hash ), g.color});
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 0.0f }, hash ), g.color});
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x + g.box.w, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 1.0f }, hash ), g.color});
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x + g.box.w, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 0.0f }, hash ), g.color});
}
for ( size_t i = 0; i < mesh.vertices.size(); i += 6 ) {
for ( size_t i = 0; i < vertices.size(); i += 6 ) {
for ( size_t j = 0; j < 6; ++j ) {
auto& vertex = mesh.vertices[i+j];
auto& vertex = vertices[i+j];
vertex.position.x /= ext::gui::size.reference.x;
vertex.position.y /= ext::gui::size.reference.y;
vertex.position.z = metadata.depth;
}
}
mesh.bind<pod::Vertex_3F2F3F>();
mesh.insertVertices( vertices );
auto& texture = graphic.material.textures.emplace_back();
texture.loadFromImage( atlas.getAtlas() );
@ -809,15 +816,13 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
.color = metadata.color,
.mode = metadata.shader,
.depth = metadata.depth,
.depth = 1 - metadata.depth,
};
// set glyph-based uniforms
if ( isGlyph && uniform.size() == sizeof(::GlyphUniformDescriptor<>) ) {
auto& uniforms = uniform.get<::GlyphUniformDescriptor<>>();
auto& metadataGlyph = this->getComponent<ext::GuiBehavior::GlyphMetadata>();
// uniforms.gui.sdf = metadataGlyph.sdf;
// uniforms.gui.shadowbox = metadataGlyph.shadowbox;
if ( metadataGlyph.sdf ) uniforms.gui.mode &= 1 << 1;
if ( metadataGlyph.shadowbox ) uniforms.gui.mode &= 1 << 2;
@ -826,6 +831,7 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
uniforms.glyph.weight = metadataGlyph.weight;
uniforms.glyph.scale = metadataGlyph.scale;
}
// shader.updateBuffer( uniform, shader.getUniformBuffer("UBO") );
shader.updateUniform( "UBO", uniform );
// calculate click box
@ -834,6 +840,7 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
pod::Vector2f min = { 1, 1 };
pod::Vector2f max = { -1, -1 };
/*
if ( this->hasComponent<ext::Gui::mesh_t>() ) {
auto& mesh = this->getComponent<ext::Gui::mesh_t>();
for ( auto& vertex : mesh.vertices ) {
@ -859,6 +866,7 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
max.y = std::max( max.y, translated.y );
}
}
*/
metadata.box.min.x = min.x;
metadata.box.min.y = min.y;

View File

@ -22,8 +22,8 @@ namespace pod {
namespace ext {
class EXT_API Gui : public uf::Object {
public:
typedef uf::Mesh<pod::Vertex_3F2F3F, uint16_t> mesh_t;
typedef uf::Mesh<pod::Vertex_3F2F3F, uint16_t> glyph_mesh_t;
// typedef uf::Mesh<pod::Vertex_3F2F3F, uint16_t> mesh_t;
// typedef uf::Mesh<pod::Vertex_3F2F3F, uint16_t> glyph_mesh_t;
// Gui();
uf::stl::vector<pod::GlyphBox> generateGlyphs( const uf::stl::string& = "" );
void load( const uf::Image& );

View File

@ -160,9 +160,9 @@ void ext::GuiManagerBehavior::tick( uf::Object& self ) {
uniforms.cursor.color = metadata.overlay.cursor.color;
}
#if UF_UNIFORMS_REUSE
blitter.updateUniform( "UBO", uniform );
shader.updateUniform( "UBO", uniform );
#else
blitter.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
#endif
#endif
}

24
g++.exe.stackdump Normal file
View File

@ -0,0 +1,24 @@
Stack trace:
Frame Function Args
000FFFF5848 00180062C9C (000FFFF5A68, 00010000002, 000FFFFCE00, 000FFFFDE50)
000FFFF58F0 00180065090 (001800FA0BE, 00100140000, 100000000000101, 00000000000)
000FFFF5F70 00180047D1B (00000000000, 00000000000, 00000000000, 00000000000)
000FFFF6050 001801711AC (00000000001, 00000000000, 0000000019C, FFFFFFFF00000000)
000FFFF99F0 0018014761E (0018035B200, 008000F0610, 008000B36F0, 00000001003)
000FFFFAB80 00180148201 (00180352408, 0018037A8A0, 000FFFFAD02, 00000000000)
000FFFFAC30 00180065873 (001801B48F6, 000FFFFAE48, 00000000000, FFFFFFFFFFFFFFFF)
000FFFFAD90 001801389AB (001801B48F6, 000FFFFAE48, 00000000000, FFFFFFFFFFFFFFFF)
000FFFFAD90 0010040E131 (000FFFFAE48, 008000FE8F0, 00000000000, 001FFFFAE48)
00100433CA8 0010040E3DB (0080006D408, 008000F0610, 008000ED0A0, 008000B2AF0)
00100433CA8 0010040E8E4 (00000000000, 008000E8D43, 00000000008, 008000E8D3A)
000FFFFAFF0 0010040F34B (00100000000, 000FFFFB0F0, 00000000000, 00000000001)
000FFFFAFF0 0010040FB20 (00000000000, 183A92A3F1E23A87, 000000020C0, 00800063A21)
00000000001 0010041A5AF (00100000002, 0010040BA66, 00000000001, 001004335A8)
00000000001 0010041A9D9 (0080006CA36, 00000000001, 00000000028, 0080006CF10)
00000000001 00100419958 (00800000000, 6176652D2A2D2824, 2D7367616C662D6C, 00000292D2A)
001004369F0 0010041ADC7 (00100423B48, 00000000001, 00430B39190, 00000000000)
000FFFFB400 00100423FD8 (000FFFFCC90, 00800000160, 00000000000, 00180330BA0)
000FFFFCCE0 0018004A01B (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFCDA0 0018004794A (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFCE50 00180047A0C (00000000000, 00000000000, 00000000000, 00000000000)
End of stack trace