Index: ps/trunk/source/graphics/GameView.cpp =================================================================== --- ps/trunk/source/graphics/GameView.cpp +++ ps/trunk/source/graphics/GameView.cpp @@ -243,7 +243,7 @@ void CGameView::Render() { - g_Renderer.GetSceneRenderer().RenderScene(*this); + g_Renderer.GetSceneRenderer().RenderScene(g_Renderer.GetDeviceCommandContext(), *this); } /////////////////////////////////////////////////////////// Index: ps/trunk/source/graphics/LOSTexture.h =================================================================== --- ps/trunk/source/graphics/LOSTexture.h +++ ps/trunk/source/graphics/LOSTexture.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -22,8 +22,11 @@ #include "graphics/ShaderTechniquePtr.h" #include "maths/Matrix3D.h" +#include "renderer/backend/gl/DeviceCommandContext.h" #include "renderer/backend/gl/Texture.h" +#include + class CLosQuerier; class CSimulation2; @@ -52,10 +55,10 @@ * The texture is in 8-bit ALPHA format. */ Renderer::Backend::GL::CTexture* GetTexture(); - - void InterpolateLOS(); Renderer::Backend::GL::CTexture* GetTextureSmooth(); + void InterpolateLOS(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext); + /** * Returns a matrix to map (x,y,z) world coordinates onto (u,v) LOS texture * coordinates, in the form expected by a matrix uniform. @@ -68,13 +71,13 @@ * coordinates, in the form expected by a matrix uniform. * This must only be called after BindTexture. */ - const CMatrix3D* GetMinimapTextureMatrix(); + const CMatrix3D& GetMinimapTextureMatrix(); private: void DeleteTexture(); bool CreateShader(); - void ConstructTexture(); - void RecomputeTexture(); + void ConstructTexture(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext); + void RecomputeTexture(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext); size_t GetBitmapSize(size_t w, size_t h, size_t* pitch); void GenerateBitmap(const CLosQuerier& los, u8* losData, size_t w, size_t h, size_t pitch); @@ -88,13 +91,12 @@ std::unique_ptr m_Texture, m_TextureSmooth1, m_TextureSmooth2; - bool whichTex; + bool m_WhichTex; GLuint m_smoothFbo; CShaderTechniquePtr m_smoothShader; size_t m_MapSize; // vertexes per side - GLsizei m_TextureSize; // texels per side CMatrix3D m_TextureMatrix; CMatrix3D m_MinimapTextureMatrix; Index: ps/trunk/source/graphics/LOSTexture.cpp =================================================================== --- ps/trunk/source/graphics/LOSTexture.cpp +++ ps/trunk/source/graphics/LOSTexture.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -53,7 +53,7 @@ // Keep it in relation to the number of impassable tiles in MAP_EDGE_TILES. static const size_t g_BlurSize = 7; -// Alignment (in bytes) of the pixel data passed into glTexSubImage2D. +// Alignment (in bytes) of the pixel data passed into texture uploading. // This must be a multiple of GL_UNPACK_ALIGNMENT, which ought to be 1 (since // that's what we set it to) but in some weird cases appears to have a different // value. (See Trac #2594). Multiples of 4 are possibly good for performance anyway. @@ -61,7 +61,7 @@ CLOSTexture::CLOSTexture(CSimulation2& simulation) : m_Simulation(simulation), m_Dirty(true), m_ShaderInitialized(false), - m_smoothFbo(0), m_MapSize(0), m_TextureSize(0), whichTex(true) + m_smoothFbo(0), m_MapSize(0), m_WhichTex(true) { if (CRenderer::IsInitialised() && g_RenderingOptions.GetSmoothLOS()) CreateShader(); @@ -112,35 +112,36 @@ if (CRenderer::IsInitialised() && !g_RenderingOptions.GetSmoothLOS()) return GetTexture(); else - return (whichTex ? m_TextureSmooth1 : m_TextureSmooth2).get(); + return (m_WhichTex ? m_TextureSmooth1 : m_TextureSmooth2).get(); } -void CLOSTexture::InterpolateLOS() +void CLOSTexture::InterpolateLOS(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) { - if (CRenderer::IsInitialised() && !g_RenderingOptions.GetSmoothLOS()) - return; - - if (!m_ShaderInitialized) + const bool skipSmoothLOS = CRenderer::IsInitialised() && !g_RenderingOptions.GetSmoothLOS(); + if (!skipSmoothLOS && !m_ShaderInitialized) { if (!CreateShader()) return; - // RecomputeTexture(0) will not cause the ConstructTexture to run. + // RecomputeTexture will not cause the ConstructTexture to run. // Force the textures to be created. DeleteTexture(); - ConstructTexture(); + ConstructTexture(deviceCommandContext); m_Dirty = true; } if (m_Dirty) { - RecomputeTexture(); + RecomputeTexture(deviceCommandContext); m_Dirty = false; } + if (skipSmoothLOS) + return; + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_smoothFbo); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, - (whichTex ? m_TextureSmooth2 : m_TextureSmooth1)->GetHandle(), 0); + (m_WhichTex ? m_TextureSmooth2 : m_TextureSmooth1)->GetHandle(), 0); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) @@ -156,15 +157,21 @@ shader->Bind(); shader->BindTexture(str_losTex1, m_Texture.get()); - shader->BindTexture(str_losTex2, (whichTex ? m_TextureSmooth1 : m_TextureSmooth2).get()); + shader->BindTexture(str_losTex2, (m_WhichTex ? m_TextureSmooth1 : m_TextureSmooth2).get()); shader->Uniform(str_delta, (float)g_Renderer.GetTimeManager().GetFrameDelta() * 4.0f, 0.0f, 0.0f, 0.0f); const SViewPort oldVp = g_Renderer.GetViewport(); - const SViewPort vp = { 0, 0, m_TextureSize, m_TextureSize }; + const SViewPort vp = + { + 0, 0, + static_cast(m_Texture->GetWidth()), + static_cast(m_Texture->GetHeight()) + }; g_Renderer.SetViewport(vp); - float quadVerts[] = { + float quadVerts[] = + { 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, @@ -173,7 +180,8 @@ 1.0f, -1.0f, 1.0f, 1.0f }; - float quadTex[] = { + float quadTex[] = + { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, @@ -196,18 +204,13 @@ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - whichTex = !whichTex; + m_WhichTex = !m_WhichTex; } Renderer::Backend::GL::CTexture* CLOSTexture::GetTexture() { - if (m_Dirty) - { - RecomputeTexture(); - m_Dirty = false; - } - + ENSURE(!m_Dirty); return m_Texture.get(); } @@ -217,13 +220,13 @@ return m_TextureMatrix; } -const CMatrix3D* CLOSTexture::GetMinimapTextureMatrix() +const CMatrix3D& CLOSTexture::GetMinimapTextureMatrix() { ENSURE(!m_Dirty); - return &m_MinimapTextureMatrix; + return m_MinimapTextureMatrix; } -void CLOSTexture::ConstructTexture() +void CLOSTexture::ConstructTexture(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) { CmpPtr cmpRangeManager(m_Simulation, SYSTEM_ENTITY); if (!cmpRangeManager) @@ -231,7 +234,7 @@ m_MapSize = cmpRangeManager->GetVerticesPerSide(); - m_TextureSize = (GLsizei)round_up_to_pow2(round_up((size_t)m_MapSize + g_BlurSize - 1, g_SubTextureAlignment)); + const size_t textureSize = round_up_to_pow2(round_up((size_t)m_MapSize + g_BlurSize - 1, g_SubTextureAlignment)); const Renderer::Backend::Sampler::Desc defaultSamplerDesc = Renderer::Backend::Sampler::MakeDefaultSampler( @@ -239,31 +242,27 @@ Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE); m_Texture = Renderer::Backend::GL::CTexture::Create2D( - Renderer::Backend::Format::A8, m_TextureSize, m_TextureSize, defaultSamplerDesc); + Renderer::Backend::Format::A8, textureSize, textureSize, defaultSamplerDesc); // Initialise texture with SoD color, for the areas we don't - // overwrite with glTexSubImage2D later - u8* texData = new u8[m_TextureSize * m_TextureSize * 4]; - memset(texData, 0x00, m_TextureSize * m_TextureSize * 4); + // overwrite with uploading later. + std::unique_ptr texData = std::make_unique(textureSize * textureSize); + memset(texData.get(), 0x00, textureSize * textureSize); if (CRenderer::IsInitialised() && g_RenderingOptions.GetSmoothLOS()) { m_TextureSmooth1 = Renderer::Backend::GL::CTexture::Create2D( - Renderer::Backend::Format::R8G8B8A8, m_TextureSize, m_TextureSize, defaultSamplerDesc); + Renderer::Backend::Format::A8, textureSize, textureSize, defaultSamplerDesc); m_TextureSmooth2 = Renderer::Backend::GL::CTexture::Create2D( - Renderer::Backend::Format::R8G8B8A8, m_TextureSize, m_TextureSize, defaultSamplerDesc); - - g_Renderer.BindTexture(0, m_TextureSmooth1->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texData); + Renderer::Backend::Format::A8, textureSize, textureSize, defaultSamplerDesc); - g_Renderer.BindTexture(0, m_TextureSmooth2->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texData); + deviceCommandContext->UploadTexture(m_TextureSmooth1.get(), Renderer::Backend::Format::A8, texData.get(), textureSize * textureSize); + deviceCommandContext->UploadTexture(m_TextureSmooth2.get(), Renderer::Backend::Format::A8, texData.get(), textureSize * textureSize); } - g_Renderer.BindTexture(0, m_Texture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texData); + deviceCommandContext->UploadTexture(m_Texture.get(), Renderer::Backend::Format::A8, texData.get(), textureSize * textureSize); - delete[] texData; + texData.reset(); { // Texture matrix: We want to map @@ -272,8 +271,8 @@ // world pos ((mapsize-1)*cellsize, y, (mapsize-1)*cellsize) (i.e. last vertex) // onto texcoord ((mapsize-0.5) / texsize, (mapsize-0.5) / texsize) (i.e. middle of last texel) - float s = (m_MapSize-1) / (float)(m_TextureSize * (m_MapSize-1) * LOS_TILE_SIZE); - float t = 0.5f / m_TextureSize; + float s = (m_MapSize-1) / static_cast(textureSize * (m_MapSize-1) * LOS_TILE_SIZE); + float t = 0.5f / textureSize; m_TextureMatrix.SetZero(); m_TextureMatrix._11 = s; m_TextureMatrix._23 = s; @@ -285,7 +284,7 @@ { // Minimap matrix: We want to map UV (0,0)-(1,1) onto (0,0)-(mapsize/texsize, mapsize/texsize) - float s = m_MapSize / (float)m_TextureSize; + float s = m_MapSize / (float)textureSize; m_MinimapTextureMatrix.SetZero(); m_MinimapTextureMatrix._11 = s; m_MinimapTextureMatrix._22 = s; @@ -293,7 +292,7 @@ } } -void CLOSTexture::RecomputeTexture() +void CLOSTexture::RecomputeTexture(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) { // If the map was resized, delete and regenerate the texture if (m_Texture) @@ -306,15 +305,16 @@ bool recreated = false; if (!m_Texture) { - ConstructTexture(); + ConstructTexture(deviceCommandContext); recreated = true; } PROFILE("recompute LOS texture"); - std::vector losData; size_t pitch; - losData.resize(GetBitmapSize(m_MapSize, m_MapSize, &pitch)); + const size_t dataSize = GetBitmapSize(m_MapSize, m_MapSize, &pitch); + ENSURE(pitch * m_MapSize <= dataSize); + std::unique_ptr losData = std::make_unique(dataSize); CmpPtr cmpRangeManager(m_Simulation, SYSTEM_ENTITY); if (!cmpRangeManager) @@ -326,14 +326,17 @@ if (CRenderer::IsInitialised() && g_RenderingOptions.GetSmoothLOS() && recreated) { - g_Renderer.BindTexture(0, m_TextureSmooth1->GetHandle()); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pitch, m_MapSize, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]); - g_Renderer.BindTexture(0, m_TextureSmooth2->GetHandle()); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pitch, m_MapSize, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]); + deviceCommandContext->UploadTextureRegion( + m_TextureSmooth1.get(), Renderer::Backend::Format::A8, losData.get(), + pitch * m_MapSize, 0, 0, pitch, m_MapSize); + deviceCommandContext->UploadTextureRegion( + m_TextureSmooth2.get(), Renderer::Backend::Format::A8, losData.get(), + pitch * m_MapSize, 0, 0, pitch, m_MapSize); } - g_Renderer.BindTexture(0, m_Texture->GetHandle()); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pitch, m_MapSize, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]); + deviceCommandContext->UploadTextureRegion( + m_Texture.get(), Renderer::Backend::Format::A8, losData.get(), + pitch * m_MapSize, 0, 0, pitch, m_MapSize); } size_t CLOSTexture::GetBitmapSize(size_t w, size_t h, size_t* pitch) Index: ps/trunk/source/graphics/MiniMapTexture.h =================================================================== --- ps/trunk/source/graphics/MiniMapTexture.h +++ ps/trunk/source/graphics/MiniMapTexture.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -19,9 +19,12 @@ #define INCLUDED_MINIMAPTEXTURE #include "lib/ogl.h" +#include "renderer/backend/gl/DeviceCommandContext.h" #include "renderer/backend/gl/Texture.h" #include "renderer/VertexArray.h" +#include + class CSimulation2; class CTerrain; @@ -40,7 +43,7 @@ /** * Redraws the texture if it's dirty. */ - void Render(); + void Render(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext); Renderer::Backend::GL::CTexture* GetTexture() const { return m_FinalTexture.get(); } @@ -50,9 +53,13 @@ static float GetShallowPassageHeight(); private: - void CreateTextures(const CTerrain* terrain); + void CreateTextures( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, + const CTerrain* terrain); void DestroyTextures(); - void RebuildTerrainTexture(const CTerrain* terrain); + void RebuildTerrainTexture( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, + const CTerrain* terrain); void RenderFinalTexture(); CSimulation2& m_Simulation; @@ -68,14 +75,11 @@ GLuint m_FinalTextureFBO = 0; // texture data - u32* m_TerrainData = nullptr; + std::unique_ptr m_TerrainData; // map size ssize_t m_MapSize = 0; - // texture size - GLsizei m_TextureSize = 0; - // Maximal water height to allow the passage of a unit (for underwater shallows). float m_ShallowPassageHeight = 0.0f; float m_WaterHeight = 0.0f; Index: ps/trunk/source/graphics/MiniMapTexture.cpp =================================================================== --- ps/trunk/source/graphics/MiniMapTexture.cpp +++ ps/trunk/source/graphics/MiniMapTexture.cpp @@ -188,27 +188,28 @@ } } -void CMiniMapTexture::Render() +void CMiniMapTexture::Render(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) { const CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); if (!terrain) return; if (!m_TerrainTexture) - CreateTextures(terrain); + CreateTextures(deviceCommandContext, terrain); if (m_TerrainTextureDirty) - RebuildTerrainTexture(terrain); + RebuildTerrainTexture(deviceCommandContext, terrain); RenderFinalTexture(); } -void CMiniMapTexture::CreateTextures(const CTerrain* terrain) +void CMiniMapTexture::CreateTextures( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, const CTerrain* terrain) { DestroyTextures(); m_MapSize = terrain->GetVerticesPerSide(); - m_TextureSize = static_cast(round_up_to_pow2(static_cast(m_MapSize))); + const size_t textureSize = round_up_to_pow2(static_cast(m_MapSize)); const Renderer::Backend::Sampler::Desc defaultSamplerDesc = Renderer::Backend::Sampler::MakeDefaultSampler( @@ -217,25 +218,23 @@ // Create terrain texture m_TerrainTexture = Renderer::Backend::GL::CTexture::Create2D( - Renderer::Backend::Format::R8G8B8A8, m_TextureSize, m_TextureSize, defaultSamplerDesc); + Renderer::Backend::Format::R8G8B8A8, textureSize, textureSize, defaultSamplerDesc); // Initialise texture with solid black, for the areas we don't - // overwrite with glTexSubImage2D later - u32* texData = new u32[m_TextureSize * m_TextureSize]; - for (ssize_t i = 0; i < m_TextureSize * m_TextureSize; ++i) + // overwrite with uploading later. + std::unique_ptr texData = std::make_unique(textureSize * textureSize); + for (size_t i = 0; i < textureSize * textureSize; ++i) texData[i] = 0xFF000000; - g_Renderer.BindTexture(0, m_TerrainTexture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_TextureSize, m_TextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData); - delete[] texData; + deviceCommandContext->UploadTexture( + m_TerrainTexture.get(), Renderer::Backend::Format::R8G8B8A8, + texData.get(), textureSize * textureSize * 4); + texData.reset(); - m_TerrainData = new u32[(m_MapSize - 1) * (m_MapSize - 1)]; + m_TerrainData = std::make_unique((m_MapSize - 1) * (m_MapSize - 1)); m_FinalTexture = Renderer::Backend::GL::CTexture::Create2D( Renderer::Backend::Format::R8G8B8A8, FINAL_TEXTURE_SIZE, FINAL_TEXTURE_SIZE, defaultSamplerDesc); - g_Renderer.BindTexture(0, m_FinalTexture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, FINAL_TEXTURE_SIZE, FINAL_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glGenFramebuffersEXT(1, &m_FinalTextureFBO); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FinalTextureFBO); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_FinalTexture->GetHandle(), 0); @@ -253,11 +252,12 @@ { m_TerrainTexture.reset(); m_FinalTexture.reset(); - - SAFE_ARRAY_DELETE(m_TerrainData); + m_TerrainData.reset(); } -void CMiniMapTexture::RebuildTerrainTexture(const CTerrain* terrain) +void CMiniMapTexture::RebuildTerrainTexture( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, + const CTerrain* terrain) { const u32 x = 0; const u32 y = 0; @@ -269,7 +269,7 @@ for (u32 j = 0; j < height; ++j) { - u32* dataPtr = m_TerrainData + ((y + j) * width) + x; + u32* dataPtr = m_TerrainData.get() + ((y + j) * width) + x; for (u32 i = 0; i < width; ++i) { const float avgHeight = ( terrain->GetVertexGroundLevel((int)i, (int)j) @@ -316,9 +316,9 @@ } // Upload the texture - g_Renderer.BindTexture(0, m_TerrainTexture->GetHandle()); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, m_TerrainData); - g_Renderer.BindTexture(0, 0); + deviceCommandContext->UploadTextureRegion( + m_TerrainTexture.get(), Renderer::Backend::Format::R8G8B8A8, + m_TerrainData.get(), width * height * 4, 0, 0, width, height); } void CMiniMapTexture::RenderFinalTexture() @@ -346,7 +346,7 @@ CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture(); const float invTileMapSize = 1.0f / static_cast(TERRAIN_TILE_SIZE * m_MapSize); - const float texCoordMax = (float)(m_MapSize - 1) / (float)m_TextureSize; + const float texCoordMax = m_TerrainTexture ? static_cast(m_MapSize - 1) / m_TerrainTexture->GetWidth() : 1.0f; CShaderProgramPtr shader; CShaderTechniquePtr tech; @@ -384,8 +384,7 @@ shader->BindTexture(str_baseTex, territoryTexture.GetTexture()); shader->Uniform(str_transform, baseTransform); - CMatrix3D territoryTransform = *territoryTexture.GetMinimapTextureMatrix(); - shader->Uniform(str_textureTransform, territoryTransform); + shader->Uniform(str_textureTransform, territoryTexture.GetMinimapTextureMatrix()); DrawTexture(shader); @@ -393,9 +392,8 @@ glColorMask(0, 0, 0, 1); shader->BindTexture(str_baseTex, losTexture.GetTexture()); - CMatrix3D losTransform = *losTexture.GetMinimapTextureMatrix(); shader->Uniform(str_transform, baseTransform); - shader->Uniform(str_textureTransform, losTransform); + shader->Uniform(str_textureTransform, losTexture.GetMinimapTextureMatrix()); DrawTexture(shader); Index: ps/trunk/source/graphics/TerritoryTexture.h =================================================================== --- ps/trunk/source/graphics/TerritoryTexture.h +++ ps/trunk/source/graphics/TerritoryTexture.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -17,6 +17,7 @@ #include "maths/Matrix3D.h" #include "renderer/backend/gl/Texture.h" +#include "renderer/backend/gl/DeviceCommandContext.h" class CSimulation2; template @@ -53,7 +54,13 @@ * coordinates, in the form expected by a matrix uniform. * This must only be called after BindTexture. */ - const CMatrix3D* GetMinimapTextureMatrix(); + const CMatrix3D& GetMinimapTextureMatrix(); + + /** + * Updates the texture if needed (territory was changed or the texture + * wasn't created). + */ + void UpdateIfNeeded(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext); private: /** @@ -62,8 +69,8 @@ bool UpdateDirty(); void DeleteTexture(); - void ConstructTexture(); - void RecomputeTexture(); + void ConstructTexture(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext); + void RecomputeTexture(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext); void GenerateBitmap(const Grid& territories, u8* bitmap, ssize_t w, ssize_t h); Index: ps/trunk/source/graphics/TerritoryTexture.cpp =================================================================== --- ps/trunk/source/graphics/TerritoryTexture.cpp +++ ps/trunk/source/graphics/TerritoryTexture.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -57,9 +57,7 @@ Renderer::Backend::GL::CTexture* CTerritoryTexture::GetTexture() { - if (UpdateDirty()) - RecomputeTexture(); - + ENSURE(!UpdateDirty()); return m_Texture.get(); } @@ -69,13 +67,13 @@ return &m_TextureMatrix._11; } -const CMatrix3D* CTerritoryTexture::GetMinimapTextureMatrix() +const CMatrix3D& CTerritoryTexture::GetMinimapTextureMatrix() { ENSURE(!UpdateDirty()); - return &m_MinimapTextureMatrix; + return m_MinimapTextureMatrix; } -void CTerritoryTexture::ConstructTexture() +void CTerritoryTexture::ConstructTexture(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) { CmpPtr cmpTerrain(m_Simulation, SYSTEM_ENTITY); if (!cmpTerrain) @@ -93,12 +91,12 @@ Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); // Initialise texture with transparency, for the areas we don't - // overwrite with glTexSubImage2D later - u8* texData = new u8[textureSize * textureSize * 4]; - memset(texData, 0x00, textureSize * textureSize * 4); - g_Renderer.BindTexture(0, m_Texture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureSize, textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData); - delete[] texData; + // overwrite with uploading later. + std::unique_ptr texData = std::make_unique(textureSize * textureSize * 4); + memset(texData.get(), 0x00, textureSize * textureSize * 4); + deviceCommandContext->UploadTexture( + m_Texture.get(), Renderer::Backend::Format::R8G8B8A8, texData.get(), textureSize * textureSize * 4); + texData.reset(); { // Texture matrix: We want to map @@ -128,7 +126,7 @@ } } -void CTerritoryTexture::RecomputeTexture() +void CTerritoryTexture::RecomputeTexture(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) { // If the map was resized, delete and regenerate the texture if (m_Texture) @@ -139,7 +137,7 @@ } if (!m_Texture) - ConstructTexture(); + ConstructTexture(deviceCommandContext); PROFILE("recompute territory texture"); @@ -147,11 +145,12 @@ if (!cmpTerritoryManager) return; - std::vector bitmap(m_MapSize * m_MapSize * 4); - GenerateBitmap(cmpTerritoryManager->GetTerritoryGrid(), &bitmap[0], m_MapSize, m_MapSize); + std::unique_ptr bitmap = std::make_unique(m_MapSize * m_MapSize * 4); + GenerateBitmap(cmpTerritoryManager->GetTerritoryGrid(), bitmap.get(), m_MapSize, m_MapSize); - g_Renderer.BindTexture(0, m_Texture->GetHandle()); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize, m_MapSize, GL_RGBA, GL_UNSIGNED_BYTE, &bitmap[0]); + deviceCommandContext->UploadTextureRegion( + m_Texture.get(), Renderer::Backend::Format::R8G8B8A8, bitmap.get(), m_MapSize * m_MapSize * 4, + 0, 0, m_MapSize, m_MapSize); } void CTerritoryTexture::GenerateBitmap(const Grid& territories, u8* bitmap, ssize_t w, ssize_t h) @@ -243,3 +242,9 @@ if (bitmap[(j*w+i)*4 + 3] == alphaMax) bitmap[(j*w+i)*4 + 3] = 0; } + +void CTerritoryTexture::UpdateIfNeeded(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) +{ + if (UpdateDirty()) + RecomputeTexture(deviceCommandContext); +} Index: ps/trunk/source/renderer/PostprocManager.cpp =================================================================== --- ps/trunk/source/renderer/PostprocManager.cpp +++ ps/trunk/source/renderer/PostprocManager.cpp @@ -120,9 +120,7 @@ Renderer::Backend::Format::R8G8B8A8, w, h, \ Renderer::Backend::Sampler::MakeDefaultSampler( \ Renderer::Backend::Sampler::Filter::LINEAR, \ - Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); \ - glBindTexture(GL_TEXTURE_2D, name->GetHandle()); \ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); // Two fullscreen ping-pong textures. GEN_BUFFER_RGBA(m_ColorTex1, m_Width, m_Height); @@ -149,12 +147,9 @@ Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); - glBindTexture(GL_TEXTURE_2D, m_DepthTex->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, m_Width, m_Height, - 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0); + glBindTexture(GL_TEXTURE_2D, m_DepthTex->GetHandle()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - glBindTexture(GL_TEXTURE_2D, 0); // Set up the framebuffers with some initial textures. @@ -682,10 +677,7 @@ Renderer::Backend::Format::R8G8B8A8, m_Width, m_Height, Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::Filter::LINEAR, - Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleColorTex->GetHandle()); - glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleCount, GL_RGBA, m_Width, m_Height, GL_TRUE); + Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1, m_MultisampleCount); // Allocate the Depth/Stencil texture. m_MultisampleDepthTex = Renderer::Backend::GL::CTexture::Create( @@ -693,15 +685,7 @@ Renderer::Backend::Format::D24_S8, m_Width, m_Height, Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::Filter::LINEAR, - Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleDepthTex->GetHandle()); - glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleCount, GL_DEPTH24_STENCIL8_EXT, m_Width, m_Height, GL_TRUE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); - - ogl_WarnIfError(); + Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1, m_MultisampleCount); // Set up the framebuffers with some initial textures. glGenFramebuffersEXT(1, &m_MultisampleFBO); Index: ps/trunk/source/renderer/Renderer.h =================================================================== --- ps/trunk/source/renderer/Renderer.h +++ ps/trunk/source/renderer/Renderer.h @@ -22,6 +22,7 @@ #include "graphics/ShaderDefines.h" #include "graphics/ShaderProgramPtr.h" #include "ps/Singleton.h" +#include "renderer/backend/gl/DeviceCommandContext.h" #include "renderer/RenderingOptions.h" #include "renderer/Scene.h" @@ -155,6 +156,8 @@ */ void MakeScreenShotOnNextFrame(ScreenShotType screenShotType); + Renderer::Backend::GL::CDeviceCommandContext* GetDeviceCommandContext(); + protected: friend class CPatchRData; friend class CDecalRData; Index: ps/trunk/source/renderer/Renderer.cpp =================================================================== --- ps/trunk/source/renderer/Renderer.cpp +++ ps/trunk/source/renderer/Renderer.cpp @@ -270,6 +270,8 @@ CFontManager fontManager; + std::unique_ptr deviceCommandContext; + Internals() : IsOpen(false), ShadersDirty(true), profileTable(g_Renderer.m_Stats), textureManager(g_VFS, false, false) { @@ -398,6 +400,8 @@ // Validate the currently selected render path SetRenderPath(g_RenderingOptions.GetRenderPath()); + m->deviceCommandContext = Renderer::Backend::GL::CDeviceCommandContext::Create(); + if (g_RenderingOptions.GetPostProc()) m->postprocManager.Initialize(); @@ -853,3 +857,8 @@ { m_ScreenShotType = screenShotType; } + +Renderer::Backend::GL::CDeviceCommandContext* CRenderer::GetDeviceCommandContext() +{ + return m->deviceCommandContext.get(); +} Index: ps/trunk/source/renderer/SceneRenderer.h =================================================================== --- ps/trunk/source/renderer/SceneRenderer.h +++ ps/trunk/source/renderer/SceneRenderer.h @@ -22,6 +22,7 @@ #include "graphics/ShaderDefines.h" #include "graphics/ShaderProgramPtr.h" #include "ps/Singleton.h" +#include "renderer/backend/gl/DeviceCommandContext.h" #include "renderer/RenderingOptions.h" #include "renderer/Scene.h" @@ -95,7 +96,7 @@ * Render the given scene immediately. * @param scene a Scene object describing what should be rendered. */ - void RenderScene(Scene& scene); + void RenderScene(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, Scene& scene); /** * Return the scene that is currently being rendered. @@ -192,7 +193,9 @@ void SubmitNonRecursive(CModel* model) override; // render any batched objects - void RenderSubmissions(const CBoundingBoxAligned& waterScissor); + void RenderSubmissions( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, + const CBoundingBoxAligned& waterScissor); // patch rendering stuff void RenderPatches(const CShaderDefines& context, int cullGroup); Index: ps/trunk/source/renderer/SceneRenderer.cpp =================================================================== --- ps/trunk/source/renderer/SceneRenderer.cpp +++ ps/trunk/source/renderer/SceneRenderer.cpp @@ -19,14 +19,6 @@ #include "SceneRenderer.h" -#include "maths/Matrix3D.h" -#include "maths/MathUtil.h" -#include "ps/CLogger.h" -#include "ps/ConfigDB.h" -#include "ps/CStrInternStatic.h" -#include "ps/Game.h" -#include "ps/Profile.h" -#include "ps/World.h" #include "graphics/Camera.h" #include "graphics/Decal.h" #include "graphics/GameView.h" @@ -39,10 +31,19 @@ #include "graphics/ParticleManager.h" #include "graphics/Patch.h" #include "graphics/ShaderManager.h" +#include "graphics/TerritoryTexture.h" #include "graphics/Terrain.h" #include "graphics/Texture.h" #include "graphics/TextureManager.h" +#include "maths/Matrix3D.h" +#include "maths/MathUtil.h" +#include "ps/CLogger.h" +#include "ps/ConfigDB.h" +#include "ps/CStrInternStatic.h" +#include "ps/Game.h" +#include "ps/Profile.h" #include "ps/VideoMode.h" +#include "ps/World.h" #include "renderer/DebugRenderer.h" #include "renderer/HWLightingModelRenderer.h" #include "renderer/InstancingModelRenderer.h" @@ -830,14 +831,16 @@ } // RenderSubmissions: force rendering of any batched objects -void CSceneRenderer::RenderSubmissions(const CBoundingBoxAligned& waterScissor) +void CSceneRenderer::RenderSubmissions( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, + const CBoundingBoxAligned& waterScissor) { PROFILE3("render submissions"); OGL_SCOPED_DEBUG_GROUP("Render submissions"); - GetScene().GetLOSTexture().InterpolateLOS(); - - GetScene().GetMiniMapTexture().Render(); + GetScene().GetLOSTexture().InterpolateLOS(deviceCommandContext); + GetScene().GetTerritoryTexture().UpdateIfNeeded(deviceCommandContext); + GetScene().GetMiniMapTexture().Render(deviceCommandContext); CShaderDefines context = m->globalContext; @@ -954,7 +957,7 @@ } // render debug-related terrain overlays - ITerrainOverlay::RenderOverlaysAfterWater(cullGroup); + ITerrainOverlay::RenderOverlaysAfterWater(deviceCommandContext, cullGroup); ogl_WarnIfError(); // render some other overlays after water (so they can be displayed on top of water) @@ -1172,7 +1175,8 @@ } // Render the given scene -void CSceneRenderer::RenderScene(Scene& scene) +void CSceneRenderer::RenderScene( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, Scene& scene) { m_CurrentScene = &scene; @@ -1245,7 +1249,7 @@ ogl_WarnIfError(); - RenderSubmissions(waterScissor); + RenderSubmissions(deviceCommandContext, waterScissor); m_CurrentScene = NULL; } Index: ps/trunk/source/renderer/ShadowMap.cpp =================================================================== --- ps/trunk/source/renderer/ShadowMap.cpp +++ ps/trunk/source/renderer/ShadowMap.cpp @@ -526,20 +526,18 @@ EffectiveWidth = Width; EffectiveHeight = Height; - GLenum format; const char* formatName; Renderer::Backend::Format backendFormat = Renderer::Backend::Format::UNDEFINED; #if CONFIG2_GLES - format = GL_DEPTH_COMPONENT; formatName = "DEPTH_COMPONENT"; backendFormat = Renderer::Backend::Format::D24; #else switch (DepthTextureBits) { - case 16: format = GL_DEPTH_COMPONENT16; formatName = "DEPTH_COMPONENT16"; backendFormat = Renderer::Backend::Format::D16; break; - case 24: format = GL_DEPTH_COMPONENT24; formatName = "DEPTH_COMPONENT24"; backendFormat = Renderer::Backend::Format::D24; break; - case 32: format = GL_DEPTH_COMPONENT32; formatName = "DEPTH_COMPONENT32"; backendFormat = Renderer::Backend::Format::D32; break; - default: format = GL_DEPTH_COMPONENT; formatName = "DEPTH_COMPONENT"; backendFormat = Renderer::Backend::Format::D24; break; + case 16: formatName = "Format::D16"; backendFormat = Renderer::Backend::Format::D16; break; + case 24: formatName = "Format::D24"; backendFormat = Renderer::Backend::Format::D24; break; + case 32: formatName = "Format::D32"; backendFormat = Renderer::Backend::Format::D32; break; + default: formatName = "Format::D24"; backendFormat = Renderer::Backend::Format::D24; break; } #endif ENSURE(formatName); @@ -554,9 +552,6 @@ Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::Filter::NEAREST, Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); - - g_Renderer.BindTexture(0, DummyTexture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); } Texture = Renderer::Backend::GL::CTexture::Create2D( @@ -572,21 +567,19 @@ #endif Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); - g_Renderer.BindTexture(0, Texture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, format, Width, Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL); - // GLES requires type == UNSIGNED_SHORT or UNSIGNED_INT #if !CONFIG2_GLES + g_Renderer.BindTexture(0, Texture->GetHandle()); // Enable automatic depth comparisons glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + glBindTexture(GL_TEXTURE_2D, 0); #endif ogl_WarnIfError(); // bind to framebuffer object - glBindTexture(GL_TEXTURE_2D, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Framebuffer); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, Texture->GetHandle(), 0); Index: ps/trunk/source/renderer/SkyManager.cpp =================================================================== --- ps/trunk/source/renderer/SkyManager.cpp +++ ps/trunk/source/renderer/SkyManager.cpp @@ -115,7 +115,7 @@ Renderer::Backend::Format::R8G8B8A8, textures[0].m_Width, textures[0].m_Height, Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::Filter::LINEAR, - Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1); + Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1, 1); glBindTexture(GL_TEXTURE_CUBE_MAP, m_SkyCubeMap->GetHandle()); Index: ps/trunk/source/renderer/TerrainOverlay.h =================================================================== --- ps/trunk/source/renderer/TerrainOverlay.h +++ ps/trunk/source/renderer/TerrainOverlay.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -23,6 +23,7 @@ #ifndef INCLUDED_TERRAINOVERLAY #define INCLUDED_TERRAINOVERLAY +#include "renderer/backend/gl/DeviceCommandContext.h" #include "renderer/backend/gl/Texture.h" struct CColor; @@ -45,7 +46,8 @@ virtual void RenderBeforeWater() { } - virtual void RenderAfterWater(int UNUSED(cullGroup)) { } + virtual void RenderAfterWater( + Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext), int UNUSED(cullGroup)) { } /** * Draw all ITerrainOverlay objects that exist @@ -57,7 +59,8 @@ * Draw all ITerrainOverlay objects that exist * and that should be drawn after water. */ - static void RenderOverlaysAfterWater(int cullGroup); + static void RenderOverlaysAfterWater( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, int cullGroup); protected: ITerrainOverlay(int priority); @@ -176,7 +179,7 @@ public: TerrainTextureOverlay(float texelsPerTile, int priority = 100); - virtual ~TerrainTextureOverlay(); + ~TerrainTextureOverlay() override; protected: /** @@ -194,7 +197,8 @@ SColor4ub GetColor(size_t idx, u8 alpha) const; private: - void RenderAfterWater(int cullGroup); + void RenderAfterWater( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, int cullGroup) override; float m_TexelsPerTile; std::unique_ptr m_Texture; Index: ps/trunk/source/renderer/TerrainOverlay.cpp =================================================================== --- ps/trunk/source/renderer/TerrainOverlay.cpp +++ ps/trunk/source/renderer/TerrainOverlay.cpp @@ -74,7 +74,8 @@ g_TerrainOverlayList[i].first->RenderBeforeWater(); } -void ITerrainOverlay::RenderOverlaysAfterWater(int cullGroup) +void ITerrainOverlay::RenderOverlaysAfterWater( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, int cullGroup) { if (g_TerrainOverlayList.empty()) return; @@ -82,7 +83,7 @@ PROFILE3_GPU("terrain overlays (after)"); for (size_t i = 0; i < g_TerrainOverlayList.size(); ++i) - g_TerrainOverlayList[i].first->RenderAfterWater(cullGroup); + g_TerrainOverlayList[i].first->RenderAfterWater(deviceCommandContext, cullGroup); } ////////////////////////////////////////////////////////////////////////// @@ -312,7 +313,8 @@ TerrainTextureOverlay::~TerrainTextureOverlay() = default; -void TerrainTextureOverlay::RenderAfterWater(int cullGroup) +void TerrainTextureOverlay::RenderAfterWater( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, int cullGroup) { CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); @@ -332,16 +334,13 @@ Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::Filter::NEAREST, Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); - - glBindTexture(GL_TEXTURE_2D, m_Texture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_Texture->GetWidth(), m_Texture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); } u8* data = (u8*)calloc(w * h, 4); BuildTextureRGBA(data, w, h); - glBindTexture(GL_TEXTURE_2D, m_Texture->GetHandle()); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data); + deviceCommandContext->UploadTexture( + m_Texture.get(), Renderer::Backend::Format::R8G8B8A8, data, w * h * 4); free(data); Index: ps/trunk/source/renderer/WaterManager.cpp =================================================================== --- ps/trunk/source/renderer/WaterManager.cpp +++ ps/trunk/source/renderer/WaterManager.cpp @@ -214,9 +214,6 @@ Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT)); - glBindTexture(GL_TEXTURE_2D, m_ReflectionTexture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_RefTextureSize, (GLsizei)m_RefTextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - // Create refraction texture m_RefractionTexture = Renderer::Backend::GL::CTexture::Create2D( Renderer::Backend::Format::R8G8B8A8, m_RefTextureSize, m_RefTextureSize, @@ -224,9 +221,6 @@ Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::AddressMode::MIRRORED_REPEAT)); - glBindTexture(GL_TEXTURE_2D, m_RefractionTexture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_RefTextureSize, (GLsizei)m_RefTextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - // Create depth textures m_ReflFboDepthTexture = Renderer::Backend::GL::CTexture::Create2D( Renderer::Backend::Format::D32, m_RefTextureSize, m_RefTextureSize, @@ -234,20 +228,12 @@ Renderer::Backend::Sampler::Filter::NEAREST, Renderer::Backend::Sampler::AddressMode::REPEAT)); - glBindTexture(GL_TEXTURE_2D, m_ReflFboDepthTexture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, (GLsizei)m_RefTextureSize, (GLsizei)m_RefTextureSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL); - m_RefrFboDepthTexture = Renderer::Backend::GL::CTexture::Create2D( Renderer::Backend::Format::D32, m_RefTextureSize, m_RefTextureSize, Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::Filter::NEAREST, Renderer::Backend::Sampler::AddressMode::REPEAT)); - glBindTexture(GL_TEXTURE_2D, m_RefrFboDepthTexture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, (GLsizei)m_RefTextureSize, (GLsizei)m_RefTextureSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL); - - glBindTexture(GL_TEXTURE_2D, 0); - Resize(); // Create the water framebuffers @@ -322,19 +308,11 @@ Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::AddressMode::REPEAT)); - glBindTexture(GL_TEXTURE_2D, m_FancyTexture->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)g_Renderer.GetWidth(), (GLsizei)g_Renderer.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_SHORT, NULL); - m_FancyTextureDepth = Renderer::Backend::GL::CTexture::Create2D( Renderer::Backend::Format::D32, g_Renderer.GetWidth(), g_Renderer.GetHeight(), Renderer::Backend::Sampler::MakeDefaultSampler( Renderer::Backend::Sampler::Filter::LINEAR, Renderer::Backend::Sampler::AddressMode::REPEAT)); - - glBindTexture(GL_TEXTURE_2D, m_FancyTextureDepth->GetHandle()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, (GLsizei)g_Renderer.GetWidth(), (GLsizei)g_Renderer.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL); - - glBindTexture(GL_TEXTURE_2D, 0); } void WaterManager::ReloadWaterNormalTextures() Index: ps/trunk/source/renderer/backend/gl/DeviceCommandContext.h =================================================================== --- ps/trunk/source/renderer/backend/gl/DeviceCommandContext.h +++ ps/trunk/source/renderer/backend/gl/DeviceCommandContext.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2022 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_RENDERER_GL_DEVICECOMMANDCONTEXT +#define INCLUDED_RENDERER_GL_DEVICECOMMANDCONTEXT + +#include "renderer/backend/Format.h" + +#include + +namespace Renderer +{ + +namespace Backend +{ + +namespace GL +{ + +class CTexture; + +class CDeviceCommandContext +{ +public: + ~CDeviceCommandContext(); + + static std::unique_ptr Create(); + + void UploadTexture(CTexture* texture, const Format format, const void* data, const size_t dataSize); + void UploadTextureRegion(CTexture* texture, const Format format, const void* data, const size_t dataSize, + const uint32_t xOffset, const uint32_t yOffset, const uint32_t width, const uint32_t height); + +private: + CDeviceCommandContext(); +}; + +} // namespace GL + +} // namespace Backend + +} // namespace Renderer + +#endif // INCLUDED_RENDERER_GL_DEVICECOMMANDCONTEXT Index: ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp +++ ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp @@ -0,0 +1,84 @@ +/* Copyright (C) 2022 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "DeviceCommandContext.h" + +#include "renderer/backend/gl/Texture.h" + +namespace Renderer +{ + +namespace Backend +{ + +namespace GL +{ + +// static +std::unique_ptr CDeviceCommandContext::Create() +{ + std::unique_ptr deviceCommandContext(new CDeviceCommandContext()); + + return deviceCommandContext; +} + +CDeviceCommandContext::CDeviceCommandContext() = default; + +CDeviceCommandContext::~CDeviceCommandContext() = default; + +void CDeviceCommandContext::UploadTexture( + CTexture* texture, const Format format, const void* data, const size_t dataSize) +{ + UploadTextureRegion(texture, format, data, dataSize, 0, 0, texture->GetWidth(), texture->GetHeight()); +} + +void CDeviceCommandContext::UploadTextureRegion(CTexture* texture, const Format format, const void* data, const size_t dataSize, + const uint32_t xOffset, const uint32_t yOffset, const uint32_t width, const uint32_t height) +{ + if (texture->GetType() == CTexture::Type::TEXTURE_2D) + { + if (texture->GetFormat() == Format::R8G8B8A8 || texture->GetFormat() == Format::A8) + { + ENSURE(width > 0 && height > 0); + ENSURE(texture->GetFormat() == format); + const size_t bpp = format == Format::R8G8B8A8 ? 4 : 1; + ENSURE(dataSize == width * height * bpp); + ENSURE(xOffset + width <= texture->GetWidth()); + ENSURE(yOffset + height <= texture->GetHeight()); + + glBindTexture(GL_TEXTURE_2D, texture->GetHandle()); + glTexSubImage2D(GL_TEXTURE_2D, 0, + xOffset, yOffset, width, height, + format == Format::R8G8B8A8 ? GL_RGBA : GL_ALPHA, GL_UNSIGNED_BYTE, data); + glBindTexture(GL_TEXTURE_2D, 0); + + ogl_WarnIfError(); + } + else + debug_warn("Unsupported format"); + } + else + debug_warn("Unsupported type"); +} + +} // namespace GL + +} // namespace Backend + +} // namespace Renderer Index: ps/trunk/source/renderer/backend/gl/Texture.h =================================================================== --- ps/trunk/source/renderer/backend/gl/Texture.h +++ ps/trunk/source/renderer/backend/gl/Texture.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -52,12 +52,12 @@ // an own default sampler. static std::unique_ptr Create(const Type type, const Format format, const uint32_t width, const uint32_t height, - const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount); + const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount, const uint32_t sampleCount); // Shorthands for particular types. static std::unique_ptr Create2D(const Format format, const uint32_t width, const uint32_t height, - const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount = 1); + const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount = 1, const uint32_t sampleCount = 1); GLuint GetHandle() const { return m_Handle; } Index: ps/trunk/source/renderer/backend/gl/Texture.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/Texture.cpp +++ ps/trunk/source/renderer/backend/gl/Texture.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -19,6 +19,7 @@ #include "Texture.h" +#include "lib/code_annotation.h" #include "lib/config2.h" #include "lib/res/graphics/ogl_tex.h" #include "renderer/backend/gl/Device.h" @@ -85,20 +86,21 @@ // static std::unique_ptr CTexture::Create2D(const Format format, const uint32_t width, const uint32_t height, - const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount) + const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount, const uint32_t sampleCount) { - return Create(Type::TEXTURE_2D, format, width, height, defaultSamplerDesc, mipCount); + return Create(Type::TEXTURE_2D, format, width, height, defaultSamplerDesc, mipCount, sampleCount); } // static std::unique_ptr CTexture::Create(const Type type, const Format format, const uint32_t width, const uint32_t height, - const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount) + const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount, const uint32_t sampleCount) { std::unique_ptr texture(new CTexture()); ENSURE(format != Format::UNDEFINED); ENSURE(width > 0 && height > 0 && mipCount > 0); + ENSURE((type == Type::TEXTURE_2D_MULTISAMPLE && sampleCount > 1) || sampleCount == 1); texture->m_Format = format; texture->m_Width = width; @@ -154,6 +156,85 @@ ogl_WarnIfError(); + ENSURE(mipCount == 1); + + if (type == CTexture::Type::TEXTURE_2D) + { + GLint internalFormat = GL_RGBA; + // Actually pixel data is nullptr so it doesn't make sense to account + // it, but in theory some buggy drivers might complain about invalid + // pixel format. + GLenum pixelFormat = GL_RGBA; + GLenum pixelType = GL_UNSIGNED_BYTE; + switch (format) + { + case Format::UNDEFINED: + debug_warn("Texture should defined format"); + break; + case Format::R8G8B8A8: + break; + case Format::A8: + internalFormat = GL_ALPHA; + pixelFormat = GL_ALPHA; + pixelType = GL_UNSIGNED_BYTE; + break; +#if CONFIG2_GLES + // GLES requires pixel type == UNSIGNED_SHORT or UNSIGNED_INT for depth. + case Format::D16: FALLTHROUGH; + case Format::D24: FALLTHROUGH; + case Format::D32: + internalFormat = GL_DEPTH_COMPONENT; + pixelFormat = GL_DEPTH_COMPONENT; + pixelType = GL_UNSIGNED_SHORT; + break; + case Format::D24_S8: + debug_warn("Unsupported format"); + break; +#else + case Format::D16: + internalFormat = GL_DEPTH_COMPONENT16; + pixelFormat = GL_DEPTH_COMPONENT; + pixelType = GL_UNSIGNED_SHORT; + break; + case Format::D24: + internalFormat = GL_DEPTH_COMPONENT24; + pixelFormat = GL_DEPTH_COMPONENT; + pixelType = GL_UNSIGNED_SHORT; + break; + case Format::D32: + internalFormat = GL_DEPTH_COMPONENT32; + pixelFormat = GL_DEPTH_COMPONENT; + pixelType = GL_UNSIGNED_SHORT; + break; + case Format::D24_S8: + internalFormat = GL_DEPTH24_STENCIL8_EXT; + pixelFormat = GL_DEPTH_STENCIL_EXT; + pixelType = GL_UNSIGNED_INT_24_8_EXT; + break; +#endif + } + glTexImage2D(target, 0, internalFormat, width, height, 0, pixelFormat, pixelType, nullptr); + } + else if (type == CTexture::Type::TEXTURE_2D_MULTISAMPLE) + { +#if !CONFIG2_GLES + if (format == Format::R8G8B8A8) + { + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, GL_RGBA8, width, height, GL_TRUE); + } + else if (format == Format::D24_S8) + { + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, GL_DEPTH24_STENCIL8_EXT, width, height, GL_TRUE); + } + else +#endif // !CONFIG2_GLES + { + debug_warn("Unsupported format"); + } + } + + ogl_WarnIfError(); + glBindTexture(target, 0); return texture; Index: ps/trunk/source/tools/atlas/GameInterface/ActorViewer.cpp =================================================================== --- ps/trunk/source/tools/atlas/GameInterface/ActorViewer.cpp +++ ps/trunk/source/tools/atlas/GameInterface/ActorViewer.cpp @@ -523,7 +523,7 @@ g_Renderer.GetSceneRenderer().SetSceneCamera(camera, camera); - g_Renderer.GetSceneRenderer().RenderScene(m); + g_Renderer.GetSceneRenderer().RenderScene(g_Renderer.GetDeviceCommandContext(), m); glDisable(GL_DEPTH_TEST); g_Logger->Render();