From 7c6a01affb56ac47300060454a65da6fd18f04da Mon Sep 17 00:00:00 2001 From: coulsonwang Date: Mon, 11 Mar 2019 20:52:23 +0800 Subject: [PATCH 1/5] [Feature] fix uniform filled in metal --- cocos/renderer/backend/ProgramState.cpp | 80 ++++++++++++++++++- cocos/renderer/backend/ProgramState.h | 3 + cocos/renderer/backend/Types.h | 9 +++ .../renderer/backend/metal/ShaderModuleMTL.mm | 3 + 4 files changed, 94 insertions(+), 1 deletion(-) diff --git a/cocos/renderer/backend/ProgramState.cpp b/cocos/renderer/backend/ProgramState.cpp index 287321cd72..993e7d7b3a 100644 --- a/cocos/renderer/backend/ProgramState.cpp +++ b/cocos/renderer/backend/ProgramState.cpp @@ -6,6 +6,30 @@ CC_BACKEND_BEGIN +namespace { +#define MAT3_SIZE 36 +#define MAT4_SIZE 64 +#define VEC3_SIZE 12 +#define VEC4_SIZE 16 + + void convertVec3ToVec4(const float* src, float* dst) + { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = 0.0f; + } + + void convertMat3ToMat3x4(const float* src, float* dst) + { + dst[3] = dst[7] = dst[11] = 0.0f; + dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; + dst[4] = src[3]; dst[5] = src[4]; dst[6] = src[5]; + dst[8] = src[6]; dst[9] = src[7]; dst[10] = src[8]; + } +} + + UniformBuffer::UniformBuffer(const backend::UniformInfo &_uniformInfo) : uniformInfo(_uniformInfo) { @@ -200,11 +224,57 @@ void ProgramState::setUniform(const backend::UniformLocation& uniformLocation, c } } +void ProgramState::convertUniformData(const backend::UniformInfo& uniformInfo, const void* srcData, uint32_t srcSize, std::vector& uniformData) +{ + auto basicType = static_cast(uniformInfo.type); + char* convertedData = new char[uniformInfo.bufferSize]; + memset(convertedData, 0, uniformInfo.bufferSize); + switch (basicType) { + case BasicType::FLOAT: + { + for (int i=0; i= srcSize) + break; + + convertMat3ToMat3x4((float*)srcData + offset, (float*)convertedData + i * MAT4_SIZE); + } + else + { + offset = i*VEC3_SIZE; + if(offset >= srcSize) + break; + convertVec3ToVec4((float*)srcData +offset, (float*)convertedData + i * VEC4_SIZE); + } + + } + + uniformData.assign(convertedData, convertedData + uniformInfo.bufferSize); + break; + } + default: + CCLOGINFO("Not yet implemented..."); + break; + } + CC_SAFE_DELETE_ARRAY(convertedData); +} + void ProgramState::setVertexUniform(int location, const void* data, uint32_t size) { if(location < 0) return; - +#ifdef CC_USE_METAL + auto uniformInfo = _vertexUniformInfos[location].uniformInfo; + if(uniformInfo.needConvert) + { + convertUniformData(uniformInfo, data, size, _vertexUniformInfos[location].data); + return; + } +#endif _vertexUniformInfos[location].data.assign((char*)data, (char*)data + size); } @@ -212,6 +282,14 @@ void ProgramState::setFragmentUniform(int location, const void* data, uint32_t s { if(location < 0) return; +#ifdef CC_USE_METAL + auto uniformInfo = _fragmentUniformInfos[location].uniformInfo; + if(uniformInfo.needConvert) + { + convertUniformData(uniformInfo, data, size, _fragmentUniformInfos[location].data); + return; + } +#endif _fragmentUniformInfos[location].data.assign((char *)data, (char *)data + size); } diff --git a/cocos/renderer/backend/ProgramState.h b/cocos/renderer/backend/ProgramState.h index 2b9e0e641f..738dfc0e6c 100644 --- a/cocos/renderer/backend/ProgramState.h +++ b/cocos/renderer/backend/ProgramState.h @@ -84,6 +84,9 @@ protected: void setTexture(int location, uint32_t slot, backend::Texture* texture, std::unordered_map& textureInfo); void setTextureArray(int location, const std::vector& slots, const std::vector textures, std::unordered_map& textureInfo); + //float3 etc in Metal has both sizeof and alignment same as float4, convert it before fill into uniform buffer + void convertUniformData(const backend::UniformInfo& uniformInfo, const void* srcData, uint32_t srcSize, std::vector& uniformData); + backend::Program* _program = nullptr; std::vector _vertexUniformInfos; std::vector _fragmentUniformInfos; diff --git a/cocos/renderer/backend/Types.h b/cocos/renderer/backend/Types.h index 8def508499..4be95008ed 100644 --- a/cocos/renderer/backend/Types.h +++ b/cocos/renderer/backend/Types.h @@ -218,6 +218,13 @@ enum class Winding: uint32_t COUNTER_CLOCK_WISE }; +enum class BasicType: uint32_t +{ + FLOAT, + INT, + BOOL +}; + struct UniformInfo { int count = 0; @@ -225,6 +232,8 @@ struct UniformInfo unsigned int type = 0; bool isArray = false; unsigned int bufferSize = 0; + bool isMatrix = false; + bool needConvert = false; }; struct UniformLocation diff --git a/cocos/renderer/backend/metal/ShaderModuleMTL.mm b/cocos/renderer/backend/metal/ShaderModuleMTL.mm index b1c44de662..7fb5251e01 100644 --- a/cocos/renderer/backend/metal/ShaderModuleMTL.mm +++ b/cocos/renderer/backend/metal/ShaderModuleMTL.mm @@ -122,6 +122,9 @@ void ShaderModuleMTL::parseUniform(id mtlDevice, glslopt_shader* shad uniform.location = location; uniform.isArray = parArrSize; uniform.bufferSize = nextLocation - location; + uniform.needConvert = (parVecSize == 3) ? true : false; + uniform.type = static_cast(parType); + uniform.isMatrix = (parMatSize > 1) ? true : false; _uniformInfos[parName] = uniform; _maxLocation = _maxLocation < location ? (location + 1) : _maxLocation; From c17d361e50cd710c9099740cb4b129707d492991 Mon Sep 17 00:00:00 2001 From: coulsonwang Date: Tue, 12 Mar 2019 11:10:57 +0800 Subject: [PATCH 2/5] [Feature] float3 etc in Metal has both sizeof and alignment same as float4, need convert to correct laytout --- cocos/renderer/backend/ProgramState.cpp | 66 ++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/cocos/renderer/backend/ProgramState.cpp b/cocos/renderer/backend/ProgramState.cpp index 993e7d7b3a..cb2d14adc6 100644 --- a/cocos/renderer/backend/ProgramState.cpp +++ b/cocos/renderer/backend/ProgramState.cpp @@ -8,9 +8,29 @@ CC_BACKEND_BEGIN namespace { #define MAT3_SIZE 36 -#define MAT4_SIZE 64 +#define MAT4X3_SIZE 48 #define VEC3_SIZE 12 #define VEC4_SIZE 16 +#define BVEC3_SIZE 3 +#define BVEC4_SIZE 4 +#define IVEC3_SIZE 12 +#define IVEC4_SIZE 16 + + void convertbVec3TobVec4(const bool* src, bool* dst) + { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = false; + } + + void convertiVec3ToiVec4(const int* src, int* dst) + { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = 0; + } void convertVec3ToVec4(const float* src, float* dst) { @@ -20,7 +40,7 @@ namespace { dst[3] = 0.0f; } - void convertMat3ToMat3x4(const float* src, float* dst) + void convertMat3ToMat4x3(const float* src, float* dst) { dst[3] = dst[7] = dst[11] = 0.0f; dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; @@ -229,7 +249,8 @@ void ProgramState::convertUniformData(const backend::UniformInfo& uniformInfo, c auto basicType = static_cast(uniformInfo.type); char* convertedData = new char[uniformInfo.bufferSize]; memset(convertedData, 0, uniformInfo.bufferSize); - switch (basicType) { + switch (basicType) + { case BasicType::FLOAT: { for (int i=0; i= srcSize) break; - convertMat3ToMat3x4((float*)srcData + offset, (float*)convertedData + i * MAT4_SIZE); + convertMat3ToMat4x3((float*)srcData + offset, (float*)convertedData + i * MAT4X3_SIZE); } else { @@ -250,16 +271,41 @@ void ProgramState::convertUniformData(const backend::UniformInfo& uniformInfo, c break; convertVec3ToVec4((float*)srcData +offset, (float*)convertedData + i * VEC4_SIZE); } - } - - uniformData.assign(convertedData, convertedData + uniformInfo.bufferSize); + break; + } + case BasicType::BOOL: + { + for (int i=0; i= srcSize) + break; + + convertbVec3TobVec4((bool*)srcData + offset, (bool*)convertedData + i * BVEC4_SIZE); + } + break; + } + case BasicType::INT: + { + for (int i=0; i= srcSize) + break; + + convertiVec3ToiVec4((int*)srcData + offset, (int*)convertedData + i * IVEC4_SIZE); + } break; } default: - CCLOGINFO("Not yet implemented..."); + CC_ASSERT(false); break; } + + uniformData.assign(convertedData, convertedData + uniformInfo.bufferSize); CC_SAFE_DELETE_ARRAY(convertedData); } @@ -267,6 +313,8 @@ void ProgramState::setVertexUniform(int location, const void* data, uint32_t siz { if(location < 0) return; + +//float3 etc in Metal has both sizeof and alignment same as float4, need convert to correct laytout #ifdef CC_USE_METAL auto uniformInfo = _vertexUniformInfos[location].uniformInfo; if(uniformInfo.needConvert) @@ -282,6 +330,8 @@ void ProgramState::setFragmentUniform(int location, const void* data, uint32_t s { if(location < 0) return; + +//float3 etc in Metal has both sizeof and alignment same as float4, need convert to correct laytout #ifdef CC_USE_METAL auto uniformInfo = _fragmentUniformInfos[location].uniformInfo; if(uniformInfo.needConvert) From 605975bfa0eebbce9e90ce76259dee6627c1c996 Mon Sep 17 00:00:00 2001 From: coulsonwang Date: Tue, 12 Mar 2019 14:18:16 +0800 Subject: [PATCH 3/5] [Feature] use references and rename the structure to a more meaningful name --- cocos/renderer/backend/ProgramState.cpp | 12 ++++++------ cocos/renderer/backend/Types.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cocos/renderer/backend/ProgramState.cpp b/cocos/renderer/backend/ProgramState.cpp index cb2d14adc6..7b1897ee30 100644 --- a/cocos/renderer/backend/ProgramState.cpp +++ b/cocos/renderer/backend/ProgramState.cpp @@ -246,12 +246,12 @@ void ProgramState::setUniform(const backend::UniformLocation& uniformLocation, c void ProgramState::convertUniformData(const backend::UniformInfo& uniformInfo, const void* srcData, uint32_t srcSize, std::vector& uniformData) { - auto basicType = static_cast(uniformInfo.type); + auto basicType = static_cast(uniformInfo.type); char* convertedData = new char[uniformInfo.bufferSize]; memset(convertedData, 0, uniformInfo.bufferSize); switch (basicType) { - case BasicType::FLOAT: + case UniformBasicType::FLOAT: { for (int i=0; i Date: Tue, 12 Mar 2019 15:35:42 +0800 Subject: [PATCH 4/5] [Feature] use glslopt_basic_type --- cocos/renderer/backend/ProgramState.cpp | 9 +++++---- cocos/renderer/backend/Types.h | 11 ++++------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/cocos/renderer/backend/ProgramState.cpp b/cocos/renderer/backend/ProgramState.cpp index 7b1897ee30..3025a73562 100644 --- a/cocos/renderer/backend/ProgramState.cpp +++ b/cocos/renderer/backend/ProgramState.cpp @@ -3,6 +3,7 @@ #include "renderer/backend/Program.h" #include "renderer/backend/Texture.h" #include "renderer/backend/Types.h" +#include "glsl_optimizer.h" CC_BACKEND_BEGIN @@ -246,12 +247,12 @@ void ProgramState::setUniform(const backend::UniformLocation& uniformLocation, c void ProgramState::convertUniformData(const backend::UniformInfo& uniformInfo, const void* srcData, uint32_t srcSize, std::vector& uniformData) { - auto basicType = static_cast(uniformInfo.type); + auto basicType = static_cast(uniformInfo.type); char* convertedData = new char[uniformInfo.bufferSize]; memset(convertedData, 0, uniformInfo.bufferSize); switch (basicType) { - case UniformBasicType::FLOAT: + case kGlslTypeFloat: { for (int i=0; i Date: Wed, 13 Mar 2019 10:10:15 +0800 Subject: [PATCH 5/5] [feature] fix android compile error --- cocos/renderer/backend/ProgramState.cpp | 4 ++++ cocos/renderer/backend/ProgramState.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/cocos/renderer/backend/ProgramState.cpp b/cocos/renderer/backend/ProgramState.cpp index 3025a73562..5ca55bc4ec 100644 --- a/cocos/renderer/backend/ProgramState.cpp +++ b/cocos/renderer/backend/ProgramState.cpp @@ -3,7 +3,9 @@ #include "renderer/backend/Program.h" #include "renderer/backend/Texture.h" #include "renderer/backend/Types.h" +#ifdef CC_USE_METAL #include "glsl_optimizer.h" +#endif CC_BACKEND_BEGIN @@ -245,6 +247,7 @@ void ProgramState::setUniform(const backend::UniformLocation& uniformLocation, c } } +#ifdef CC_USE_METAL void ProgramState::convertUniformData(const backend::UniformInfo& uniformInfo, const void* srcData, uint32_t srcSize, std::vector& uniformData) { auto basicType = static_cast(uniformInfo.type); @@ -309,6 +312,7 @@ void ProgramState::convertUniformData(const backend::UniformInfo& uniformInfo, c uniformData.assign(convertedData, convertedData + uniformInfo.bufferSize); CC_SAFE_DELETE_ARRAY(convertedData); } +#endif void ProgramState::setVertexUniform(int location, const void* data, uint32_t size) { diff --git a/cocos/renderer/backend/ProgramState.h b/cocos/renderer/backend/ProgramState.h index 738dfc0e6c..fda01ee8dc 100644 --- a/cocos/renderer/backend/ProgramState.h +++ b/cocos/renderer/backend/ProgramState.h @@ -84,8 +84,10 @@ protected: void setTexture(int location, uint32_t slot, backend::Texture* texture, std::unordered_map& textureInfo); void setTextureArray(int location, const std::vector& slots, const std::vector textures, std::unordered_map& textureInfo); +#ifdef CC_USE_METAL //float3 etc in Metal has both sizeof and alignment same as float4, convert it before fill into uniform buffer void convertUniformData(const backend::UniformInfo& uniformInfo, const void* srcData, uint32_t srcSize, std::vector& uniformData); +#endif backend::Program* _program = nullptr; std::vector _vertexUniformInfos;