diff --git a/neo/renderer/Interaction.cpp b/neo/renderer/Interaction.cpp index 7ef79de3..eca42fc1 100644 --- a/neo/renderer/Interaction.cpp +++ b/neo/renderer/Interaction.cpp @@ -661,7 +661,7 @@ void idInteraction::CreateStaticInteraction( nvrhi::ICommandList* commandList ) { // make a static index cache sint->numLightTrisIndexes = lightTris->numIndexes; - sint->lightTrisIndexCache = vertexCache.AllocStaticIndex( lightTris->indexes, ALIGN( lightTris->numIndexes * sizeof( lightTris->indexes[0] ), INDEX_CACHE_ALIGN ), commandList ); + sint->lightTrisIndexCache = vertexCache.AllocStaticIndex( lightTris->indexes, lightTris->numIndexes * sizeof( lightTris->indexes[0] ), commandList ); interactionGenerated = true; R_FreeStaticTriSurf( lightTris ); diff --git a/neo/renderer/NVRHI/BufferObject_NVRHI.cpp b/neo/renderer/NVRHI/BufferObject_NVRHI.cpp index b9c7b04f..2b13f2f8 100644 --- a/neo/renderer/NVRHI/BufferObject_NVRHI.cpp +++ b/neo/renderer/NVRHI/BufferObject_NVRHI.cpp @@ -30,6 +30,9 @@ If you have questions concerning this license or the applicable additional terms #include "precompiled.h" #pragma hdrstop #include "../RenderCommon.h" +#include "../VertexCache.h" + +extern idVertexCache vertexCache; #include "sys/DeviceManager.h" @@ -185,24 +188,23 @@ bool idVertexBuffer::AllocBufferObject( const void* data, int allocSize, bufferU idLib::Error( "idVertexBuffer::AllocBufferObject: allocSize = %i", allocSize ); } - size = allocSize; + size = ALIGN( allocSize, VERTEX_CACHE_ALIGN ); usage = _usage; - int numBytes = GetAllocedSize(); + const int numBytes = GetAllocedSize(); nvrhi::BufferDesc vertexBufferDesc; vertexBufferDesc.byteSize = numBytes; vertexBufferDesc.isVertexBuffer = true; + vertexBufferDesc.initialState = nvrhi::ResourceStates::CopyDest; if( usage == BU_DYNAMIC ) { - vertexBufferDesc.initialState = nvrhi::ResourceStates::CopyDest; vertexBufferDesc.cpuAccess = nvrhi::CpuAccessMode::Write; vertexBufferDesc.debugName = "Mapped idDrawVert vertex buffer"; } else { - vertexBufferDesc.initialState = nvrhi::ResourceStates::CopyDest; vertexBufferDesc.keepInitialState = true; vertexBufferDesc.debugName = "Static idDrawVert vertex buffer"; } @@ -307,14 +309,15 @@ void idVertexBuffer::Update( const void* data, int updateSize, int offset, bool assert( bufferHandle ); assert_16_byte_aligned( data ); assert( ( GetOffset() & 15 ) == 0 ); + assert( ( offset & VERTEX_CACHE_ALIGN - 1 ) == 0 ); - if( updateSize > GetSize() ) + const int numBytes = ( updateSize + 15 ) & ~15; + + if( offset + numBytes > GetSize() ) { - idLib::FatalError( "idVertexBuffer::Update: size overrun, %i > %i\n", updateSize, GetSize() ); + idLib::FatalError( "idVertexBuffer::Update: size overrun, %i + %i > %i\n", offset, numBytes, GetSize() ); } - int numBytes = ( updateSize + 15 ) & ~15; - if( usage == BU_DYNAMIC ) { assert( IsMapped() ); @@ -450,10 +453,10 @@ bool idIndexBuffer::AllocBufferObject( const void* data, int allocSize, bufferUs idLib::Error( "idIndexBuffer::AllocBufferObject: allocSize = %i", allocSize ); } - size = allocSize; + size = ALIGN( allocSize, INDEX_CACHE_ALIGN ); usage = _usage; - int numBytes = GetAllocedSize(); + const int numBytes = GetAllocedSize(); nvrhi::BufferDesc indexBufferDesc; indexBufferDesc.byteSize = numBytes; @@ -573,14 +576,15 @@ void idIndexBuffer::Update( const void* data, int updateSize, int offset, bool i assert( bufferHandle ); assert_16_byte_aligned( data ); assert( ( GetOffset() & 15 ) == 0 ); - - if( updateSize > GetSize() ) - { - idLib::FatalError( "idIndexBuffer::Update: size overrun, %i > %i\n", updateSize, GetSize() ); - } + assert( ( offset & INDEX_CACHE_ALIGN - 1 ) == 0 ); const int numBytes = ( updateSize + 15 ) & ~15; + if( offset + numBytes > GetSize() ) + { + idLib::FatalError( "idIndexBuffer::Update: size overrun, %i + %i > %i\n", offset, numBytes, GetSize() ); + } + if( usage == BU_DYNAMIC ) { assert( IsMapped() ); @@ -717,7 +721,7 @@ bool idUniformBuffer::AllocBufferObject( const void* data, int allocSize, buffer idLib::Error( "idUniformBuffer::AllocBufferObject: allocSize = %i", allocSize ); } - size = allocSize; + size = ALIGN( allocSize, vertexCache.uniformBufferOffsetAlignment ); usage = allocatedUsage; const int numBytes = GetAllocedSize(); @@ -725,14 +729,9 @@ bool idUniformBuffer::AllocBufferObject( const void* data, int allocSize, buffer // This buffer is a shader resource as opposed to a constant buffer due to // constant buffers not being able to be sub-ranged. nvrhi::BufferDesc bufferDesc; - //bufferDesc.initialState = nvrhi::ResourceStates::ConstantBuffer; // SRS - shouldn't this be initialized to CopyDest? - bufferDesc.initialState = nvrhi::ResourceStates::CopyDest; - //bufferDesc.keepInitialState = true; // SRS - shouldn't this be set for BU_STATIC only? - bufferDesc.canHaveTypedViews = true; - bufferDesc.canHaveRawViews = true; bufferDesc.byteSize = numBytes; - bufferDesc.structStride = sizeof( idVec4 ); - bufferDesc.isConstantBuffer = true; + bufferDesc.structStride = sizeof( idVec4 ); // SRS - this defines a structured storage buffer vs. a constant buffer + bufferDesc.initialState = nvrhi::ResourceStates::Common; if( usage == BU_DYNAMIC ) { @@ -845,14 +844,15 @@ void idUniformBuffer::Update( const void* data, int updateSize, int offset, bool assert( bufferHandle ); assert_16_byte_aligned( data ); assert( ( GetOffset() & 15 ) == 0 ); + assert( ( offset & vertexCache.uniformBufferOffsetAlignment - 1 ) == 0 ); - if( updateSize > GetSize() ) + const int numBytes = ( updateSize + 15 ) & ~15; + + if( offset + numBytes > GetSize() ) { - idLib::FatalError( "idUniformBuffer::Update: size overrun, %i > %i\n", updateSize, GetSize() ); + idLib::FatalError( "idUniformBuffer::Update: size overrun, %i + %i > %i\n", offset, numBytes, GetSize() ); } - int numBytes = ( updateSize + 15 ) & ~15; - if( usage == BU_DYNAMIC ) { assert( IsMapped() ); diff --git a/neo/renderer/VertexCache.cpp b/neo/renderer/VertexCache.cpp index eb66c035..ecab2edc 100644 --- a/neo/renderer/VertexCache.cpp +++ b/neo/renderer/VertexCache.cpp @@ -215,7 +215,8 @@ vertCacheHandle_t idVertexCache::ActuallyAlloc( geoBufferSet_t& vcs, const void* assert( ( ( ( uintptr_t )( data ) ) & 15 ) == 0 ); // RB end - assert( ( bytes & 15 ) == 0 ); + // SRS - enforce cache alignment without read beyond boundary for each cache type below + //assert( ( bytes & 15 ) == 0 ); int endPos = 0; int offset = 0; @@ -224,13 +225,15 @@ vertCacheHandle_t idVertexCache::ActuallyAlloc( geoBufferSet_t& vcs, const void* { case CACHE_INDEX: { - endPos = vcs.indexMemUsed.Add( bytes ); + // SRS - calculate alignedBytes retaining original to prevent read beyond data boundary during update + int alignedBytes = ALIGN( bytes, INDEX_CACHE_ALIGN ); + endPos = vcs.indexMemUsed.Add( alignedBytes ); if( endPos > vcs.indexBuffer.GetAllocedSize() ) { idLib::Error( "Out of index cache" ); } - offset = endPos - bytes; + offset = endPos - alignedBytes; if( data != NULL ) { @@ -245,13 +248,15 @@ vertCacheHandle_t idVertexCache::ActuallyAlloc( geoBufferSet_t& vcs, const void* } case CACHE_VERTEX: { - endPos = vcs.vertexMemUsed.Add( bytes ); + // SRS - calculate alignedBytes retaining original to prevent read beyond data boundary during update + int alignedBytes = ALIGN( bytes, VERTEX_CACHE_ALIGN ); + endPos = vcs.vertexMemUsed.Add( alignedBytes ); if( endPos > vcs.vertexBuffer.GetAllocedSize() ) { idLib::Error( "Out of vertex cache" ); } - offset = endPos - bytes; + offset = endPos - alignedBytes; if( data != NULL ) { @@ -266,13 +271,15 @@ vertCacheHandle_t idVertexCache::ActuallyAlloc( geoBufferSet_t& vcs, const void* } case CACHE_JOINT: { - endPos = vcs.jointMemUsed.Add( bytes ); + // SRS - calculate alignedBytes retaining original to prevent read beyond data boundary during update + int alignedBytes = ALIGN( bytes, uniformBufferOffsetAlignment ); + endPos = vcs.jointMemUsed.Add( alignedBytes ); if( endPos > vcs.jointBuffer.GetAllocedSize() ) { idLib::Error( "Out of joint buffer cache" ); } - offset = endPos - bytes; + offset = endPos - alignedBytes; if( data != NULL ) { @@ -308,7 +315,7 @@ idVertexCache::AllocVertex */ vertCacheHandle_t idVertexCache::AllocVertex( const void* data, int num, size_t size /*= sizeof( idDrawVert ) */, nvrhi::ICommandList* commandList ) { - return ActuallyAlloc( frameData[ listNum ], data, ALIGN( num * size, VERTEX_CACHE_ALIGN ), CACHE_VERTEX, commandList ); + return ActuallyAlloc( frameData[ listNum ], data, num * size, CACHE_VERTEX, commandList ); } /* @@ -318,7 +325,7 @@ idVertexCache::AllocIndex */ vertCacheHandle_t idVertexCache::AllocIndex( const void* data, int num, size_t size /*= sizeof( triIndex_t ) */, nvrhi::ICommandList* commandList ) { - return ActuallyAlloc( frameData[ listNum ], data, ALIGN( num * size, INDEX_CACHE_ALIGN ), CACHE_INDEX, commandList ); + return ActuallyAlloc( frameData[ listNum ], data, num * size, CACHE_INDEX, commandList ); } /* @@ -328,7 +335,7 @@ idVertexCache::AllocJoint */ vertCacheHandle_t idVertexCache::AllocJoint( const void* data, int num, size_t size /*= sizeof( idJointMat ) */, nvrhi::ICommandList* commandList ) { - return ActuallyAlloc( frameData[ listNum ], data, ALIGN( num * size, uniformBufferOffsetAlignment ), CACHE_JOINT, commandList ); + return ActuallyAlloc( frameData[ listNum ], data, num * size, CACHE_JOINT, commandList ); } /* diff --git a/neo/renderer/tr_trisurf.cpp b/neo/renderer/tr_trisurf.cpp index 7b3d8c17..3aa175f8 100644 --- a/neo/renderer/tr_trisurf.cpp +++ b/neo/renderer/tr_trisurf.cpp @@ -1819,8 +1819,8 @@ Uploads static vertices to the vertex cache. */ void R_CreateDeformStaticVertices( deformInfo_t* deform, nvrhi::ICommandList* commandList ) { - deform->staticAmbientCache = vertexCache.AllocStaticVertex( deform->verts, ALIGN( deform->numOutputVerts * sizeof( idDrawVert ), VERTEX_CACHE_ALIGN ), commandList ); - deform->staticIndexCache = vertexCache.AllocStaticIndex( deform->indexes, ALIGN( deform->numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ), commandList ); + deform->staticAmbientCache = vertexCache.AllocStaticVertex( deform->verts, deform->numOutputVerts * sizeof( idDrawVert ), commandList ); + deform->staticIndexCache = vertexCache.AllocStaticIndex( deform->indexes, deform->numIndexes * sizeof( triIndex_t ), commandList ); } /* @@ -1948,13 +1948,13 @@ void R_CreateStaticBuffersForTri( srfTriangles_t& tri, nvrhi::ICommandList* comm // index cache if( tri.indexes != NULL ) { - tri.indexCache = vertexCache.AllocStaticIndex( tri.indexes, ALIGN( tri.numIndexes * sizeof( tri.indexes[0] ), INDEX_CACHE_ALIGN ), commandList ); + tri.indexCache = vertexCache.AllocStaticIndex( tri.indexes, tri.numIndexes * sizeof( tri.indexes[0] ), commandList ); } // vertex cache if( tri.verts != NULL ) { - tri.ambientCache = vertexCache.AllocStaticVertex( tri.verts, ALIGN( tri.numVerts * sizeof( tri.verts[0] ), VERTEX_CACHE_ALIGN ), commandList ); + tri.ambientCache = vertexCache.AllocStaticVertex( tri.verts, tri.numVerts * sizeof( tri.verts[0] ), commandList ); } } @@ -2128,4 +2128,4 @@ idVec3 R_ClosestPointPointTriangle( const idVec3& point, const idVec3& vertex1, result = vertex1 + ab * v2 + ac * w2; //= u*vertex1 + v*vertex2 + w*vertex3, u = va * denom = 1.0f - v - w return result; -} \ No newline at end of file +}