Skip to content
This repository has been archived by the owner on Nov 19, 2019. It is now read-only.

Commit

Permalink
[d3d9] Grow dynamic buffers, use NO_OVERWRITE and offsets.
Browse files Browse the repository at this point in the history
  • Loading branch information
misyltoad committed Jan 29, 2019
1 parent a3a8075 commit 3dc00a5
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 73 deletions.
45 changes: 27 additions & 18 deletions src/d3d9/d3d11_dynamic_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
}
10 changes: 6 additions & 4 deletions src/d3d9/d3d11_dynamic_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,20 @@ 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();

private:

ID3D11Device* m_device;
Com<ID3D11Buffer> m_buffer;
uint32_t m_length;
uint32_t m_size;
uint32_t m_offset;
uint32_t m_bindFlags;

};
Expand Down
57 changes: 36 additions & 21 deletions src/d3d9/d3d9_constant_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <memory>
#include <cstring>
#include "../util/vectypes.h"
#include "d3d11_dynamic_buffer.h"

namespace dxup {

Expand All @@ -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));

Expand All @@ -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:
Expand All @@ -76,7 +90,8 @@ namespace dxup {
ID3D11Device1* m_device;
ID3D11DeviceContext1* m_context;

Com<ID3D11Buffer> m_buffer;
D3D11DynamicBuffer m_buffer;
uint32_t m_offset;
};

}
1 change: 1 addition & 0 deletions src/d3d9/d3d9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
62 changes: 34 additions & 28 deletions src/d3d9/d3d9_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions src/d3d9/d3d9_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace dxup {
void handleDepthStencilDiscard();

void blit(Direct3DSurface9* dst, Direct3DSurface9* src);
void endFrame();

private:

Expand Down
4 changes: 2 additions & 2 deletions src/util/misc_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit 3dc00a5

Please sign in to comment.