diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index be877b5db9..d3d151db12 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -1199,6 +1199,9 @@ void MaterialSystem::GenerateDepthImages( const int width, const int height, ima mipmapWidth = mipmapWidth > 1 ? mipmapWidth >> 1 : 1; mipmapHeight = mipmapHeight > 1 ? mipmapHeight >> 1 : 1; } + + depthImage->texture->GenBindlessImageHandle(); + depthImage->texture->MakeImagesResident( GL_READ_WRITE ); } static void BindShaderGeneric( Material* material ) { @@ -1852,7 +1855,11 @@ void MaterialSystem::DepthReduction() { uint32_t globalWorkgroupY = ( height + 7 ) / 8; gl_depthReductionShader->SetUniform_DepthMapBindless( GL_BindToTMU( 0, tr.currentDepthImage ) ); - glBindImageTexture( 2, depthImage->texnum, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32F ); + // glBindImageTexture( 2, depthImage->texnum, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32F ); + // glUniformHandleui64ARB( 1, depthImage->texture->bindlessImageHandles[0] + GL_CheckErrors(); + glUniform2uiv( 1, 1, ( const GLuint* ) &depthImage->texture->bindlessImageHandles[0] ); + GL_CheckErrors(); gl_depthReductionShader->SetUniform_InitialDepthLevel( true ); gl_depthReductionShader->SetUniform_ViewWidth( width ); @@ -1866,8 +1873,15 @@ void MaterialSystem::DepthReduction() { globalWorkgroupX = ( width + 7 ) / 8; globalWorkgroupY = ( height + 7 ) / 8; - glBindImageTexture( 1, depthImage->texnum, i, GL_FALSE, 0, GL_READ_ONLY, GL_R32F ); - glBindImageTexture( 2, depthImage->texnum, i + 1, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32F ); + // glBindImageTexture( 1, depthImage->texnum, i, GL_FALSE, 0, GL_READ_ONLY, GL_R32F ); + // glBindImageTexture( 2, depthImage->texnum, i + 1, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32F ); + // glUniformHandleui64ARB( 0, depthImage->texture->bindlessImageHandles[i] ); + // glUniformHandleui64ARB( 1, depthImage->texture->bindlessImageHandles[i + 1] ); + GL_CheckErrors(); + glUniform2uiv( 0, 1, ( const GLuint* ) &depthImage->texture->bindlessImageHandles[i] ); + GL_CheckErrors(); + glUniform2uiv( 1, 1, ( const GLuint* ) &depthImage->texture->bindlessImageHandles[i + 1] ); + GL_CheckErrors(); gl_depthReductionShader->SetUniform_InitialDepthLevel( false ); gl_depthReductionShader->SetUniform_ViewWidth( width ); @@ -2077,6 +2091,8 @@ void MaterialSystem::Free() { portalSurfacesSSBO.UnmapBuffer(); } + depthImage->texture->MakeImagesNonResident(); + currentFrame = 0; nextFrame = 1; maxStages = 0; diff --git a/src/engine/renderer/TextureManager.cpp b/src/engine/renderer/TextureManager.cpp index 992453aed8..aa0843b472 100644 --- a/src/engine/renderer/TextureManager.cpp +++ b/src/engine/renderer/TextureManager.cpp @@ -48,16 +48,34 @@ bool Texture::IsResident() const { return bindlessTextureResident; } +bool Texture::AreImagesResident() const { + return bindlessImagesResident; +} + void Texture::MakeResident() { glMakeTextureHandleResidentARB( bindlessTextureHandle ); bindlessTextureResident = true; } +void Texture::MakeImagesResident( const GLenum access ) { + for ( uint8_t i = 0; i < mipLevels; i++ ) { + glMakeImageHandleResidentARB( bindlessImageHandles[i], access ); + } + bindlessImagesResident = true; +} + void Texture::MakeNonResident() { glMakeTextureHandleNonResidentARB( bindlessTextureHandle ); bindlessTextureResident = false; } +void Texture::MakeImagesNonResident() { + for ( uint8_t i = 0; i < mipLevels; i++ ) { + glMakeImageHandleNonResidentARB( bindlessImageHandles[i] ); + } + bindlessImagesResident = false; +} + void Texture::GenBindlessHandle() { bindlessTextureHandle = glGetTextureHandleARB( textureHandle ); @@ -68,6 +86,21 @@ void Texture::GenBindlessHandle() { hasBindlessHandle = true; } +void Texture::GenBindlessImageHandle() { + if ( target != GL_TEXTURE_2D ) { + Sys::Drop( "Bindless image handles for layered textures are currently unsupported" ); + } + + for ( uint8_t level = 0; level < mipLevels; level++ ) { + bindlessImageHandles[level] = glGetImageHandleARB( textureHandle, level, GL_FALSE, 0, format ); + if ( bindlessImageHandles[level] == 0 ) { + Sys::Drop( "Failed to generate bindless image handle" ); + } + } + + hasBindlessImageHandles = true; +} + TextureManager::TextureManager() = default; TextureManager::~TextureManager() = default; diff --git a/src/engine/renderer/TextureManager.h b/src/engine/renderer/TextureManager.h index 3c40250ac7..2e3eadb8e9 100644 --- a/src/engine/renderer/TextureManager.h +++ b/src/engine/renderer/TextureManager.h @@ -43,18 +43,28 @@ class Texture { bool hasBindlessHandle = false; GLenum target = GL_TEXTURE_2D; + GLenum format = GL_RGBA8; + + bool hasBindlessImageHandles = false; + uint8_t mipLevels = 0; + GLuint64 bindlessImageHandles[16]; // Enough for all mipmaps of a 32768x32768 texture, which is the current maximum Texture(); ~Texture(); bool IsResident() const; + bool AreImagesResident() const; void MakeResident(); + void MakeImagesResident( const GLenum access ); void MakeNonResident(); + void MakeImagesNonResident(); - void GenBindlessHandle();; + void GenBindlessHandle(); + void GenBindlessImageHandle(); private: bool bindlessTextureResident = false; + bool bindlessImagesResident = false; }; class TextureManager { diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 3d40317416..b22a86caad 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -564,6 +564,7 @@ static std::string GenComputeHeader() { if ( glConfig2.bindlessTexturesAvailable ) { str += "layout(bindless_sampler) uniform;\n"; + str += "layout(bindless_image) uniform;\n"; } return str; diff --git a/src/engine/renderer/glsl_source/cull_cp.glsl b/src/engine/renderer/glsl_source/cull_cp.glsl index ae0230907a..40fae79a7f 100644 --- a/src/engine/renderer/glsl_source/cull_cp.glsl +++ b/src/engine/renderer/glsl_source/cull_cp.glsl @@ -37,7 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Keep this to 64 because we don't want extra shared mem etc. to be allocated, and to minimize wasted lanes layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in; -uniform sampler2D u_DepthMap; +/* layout(binding = 0) */ uniform sampler2D u_DepthMap; struct BoundingSphere { vec3 origin; diff --git a/src/engine/renderer/glsl_source/depthReduction_cp.glsl b/src/engine/renderer/glsl_source/depthReduction_cp.glsl index c50134d028..f9de8a408d 100644 --- a/src/engine/renderer/glsl_source/depthReduction_cp.glsl +++ b/src/engine/renderer/glsl_source/depthReduction_cp.glsl @@ -37,9 +37,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Keep this to 8x8 because we don't want extra shared mem etc. to be allocated, and to minimize wasted lanes layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; -uniform sampler2D u_DepthMap; -layout(r32f, binding = 1) uniform readonly image2D depthImageIn; -layout(r32f, binding = 2) uniform writeonly image2D depthImageOut; +/* layout(binding = 0) */ uniform sampler2D u_DepthMap; +// layout(r32f, binding = 1) uniform readonly image2D depthImageIn; +// layout(r32f, binding = 2) uniform writeonly image2D depthImageOut; + +layout(location = 0) uniform uvec2 depthInTest; +layout(location = 1) uniform uvec2 depthOutTest; uniform uint u_ViewWidth; uniform uint u_ViewHeight; @@ -55,6 +58,9 @@ void main() { return; }; + layout(r32f) image2D depthImageIn = layout(r32f) image2D( depthInTest ); + layout(r32f) image2D depthImageOut = layout(r32f) image2D( depthOutTest ); + // Depth buffer uses a packed D24S8 format, so we have to copy it over to an r32f image first if( u_InitialDepthLevel ) { vec4 depthOut = texelFetch( u_DepthMap, position, 0 ); diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index ffee94b8a7..3207589aec 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -1330,6 +1330,9 @@ void R_UploadImage( const byte **dataArray, int numLayers, int numMips, image_t image->bits |= IF_ALPHA; } + image->texture->format = internalFormat; + image->texture->mipLevels = log2f( std::max( image->uploadWidth, image->uploadHeight ) ) + 1; + GL_Unbind( image ); }