diff --git a/code/nel/include/nel/3d/driver.h b/code/nel/include/nel/3d/driver.h index 0fe4c6511..ca6bc0601 100644 --- a/code/nel/include/nel/3d/driver.h +++ b/code/nel/include/nel/3d/driver.h @@ -1132,7 +1132,7 @@ public: /** Return true if the driver supports the specified pixel program profile. */ - virtual bool supportPixelProgram(CPixelProgram::TProfile profile = CPixelProgram::nelvp) const = 0; + virtual bool supportPixelProgram(CPixelProgram::TProfile profile) const = 0; /** Compile the given pixel program, return if successful. Error information is returned as a string. */ @@ -1162,10 +1162,16 @@ public: virtual void setUniform2i(TProgram program, uint index, sint32 i0, sint32 i1) = 0; virtual void setUniform3i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2) = 0; virtual void setUniform4i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3) = 0; + virtual void setUniform1ui(TProgram program, uint index, uint32 ui0) = 0; + virtual void setUniform2ui(TProgram program, uint index, uint32 ui0, uint32 ui1) = 0; + virtual void setUniform3ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2) = 0; + virtual void setUniform4ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3) = 0; virtual void setUniform3f(TProgram program, uint index, const NLMISC::CVector& v) = 0; virtual void setUniform4f(TProgram program, uint index, const NLMISC::CVector& v, float f3) = 0; virtual void setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m) = 0; virtual void setUniform4fv(TProgram program, uint index, size_t num, const float *src) = 0; + virtual void setUniform4iv(TProgram program, uint index, size_t num, const sint32 *src) = 0; + virtual void setUniform4uiv(TProgram program, uint index, size_t num, const uint32 *src) = 0; // Set builtin parameters virtual void setUniformMatrix(TProgram program, uint index, TMatrix matrix, TTransform transform) = 0; virtual void setUniformFog(TProgram program, uint index) = 0; diff --git a/code/nel/include/nel/3d/gpu_program_params.h b/code/nel/include/nel/3d/gpu_program_params.h index 270c6cff5..ce6b8b2f0 100644 --- a/code/nel/include/nel/3d/gpu_program_params.h +++ b/code/nel/include/nel/3d/gpu_program_params.h @@ -60,7 +60,7 @@ class CGPUProgramParams { public: enum TType { Float, Int, UInt }; - struct CMeta { uint Index, Size, Count; TType Type; size_t Next, Prev; }; // size is element size, count is nb of elements + struct CMeta { uint Index, Size, Count; TType Type; std::string Name; size_t Next, Prev; }; // size is element size, count is nb of elements private: union CVec { float F[4]; sint32 I[4]; uint32 UI[4]; }; @@ -69,6 +69,8 @@ public: CGPUProgramParams(); virtual ~CGPUProgramParams(); + /// \name User functions + // @{ // Copy from another params storage void copy(CGPUProgramParams *params); @@ -81,10 +83,16 @@ public: void set2i(uint index, sint32 i0, sint32 i1); void set3i(uint index, sint32 i0, sint32 i1, sint32 i2); void set4i(uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3); + void set1ui(uint index, uint32 ui0); + void set2ui(uint index, uint32 ui0, uint32 ui1); + void set3ui(uint index, uint32 ui0, uint32 ui1, uint32 ui2); + void set4ui(uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3); void set3f(uint index, const NLMISC::CVector& v); void set4f(uint index, const NLMISC::CVector& v, float f3); void set4x4f(uint index, const NLMISC::CMatrix& m); void set4fv(uint index, size_t num, const float *src); + void set4iv(uint index, size_t num, const sint32 *src); + void set4uiv(uint index, size_t num, const uint32 *src); void unset(uint index); // Set by name, it is recommended to use index when repeatedly setting an element @@ -96,25 +104,42 @@ public: void set2i(const std::string &name, sint32 i0, sint32 i1); void set3i(const std::string &name, sint32 i0, sint32 i1, sint32 i2); void set4i(const std::string &name, sint32 i0, sint32 i1, sint32 i2, sint32 i3); + void set1ui(const std::string &name, uint32 ui0); + void set2ui(const std::string &name, uint32 ui0, uint32 ui1); + void set3ui(const std::string &name, uint32 ui0, uint32 ui1, uint32 ui2); + void set4ui(const std::string &name, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3); void set3f(const std::string &name, const NLMISC::CVector& v); void set4f(const std::string &name, const NLMISC::CVector& v, float f3); void set4x4f(const std::string &name, const NLMISC::CMatrix& m); void set4fv(const std::string &name, size_t num, const float *src); + void set4iv(const std::string &name, size_t num, const sint32 *src); + void set4uiv(const std::string &name, size_t num, const uint32 *src); void unset(const std::string &name); + // @} - /// Maps the given name to the given index, on duplicate entry the data set by name will be prefered as it can be assumed to have been set after the data set by index + // Maps the given name to the given index. + // on duplicate entry the data set by name will be prefered, as it can be + // assumed to have been set after the data set by index, and the mapping + // will usually happen while iterating and finding an element with name + // but no known index. + // Unknown index will be set to ~0, unknown name will have an empty string. void map(uint index, const std::string &name); - // Internal - /// Allocate specified number of components if necessary + /// \name Internal + // @{ + /// Allocate specified number of components if necessary (internal use only) size_t allocOffset(uint index, uint size, uint count, TType type); size_t allocOffset(const std::string &name, uint size, uint count, TType type); + size_t allocOffset(uint size, uint count, TType type); /// Return offset for specified index size_t getOffset(uint index) const; size_t getOffset(const std::string &name) const; /// Remove by offset void freeOffset(size_t offset); + // @} + /// \name Driver and dev tools + // @{ // Iteration (returns the offsets for access using getFooByOffset) inline size_t getBegin() const { return m_Meta.size() ? m_First : s_End; } inline size_t getNext(size_t offset) const { return m_Meta[offset].Next; } @@ -129,7 +154,8 @@ public: inline uint32 *getPtrUIByOffset(size_t offset) { return m_Vec[offset].UI; } inline TType getTypeByOffset(size_t offset) const { return m_Meta[offset].Type; } inline uint getIndexByOffset(size_t offset) const { return m_Meta[offset].Index; } - const std::string *getNameByOffset(size_t offset) const; // non-optimized for dev tools only, may return NULL if name unknown + const std::string &getNameByOffset(size_t offset) const { return m_Meta[offset].Name; }; + // @} // Utility static inline uint getNbRegistersByComponents(uint nbComponents) { return (nbComponents + 3) >> 2; } // vector register per 4 components diff --git a/code/nel/src/3d/gpu_program_params.cpp b/code/nel/src/3d/gpu_program_params.cpp index bfcc4d32c..87ba01381 100644 --- a/code/nel/src/3d/gpu_program_params.cpp +++ b/code/nel/src/3d/gpu_program_params.cpp @@ -83,36 +83,66 @@ void CGPUProgramParams::set4f(uint index, float f0, float f1, float f2, float f3 f[3] = f3; } -void CGPUProgramParams::set1i(uint index, int i0) +void CGPUProgramParams::set1i(uint index, sint32 i0) { - int *i = getPtrIByOffset(allocOffset(index, 1, 1, Int)); + sint32 *i = getPtrIByOffset(allocOffset(index, 1, 1, Int)); i[0] = i0; } -void CGPUProgramParams::set2i(uint index, int i0, int i1) +void CGPUProgramParams::set2i(uint index, sint32 i0, sint32 i1) { - int *i = getPtrIByOffset(allocOffset(index, 2, 1, Int)); + sint32 *i = getPtrIByOffset(allocOffset(index, 2, 1, Int)); i[0] = i0; i[1] = i1; } -void CGPUProgramParams::set3i(uint index, int i0, int i1, int i2) +void CGPUProgramParams::set3i(uint index, sint32 i0, sint32 i1, sint32 i2) { - int *i = getPtrIByOffset(allocOffset(index, 3, 1, Int)); + sint32 *i = getPtrIByOffset(allocOffset(index, 3, 1, Int)); i[0] = i0; i[1] = i1; i[2] = i2; } -void CGPUProgramParams::set4i(uint index, int i0, int i1, int i2, int i3) +void CGPUProgramParams::set4i(uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3) { - int *i = getPtrIByOffset(allocOffset(index, 4, 1, Int)); + sint32 *i = getPtrIByOffset(allocOffset(index, 4, 1, Int)); i[0] = i0; i[1] = i1; i[2] = i2; i[3] = i3; } +void CGPUProgramParams::set1ui(uint index, uint32 ui0) +{ + uint32 *ui = getPtrUIByOffset(allocOffset(index, 1, 1, UInt)); + ui[0] = ui0; +} + +void CGPUProgramParams::set2ui(uint index, uint32 ui0, uint32 ui1) +{ + uint32 *ui = getPtrUIByOffset(allocOffset(index, 2, 1, UInt)); + ui[0] = ui0; + ui[1] = ui1; +} + +void CGPUProgramParams::set3ui(uint index, uint32 ui0, uint32 ui1, uint32 ui2) +{ + uint32 *ui = getPtrUIByOffset(allocOffset(index, 3, 1, UInt)); + ui[0] = ui0; + ui[1] = ui1; + ui[2] = ui2; +} + +void CGPUProgramParams::set4ui(uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3) +{ + uint32 *ui = getPtrUIByOffset(allocOffset(index, 4, 1, UInt)); + ui[0] = ui0; + ui[1] = ui1; + ui[2] = ui2; + ui[3] = ui3; +} + void CGPUProgramParams::set3f(uint index, const NLMISC::CVector& v) { float *f = getPtrFByOffset(allocOffset(index, 3, 1, Float)); @@ -121,6 +151,15 @@ void CGPUProgramParams::set3f(uint index, const NLMISC::CVector& v) f[2] = v.z; } +void CGPUProgramParams::set4f(uint index, const NLMISC::CVector& v, float f3) +{ + float *f = getPtrFByOffset(allocOffset(index, 4, 1, Float)); + f[0] = v.x; + f[1] = v.y; + f[2] = v.z; + f[3] = f3; +} + void CGPUProgramParams::set4x4f(uint index, const NLMISC::CMatrix& m) { // TODO: Verify this! @@ -138,6 +177,210 @@ void CGPUProgramParams::set4fv(uint index, size_t num, const float *src) f[c] = src[c]; } +void CGPUProgramParams::set4iv(uint index, size_t num, const sint32 *src) +{ + sint32 *i = getPtrIByOffset(allocOffset(index, 4, num, Int)); + size_t nb = 4 * num; + for (uint c = 0; c < nb; ++c) + i[c] = src[c]; +} + +void CGPUProgramParams::set4uiv(uint index, size_t num, const uint32 *src) +{ + uint32 *ui = getPtrUIByOffset(allocOffset(index, 4, num, UInt)); + size_t nb = 4 * num; + for (uint c = 0; c < nb; ++c) + ui[c] = src[c]; +} + +void CGPUProgramParams::unset(uint index) +{ + size_t offset = getOffset(index); + if (offset != getEnd()) + { + freeOffset(offset); + } +} + +void CGPUProgramParams::set1f(const std::string &name, float f0) +{ + float *f = getPtrFByOffset(allocOffset(name, 1, 1, Float)); + f[0] = f0; +} + +void CGPUProgramParams::set2f(const std::string &name, float f0, float f1) +{ + float *f = getPtrFByOffset(allocOffset(name, 2, 1, Float)); + f[0] = f0; + f[1] = f1; +} + +void CGPUProgramParams::set3f(const std::string &name, float f0, float f1, float f2) +{ + float *f = getPtrFByOffset(allocOffset(name, 3, 1, Float)); + f[0] = f0; + f[1] = f1; + f[2] = f2; +} + +void CGPUProgramParams::set4f(const std::string &name, float f0, float f1, float f2, float f3) +{ + float *f = getPtrFByOffset(allocOffset(name, 4, 1, Float)); + f[0] = f0; + f[1] = f1; + f[2] = f2; + f[3] = f3; +} + +void CGPUProgramParams::set1i(const std::string &name, sint32 i0) +{ + sint32 *i = getPtrIByOffset(allocOffset(name, 1, 1, Int)); + i[0] = i0; +} + +void CGPUProgramParams::set2i(const std::string &name, sint32 i0, sint32 i1) +{ + sint32 *i = getPtrIByOffset(allocOffset(name, 2, 1, Int)); + i[0] = i0; + i[1] = i1; +} + +void CGPUProgramParams::set3i(const std::string &name, sint32 i0, sint32 i1, sint32 i2) +{ + sint32 *i = getPtrIByOffset(allocOffset(name, 3, 1, Int)); + i[0] = i0; + i[1] = i1; + i[2] = i2; +} + +void CGPUProgramParams::set4i(const std::string &name, sint32 i0, sint32 i1, sint32 i2, sint32 i3) +{ + sint32 *i = getPtrIByOffset(allocOffset(name, 4, 1, Int)); + i[0] = i0; + i[1] = i1; + i[2] = i2; + i[3] = i3; +} + +void CGPUProgramParams::set1ui(const std::string &name, uint32 ui0) +{ + uint32 *ui = getPtrUIByOffset(allocOffset(name, 1, 1, UInt)); + ui[0] = ui0; +} + +void CGPUProgramParams::set2ui(const std::string &name, uint32 ui0, uint32 ui1) +{ + uint32 *ui = getPtrUIByOffset(allocOffset(name, 2, 1, UInt)); + ui[0] = ui0; + ui[1] = ui1; +} + +void CGPUProgramParams::set3ui(const std::string &name, uint32 ui0, uint32 ui1, uint32 ui2) +{ + uint32 *ui = getPtrUIByOffset(allocOffset(name, 3, 1, UInt)); + ui[0] = ui0; + ui[1] = ui1; + ui[2] = ui2; +} + +void CGPUProgramParams::set4ui(const std::string &name, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3) +{ + uint32 *ui = getPtrUIByOffset(allocOffset(name, 4, 1, UInt)); + ui[0] = ui0; + ui[1] = ui1; + ui[2] = ui2; + ui[3] = ui3; +} + +void CGPUProgramParams::set3f(const std::string &name, const NLMISC::CVector& v) +{ + float *f = getPtrFByOffset(allocOffset(name, 3, 1, Float)); + f[0] = v.x; + f[1] = v.y; + f[2] = v.z; +} + +void CGPUProgramParams::set4f(const std::string &name, const NLMISC::CVector& v, float f3) +{ + float *f = getPtrFByOffset(allocOffset(name, 4, 1, Float)); + f[0] = v.x; + f[1] = v.y; + f[2] = v.z; + f[3] = f3; +} + +void CGPUProgramParams::set4x4f(const std::string &name, const NLMISC::CMatrix& m) +{ + // TODO: Verify this! + float *f = getPtrFByOffset(allocOffset(name, 4, 4, Float)); + NLMISC::CMatrix mt = m; + mt.transpose(); + mt.get(f); +} + +void CGPUProgramParams::set4fv(const std::string &name, size_t num, const float *src) +{ + float *f = getPtrFByOffset(allocOffset(name, 4, num, Float)); + size_t nb = 4 * num; + for (uint c = 0; c < nb; ++c) + f[c] = src[c]; +} + +void CGPUProgramParams::set4iv(const std::string &name, size_t num, const sint32 *src) +{ + sint32 *i = getPtrIByOffset(allocOffset(name, 4, num, Int)); + size_t nb = 4 * num; + for (uint c = 0; c < nb; ++c) + i[c] = src[c]; +} + +void CGPUProgramParams::set4uiv(const std::string &name, size_t num, const uint32 *src) +{ + uint32 *ui = getPtrUIByOffset(allocOffset(name, 4, num, UInt)); + size_t nb = 4 * num; + for (uint c = 0; c < nb; ++c) + ui[c] = src[c]; +} + +void CGPUProgramParams::unset(const std::string &name) +{ + size_t offset = getOffset(name); + if (offset != getEnd()) + { + freeOffset(offset); + } +} + +void CGPUProgramParams::map(uint index, const std::string &name) +{ + size_t offsetIndex = getOffset(index); + size_t offsetName = getOffset(name); + if (offsetName != getEnd()) + { + // Remove possible duplicate + if (offsetIndex != getEnd()) + { + freeOffset(offsetIndex); + } + + // Set index + m_Meta[offsetName].Index = index; + + // Map index to name + if (index >= m_Map.size()) + m_Map.resize(index + 1, s_End); + m_Map[index] = offsetName; + } + else if (offsetIndex != getEnd()) + { + // Set name + m_Meta[offsetIndex].Name = name; + + // Map name to index + m_MapName[name] = offsetIndex; + } +} + /// Allocate specified number of components if necessary size_t CGPUProgramParams::allocOffset(uint index, uint size, uint count, TType type) { @@ -163,18 +406,67 @@ size_t CGPUProgramParams::allocOffset(uint index, uint size, uint count, TType t } // Allocate space - offset = m_Meta.size(); - uint blocks = getNbRegistersByComponents(nbComponents); // per 4 components - m_Meta.resize(offset + blocks); - m_Vec.resize(offset + blocks); + offset = allocOffset(size, count, type); + + // Fill + m_Meta[offset].Index = index; // Store offset in map if (index >= m_Map.size()) m_Map.resize(index + 1, s_End); m_Map[index] = offset; + return offset; +} + +/// Allocate specified number of components if necessary +size_t CGPUProgramParams::allocOffset(const std::string &name, uint size, uint count, TType type) +{ + nlassert(count > 0); // this code will not properly handle 0 + nlassert(size > 0); // this code will not properly handle 0 + nlassert(!name.empty()); // sanity check + + uint nbComponents = size * count; + size_t offset = getOffset(name); + if (offset != s_End) + { + if (getCountByOffset(offset) >= nbComponents) + { + m_Meta[offset].Type = type; + m_Meta[offset].Size = size; + m_Meta[offset].Count = count; + return offset; + } + if (getCountByOffset(offset) < nbComponents) + { + freeOffset(offset); + } + } + + // Allocate space + offset = allocOffset(size, count, type); + + // Fill + m_Meta[offset].Name = name; + + // Store offset in map + m_MapName[name] = offset; + + return offset; +} + +/// Allocate specified number of components if necessary +size_t CGPUProgramParams::allocOffset(uint size, uint count, TType type) +{ + uint nbComponents = size * count; + + // Allocate space + size_t offset = m_Meta.size(); + uint blocks = getNbRegistersByComponents(nbComponents); // per 4 components + m_Meta.resize(offset + blocks); + m_Vec.resize(offset + blocks); + // Fill - m_Meta[offset].Index = index; m_Meta[offset].Size = size; m_Meta[offset].Count = count; m_Meta[offset].Type = type; @@ -207,6 +499,22 @@ size_t CGPUProgramParams::getOffset(uint index) const /// Remove by offset void CGPUProgramParams::freeOffset(size_t offset) { + uint index = getIndexByOffset(offset); + if (index != ~0) + { + if (m_Map.size() > index) + { + m_Map[index] = getEnd(); + } + } + const std::string &name = getNameByOffset(offset); + if (!name.empty()) + { + if (m_MapName.find(name) != m_MapName.end()) + { + m_MapName.erase(name); + } + } if (offset == m_Last) { nlassert(m_Meta[offset].Next == s_End);