diff --git a/src/d3d9/d3d11_dynamic_buffer.cpp b/src/d3d9/d3d11_dynamic_buffer.cpp index 84db691..75dae57 100644 --- a/src/d3d9/d3d11_dynamic_buffer.cpp +++ b/src/d3d9/d3d11_dynamic_buffer.cpp @@ -4,21 +4,22 @@ namespace dxup { D3D11DynamicBuffer::D3D11DynamicBuffer(ID3D11Device* device, uint32_t bindFlags) : m_device{ device } - , m_length{ 0 } + , m_size{ 0 } + , m_offset{ 0 } , m_bindFlags{ bindFlags } {} ID3D11Buffer* D3D11DynamicBuffer::getBuffer() { return m_buffer.ptr(); } - bool D3D11DynamicBuffer::reserve(uint32_t length) { - if (m_buffer != nullptr && m_length >= length) - return false; + void D3D11DynamicBuffer::reserve(uint32_t length) { + if (m_buffer != nullptr && m_size >= m_offset + length) + return; m_buffer = nullptr; D3D11_BUFFER_DESC desc; - desc.ByteWidth = length; + desc.ByteWidth = m_offset + length; desc.BindFlags = m_bindFlags; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.Usage = D3D11_USAGE_DYNAMIC; @@ -28,32 +29,40 @@ namespace dxup { Com buffer; HRESULT result = m_device->CreateBuffer(&desc, nullptr, &buffer); if (FAILED(result)) { - log::warn("reserve: CreateBuffer failed (length = %d.)", length); - return false; + log::warn("reserve: CreateBuffer failed (length = %d + %d.)", m_offset + length); + return; } m_buffer = buffer; - m_length = length; + m_size = m_offset + length; - return true; + m_offset = 0; + + return; } - // TODO! _OVERWRITE optimization. - void D3D11DynamicBuffer::update(ID3D11DeviceContext* context, const void* src, uint32_t length) { - D3D11_MAPPED_SUBRESOURCE res; - context->Map(m_buffer.ptr(), 0, D3D11_MAP_WRITE_DISCARD, 0, &res); - std::memcpy(res.pData, src, length); - context->Unmap(m_buffer.ptr(), 0); + uint32_t D3D11DynamicBuffer::update(ID3D11DeviceContext* context, const void* src, uint32_t length) { + void* data; + this->map(context, &data, length); + std::memcpy(&data, src, length); + return this->unmap(context, length); } void D3D11DynamicBuffer::map(ID3D11DeviceContext* context, void** data, uint32_t length) { D3D11_MAPPED_SUBRESOURCE res; - context->Map(m_buffer.ptr(), 0, D3D11_MAP_WRITE_DISCARD, 0, &res); - *data = res.pData; + context->Map(m_buffer.ptr(), 0, m_offset == 0 ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE, 0, &res); + uint8_t* resourceData = (uint8_t*)res.pData; + *data = resourceData + m_offset; } - void D3D11DynamicBuffer::unmap(ID3D11DeviceContext* context) { + uint32_t D3D11DynamicBuffer::unmap(ID3D11DeviceContext* context, uint32_t length) { context->Unmap(m_buffer.ptr(), 0); + uint32_t offset = m_offset; + m_offset += length; + return offset; } + void D3D11DynamicBuffer::endFrame() { + m_offset = 0; + } } \ No newline at end of file diff --git a/src/d3d9/d3d11_dynamic_buffer.h b/src/d3d9/d3d11_dynamic_buffer.h index cc38746..132face 100644 --- a/src/d3d9/d3d11_dynamic_buffer.h +++ b/src/d3d9/d3d11_dynamic_buffer.h @@ -10,10 +10,11 @@ namespace dxup { D3D11DynamicBuffer(ID3D11Device* device, uint32_t bindFlags); - bool reserve(uint32_t length); - void update(ID3D11DeviceContext* context, const void* src, uint32_t length); + void reserve(uint32_t length); + uint32_t update(ID3D11DeviceContext* context, const void* src, uint32_t length); void map(ID3D11DeviceContext* context, void** data, uint32_t length); - void unmap(ID3D11DeviceContext* context); + uint32_t unmap(ID3D11DeviceContext* context, uint32_t length); + void endFrame(); ID3D11Buffer* getBuffer(); @@ -21,7 +22,8 @@ namespace dxup { ID3D11Device* m_device; Com m_buffer; - uint32_t m_length; + uint32_t m_size; + uint32_t m_offset; uint32_t m_bindFlags; }; diff --git a/src/d3d9/d3d9_constant_buffer.h b/src/d3d9/d3d9_constant_buffer.h index 53575de..4903bd1 100644 --- a/src/d3d9/d3d9_constant_buffer.h +++ b/src/d3d9/d3d9_constant_buffer.h @@ -6,6 +6,7 @@ #include #include #include "../util/vectypes.h" +#include "d3d11_dynamic_buffer.h" namespace dxup { @@ -28,28 +29,32 @@ namespace dxup { D3D9ConstantBuffer(ID3D11Device1* device, ID3D11DeviceContext1* context) : m_device{ device } - , m_context{ context } { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(D3D9ShaderConstants::floatConstants) + sizeof(D3D9ShaderConstants::intConstants) + (4 * sizeof(D3D9ShaderConstants::boolConstants)); // TODO make bool constants a bitfield. - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - cbDesc.StructureByteStride = 0; - - HRESULT result = m_device->CreateBuffer(&cbDesc, nullptr, &m_buffer); - if (FAILED(result)) - log::fail("Couldn't create constant buffer."); + , m_context{ context } + , m_buffer{ device, D3D11_BIND_CONSTANT_BUFFER } + , m_offset{ 0 } { + } - bind(); + constexpr uint32_t getConstantSize() { + return 4 * sizeof(float); + } + + constexpr uint32_t getLength() { + uint32_t length = sizeof(D3D9ShaderConstants::floatConstants) + sizeof(D3D9ShaderConstants::intConstants) + (4 * sizeof(D3D9ShaderConstants::boolConstants)); + return alignTo(length, 16 * getConstantSize()); + } + + constexpr uint32_t getConstantCount() { + return getLength() / (getConstantSize()); } void update(const D3D9ShaderConstants& constants) { - D3D11_MAPPED_SUBRESOURCE res; - m_context->Map(m_buffer.ptr(), 0, D3D11_MAP_WRITE_DISCARD, 0, &res); + const uint32_t length = getLength(); + m_buffer.reserve(length); // TODO make bool constants a bitfield. + + uint8_t* data; + m_buffer.map(m_context, (void**)(&data), length); // This can probably be consolidated into a single one. - uint8_t* data = (uint8_t*)res.pData; std::memcpy(data, constants.floatConstants.data(), sizeof(constants.floatConstants)); std::memcpy(data + sizeof(constants.floatConstants), constants.intConstants.data(), sizeof(constants.intConstants)); @@ -59,15 +64,24 @@ namespace dxup { boolData[i * 4 + j] = constants.boolConstants[i]; } - m_context->Unmap(m_buffer.ptr(), 0); + m_offset = m_buffer.unmap(m_context, length); + bind(); } void bind() { - ID3D11Buffer* buffer = m_buffer.ptr(); + const uint32_t constantOffset = m_offset / getConstantSize(); + const uint32_t constantCount = getConstantCount(); + + ID3D11Buffer* buffer = m_buffer.getBuffer(); + if constexpr (Pixel) - m_context->PSSetConstantBuffers(0, 1, &buffer); + m_context->PSSetConstantBuffers1(0, 1, &buffer, &constantOffset, &constantCount); else - m_context->VSSetConstantBuffers(0, 1, &buffer); + m_context->VSSetConstantBuffers1(0, 1, &buffer, &constantOffset, &constantCount); + } + + void endFrame() { + m_buffer.endFrame(); } private: @@ -76,7 +90,8 @@ namespace dxup { ID3D11Device1* m_device; ID3D11DeviceContext1* m_context; - Com m_buffer; + D3D11DynamicBuffer m_buffer; + uint32_t m_offset; }; } \ No newline at end of file diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 5403ad9..1ed2218 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -593,6 +593,7 @@ namespace dxup { HRESULT STDMETHODCALLTYPE Direct3DDevice9Ex::Present(CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) { CriticalSection cs(this); + m_renderer->endFrame(); return PresentEx(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0); } HRESULT STDMETHODCALLTYPE Direct3DDevice9Ex::GetBackBuffer(UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) { diff --git a/src/d3d9/d3d9_renderer.cpp b/src/d3d9/d3d9_renderer.cpp index bd1d984..348c2fc 100644 --- a/src/d3d9/d3d9_renderer.cpp +++ b/src/d3d9/d3d9_renderer.cpp @@ -46,6 +46,15 @@ namespace dxup { log::warn("D3D9ImmediateRenderer: failed to create blit ps."); } + void D3D9ImmediateRenderer::endFrame() { + m_fanIndexBuffer.endFrame(); + m_upIndexBuffer.endFrame(); + m_upVertexBuffer.endFrame(); + + m_vsConstants.endFrame(); + m_psConstants.endFrame(); + } + HRESULT D3D9ImmediateRenderer::Clear(DWORD Count, const D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) { if (Count >= 1) { bool fullRectClear = pRects->x1 == 0 && @@ -96,40 +105,39 @@ namespace dxup { const uint32_t newPrimitiveCount = PrimitiveCount * 3; const uint32_t length = newPrimitiveCount * sizeof(uint16_t); - bool reserved = m_fanIndexBuffer.reserve(length); - if (indexed || m_fanIndexed || reserved) { - uint16_t* data = nullptr; - m_fanIndexBuffer.map(m_context, (void**)&data, length); + m_fanIndexBuffer.reserve(length); - if (indexed && m_state->indexBuffer != nullptr) { - D3D11_MAPPED_SUBRESOURCE res; - ID3D11Resource* originalIndexBuffer = m_state->indexBuffer->GetDXUPResource()->GetStaging(); - m_context->Map(originalIndexBuffer, 0, D3D11_MAP_READ, 0, &res); + uint16_t* data = nullptr; + m_fanIndexBuffer.map(m_context, (void**)&data, length); - uint16_t* originalIndices = reinterpret_cast(res.pData); + if (indexed && m_state->indexBuffer != nullptr) { + D3D11_MAPPED_SUBRESOURCE res; + ID3D11Resource* originalIndexBuffer = m_state->indexBuffer->GetDXUPResource()->GetStaging(); + m_context->Map(originalIndexBuffer, 0, D3D11_MAP_READ, 0, &res); - for (UINT i = 0; i < PrimitiveCount; i++) { - data[3 * i + 0] = originalIndices[StartIndex + i + 1]; - data[3 * i + 1] = originalIndices[StartIndex + i + 2]; - data[3 * i + 2] = originalIndices[StartIndex + 0]; - } + uint16_t* originalIndices = reinterpret_cast(res.pData); - m_context->Unmap(originalIndexBuffer, 0); - } - else { - for (UINT i = 0; i < PrimitiveCount; i++) { - data[3 * i + 0] = i + 1; - data[3 * i + 1] = i + 2; - data[3 * i + 2] = 0; - } + for (UINT i = 0; i < PrimitiveCount; i++) { + data[3 * i + 0] = originalIndices[StartIndex + i + 1]; + data[3 * i + 1] = originalIndices[StartIndex + i + 2]; + data[3 * i + 2] = originalIndices[StartIndex + 0]; } - m_fanIndexBuffer.unmap(m_context); + m_context->Unmap(originalIndexBuffer, 0); } + else { + for (UINT i = 0; i < PrimitiveCount; i++) { + data[3 * i + 0] = i + 1; + data[3 * i + 1] = i + 2; + data[3 * i + 2] = 0; + } + } + + uint32_t offset = m_fanIndexBuffer.unmap(m_context, length); m_fanIndexed = indexed; - m_context->IASetIndexBuffer(m_fanIndexBuffer.getBuffer(), DXGI_FORMAT_R16_UINT, 0); + m_context->IASetIndexBuffer(m_fanIndexBuffer.getBuffer(), DXGI_FORMAT_R16_UINT, offset); HRESULT result = DrawIndexedPrimitive(D3DPT_TRIANGLELIST, BaseVertexIndex, 0, PrimitiveCount + 2, 0, newPrimitiveCount); m_state->dirtyFlags |= dirtyFlags::indexBuffer; return result; @@ -173,9 +181,8 @@ namespace dxup { UINT length = drawCount * VertexStreamZeroStride; m_upVertexBuffer.reserve(length); - m_upVertexBuffer.update(m_context, pVertexStreamZeroData, length); + uint32_t offset = m_upVertexBuffer.update(m_context, pVertexStreamZeroData, length); - const UINT offset = 0; ID3D11Buffer* buffer = m_upVertexBuffer.getBuffer(); m_context->IASetVertexBuffers(0, 1, &buffer, &VertexStreamZeroStride, &offset); @@ -209,9 +216,8 @@ namespace dxup { UINT length = (MinVertexIndex + NumVertices) * VertexStreamZeroStride; m_upVertexBuffer.reserve(length); - m_upVertexBuffer.update(m_context, pVertexStreamZeroData, length); + uint32_t offset = m_upVertexBuffer.update(m_context, pVertexStreamZeroData, length); - const UINT offset = 0; ID3D11Buffer* buffer = m_upVertexBuffer.getBuffer(); m_context->IASetVertexBuffers(0, 1, &buffer, &VertexStreamZeroStride, &offset); diff --git a/src/d3d9/d3d9_renderer.h b/src/d3d9/d3d9_renderer.h index e36b3f6..6274cd9 100644 --- a/src/d3d9/d3d9_renderer.h +++ b/src/d3d9/d3d9_renderer.h @@ -22,6 +22,7 @@ namespace dxup { void handleDepthStencilDiscard(); void blit(Direct3DSurface9* dst, Direct3DSurface9* src); + void endFrame(); private: diff --git a/src/util/misc_helpers.h b/src/util/misc_helpers.h index 2206ec7..8acd2b9 100644 --- a/src/util/misc_helpers.h +++ b/src/util/misc_helpers.h @@ -31,12 +31,12 @@ namespace dxup { } template - T alignTo(T num, T align) { + constexpr T alignTo(T num, T align) { return ((num + align - 1) / align) * align; } template - T alignDown(T num, T align) { + constexpr T alignDown(T num, T align) { return (num / align) * align; }