-
Notifications
You must be signed in to change notification settings - Fork 910
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] workaround for EDG frontend based compilers #3800
[d3d9] workaround for EDG frontend based compilers #3800
Conversation
@daveedvdv |
Although relying on the order of passes within the compiler definitely sounds a bit like depending on undefined behavior (though I'm not sure, maybe the expectations from According to this example, it should be possible to explicitly specialize a template based on enum values. So, it's possible to implement "callbacks" for the three types either by specializing a function (however, it appears that functions may be specialized only fully — and that would restrict the type template <
D3D9ConstantType ConstantType,
typename T,
typename StateType>
class StateConstantUpdater {};
template <
typename T,
typename StateType>
class StateConstantUpdater<D3D9ConstantType::Float, T, StateType> {
public:
static HRESULT UpdateStateConstants(
StateType* pState,
UINT StartRegister,
const T* pConstantData,
UINT Count,
bool FloatEmu) {
if (!FloatEmu) {
size_t size = Count * sizeof(Vector4);
std::memcpy(set->fConsts[StartRegister].data, pConstantData, size);
}
else {
for (UINT i = 0; i < Count; i++)
set->fConsts[StartRegister + i] = replaceNaN(pConstantData + (i * 4));
}
return D3D_OK;
}
};
template <
typename T,
typename StateType>
class StateConstantUpdater<D3D9ConstantType::Int, T, StateType> {
public:
static HRESULT UpdateStateConstants(
StateType* pState,
UINT StartRegister,
const T* pConstantData,
UINT Count,
bool FloatEmu) {
size_t size = Count * sizeof(Vector4i);
std::memcpy(set->iConsts[StartRegister].data, pConstantData, size);
return D3D_OK;
}
};
template <
typename T,
typename StateType>
class StateConstantUpdater<D3D9ConstantType::Bool, T, StateType> {
public:
static HRESULT UpdateStateConstants(
StateType* pState,
UINT StartRegister,
const T* pConstantData,
UINT Count,
bool FloatEmu) {
for (uint32_t i = 0; i < Count; i++) {
const uint32_t constantIdx = StartRegister + i;
const uint32_t arrayIdx = constantIdx / 32;
const uint32_t bitIdx = constantIdx % 32;
const uint32_t bit = 1u << bitIdx;
set->bConsts[arrayIdx] &= ~bit;
if (pConstantData[i])
set->bConsts[arrayIdx] |= bit;
}
return D3D_OK;
}
}; Though I haven't checked, but maybe for nested templates (like a template class in a template function, or even a template function in a template function — in which case maybe it can be fully specialized) it should even be possible to reuse parameters: template <
DxsoProgramType ProgramType,
D3D9ConstantType ConstantType,
typename T,
typename StateType>
HRESULT UpdateStateConstants(
StateType* pState,
UINT StartRegister,
const T* pConstantData,
UINT Count,
bool FloatEmu) {
template <D3D9ConstantType ConstantType>
class StateConstantUpdater {};
template <>
class StateConstantUpdater<D3D9ConstantType::Float> {
public:
static HRESULT UpdateStateConstants(
StateType* pState,
UINT StartRegister,
const T* pConstantData,
UINT Count,
bool FloatEmu) {
if (!FloatEmu) {
size_t size = Count * sizeof(Vector4);
std::memcpy(set->fConsts[StartRegister].data, pConstantData, size);
}
else {
for (UINT i = 0; i < Count; i++)
set->fConsts[StartRegister + i] = replaceNaN(pConstantData + (i * 4));
}
return D3D_OK;
}
};
template <>
class StateConstantUpdater<D3D9ConstantType::Int> {
public:
static HRESULT UpdateStateConstants(
StateType* pState,
UINT StartRegister,
const T* pConstantData,
UINT Count,
bool FloatEmu) {
size_t size = Count * sizeof(Vector4i);
std::memcpy(set->iConsts[StartRegister].data, pConstantData, size);
return D3D_OK;
}
};
template <>
class StateConstantUpdater<D3D9ConstantType::Bool> {
public:
static HRESULT UpdateStateConstants(
StateType* pState,
UINT StartRegister,
const T* pConstantData,
UINT Count,
bool FloatEmu) {
for (uint32_t i = 0; i < Count; i++) {
const uint32_t constantIdx = StartRegister + i;
const uint32_t arrayIdx = constantIdx / 32;
const uint32_t bitIdx = constantIdx % 32;
const uint32_t bit = 1u << bitIdx;
set->bConsts[arrayIdx] &= ~bit;
if (pConstantData[i])
set->bConsts[arrayIdx] |= bit;
}
return D3D_OK;
}
};
return ProgramType == DxsoProgramTypes::VertexShader
? StateConstantUpdater<ConstantType>::UpdateStateConstants(pState->vsConsts,
StartRegister,
pConstantData,
Count,
FloatEmu)
: StateConstantUpdater<ConstantType>::UpdateStateConstants(pState->psConsts,
StartRegister,
pConstantData,
Count,
FloatEmu);
} (or the same with a Another option would be to replace the |
I redid my patch. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Sorry, but I gotta ask: Why are you even using that compiler? Why not just use GCC, MSVC or Clang? |
Hallo Robin! Sorry for long reply. On my hardware platform (Elbrus-2000) only one compiler is available so far and it uses the EDG frontend. |
EDG frontend based compilers can't find suitable constructor to convert from "const int *"
Added workaround for this case.