1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Fixed texture stage count determination

This commit is contained in:
narzoul 2023-01-29 23:48:50 +01:00
parent bfc5a0be24
commit bf9833946a
5 changed files with 42 additions and 12 deletions

View File

@ -47,11 +47,13 @@ namespace D3dDdi
, m_vertexShaderConst{} , m_vertexShaderConst{}
, m_vertexShaderConstB{} , m_vertexShaderConstB{}
, m_vertexShaderConstI{} , m_vertexShaderConstI{}
, m_vertexDecl(nullptr)
, m_changedStates(0) , m_changedStates(0)
, m_maxChangedTextureStage(0) , m_maxChangedTextureStage(0)
, m_changedTextureStageStates{} , m_changedTextureStageStates{}
, m_vsVertexFixup(createVertexShader(g_vsVertexFixup)) , m_vsVertexFixup(createVertexShader(g_vsVertexFixup))
, m_textureResource{} , m_textureResource{}
, m_pixelShader(nullptr)
, m_isLocked(false) , m_isLocked(false)
, m_spriteMode(false) , m_spriteMode(false)
{ {
@ -275,11 +277,15 @@ namespace D3dDdi
return m_textureResource[stage]; return m_textureResource[stage];
} }
UINT DeviceState::getTextureStageCount() const
{
return m_pixelShader ? m_pixelShader->textureStageCount : 0;
}
const DeviceState::VertexDecl& DeviceState::getVertexDecl() const const DeviceState::VertexDecl& DeviceState::getVertexDecl() const
{ {
static const VertexDecl emptyDecl = {}; static const VertexDecl emptyDecl = {};
auto it = m_vertexShaderDecls.find(m_app.vertexShaderDecl); return m_vertexDecl ? *m_vertexDecl : emptyDecl;
return it != m_vertexShaderDecls.end() ? it->second : emptyDecl;
} }
bool DeviceState::isColorKeyUsed() bool DeviceState::isColorKeyUsed()
@ -290,7 +296,8 @@ namespace D3dDdi
} }
bool used = false; bool used = false;
for (UINT i = 0; i < getVertexDecl().textureStageCount && !used; ++i) UINT textureStageCount = getTextureStageCount();
for (UINT i = 0; i < textureStageCount && !used; ++i)
{ {
used = !m_app.textureStageState[i][D3DDDITSS_DISABLETEXTURECOLORKEY]; used = !m_app.textureStageState[i][D3DDDITSS_DISABLETEXTURECOLORKEY];
} }
@ -426,15 +433,17 @@ namespace D3dDdi
HRESULT DeviceState::pfnCreatePixelShader(D3DDDIARG_CREATEPIXELSHADER* data, const UINT* code) HRESULT DeviceState::pfnCreatePixelShader(D3DDDIARG_CREATEPIXELSHADER* data, const UINT* code)
{ {
ShaderAssembler shaderAssembler(code, data->CodeSize);
LOG_DEBUG << "Pixel shader bytecode: " << Compat::hexDump(code, data->CodeSize); LOG_DEBUG << "Pixel shader bytecode: " << Compat::hexDump(code, data->CodeSize);
LOG_DEBUG << ShaderAssembler(code, data->CodeSize).disassemble(); LOG_DEBUG << shaderAssembler.disassemble();
HRESULT result = m_device.getOrigVtable().pfnCreatePixelShader(m_device, data, code); HRESULT result = m_device.getOrigVtable().pfnCreatePixelShader(m_device, data, code);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
m_pixelShaders.emplace(data->ShaderHandle, m_pixelShaders.emplace(data->ShaderHandle,
PixelShader{ std::vector<UINT>(code, code + data->CodeSize / 4), PixelShader{ std::vector<UINT>(code, code + data->CodeSize / 4),
std::unique_ptr<void, ResourceDeleter>( std::unique_ptr<void, ResourceDeleter>(
nullptr, ResourceDeleter(m_device, m_device.getOrigVtable().pfnDeleteVertexShaderFunc)) }); nullptr, ResourceDeleter(m_device, m_device.getOrigVtable().pfnDeleteVertexShaderFunc)),
shaderAssembler.getTextureStageCount(), false });
} }
return result; return result;
} }
@ -459,10 +468,6 @@ namespace D3dDdi
{ {
decl.texCoordOffset[vertexElements[i].UsageIndex] = vertexElements[i].Offset; decl.texCoordOffset[vertexElements[i].UsageIndex] = vertexElements[i].Offset;
decl.texCoordType[vertexElements[i].UsageIndex] = vertexElements[i].Type; decl.texCoordType[vertexElements[i].UsageIndex] = vertexElements[i].Type;
if (vertexElements[i].UsageIndex >= decl.textureStageCount)
{
decl.textureStageCount = vertexElements[i].UsageIndex + 1;
}
} }
else if (D3DDECLUSAGE_POSITIONT == vertexElements[i].Usage) else if (D3DDECLUSAGE_POSITIONT == vertexElements[i].Usage)
{ {
@ -487,6 +492,10 @@ namespace D3dDdi
auto it = m_pixelShaders.find(shader); auto it = m_pixelShaders.find(shader);
if (it != m_pixelShaders.end()) if (it != m_pixelShaders.end())
{ {
if (m_pixelShader == &it->second)
{
m_pixelShader = nullptr;
}
if (it->second.modifiedPixelShader) if (it->second.modifiedPixelShader)
{ {
deleteShader(it->second.modifiedPixelShader.release(), &State::pixelShader, deleteShader(it->second.modifiedPixelShader.release(), &State::pixelShader,
@ -500,9 +509,14 @@ namespace D3dDdi
HRESULT DeviceState::pfnDeleteVertexShaderDecl(HANDLE shader) HRESULT DeviceState::pfnDeleteVertexShaderDecl(HANDLE shader)
{ {
const bool isCurrent = m_app.vertexShaderDecl == shader;
HRESULT result = deleteShader(shader, &State::vertexShaderDecl, m_device.getOrigVtable().pfnDeleteVertexShaderDecl); HRESULT result = deleteShader(shader, &State::vertexShaderDecl, m_device.getOrigVtable().pfnDeleteVertexShaderDecl);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
if (isCurrent)
{
m_vertexDecl = nullptr;
}
m_vertexShaderDecls.erase(shader); m_vertexShaderDecls.erase(shader);
} }
return result; return result;
@ -525,6 +539,8 @@ namespace D3dDdi
{ {
m_app.pixelShader = shader; m_app.pixelShader = shader;
m_changedStates |= CS_SHADER; m_changedStates |= CS_SHADER;
auto it = m_pixelShaders.find(shader);
m_pixelShader = it != m_pixelShaders.end() ? &it->second : nullptr;
return S_OK; return S_OK;
} }
@ -636,6 +652,8 @@ namespace D3dDdi
{ {
m_app.vertexShaderDecl = shader; m_app.vertexShaderDecl = shader;
m_changedStates |= CS_SHADER; m_changedStates |= CS_SHADER;
auto it = m_vertexShaderDecls.find(shader);
m_vertexDecl = it != m_vertexShaderDecls.end() ? &it->second : nullptr;
return S_OK; return S_OK;
} }
@ -669,7 +687,8 @@ namespace D3dDdi
void DeviceState::prepareTextures() void DeviceState::prepareTextures()
{ {
for (UINT stage = 0; stage < getVertexDecl().textureStageCount; ++stage) UINT textureStageCount = getTextureStageCount();
for (UINT stage = 0; stage < textureStageCount; ++stage)
{ {
auto resource = getTextureResource(stage); auto resource = getTextureResource(stage);
if (resource) if (resource)

View File

@ -80,7 +80,6 @@ namespace D3dDdi
std::vector<D3DDDIVERTEXELEMENT> elements; std::vector<D3DDDIVERTEXELEMENT> elements;
std::array<UINT, 8> texCoordOffset; std::array<UINT, 8> texCoordOffset;
std::array<UINT, 8> texCoordType; std::array<UINT, 8> texCoordType;
UINT textureStageCount;
bool isTransformed; bool isTransformed;
}; };
@ -130,6 +129,7 @@ namespace D3dDdi
const State& getAppState() const { return m_app; } const State& getAppState() const { return m_app; }
const State& getCurrentState() const { return m_current; } const State& getCurrentState() const { return m_current; }
Resource* getTextureResource(UINT stage); Resource* getTextureResource(UINT stage);
UINT getTextureStageCount() const;
const VertexDecl& getVertexDecl() const; const VertexDecl& getVertexDecl() const;
HANDLE getVertexFixupDecl() const { return m_vsVertexFixup.get(); } HANDLE getVertexFixupDecl() const { return m_vsVertexFixup.get(); }
bool isLocked() const { return m_isLocked; } bool isLocked() const { return m_isLocked; }
@ -153,6 +153,7 @@ namespace D3dDdi
{ {
std::vector<UINT> tokens; std::vector<UINT> tokens;
std::unique_ptr<void, ResourceDeleter> modifiedPixelShader; std::unique_ptr<void, ResourceDeleter> modifiedPixelShader;
UINT textureStageCount;
bool isModified; bool isModified;
}; };
@ -217,6 +218,7 @@ namespace D3dDdi
std::array<ShaderConstB, 16> m_vertexShaderConstB; std::array<ShaderConstB, 16> m_vertexShaderConstB;
std::array<ShaderConstI, 16> m_vertexShaderConstI; std::array<ShaderConstI, 16> m_vertexShaderConstI;
std::map<HANDLE, VertexDecl> m_vertexShaderDecls; std::map<HANDLE, VertexDecl> m_vertexShaderDecls;
VertexDecl* m_vertexDecl;
UINT m_changedStates; UINT m_changedStates;
UINT m_maxChangedTextureStage; UINT m_maxChangedTextureStage;
UINT m_usedTextureStages; UINT m_usedTextureStages;
@ -225,6 +227,7 @@ namespace D3dDdi
std::unique_ptr<void, ResourceDeleter> m_vsVertexFixup; std::unique_ptr<void, ResourceDeleter> m_vsVertexFixup;
std::array<Resource*, 8> m_textureResource; std::array<Resource*, 8> m_textureResource;
std::map<HANDLE, PixelShader> m_pixelShaders; std::map<HANDLE, PixelShader> m_pixelShaders;
PixelShader* m_pixelShader;
bool m_isLocked; bool m_isLocked;
bool m_spriteMode; bool m_spriteMode;
}; };

View File

@ -829,9 +829,10 @@ namespace D3dDdi
auto& state = m_device.getState(); auto& state = m_device.getState();
auto& appState = state.getAppState(); auto& appState = state.getAppState();
auto& decl = state.getVertexDecl(); auto& decl = state.getVertexDecl();
auto textureStageCount = state.getTextureStageCount();
auto vertices = m_streamSource.vertices + baseVertexIndex * m_streamSource.stride; auto vertices = m_streamSource.vertices + baseVertexIndex * m_streamSource.stride;
for (UINT stage = 0; stage < decl.textureStageCount; ++stage) for (UINT stage = 0; stage < textureStageCount; ++stage)
{ {
const UINT D3DDECLTYPE_FLOAT2 = 1; const UINT D3DDECLTYPE_FLOAT2 = 1;
if (!appState.textures[stage] || if (!appState.textures[stage] ||

View File

@ -696,6 +696,12 @@ namespace D3dDdi
return static_cast<ShaderType>(m_tokens.front() >> 16); return static_cast<ShaderType>(m_tokens.front() >> 16);
} }
UINT ShaderAssembler::getTextureStageCount()
{
auto usedSamplers = getUsedRegisterNumbers(D3DSPR_SAMPLER);
return usedSamplers.empty() ? 0 : (*usedSamplers.rbegin() + 1);
}
template <typename Token> template <typename Token>
Token ShaderAssembler::getToken(UINT offset) const Token ShaderAssembler::getToken(UINT offset) const
{ {

View File

@ -16,6 +16,7 @@ namespace D3dDdi
bool addAlphaTest(UINT alphaRef); bool addAlphaTest(UINT alphaRef);
std::string disassemble(); std::string disassemble();
UINT getTextureStageCount();
const std::vector<UINT>& getTokens() const { return m_tokens; } const std::vector<UINT>& getTokens() const { return m_tokens; }
private: private: