Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[d3d9] Refactor state blocks to allocate dynamically. #3248

Merged
merged 1 commit into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 struct D3D9State<dynamic_item>;
template struct 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