Skip to content

Commit

Permalink
[d3d9] Refactor state blocks to allocate dynamically.
Browse files Browse the repository at this point in the history
  • Loading branch information
misyltoad committed Mar 7, 2023
1 parent caf3103 commit 4bd9f36
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 71 deletions.
22 changes: 11 additions & 11 deletions src/d3d9/d3d9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5147,9 +5147,9 @@ namespace dxvk {
if (CanSWVP())
return UploadSoftwareConstantSet(m_state.vsConsts, m_vsLayout);
else
return UploadConstantSet<ShaderStage, D3D9ShaderConstantsVSHardware>(m_state.vsConsts, m_vsLayout, m_state.vertexShader);
return UploadConstantSet<ShaderStage, D3D9ShaderConstantsVSHardware>(m_state.vsConsts.get(), m_vsLayout, m_state.vertexShader);
} else {
return UploadConstantSet<ShaderStage, D3D9ShaderConstantsPS> (m_state.psConsts, m_psLayout, m_state.pixelShader);
return UploadConstantSet<ShaderStage, D3D9ShaderConstantsPS> (m_state.psConsts.get(), m_psLayout, m_state.pixelShader);
}
}

Expand Down Expand Up @@ -6257,7 +6257,7 @@ namespace dxvk {

if (likely(!CanSWVP())) {
UpdateVertexBoolSpec(
m_state.vsConsts.bConsts[0] &
m_state.vsConsts->bConsts[0] &
m_consts[DxsoProgramType::VertexShader].meta.boolConstantMask);
} else
UpdateVertexBoolSpec(0);
Expand Down Expand Up @@ -6285,7 +6285,7 @@ namespace dxvk {
UpdatePixelShaderSamplerSpec(m_textureTypes, programInfo.minorVersion() >= 4 ? 0u : projected, fetch4); // For implicit samplers...

UpdatePixelBoolSpec(
m_state.psConsts.bConsts[0] &
m_state.psConsts->bConsts[0] &
m_consts[DxsoProgramType::PixelShader].meta.boolConstantMask);
}
else {
Expand Down Expand Up @@ -6526,16 +6526,16 @@ namespace dxvk {


void D3D9DeviceEx::SetVertexBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits) {
m_state.vsConsts.bConsts[idx] &= ~mask;
m_state.vsConsts.bConsts[idx] |= bits & mask;
m_state.vsConsts->bConsts[idx] &= ~mask;
m_state.vsConsts->bConsts[idx] |= bits & mask;

m_consts[DxsoProgramTypes::VertexShader].dirty = true;
}


void D3D9DeviceEx::SetPixelBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits) {
m_state.psConsts.bConsts[idx] &= ~mask;
m_state.psConsts.bConsts[idx] |= bits & mask;
m_state.psConsts->bConsts[idx] &= ~mask;
m_state.psConsts->bConsts[idx] |= bits & mask;

m_consts[DxsoProgramTypes::PixelShader].dirty = true;
}
Expand Down Expand Up @@ -7246,11 +7246,11 @@ namespace dxvk {
for (uint32_t i = 0; i < caps::MaxStreams; i++)
m_state.streamFreq[i] = 1;

for (uint32_t i = 0; i < m_state.textures.size(); i++)
for (uint32_t i = 0; i < m_state.textures->size(); i++)
SetStateTexture(i, nullptr);

EmitCs([
cSize = m_state.textures.size()
cSize = m_state.textures->size()
](DxvkContext* ctx) {
VkShaderStageFlags stage = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;

Expand All @@ -7265,7 +7265,7 @@ namespace dxvk {
m_depthTextures = 0;
m_cubeTextures = 0;

auto& ss = m_state.samplerStates;
auto& ss = m_state.samplerStates.get();
for (uint32_t i = 0; i < ss.size(); i++) {
auto& state = ss[i];
state[D3DSAMP_ADDRESSU] = D3DTADDRESS_WRAP;
Expand Down
6 changes: 3 additions & 3 deletions src/d3d9/d3d9_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -1093,13 +1093,13 @@ namespace dxvk {
return D3DERR_INVALIDCALL;

if constexpr (ConstantType == D3D9ConstantType::Float) {
const float* source = set.fConsts[StartRegister].data;
const float* source = set->fConsts[StartRegister].data;
const size_t size = Count * sizeof(Vector4);

std::memcpy(pConstantData, source, size);
}
else if constexpr (ConstantType == D3D9ConstantType::Int) {
const int* source = set.iConsts[StartRegister].data;
const int* source = set->iConsts[StartRegister].data;
const size_t size = Count * sizeof(Vector4i);

std::memcpy(pConstantData, source, size);
Expand All @@ -1112,7 +1112,7 @@ namespace dxvk {

const uint32_t bit = (1u << bitIdx);

bool constValue = set.bConsts[arrayIdx] & bit;
bool constValue = set->bConsts[arrayIdx] & bit;
pConstantData[i] = constValue ? TRUE : FALSE;
}
}
Expand Down
32 changes: 20 additions & 12 deletions src/d3d9/d3d9_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,25 @@

namespace dxvk {

D3D9CapturableState::D3D9CapturableState() {
for (uint32_t i = 0; i < streamFreq.size(); i++)
streamFreq[i] = 1;

for (uint32_t i = 0; i < enabledLightIndices.size(); i++)
enabledLightIndices[i] = UINT32_MAX;
}

D3D9CapturableState::~D3D9CapturableState() {
for (uint32_t i = 0; i < textures.size(); i++)
TextureChangePrivate(textures[i], nullptr);
}
template <template <typename T> typename ItemType>
D3D9State<ItemType>::D3D9State() {
for (uint32_t i = 0; i < streamFreq.size(); i++)
streamFreq[i] = 1;

for (uint32_t i = 0; i < enabledLightIndices.size(); i++)
enabledLightIndices[i] = UINT32_MAX;
}


template <template <typename T> typename ItemType>
D3D9State<ItemType>::~D3D9State() {
if (textures) {
for (uint32_t i = 0; i < textures->size(); i++)
TextureChangePrivate(textures[i], nullptr);
}
}

template D3D9State<dynamic_item>;
template D3D9State<static_item>;

}
118 changes: 84 additions & 34 deletions src/d3d9/d3d9_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,64 +181,114 @@ namespace dxvk {
0.0f // Phi
};

struct D3D9CapturableState {
D3D9CapturableState();
template <typename T>
class dynamic_item {
public:
auto& operator [] (size_t idx) { ensure(); return (*m_data)[idx]; }
const auto& operator [] (size_t idx) const { ensure(); return (*m_data)[idx]; }

~D3D9CapturableState();
T& operator=(const T& x) { ensure(); *m_data = x; return *m_data; }

Com<D3D9VertexDecl, false> vertexDecl;
Com<D3D9IndexBuffer, false> indices;
const T* operator -> () const { ensure(); return m_data.get(); }
T* operator -> () { ensure(); return m_data.get(); }

std::array<DWORD, RenderStateCount> renderStates = {};
const T* operator & () const { ensure(); return m_data.get(); }
T* operator & () { ensure(); return m_data.get(); }

std::array<
operator bool() { return m_data != nullptr; }
operator T() { ensure(); return *m_data; }

void ensure() const { if (!m_data) m_data = std::make_unique<T>(); }

T& get() { ensure(); return *m_data; }
private:
mutable std::unique_ptr<T> m_data;
};

template <typename T>
class static_item {
public:
auto& operator [] (size_t idx) { return m_data[idx]; }
const auto& operator [] (size_t idx) const { return m_data[idx]; }

T& operator=(const T& x) { m_data = x; return m_data; }

operator bool() { return true; }
operator T() { return m_data; }

const T* operator -> () const { return &m_data; }
T* operator -> () { return &m_data; }

const T* operator & () const { return &m_data; }
T* operator & () { return &m_data; }

T& get() { return m_data; }
private:
T m_data;
};

template <template <typename T> typename ItemType>
struct D3D9State {
D3D9State();
~D3D9State();

Com<D3D9VertexDecl, false> vertexDecl;
Com<D3D9IndexBuffer, false> indices;

ItemType<std::array<DWORD, RenderStateCount>> renderStates = {};

ItemType<std::array<
std::array<DWORD, SamplerStateCount>,
SamplerCount> samplerStates = {};
SamplerCount>> samplerStates = {};

std::array<D3D9VBO, caps::MaxStreams> vertexBuffers = {};
ItemType<std::array<D3D9VBO, caps::MaxStreams>> vertexBuffers = {};

std::array<
ItemType<std::array<
IDirect3DBaseTexture9*,
SamplerCount> textures = {};
SamplerCount>> textures = {};

Com<D3D9VertexShader, false> vertexShader;
Com<D3D9PixelShader, false> pixelShader;
Com<D3D9VertexShader, false> vertexShader;
Com<D3D9PixelShader, false> pixelShader;

D3DVIEWPORT9 viewport = {};
RECT scissorRect = {};
D3DVIEWPORT9 viewport = {};
RECT scissorRect = {};

std::array<
ItemType<std::array<
D3D9ClipPlane,
caps::MaxClipPlanes> clipPlanes = {};
caps::MaxClipPlanes>> clipPlanes = {};

std::array<
ItemType<std::array<
std::array<DWORD, TextureStageStateCount>,
caps::TextureStageCount> textureStages = {};
caps::TextureStageCount>> textureStages = {};

D3D9ShaderConstantsVSSoftware vsConsts;
D3D9ShaderConstantsPS psConsts;
ItemType<D3D9ShaderConstantsVSSoftware> vsConsts;
ItemType<D3D9ShaderConstantsPS> psConsts;

std::array<UINT, caps::MaxStreams> streamFreq = {};
std::array<UINT, caps::MaxStreams> streamFreq = {};

std::array<Matrix4, caps::MaxTransforms> transforms = {};
ItemType<std::array<Matrix4, caps::MaxTransforms>> transforms = {};

D3DMATERIAL9 material = {};
ItemType<D3DMATERIAL9> material = {};

std::vector<std::optional<D3DLIGHT9>> lights;
std::array<DWORD, caps::MaxEnabledLights> enabledLightIndices;
std::vector<std::optional<D3DLIGHT9>> lights;
std::array<DWORD, caps::MaxEnabledLights> enabledLightIndices;

bool IsLightEnabled(DWORD Index) {
const auto& indices = enabledLightIndices;
return std::find(indices.begin(), indices.end(), Index) != indices.end();
}
};

using D3D9CapturableState = D3D9State<dynamic_item>;
using D3D9DeviceState = D3D9State<static_item>;

template <
DxsoProgramType ProgramType,
D3D9ConstantType ConstantType,
typename T>
typename T,
typename StateType>
HRESULT UpdateStateConstants(
D3D9CapturableState* pState,
StateType* pState,
UINT StartRegister,
const T* pConstantData,
UINT Count,
Expand All @@ -249,17 +299,17 @@ namespace dxvk {
if (!FloatEmu) {
size_t size = Count * sizeof(Vector4);

std::memcpy(set.fConsts[StartRegister].data, pConstantData, size);
std::memcpy(set->fConsts[StartRegister].data, pConstantData, size);
}
else {
for (UINT i = 0; i < Count; i++)
set.fConsts[StartRegister + i] = replaceNaN(pConstantData + (i * 4));
set->fConsts[StartRegister + i] = replaceNaN(pConstantData + (i * 4));
}
}
else if constexpr (ConstantType == D3D9ConstantType::Int) {
size_t size = Count * sizeof(Vector4i);

std::memcpy(set.iConsts[StartRegister].data, pConstantData, size);
std::memcpy(set->iConsts[StartRegister].data, pConstantData, size);
}
else {
for (uint32_t i = 0; i < Count; i++) {
Expand All @@ -269,9 +319,9 @@ namespace dxvk {

const uint32_t bit = 1u << bitIdx;

set.bConsts[arrayIdx] &= ~bit;
set->bConsts[arrayIdx] &= ~bit;
if (pConstantData[i])
set.bConsts[arrayIdx] |= bit;
set->bConsts[arrayIdx] |= bit;
}
}

Expand All @@ -283,7 +333,7 @@ namespace dxvk {
: UpdateHelper(pState->psConsts);
}

struct Direct3DState9 : public D3D9CapturableState {
struct Direct3DState9 : public D3D9DeviceState {

std::array<Com<D3D9Surface, false>, caps::MaxSimultaneousRenderTargets> renderTargets;
Com<D3D9Surface, false> depthStencil;
Expand Down
8 changes: 4 additions & 4 deletions src/d3d9/d3d9_stateblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,15 +333,15 @@ namespace dxvk {


HRESULT D3D9StateBlock::SetVertexBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits) {
m_state.vsConsts.bConsts[idx] &= ~mask;
m_state.vsConsts.bConsts[idx] |= bits & mask;
m_state.vsConsts->bConsts[idx] &= ~mask;
m_state.vsConsts->bConsts[idx] |= bits & mask;
return D3D_OK;
}


HRESULT D3D9StateBlock::SetPixelBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits) {
m_state.psConsts.bConsts[idx] &= ~mask;
m_state.psConsts.bConsts[idx] |= bits & mask;
m_state.psConsts->bConsts[idx] &= ~mask;
m_state.psConsts->bConsts[idx] |= bits & mask;
return D3D_OK;
}

Expand Down
Loading

0 comments on commit 4bd9f36

Please sign in to comment.