fix multi-texture2d support

This commit is contained in:
halx99 2020-08-29 16:56:48 +08:00
parent 06cf13d962
commit baa4447973
6 changed files with 139 additions and 93 deletions

View File

@ -85,21 +85,28 @@ namespace {
//static field
std::vector<ProgramState::AutoBindingResolver*> ProgramState::_customAutoBindingResolvers;
TextureInfo::TextureInfo(const std::vector<uint32_t>& _slots, const std::vector<backend::TextureBackend*> _textures)
: slot(_slots)
, textures(_textures)
TextureInfo::TextureInfo(std::vector<uint16_t>&& _slots, std::vector<backend::TextureBackend*>&& _textures)
: TextureInfo(std::move(_slots), std::vector<uint16_t>(_slots.size(), 0), std::move(_textures))
{
}
TextureInfo::TextureInfo(std::vector<uint16_t>&& _slots, std::vector<uint16_t>&& _indexs, std::vector<backend::TextureBackend*>&& _textures)
: slots(std::move(_slots)),
indexs(std::move(_indexs)),
textures(std::move(_textures))
{
retainTextures();
}
/* CLASS TextureInfo */
TextureInfo::TextureInfo(const TextureInfo &other)
: slot(other.slot)
, textures(other.textures)
#if CC_ENABLE_CACHE_TEXTURE_DATA
, location(other.location)
#endif
{
retainTextures();
this->assign(other);
}
TextureInfo::TextureInfo(TextureInfo&& other)
{
this->assign(std::move(other));
}
TextureInfo::~TextureInfo()
@ -119,42 +126,51 @@ void TextureInfo::releaseTextures()
CC_SAFE_RELEASE(texture);
}
TextureInfo& TextureInfo::operator=(TextureInfo&& rhs)
TextureInfo& TextureInfo::operator=(const TextureInfo& other) noexcept
{
if (this != &rhs)
{
slot = rhs.slot;
rhs.retainTextures();
releaseTextures();
textures = rhs.textures;
//release the textures before cleaning the vertor
rhs.releaseTextures();
rhs.textures.clear();
#if CC_ENABLE_CACHE_TEXTURE_DATA
location = rhs.location;
#endif
}
this->assign(other);
return *this;
}
TextureInfo& TextureInfo::operator=(const TextureInfo& rhs)
TextureInfo& TextureInfo::operator=(TextureInfo&& other) noexcept
{
if (this != &rhs)
this->assign(std::move(other));
return *this;
}
void TextureInfo::assign(const TextureInfo& other)
{
if (this != &other)
{
slot = rhs.slot;
textures = rhs.textures;
indexs = other.indexs;
slots = other.slots;
textures = other.textures;
retainTextures();
#if CC_ENABLE_CACHE_TEXTURE_DATA
location = rhs.location;
location = other.location;
#endif
}
return *this;
}
void TextureInfo::assign(TextureInfo&& other)
{
if (this != &other)
{
releaseTextures();
indexs = std::move(other.indexs);
slots = std::move(other.slots);
textures = std::move(other.textures);
#if CC_ENABLE_CACHE_TEXTURE_DATA
location = other.location;
other.location = -1;
#endif
}
}
/* CLASS ProgramState */
ProgramState::ProgramState(Program* program)
{
init(program);
@ -383,72 +399,75 @@ void ProgramState::setFragmentUniform(int location, const void* data, std::size_
void ProgramState::setTexture(backend::TextureBackend* texture)
{
for (int index = 0; index < texture->getCount() && index < CC_META_TEXTURES; ++index) {
auto location = getUniformLocation((backend::Uniform)(backend::Uniform::TEXTURE + index));
setTexture(location, index, texture);
for (int slot = 0; slot < texture->getCount() && slot < CC_META_TEXTURES; ++slot) {
auto location = getUniformLocation((backend::Uniform)(backend::Uniform::TEXTURE + slot));
setTexture(location, slot, slot, texture);
}
}
void ProgramState::setTexture(const backend::UniformLocation& uniformLocation, uint32_t slot, backend::TextureBackend* texture)
void ProgramState::setTexture(const backend::UniformLocation& uniformLocation, uint16_t slot, backend::TextureBackend* texture)
{
setTexture(uniformLocation, slot, 0, texture);
}
void ProgramState::setTexture(const backend::UniformLocation& uniformLocation, uint16_t slot, uint16_t index, backend::TextureBackend* texture)
{
switch (uniformLocation.shaderStage)
{
case backend::ShaderStage::VERTEX:
setTexture(uniformLocation.location[0], slot, texture, _vertexTextureInfos);
setTexture(uniformLocation.location[0], slot, index, texture, _vertexTextureInfos);
break;
case backend::ShaderStage::FRAGMENT:
setTexture(uniformLocation.location[1], slot, texture, _fragmentTextureInfos);
setTexture(uniformLocation.location[1], slot, index, texture, _fragmentTextureInfos);
break;
case backend::ShaderStage::VERTEX_AND_FRAGMENT:
setTexture(uniformLocation.location[0], slot, texture, _vertexTextureInfos);
setTexture(uniformLocation.location[1], slot, texture, _fragmentTextureInfos);
setTexture(uniformLocation.location[0], slot, index, texture, _vertexTextureInfos);
setTexture(uniformLocation.location[1], slot, index, texture, _fragmentTextureInfos);
break;
default:
break;
}
}
void ProgramState::setTextureArray(const backend::UniformLocation& uniformLocation, const std::vector<uint32_t>& slots, const std::vector<backend::TextureBackend*> textures)
void ProgramState::setTextureArray(const backend::UniformLocation& uniformLocation, std::vector<uint16_t> slots, std::vector<backend::TextureBackend*> textures)
{
switch (uniformLocation.shaderStage)
{
case backend::ShaderStage::VERTEX:
setTextureArray(uniformLocation.location[0], slots, textures, _vertexTextureInfos);
setTextureArray(uniformLocation.location[0], std::move(slots), std::move(textures), _vertexTextureInfos);
break;
case backend::ShaderStage::FRAGMENT:
setTextureArray(uniformLocation.location[1], slots, textures, _fragmentTextureInfos);
setTextureArray(uniformLocation.location[1], std::move(slots), std::move(textures), _fragmentTextureInfos);
break;
case backend::ShaderStage::VERTEX_AND_FRAGMENT:
setTextureArray(uniformLocation.location[0], slots, textures, _vertexTextureInfos);
setTextureArray(uniformLocation.location[1], slots, textures, _fragmentTextureInfos);
setTextureArray(uniformLocation.location[0], std::move(slots), std::move(textures), _vertexTextureInfos);
setTextureArray(uniformLocation.location[1], std::move(slots), std::move(textures), _fragmentTextureInfos);
break;
default:
break;
}
}
void ProgramState::setTexture(int location, uint32_t slot, backend::TextureBackend* texture, std::unordered_map<int, TextureInfo>& textureInfo)
void ProgramState::setTexture(int location, uint16_t slot, uint16_t index, backend::TextureBackend* texture, std::unordered_map<int, TextureInfo>& textureInfo)
{
if(location < 0)
return;
TextureInfo& info = textureInfo[location];
info.releaseTextures();
info.slot = {slot};
info.textures = {texture};
info.retainTextures();
auto& info = textureInfo[location];
info = { {slot}, {index}, {texture} };
#if CC_ENABLE_CACHE_TEXTURE_DATA
info.location = location;
#endif
}
void ProgramState::setTextureArray(int location, const std::vector<uint32_t>& slots, const std::vector<backend::TextureBackend*> textures, std::unordered_map<int, TextureInfo>& textureInfo)
void ProgramState::setTextureArray(int location, std::vector<uint16_t> slots, std::vector<backend::TextureBackend*> textures, std::unordered_map<int, TextureInfo>& textureInfo)
{
assert(slots.size() == textures.size());
TextureInfo& info = textureInfo[location];
info.releaseTextures();
info.slot = slots;
info.textures = textures;
info.retainTextures();
auto& info = textureInfo[location];
info = { std::move(slots), std::move(textures) };
#if CC_ENABLE_CACHE_TEXTURE_DATA
info.location = location;
#endif

View File

@ -51,17 +51,26 @@ class VertexLayout;
*/
struct TextureInfo
{
TextureInfo(const std::vector<uint32_t>& _slots, const std::vector<backend::TextureBackend*> _textures);
// TextureInfo(const std::vector<uint32_t>& _slots, const std::vector<backend::TextureBackend*> _textures);
TextureInfo(std::vector<uint16_t>&& _slots, std::vector<backend::TextureBackend*>&& _textures);
TextureInfo(std::vector<uint16_t>&& _slots, std::vector<uint16_t>&& _indexs, std::vector<backend::TextureBackend*>&& _textures);
TextureInfo() = default;
TextureInfo(const TextureInfo &);
TextureInfo(const TextureInfo&);
TextureInfo(TextureInfo&& rhs);
~TextureInfo();
TextureInfo& operator=(TextureInfo&& rhs);
TextureInfo& operator=(const TextureInfo& rhs);
TextureInfo& operator=(const TextureInfo& other) noexcept;
TextureInfo& operator=(TextureInfo&& other) noexcept;
void assign(const TextureInfo& other);
void assign(TextureInfo&& other);
void retainTextures();
void releaseTextures();
std::vector<uint32_t> slot;
std::vector<uint16_t> slots;
std::vector<uint16_t> indexs;
std::vector<backend::TextureBackend*> textures;
#if CC_ENABLE_CACHE_TEXTURE_DATA
int location = -1;
@ -145,7 +154,6 @@ public:
/**
* Set texture.
* @param uniformLocation Specifies texture location.
* @param slot Specifies texture slot selector.
* @param texture Specifies a pointer to backend texture.
*/
void setTexture(backend::TextureBackend* texture);
@ -156,7 +164,16 @@ public:
* @param slot Specifies texture slot selector.
* @param texture Specifies a pointer to backend texture.
*/
void setTexture(const backend::UniformLocation& uniformLocation, uint32_t slot, backend::TextureBackend* texture);
void setTexture(const backend::UniformLocation& uniformLocation, uint16_t slot, backend::TextureBackend* texture);
/**
* Set texture.
* @param uniformLocation Specifies texture location.
* @param slot Specifies texture slot selector.
* @param index Specifies texture index selector
* @param texture Specifies a pointer to backend texture.
*/
void setTexture(const backend::UniformLocation& uniformLocation, uint16_t slot, uint16_t index, backend::TextureBackend* texture);
/**
* Set textures in array.
@ -164,7 +181,7 @@ public:
* @param slots Specifies texture slot selector.
* @param textures Specifies a vector of backend texture object.
*/
void setTextureArray(const backend::UniformLocation& uniformLocation, const std::vector<uint32_t>& slots, const std::vector<backend::TextureBackend*> textures);
void setTextureArray(const backend::UniformLocation& uniformLocation, std::vector<uint16_t> slots, std::vector<backend::TextureBackend*> textures);
/**
* Get vertex texture informations
@ -288,7 +305,7 @@ protected:
* @param texture Specifies the texture to set in given location.
* @param textureInfo Specifies the texture information to update.
*/
void setTexture(int location, uint32_t slot, backend::TextureBackend* texture, std::unordered_map<int, TextureInfo>& textureInfo);
void setTexture(int location, uint16_t slot, uint16_t index, backend::TextureBackend* texture, std::unordered_map<int, TextureInfo>& textureInfo);
/**
* Set textures in array.
@ -297,7 +314,7 @@ protected:
* @param textures Specifies the texture to set in given location.
* @param textureInfo Specifies the texture information to update.
*/
void setTextureArray(int location, const std::vector<uint32_t>& slots, const std::vector<backend::TextureBackend*> textures, std::unordered_map<int, TextureInfo>& textureInfo);
void setTextureArray(int location, std::vector<uint16_t> slots, std::vector<backend::TextureBackend*> textures, std::unordered_map<int, TextureInfo>& textureInfo);
/**
* Reset uniform informations when EGL context lost

View File

@ -423,22 +423,24 @@ void CommandBufferMTL::doSetTextures(bool isVertex) const
for(const auto& iter : bindTextureInfos)
{
auto location = iter.first;
const auto& textures = iter.second.textures;
const auto& slot = iter.second.slot;
auto& textures = iter.second.textures;
// auto& slots = iter.second.slots;
// TODO: 1 location, mutli-slots like OpenGL?
auto& indexs = iter.second.indexs;
int i = 0;
for (const auto& texture : textures)
{
if (isVertex)
{
[_mtlRenderEncoder setVertexTexture:getMTLTexture(texture, slot[i])
[_mtlRenderEncoder setVertexTexture:getMTLTexture(texture, indexs[i])
atIndex:location];
[_mtlRenderEncoder setVertexSamplerState:getMTLSamplerState(texture)
atIndex:location];
}
else
{
[_mtlRenderEncoder setFragmentTexture:getMTLTexture(texture, slot[i])
[_mtlRenderEncoder setFragmentTexture:getMTLTexture(texture, indexs[i])
atIndex:location];
[_mtlRenderEncoder setFragmentSamplerState:getMTLSamplerState(texture)
atIndex:location];

View File

@ -54,15 +54,15 @@ namespace
}
}
void applyTexture(TextureBackend* texture, int index)
void applyTexture(TextureBackend* texture, int slot, int index)
{
switch (texture->getTextureType())
{
case TextureType::TEXTURE_2D:
static_cast<Texture2DGL*>(texture)->apply(index);
static_cast<Texture2DGL*>(texture)->apply(slot, index);
break;
case TextureType::TEXTURE_CUBE:
static_cast<TextureCubeGL*>(texture)->apply(index);
static_cast<TextureCubeGL*>(texture)->apply(slot, index);
break;
default:
assert(false);
@ -478,8 +478,9 @@ void CommandBufferGL::setUniforms(ProgramGL* program) const
const auto& textureInfo = _programState->getVertexTextureInfos();
for(const auto& iter : textureInfo)
{
const auto& textures = iter.second.textures;
const auto& slot = iter.second.slot;
auto& textures = iter.second.textures;
auto& slots = iter.second.slots;
auto& indexs = iter.second.indexs;
auto location = iter.first;
#if CC_ENABLE_CACHE_TEXTURE_DATA
location = iter.second.location;
@ -487,14 +488,15 @@ void CommandBufferGL::setUniforms(ProgramGL* program) const
int i = 0;
for (const auto& texture: textures)
{
applyTexture(texture, slot[i++]);
applyTexture(texture, slots[i], indexs[i]);
++i;
}
auto arrayCount = slot.size();
auto arrayCount = slots.size();
if (arrayCount > 1)
glUniform1iv(location, (uint32_t)arrayCount, (GLint*)slot.data());
glUniform1iv(location, (uint32_t)arrayCount, (GLint*)slots.data());
else
glUniform1i(location, slot[0]);
glUniform1i(location, slots[0]);
}
}
}

View File

@ -77,7 +77,7 @@ void TextureInfoGL::applySampler(const SamplerDescriptor& descriptor, bool isPow
// apply sampler for all internal textures
foreach([=](GLuint texID, int index) {
apply(index, target);
glBindTexture(target, textures[index]);
setCurrentTexParameters(target);
@ -93,16 +93,16 @@ void TextureInfoGL::setCurrentTexParameters(GLenum target)
glTexParameteri(target, GL_TEXTURE_WRAP_T, tAddressModeGL);
}
void TextureInfoGL::apply(int index, GLenum target) const
void TextureInfoGL::apply(int slot, int index, GLenum target) const
{
glActiveTexture(GL_TEXTURE0 + index);
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(target, index < CC_META_TEXTURES ? textures[index] : textures[0]);
}
GLuint TextureInfoGL::ensure(int index, GLenum target)
{
if (index >= CC_META_TEXTURES) return 0;
glActiveTexture(GL_TEXTURE0 + index);
// glActiveTexture(GL_TEXTURE0 + index);
auto& texID = this->textures[index];
if (!texID)
glGenTextures(1, &texID);
@ -186,7 +186,7 @@ void Texture2DGL::updateSamplerDescriptor(const SamplerDescriptor &sampler) {
void Texture2DGL::updateData(uint8_t* data, std::size_t width , std::size_t height, std::size_t level, int index)
{
if (!_textureInfo.ensure(index)) return;
if (!_textureInfo.ensure(index, GL_TEXTURE_2D)) return;
//Set the row align only when mipmapsNum == 1 and the data is uncompressed
auto mipmapEnalbed = isMipmapEnabled(_textureInfo.minFilterGL) || isMipmapEnabled(_textureInfo.magFilterGL);
@ -235,7 +235,7 @@ void Texture2DGL::updateData(uint8_t* data, std::size_t width , std::size_t heig
void Texture2DGL::updateCompressedData(uint8_t *data, std::size_t width, std::size_t height,
std::size_t dataLen, std::size_t level, int index)
{
if (!_textureInfo.ensure(index)) return;
if (!_textureInfo.ensure(index, GL_TEXTURE_2D)) return;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
@ -255,7 +255,7 @@ void Texture2DGL::updateCompressedData(uint8_t *data, std::size_t width, std::si
void Texture2DGL::updateSubData(std::size_t xoffset, std::size_t yoffset, std::size_t width, std::size_t height, std::size_t level, uint8_t* data, int index)
{
if (!_textureInfo.ensure(index)) return;
if (!_textureInfo.ensure(index, GL_TEXTURE_2D)) return;
glTexSubImage2D(GL_TEXTURE_2D,
level,
@ -276,7 +276,7 @@ void Texture2DGL::updateCompressedSubData(std::size_t xoffset, std::size_t yoffs
std::size_t height, std::size_t dataLen, std::size_t level,
uint8_t *data, int index)
{
if (!_textureInfo.ensure(index)) return;
if (!_textureInfo.ensure(index, GL_TEXTURE_2D)) return;
glCompressedTexSubImage2D(GL_TEXTURE_2D,
level,

View File

@ -54,15 +54,21 @@ struct TextureInfoGL
cb(texID, idx++);
}
GLuint ensure(int index, GLenum target = GL_TEXTURE_2D);
void recreateAll(GLenum target = GL_TEXTURE_2D);
GLuint ensure(int index, GLenum target);
void recreateAll(GLenum target);
void destroy() {
foreach([=](GLuint texID, int) { glDeleteTextures(1, &texID); });
textures.fill(0);
}
void apply(int index, GLenum target = GL_TEXTURE_2D) const;
/// <summary>
/// update shader texture
/// </summary>
/// <param name="slot">the slot in shader</param>
/// <param name="index">the index in meta textrues</param>
/// <param name="target">the target GL_TEXTURE_2D,GL_TEXTURE_CUBE_MAP</param>
void apply(int slot, int index, GLenum target) const;
GLint magFilterGL = GL_LINEAR;
GLint minFilterGL = GL_LINEAR;
@ -173,7 +179,7 @@ public:
* Set texture to pipeline
* @param index Specifies the texture image unit selector.
*/
void apply(int index) const { _textureInfo.apply(index); }
void apply(int slot, int index) const { _textureInfo.apply(slot, index, GL_TEXTURE_2D); }
int getCount() const override { return _textureInfo.maxIdx + 1; }
@ -237,7 +243,7 @@ public:
* Set texture to pipeline
* @param index Specifies the texture image unit selector.
*/
void apply(int index) const { _textureInfo.apply(index, GL_TEXTURE_CUBE_MAP); }
void apply(int slot, int index) const { _textureInfo.apply(slot, index, GL_TEXTURE_CUBE_MAP); }
int getCount() const override { return _textureInfo.maxIdx + 1; }