Commit for 2021.07.10 23-11-15.7z
This commit is contained in:
parent
bb85db104f
commit
5d9de97436
@ -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": {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) );
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
40
engine/inc/uf/engine/graph/mesh.inl
Normal file
40
engine/inc/uf/engine/graph/mesh.inl
Normal 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;
|
||||
*/
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
121
engine/inc/uf/engine/graph/pod.inl
Normal file
121
engine/inc/uf/engine/graph/pod.inl
Normal 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;
|
||||
};
|
||||
}
|
||||
15
engine/inc/uf/engine/graph/scene.inl
Normal file
15
engine/inc/uf/engine/graph/scene.inl
Normal 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;
|
||||
};
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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& );
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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; }
|
||||
@ -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;
|
||||
}
|
||||
@ -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 );
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
@ -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& );
|
||||
|
||||
@ -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 );
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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 );
|
||||
*/
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
22
engine/inc/uf/utils/memory/fifo_map.h
Normal file
22
engine/inc/uf/utils/memory/fifo_map.h
Normal 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>;
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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"
|
||||
@ -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
|
||||
@ -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
@ -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)
|
||||
);
|
||||
@ -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 ) {}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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, ®ion);
|
||||
|
||||
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, ©Region);
|
||||
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, ©Region);
|
||||
|
||||
device->flushCommandBuffer(copyCmd, true);
|
||||
staging.destroy();
|
||||
buffer.update( data, length, stage );
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 ){
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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& );
|
||||
|
||||
@ -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
24
g++.exe.stackdump
Normal 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
|
||||
Loading…
Reference in New Issue
Block a user