Просмотр исходного кода

Add support for setting the same uniform for multiple GPU programs

Daniele Bartolini 11 лет назад
Родитель
Сommit
43be837b34

+ 10 - 0
engine/renderers/backend/ConstantBuffer.h

@@ -51,6 +51,16 @@ public:
 		m_size = 0;
 	}
 
+	uint32_t position() const
+	{
+		return m_size;
+	}
+
+	void reset(uint32_t begin)
+	{
+		m_size = begin;
+	}
+
 	void write(uint32_t data)
 	{
 		write(&data, sizeof(uint32_t));

+ 13 - 0
engine/renderers/backend/RenderContext.h

@@ -184,6 +184,8 @@ struct RenderState
 		start_index = 0;
 		num_indices = 0xFFFFFFFF;
 		vertex_format = VertexFormat::COUNT;
+		begin_uniform = 0;
+		end_uniform = 0;
 
 		for (uint32_t i = 0; i < STATE_MAX_TEXTURES; i++)
 		{
@@ -205,6 +207,8 @@ public:
 	uint32_t		start_index;
 	uint32_t		num_indices;
 	VertexFormat::Enum vertex_format;
+	uint32_t		begin_uniform;
+	uint32_t		end_uniform;
 	Sampler			samplers[STATE_MAX_TEXTURES];
 };
 
@@ -399,6 +403,9 @@ struct RenderContext
 		CE_ASSERT(layer < MAX_RENDER_LAYERS, "Layer out of bounds");
 		m_render_key.m_layer = layer;
 
+		m_state.begin_uniform = m_last_uniform_offset;
+		m_state.end_uniform = m_constants.position();
+		m_last_uniform_offset = m_constants.position();
 		m_states[m_num_states] = m_state;
 		m_keys[m_num_states].key = m_render_key.encode();
 		m_keys[m_num_states].state = m_num_states;
@@ -416,6 +423,9 @@ struct RenderContext
 		m_num_states = 0;
 		m_state.clear();
 
+		m_commands.clear();
+		m_last_uniform_offset = 0;
+		m_constants.clear();
 		m_tvb_offset = 0;
 		m_tib_offset = 0;
 	}
@@ -423,6 +433,7 @@ struct RenderContext
 	void push()
 	{
 		m_commands.commit();
+		m_last_uniform_offset = 0;
 		m_constants.commit();
 	}
 
@@ -452,6 +463,8 @@ public:
 	ClearState m_clears[MAX_RENDER_LAYERS];
 
 	CommandBuffer m_commands;
+
+	uint32_t m_last_uniform_offset;
 	ConstantBuffer m_constants;
 
 	uint32_t m_tvb_offset;

+ 8 - 6
engine/renderers/backend/Renderer.h

@@ -694,12 +694,17 @@ public:
 		cmds.clear();
 	}
 
-	void update_uniforms(ConstantBuffer& cbuf)
+	void update_uniforms(ConstantBuffer& cbuf, uint32_t begin, uint32_t end)
 	{
-		UniformType::Enum type;
+		cbuf.reset(begin);
 
-		while ((type = (UniformType::Enum)cbuf.read()) != UniformType::END)
+		while (cbuf.position() < end)
 		{
+			UniformType::Enum type = (UniformType::Enum) cbuf.read();
+
+			if (type == UniformType::END)
+				break;
+
 			UniformId id;
 			uint32_t size;
 
@@ -709,8 +714,6 @@ public:
 
 			update_uniform_impl(id, size, data);
 		}
-
-		cbuf.clear();
 	}
 
 	void set_state(uint64_t flags)
@@ -839,7 +842,6 @@ public:
 		swap_contexts();
 
 		execute_commands(m_draw->m_commands);
-		update_uniforms(m_draw->m_constants);
 
 		if (m_is_initialized)
 		{

+ 48 - 66
engine/renderers/backend/gl/GLRenderer.cpp

@@ -49,6 +49,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Vector4.h"
 #include "Memory.h"
 #include "VertexFormat.h"
+#include "Hash.h"
 
 //-----------------------------------------------------------------------------
 static const char* gl_error_to_string(GLenum error)
@@ -214,6 +215,25 @@ ShaderUniform::Enum name_to_stock_uniform(const char* uniform)
 	return ShaderUniform::COUNT;
 }
 
+UniformType::Enum gl_enum_to_uniform_type(GLenum type)
+{
+	switch (type)
+	{
+		case GL_INT: return UniformType::INTEGER_1;
+		case GL_INT_VEC2: return UniformType::INTEGER_2; 
+		case GL_INT_VEC3: return UniformType::INTEGER_3;
+		case GL_INT_VEC4: return UniformType::INTEGER_4;
+		case GL_FLOAT: return UniformType::FLOAT_1;
+		case GL_FLOAT_VEC2: return UniformType::FLOAT_2;
+		case GL_FLOAT_VEC3: return UniformType::FLOAT_3;
+		case GL_FLOAT_VEC4: return UniformType::FLOAT_4;
+		case GL_FLOAT_MAT3: return UniformType::FLOAT_3x3;
+		case GL_FLOAT_MAT4: return UniformType::FLOAT_4x4;
+		case GL_SAMPLER_2D: return UniformType::INTEGER_1;
+		default: CE_FATAL("Oops, unknown uniform type"); return UniformType::END;
+	}
+}
+
 //-----------------------------------------------------------------------------
 struct VertexBuffer
 {
@@ -288,48 +308,6 @@ public:
 	uint32_t	m_size;
 };
 
-//-----------------------------------------------------------------------------
-struct Uniform
-{
-	Uniform()
-	{
-		string::strncpy(m_name, "", CE_MAX_UNIFORM_NAME_LENGTH);
-	}
-
-	void create(const char* name, UniformType::Enum type, uint8_t num)
-	{
-		string::strncpy(m_name, name, CE_MAX_UNIFORM_NAME_LENGTH);
-		m_type = type;
-		m_num = num;
-
-		size_t size = UNIFORM_SIZE_TABLE[type] * num;
-		m_data = default_allocator().allocate(size);
-		memset(m_data, 0, size);
-
-		// Log::d("Uniform created, name = %s, type = %d, num = %d, size = %ld, ptr = %p", m_name, type, num, size, m_data);
-	}
-
-	void update(size_t size, const void* data)
-	{
-		// Log::d("Uniform updated, new size = %ld, new ptr = %d", size, *((int32_t*)data));
-		memcpy(m_data, data, size);
-	}
-
-	void destroy()
-	{
-		default_allocator().deallocate(m_data);
-		string::strncpy(m_name, "", CE_MAX_UNIFORM_NAME_LENGTH); // <- this is a temporary fix
-		// Log::d("Uniform destroyed, name = %s, type = %d, num = %d, ptr = %p", m_name, m_type, m_num, m_data);
-	}
-
-public:
-
-	char m_name[CE_MAX_UNIFORM_NAME_LENGTH];
-	UniformType::Enum m_type;
-	uint8_t m_num;
-	void* m_data;
-};
-
 //-----------------------------------------------------------------------------
 struct Shader
 {
@@ -441,7 +419,7 @@ public:
 struct GPUProgram
 {
 	//-----------------------------------------------------------------------------
-	void create(const Shader& vertex, const Shader& pixel, uint32_t num_uniforms, Uniform* uniforms)
+	void create(const Shader& vertex, const Shader& pixel, const Hash<void*>& registry)
 	{
 		m_id = GL_CHECK(glCreateProgram());
 
@@ -525,16 +503,15 @@ struct GPUProgram
 			}
 			else
 			{
-				for (uint32_t i = 0; i < num_uniforms; i++)
-				{
-					if (string::strcmp(uniforms[i].m_name, uniform_name) == 0)
-					{
-						m_uniforms[m_num_uniforms] = uniforms[i].m_type;
-						m_uniform_info[m_num_uniforms].loc = uniform_location;
-						m_uniform_info[m_num_uniforms].data = uniforms[i].m_data;
-						m_num_uniforms++;
-					}
-				}
+				void* data = hash::get(registry, string::murmur2_64(uniform_name, string::strlen(uniform_name)), (void*) NULL);
+
+				if (data == NULL)
+					continue;
+
+				m_uniforms[m_num_uniforms] = gl_enum_to_uniform_type(uniform_type);
+				m_uniform_info[m_num_uniforms].loc = uniform_location;
+				m_uniform_info[m_num_uniforms].data = data;
+				m_num_uniforms++;
 			}
 
 			// Log::d("Uniform %d: name = '%s' location = '%d' stock = %s", uniform, uniform_name, uniform_location,
@@ -710,13 +687,14 @@ class RendererImplementation
 public:
 
 	//-----------------------------------------------------------------------------
-	RendererImplementation()
-		: m_max_texture_size(0)
+	RendererImplementation(Renderer* renderer)
+		: m_renderer(renderer)
+		, m_max_texture_size(0)
 		, m_max_texture_units(0)
 		, m_max_vertex_indices(0)
 		, m_max_vertex_vertices(0)
 		, m_max_anisotropy(0.0f)
-		, m_num_uniforms(0)
+		, m_uniform_registry(default_allocator())
 	{
 		m_min_max_point_size[0] = 0.0f;
 		m_min_max_point_size[1] = 0.0f;
@@ -932,6 +910,8 @@ public:
 				}
 			}
 
+			m_renderer->update_uniforms(context.m_constants, cur_state.begin_uniform, cur_state.end_uniform);
+
 			// Bind GPU program
 			if (cur_state.program.id != INVALID_ID)
 			{
@@ -1025,6 +1005,7 @@ public:
 
 private:
 
+	Renderer*			m_renderer;
 	GLContext			m_gl_context;
 
 	// Limits
@@ -1042,8 +1023,8 @@ private:
 	Texture				m_textures[CE_MAX_TEXTURES];
 	Shader				m_shaders[CE_MAX_SHADERS];
 	GPUProgram			m_gpu_programs[CE_MAX_GPU_PROGRAMS];
-	uint32_t			m_num_uniforms;
-	Uniform				m_uniforms[CE_MAX_UNIFORMS];
+	Hash<void*>			m_uniform_registry;
+	void*				m_uniforms[CE_MAX_UNIFORMS];
 	RenderTarget		m_render_targets[CE_MAX_RENDER_TARGETS];
 
 private:
@@ -1056,7 +1037,7 @@ Renderer::Renderer(Allocator& a)
 	: m_allocator(a), m_impl(NULL), m_thread("render-thread"), m_submit(&m_contexts[0]), m_draw(&m_contexts[1]),
 		m_is_initialized(false), m_should_run(false)
 {
-	m_impl = CE_NEW(a, RendererImplementation);
+	m_impl = CE_NEW(a, RendererImplementation)(this);
 }
 
 //-----------------------------------------------------------------------------
@@ -1067,7 +1048,7 @@ Renderer::~Renderer()
 	CE_ASSERT(m_textures.size() == 0, "%d textures not freed", m_textures.size());
 	CE_ASSERT(m_shaders.size() == 0, "%d shaders not freed", m_shaders.size());
 	CE_ASSERT(m_gpu_programs.size() == 0, "%d GPU programs not freed", m_gpu_programs.size());
-	CE_ASSERT(m_uniforms.size() == 0, "%d uniforms not freed", m_uniforms.size());
+	// CE_ASSERT(m_uniforms.size() == 0, "%d uniforms not freed", m_uniforms.size());
 	CE_ASSERT(m_render_targets.size() == 0, "%d render targets not freed", m_render_targets.size());
 
 	CE_DELETE(m_allocator, m_impl);
@@ -1180,7 +1161,7 @@ void Renderer::create_gpu_program_impl(GPUProgramId id, ShaderId vertex, ShaderI
 {
 	Shader& vs = m_impl->m_shaders[vertex.index];
 	Shader& ps = m_impl->m_shaders[pixel.index];
-	m_impl->m_gpu_programs[id.index].create(vs, ps, m_impl->m_num_uniforms, m_impl->m_uniforms);
+	m_impl->m_gpu_programs[id.index].create(vs, ps, m_impl->m_uniform_registry);
 }
 
 //-----------------------------------------------------------------------------
@@ -1193,22 +1174,23 @@ void Renderer::destroy_gpu_program_impl(GPUProgramId id)
 //-----------------------------------------------------------------------------
 void Renderer::create_uniform_impl(UniformId id, const char* name, UniformType::Enum type, uint8_t num)
 {
-	m_impl->m_uniforms[id.index].create(name, type, num);
-	m_impl->m_num_uniforms++;
+	const size_t size = UNIFORM_SIZE_TABLE[type] * num;
+	m_impl->m_uniforms[id.index] = default_allocator().allocate(size);
+	hash::set(m_impl->m_uniform_registry, string::murmur2_64(name, string::strlen(name)), m_impl->m_uniforms[id.index]);
+	memset(m_impl->m_uniforms[id.index], 0, size);
 }
 
 //-----------------------------------------------------------------------------
 void Renderer::update_uniform_impl(UniformId id, size_t size, const void* data)
 {
-	m_impl->m_uniforms[id.index].update(size, data);
+	memcpy(m_impl->m_uniforms[id.index], data, size);
 }
 
 //-----------------------------------------------------------------------------
 void Renderer::destroy_uniform_impl(UniformId id)
 {
-	m_impl->m_uniforms[id.index].destroy();
+	default_allocator().deallocate(m_impl->m_uniforms[id.index]);
 	m_uniforms.destroy(id);
-	m_impl->m_num_uniforms--;
 }
 
 // //-----------------------------------------------------------------------------