Commit 3dc00a52 authored by Joshua Ashton's avatar Joshua Ashton 🐸

[d3d9] Grow dynamic buffers, use NO_OVERWRITE and offsets.

parent a3a8075e
Pipeline #56 passed with stage
in 1 minute and 40 seconds
......@@ -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<ID3D11Buffer> 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
......@@ -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<ID3D11Buffer> m_buffer;
uint32_t m_length;
uint32_t m_size;
uint32_t m_offset;
uint32_t m_bindFlags;
};
......
......@@ -6,6 +6,7 @@
#include <memory>
#include <cstring>
#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<ID3D11Buffer> m_buffer;
D3D11DynamicBuffer m_buffer;
uint32_t m_offset;
};
}
\ No newline at end of file
......@@ -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) {
......
......@@ -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<uint16_t*>(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<uint16_t*>(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);
......
......@@ -22,6 +22,7 @@ namespace dxup {
void handleDepthStencilDiscard();
void blit(Direct3DSurface9* dst, Direct3DSurface9* src);
void endFrame();
private:
......
......@@ -31,12 +31,12 @@ namespace dxup {
}
template <typename T>
T alignTo(T num, T align) {
constexpr T alignTo(T num, T align) {
return ((num + align - 1) / align) * align;
}
template <typename T>
T alignDown(T num, T align) {
constexpr T alignDown(T num, T align) {
return (num / align) * align;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment