noggit goes bindless, first test

This commit is contained in:
sshumakov3
2021-08-22 21:45:55 +03:00
parent baab65de22
commit 64ee9c89b0
7 changed files with 238 additions and 8 deletions

View File

@@ -31,10 +31,14 @@ layout (std140) uniform overlay_params
};
uniform sampler2D shadow_map;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D tex2;
uniform sampler2D tex3;
uniform sampler2DArray tex0;
uniform sampler2DArray tex1;
uniform sampler2DArray tex2;
uniform sampler2DArray tex3;
uniform int tex_temp_0;
uniform int tex_temp_1;
uniform int tex_temp_2;
uniform int tex_temp_3;
uniform sampler2D stampBrush;
uniform vec2 tex_anim_0;
uniform vec2 tex_anim_1;
@@ -79,10 +83,10 @@ vec4 texture_blend()
float a1 = alpha.g;
float a2 = alpha.b;
vec3 t0 = texture(tex0, vary_texcoord + tex_anim_0).rgb;
vec3 t1 = texture(tex1, vary_texcoord + tex_anim_1).rgb;
vec3 t2 = texture(tex2, vary_texcoord + tex_anim_2).rgb;
vec3 t3 = texture(tex3, vary_texcoord + tex_anim_3).rgb;
vec3 t0 = texture(tex0, vec3(vary_texcoord + tex_anim_0, tex_temp_0)).rgb;
vec3 t1 = texture(tex1, vec3(vary_texcoord + tex_anim_1, tex_temp_1)).rgb;
vec3 t2 = texture(tex2, vec3(vary_texcoord + tex_anim_2, tex_temp_2)).rgb;
vec3 t3 = texture(tex3, vec3(vary_texcoord + tex_anim_3, tex_temp_3)).rgb;
return mix(vec4 (1.0, 1.0, 1.0, 1.0), vec4 (t0 * (1.0 - (a0 + a1 + a2)) + t1 * a0 + t2 * a1 + t3 * a2, 1.0), int(layer_count > 0));
}

View File

@@ -652,6 +652,7 @@ void MapChunk::draw ( math::frustum const& frustum
for (int i = 0; i < texture_set->num(); ++i)
{
texture_set->bindTexture(i, i + 1, textures_bound);
mcnk_shader.uniform("tex_temp_" + std::to_string(i), (*texture_set->getTextures())[i]->array_index());
if (texture_set->is_animated(i))
{

View File

@@ -10,6 +10,7 @@
#include <algorithm>
decltype (TextureManager::_) TextureManager::_;
decltype (TextureManager::_tex_arrays) TextureManager::_tex_arrays;
void TextureManager::report()
{
@@ -33,6 +34,95 @@ void TextureManager::unload_all(noggit::NoggitRenderContext context)
);
}
TexArrayParams& TextureManager::get_tex_array(int width, int height, int mip_level,
noggit::NoggitRenderContext context)
{
TexArrayParams& array_params = _tex_arrays[context][std::make_tuple(-1, width, height, mip_level)];
GLint n_layers = 0;
gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &n_layers);
int index_x = array_params.n_used / n_layers;
if (array_params.arrays.size() <= index_x)
{
GLuint array;
gl.genTextures(1, &array);
gl.bindTexture(GL_TEXTURE_2D_ARRAY, array);
array_params.arrays.emplace_back(array);
GLint n_layers = 0;
gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &n_layers);
int width_ = width;
int height_ = height;
for (int i = 0; i < mip_level; ++i)
{
gl.texImage3D(GL_TEXTURE_2D_ARRAY, i, GL_RGBA8, width_, height_, n_layers, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
width_ = std::max(width_ >> 1, 1);
height_ = std::max(height_ >> 1, 1);
}
gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, mip_level - 1);
gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
gl.bindTexture(GL_TEXTURE_2D_ARRAY, array_params.arrays[index_x]);
}
return array_params;
}
TexArrayParams& TextureManager::get_tex_array(GLint compression, int width, int height, int mip_level,
std::map<int, std::vector<uint8_t>>& comp_data, noggit::NoggitRenderContext context)
{
TexArrayParams& array_params = _tex_arrays[context][std::make_tuple(compression, width, height, mip_level)];
GLint n_layers = 0;
gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &n_layers);
int index_x = array_params.n_used / n_layers;
if (array_params.arrays.size() <= index_x)
{
GLuint array;
gl.genTextures(1, &array);
gl.bindTexture(GL_TEXTURE_2D_ARRAY, array);
array_params.arrays.emplace_back(array);
int width_ = width;
int height_ = height;
for (int i = 0; i < mip_level; ++i)
{
gl.compressedTexImage3D(GL_TEXTURE_2D_ARRAY, i, compression, width_, height_, n_layers, 0, comp_data[i].size() * n_layers, nullptr);
width_ = std::max(width_ >> 1, 1);
height_ = std::max(height_ >> 1, 1);
}
gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, mip_level - 1);
gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
gl.bindTexture(GL_TEXTURE_2D_ARRAY, array_params.arrays[index_x]);
}
return array_params;
}
#include <cstdint>
//! \todo Cross-platform syntax for packed structs.
#pragma pack(push,1)
@@ -67,6 +157,8 @@ void blp_texture::bind()
{
upload();
}
gl.bindTexture(GL_TEXTURE_2D_ARRAY, _texture_array);
}
void blp_texture::upload()
@@ -78,28 +170,57 @@ void blp_texture::upload()
int width = _width, height = _height;
GLint n_layers;
gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &n_layers);
if (!_compression_format)
{
auto& params = TextureManager::get_tex_array( _width, _height, _data.size(), _context);
int index_x = params.n_used / n_layers;
int index_y = params.n_used % n_layers;
_texture_array = params.arrays[index_x];
_array_index = index_y;
for (int i = 0; i < _data.size(); ++i)
{
gl.texImage2D(GL_TEXTURE_2D, i, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, _data[i].data());
gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, i, 0, 0, index_y, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, _data[i].data());
width = std::max(width >> 1, 1);
height = std::max(height >> 1, 1);
}
params.n_used++;
//LogDebug << "Mip level: " << std::to_string(_data.size()) << std::endl;
_data.clear();
}
else
{
auto& params = TextureManager::get_tex_array(_compression_format.get(), _width, _height, _compressed_data.size(), _compressed_data, _context);
int index_x = params.n_used / n_layers;
int index_y = params.n_used % n_layers;
_texture_array = params.arrays[index_x];
_array_index = index_y;
for (int i = 0; i < _compressed_data.size(); ++i)
{
gl.compressedTexImage2D(GL_TEXTURE_2D, i, _compression_format.get(), width, height, 0, _compressed_data[i].size(), _compressed_data[i].data());
gl.compressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, i, 0, 0, index_y, width, height, 1, _compression_format.get(), _compressed_data[i].size(), _compressed_data[i].data());
width = std::max(width >> 1, 1);
height = std::max(height >> 1, 1);
}
params.n_used++;
//LogDebug << "Mip level (compressed): " << std::to_string(_compressed_data.size()) << std::endl;
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, _compressed_data.size() - 1);
_compressed_data.clear();
}

View File

@@ -18,10 +18,27 @@
#include <boost/optional.hpp>
#include <map>
#include <unordered_map>
#include <string>
#include <vector>
#include <array>
#include <tuple>
struct tuple_hash
{
template <class T1, class T2, class T3, class T4>
std::size_t operator() (const std::tuple<T1,T2,T3, T4> &p) const
{
auto h1 = std::hash<T1>{}(std::get<0>(p));
auto h2 = std::hash<T2>{}(std::get<1>(p));
auto h3 = std::hash<T3>{}(std::get<2>(p));
auto h4 = std::hash<T4>{}(std::get<3>(p));
return h1 ^ h2 ^ h3 ^ h4; // use hash combine here
}
};
struct BLPHeader;
struct scoped_blp_texture_reference;
@@ -41,6 +58,8 @@ struct blp_texture : public opengl::texture, AsyncObject
void bind();
void upload();
void unload();
GLuint texture_array() { return _texture_array; };
int array_index() { return _array_index; };
noggit::NoggitRenderContext getContext() { return _context; };
@@ -61,6 +80,14 @@ private:
std::map<int, std::vector<uint32_t>> _data;
std::map<int, std::vector<uint8_t>> _compressed_data;
boost::optional<GLint> _compression_format;
int _array_index = -1;
GLuint _texture_array = 0;
};
struct TexArrayParams
{
std::vector<GLuint> arrays;
int n_used = 0;
};
class TextureManager
@@ -68,10 +95,14 @@ class TextureManager
public:
static void report();
static void unload_all(noggit::NoggitRenderContext context);
static TexArrayParams& get_tex_array(int width, int height, int mip_level, noggit::NoggitRenderContext context);
static TexArrayParams& get_tex_array(GLint compression, int width, int height, int mip_level, std::map<int, std::vector<uint8_t>>& comp_data, noggit::NoggitRenderContext context);
private:
friend struct scoped_blp_texture_reference;
static noggit::async_object_multimap_with_normalized_key<blp_texture> _;
static std::array<std::unordered_map<std::tuple<GLint, int, int, int>, TexArrayParams, tuple_hash>, 7> _tex_arrays;
};
struct scoped_blp_texture_reference

View File

@@ -268,6 +268,7 @@ void TextureSet::bindTexture(size_t id, size_t activeTexture, std::array<int, 4
textures[id]->bind();
textures_bound[id] = textures[id]->id();
}
}
math::vector_2d TextureSet::anim_uv_offset(int id, int animtime) const

View File

@@ -77,7 +77,31 @@ namespace opengl
BOOST_FORCEINLINE void deleteTextures (GLuint, GLuint*);
BOOST_FORCEINLINE void bindTexture (GLenum target, GLuint);
BOOST_FORCEINLINE void texImage2D (GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLvoid const* data);
BOOST_FORCEINLINE void texImage3D (GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLvoid const* data);
BOOST_FORCEINLINE void texSubImage3D (GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint zoffset,
GLsizei width,
GLsizei height,
GLsizei depth,
GLenum format,
GLenum type,
const void * pixels);
BOOST_FORCEINLINE void compressedTexSubImage3D (GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint zoffset,
GLsizei width,
GLsizei height,
GLsizei depth,
GLenum format,
GLsizei imageSize,
const void * data);
BOOST_FORCEINLINE void compressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, GLvoid const* data);
BOOST_FORCEINLINE void compressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, GLvoid const* data);
BOOST_FORCEINLINE void generateMipmap (GLenum);
BOOST_FORCEINLINE void activeTexture (GLenum);

View File

@@ -296,6 +296,47 @@ void opengl::context::texImage2D (GLenum target, GLint level, GLint internal_for
#endif
return _current_context->functions()->glTexImage2D (target, level, internal_format, width, height, border, format, type, data);
}
void opengl::context::texImage3D (GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLvoid const* data)
{
#ifndef NOGGIT_DO_NOT_CHECK_FOR_OPENGL_ERRORS
verify_context_and_check_for_gl_errors const _ (_current_context, BOOST_CURRENT_FUNCTION);
#endif
return _4_1_core_func->glTexImage3D (target, level, internal_format, width, height, depth, border, format, type, data);
}
void opengl::context::texSubImage3D (GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint zoffset,
GLsizei width,
GLsizei height,
GLsizei depth,
GLenum format,
GLenum type,
const void * pixels)
{
#ifndef NOGGIT_DO_NOT_CHECK_FOR_OPENGL_ERRORS
verify_context_and_check_for_gl_errors const _ (_current_context, BOOST_CURRENT_FUNCTION);
#endif
return _4_1_core_func->glTexSubImage3D (target, level, xoffset,yoffset ,zoffset, width, height, depth, format, type, pixels);
}
void opengl::context::compressedTexSubImage3D (GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint zoffset,
GLsizei width,
GLsizei height,
GLsizei depth,
GLenum format,
GLsizei imageSize,
const void * data)
{
#ifndef NOGGIT_DO_NOT_CHECK_FOR_OPENGL_ERRORS
verify_context_and_check_for_gl_errors const _ (_current_context, BOOST_CURRENT_FUNCTION);
#endif
return _4_1_core_func->glCompressedTexSubImage3D (target, level, xoffset,yoffset ,zoffset, width, height, depth, format, imageSize, data);
}
void opengl::context::compressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, GLvoid const* data)
{
#ifndef NOGGIT_DO_NOT_CHECK_FOR_OPENGL_ERRORS
@@ -303,6 +344,13 @@ void opengl::context::compressedTexImage2D (GLenum target, GLint level, GLenum i
#endif
return _current_context->functions()->glCompressedTexImage2D (target, level, internalformat, width, height, border, imageSize, data);
}
void opengl::context::compressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, GLvoid const* data)
{
#ifndef NOGGIT_DO_NOT_CHECK_FOR_OPENGL_ERRORS
verify_context_and_check_for_gl_errors const _ (_current_context, BOOST_CURRENT_FUNCTION);
#endif
return _4_1_core_func->glCompressedTexImage3D (target, level, internalformat, width, height, depth, border, imageSize, data);
}
void opengl::context::generateMipmap (GLenum target)
{
#ifndef NOGGIT_DO_NOT_CHECK_FOR_OPENGL_ERRORS