1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-19 05:52:11 +01:00

[d3d9] Refactor state blocks to allocate dynamically.

This commit is contained in:
Joshua Ashton 2023-02-11 21:39:05 +00:00 committed by Joshie
parent 8ecd1b3b6b
commit 996acbe3f2
6 changed files with 127 additions and 69 deletions

View File

@ -5145,9 +5145,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);
}
}
@ -6255,7 +6255,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);
@ -6283,7 +6283,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 {
@ -6524,16 +6524,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;
}
@ -7244,11 +7244,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;
@ -7263,7 +7263,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;

View File

@ -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);
@ -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;
}
}

View File

@ -4,17 +4,25 @@
namespace dxvk {
D3D9CapturableState::D3D9CapturableState() {
for (uint32_t i = 0; i < streamFreq.size(); i++)
streamFreq[i] = 1;
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;
}
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() {
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>;
}

View File

@ -181,51 +181,97 @@ 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 {
const auto& indices = enabledLightIndices;
@ -233,12 +279,16 @@ namespace dxvk {
}
};
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,
@ -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++) {
@ -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;
}
}
@ -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;

View File

@ -339,15 +339,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;
}

View File

@ -264,7 +264,7 @@ namespace dxvk {
for (uint32_t consts : bit::BitMask(m_captures.vsConsts.fConsts.dword(i))) {
uint32_t idx = i * 32 + consts;
dst->SetVertexShaderConstantF(idx, (float*)&src->vsConsts.fConsts[idx], 1);
dst->SetVertexShaderConstantF(idx, (float*)&src->vsConsts->fConsts[idx], 1);
}
}
@ -272,13 +272,13 @@ namespace dxvk {
for (uint32_t consts : bit::BitMask(m_captures.vsConsts.iConsts.dword(i))) {
uint32_t idx = i * 32 + consts;
dst->SetVertexShaderConstantI(idx, (int*)&src->vsConsts.iConsts[idx], 1);
dst->SetVertexShaderConstantI(idx, (int*)&src->vsConsts->iConsts[idx], 1);
}
}
if (m_captures.vsConsts.bConsts.any()) {
for (uint32_t i = 0; i < m_captures.vsConsts.bConsts.dwordCount(); i++)
dst->SetVertexBoolBitfield(i, m_captures.vsConsts.bConsts.dword(i), src->vsConsts.bConsts[i]);
dst->SetVertexBoolBitfield(i, m_captures.vsConsts.bConsts.dword(i), src->vsConsts->bConsts[i]);
}
}
@ -287,7 +287,7 @@ namespace dxvk {
for (uint32_t consts : bit::BitMask(m_captures.psConsts.fConsts.dword(i))) {
uint32_t idx = i * 32 + consts;
dst->SetPixelShaderConstantF(idx, (float*)&src->psConsts.fConsts[idx], 1);
dst->SetPixelShaderConstantF(idx, (float*)&src->psConsts->fConsts[idx], 1);
}
}
@ -295,13 +295,13 @@ namespace dxvk {
for (uint32_t consts : bit::BitMask(m_captures.psConsts.iConsts.dword(i))) {
uint32_t idx = i * 32 + consts;
dst->SetPixelShaderConstantI(idx, (int*)&src->psConsts.iConsts[idx], 1);
dst->SetPixelShaderConstantI(idx, (int*)&src->psConsts->iConsts[idx], 1);
}
}
if (m_captures.psConsts.bConsts.any()) {
for (uint32_t i = 0; i < m_captures.psConsts.bConsts.dwordCount(); i++)
dst->SetPixelBoolBitfield(i, m_captures.psConsts.bConsts.dword(i), src->psConsts.bConsts[i]);
dst->SetPixelBoolBitfield(i, m_captures.psConsts.bConsts.dword(i), src->psConsts->bConsts[i]);
}
}
@ -394,7 +394,7 @@ namespace dxvk {
D3D9CapturableState m_state;
D3D9StateCaptures m_captures;
D3D9CapturableState* m_deviceState;
D3D9DeviceState* m_deviceState;
bool m_applying = false;