mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Fixed rendering with non-default texture coordinate indexes
Fixes rendering issues in Ultima IX when MultiPassChromakey=1 or 2.
This commit is contained in:
parent
2da9c87a21
commit
f0946f2437
@ -90,8 +90,8 @@ namespace D3dDdi
|
|||||||
, m_vertexDecl(nullptr)
|
, m_vertexDecl(nullptr)
|
||||||
, m_changedStates(0)
|
, m_changedStates(0)
|
||||||
, m_maxChangedTextureStage(0)
|
, m_maxChangedTextureStage(0)
|
||||||
|
, m_texCoordIndexes(0)
|
||||||
, m_changedTextureStageStates{}
|
, m_changedTextureStageStates{}
|
||||||
, m_vsVertexFixup(createVertexShader(g_vsVertexFixup))
|
|
||||||
, m_textureResource{}
|
, m_textureResource{}
|
||||||
, m_pixelShader(nullptr)
|
, m_pixelShader(nullptr)
|
||||||
, m_isLocked(false)
|
, m_isLocked(false)
|
||||||
@ -187,6 +187,7 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
m_current.textureStageState[i].fill(UNINITIALIZED_STATE);
|
m_current.textureStageState[i].fill(UNINITIALIZED_STATE);
|
||||||
m_current.textureStageState[i][D3DDDITSS_TEXCOORDINDEX] = i;
|
m_current.textureStageState[i][D3DDDITSS_TEXCOORDINDEX] = i;
|
||||||
|
m_texCoordIndexes |= i << (i * 3);
|
||||||
|
|
||||||
// When ADDRESSU or ADDRESSV is set to CLAMP, their value is overridden by D3DTSS_ADDRESS.
|
// When ADDRESSU or ADDRESSV is set to CLAMP, their value is overridden by D3DTSS_ADDRESS.
|
||||||
// Setting this to CLAMP makes them behave as expected, instead of as WRAP,
|
// Setting this to CLAMP makes them behave as expected, instead of as WRAP,
|
||||||
@ -224,11 +225,11 @@ namespace D3dDdi
|
|||||||
updateConfig();
|
updateConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<void, ResourceDeleter> DeviceState::createVertexShader(const BYTE* code, UINT size)
|
std::unique_ptr<void, ResourceDeleter> DeviceState::createVertexShader(const UINT* code, UINT size)
|
||||||
{
|
{
|
||||||
D3DDDIARG_CREATEVERTEXSHADERFUNC data = {};
|
D3DDDIARG_CREATEVERTEXSHADERFUNC data = {};
|
||||||
data.Size = size;
|
data.Size = size;
|
||||||
if (FAILED(m_device.getOrigVtable().pfnCreateVertexShaderFunc(m_device, &data, reinterpret_cast<const UINT*>(code))))
|
if (FAILED(m_device.getOrigVtable().pfnCreateVertexShaderFunc(m_device, &data, code)))
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -326,6 +327,26 @@ namespace D3dDdi
|
|||||||
return m_vertexDecl ? *m_vertexDecl : emptyDecl;
|
return m_vertexDecl ? *m_vertexDecl : emptyDecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HANDLE DeviceState::getVsVertexFixup()
|
||||||
|
{
|
||||||
|
auto it = m_vsVertexFixups.find(m_texCoordIndexes);
|
||||||
|
if (it != m_vsVertexFixups.end())
|
||||||
|
{
|
||||||
|
return it->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<UINT, 8> texCoordIndexes = {};
|
||||||
|
for (UINT i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
texCoordIndexes[i] = m_app.textureStageState[i][D3DDDITSS_TEXCOORDINDEX];
|
||||||
|
}
|
||||||
|
|
||||||
|
D3dDdi::ShaderAssembler shaderAssembler(reinterpret_cast<const UINT*>(g_vsVertexFixup), sizeof(g_vsVertexFixup));
|
||||||
|
shaderAssembler.applyTexCoordIndexes(texCoordIndexes);
|
||||||
|
return m_vsVertexFixups.emplace(m_texCoordIndexes,
|
||||||
|
createVertexShader(shaderAssembler.getTokens().data(), shaderAssembler.getTokens().size() * 4)).first->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
bool DeviceState::isColorKeyUsed()
|
bool DeviceState::isColorKeyUsed()
|
||||||
{
|
{
|
||||||
if (!m_app.renderState[D3DDDIRS_COLORKEYENABLE])
|
if (!m_app.renderState[D3DDDIRS_COLORKEYENABLE])
|
||||||
@ -669,6 +690,12 @@ namespace D3dDdi
|
|||||||
m_changedRenderStates.set(D3DDDIRS_COLORKEYENABLE);
|
m_changedRenderStates.set(D3DDDIRS_COLORKEYENABLE);
|
||||||
m_changedStates |= CS_RENDER_STATE;
|
m_changedStates |= CS_RENDER_STATE;
|
||||||
}
|
}
|
||||||
|
else if (D3DDDITSS_TEXCOORDINDEX == data->State)
|
||||||
|
{
|
||||||
|
m_texCoordIndexes &= ~(7 << (data->Stage * 3));
|
||||||
|
m_texCoordIndexes |= data->Value << (data->Stage * 3);
|
||||||
|
m_changedStates |= CS_SHADER;
|
||||||
|
}
|
||||||
|
|
||||||
m_app.textureStageState[data->Stage][data->State] = data->Value;
|
m_app.textureStageState[data->Stage][data->State] = data->Value;
|
||||||
m_changedTextureStageStates[data->Stage].set(data->State);
|
m_changedTextureStageStates[data->Stage].set(data->State);
|
||||||
@ -1203,14 +1230,7 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
setPixelShader(mapPixelShader(m_app.pixelShader));
|
setPixelShader(mapPixelShader(m_app.pixelShader));
|
||||||
setVertexShaderDecl(m_app.vertexShaderDecl);
|
setVertexShaderDecl(m_app.vertexShaderDecl);
|
||||||
if (getVertexDecl().isTransformed)
|
setVertexShaderFunc(getVertexDecl().isTransformed ? getVsVertexFixup() : m_app.vertexShaderFunc);
|
||||||
{
|
|
||||||
setVertexShaderFunc(m_vsVertexFixup.get());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setVertexShaderFunc(m_app.vertexShaderFunc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceState::updateStreamSource()
|
void DeviceState::updateStreamSource()
|
||||||
|
@ -156,7 +156,6 @@ namespace D3dDdi
|
|||||||
Resource* getTextureResource(UINT stage);
|
Resource* getTextureResource(UINT stage);
|
||||||
UINT getTextureStageCount() const;
|
UINT getTextureStageCount() const;
|
||||||
const VertexDecl& getVertexDecl() const;
|
const VertexDecl& getVertexDecl() const;
|
||||||
HANDLE getVertexFixupDecl() const { return m_vsVertexFixup.get(); }
|
|
||||||
bool isLocked() const { return m_isLocked; }
|
bool isLocked() const { return m_isLocked; }
|
||||||
void onDestroyResource(Resource* resource, HANDLE resourceHandle);
|
void onDestroyResource(Resource* resource, HANDLE resourceHandle);
|
||||||
void updateConfig();
|
void updateConfig();
|
||||||
@ -183,13 +182,14 @@ namespace D3dDdi
|
|||||||
template <int N>
|
template <int N>
|
||||||
std::unique_ptr<void, ResourceDeleter> createVertexShader(const BYTE(&code)[N])
|
std::unique_ptr<void, ResourceDeleter> createVertexShader(const BYTE(&code)[N])
|
||||||
{
|
{
|
||||||
return createVertexShader(code, N);
|
return createVertexShader(reinterpret_cast<const UINT*>(code), N);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<void, ResourceDeleter> DeviceState::createVertexShader(const BYTE* code, UINT size);
|
std::unique_ptr<void, ResourceDeleter> DeviceState::createVertexShader(const UINT* code, UINT size);
|
||||||
HRESULT deleteShader(HANDLE shader, HANDLE State::* shaderMember,
|
HRESULT deleteShader(HANDLE shader, HANDLE State::* shaderMember,
|
||||||
HRESULT(APIENTRY* origDeleteShaderFunc)(HANDLE, HANDLE));
|
HRESULT(APIENTRY* origDeleteShaderFunc)(HANDLE, HANDLE));
|
||||||
|
|
||||||
|
HANDLE getVsVertexFixup();
|
||||||
bool isColorKeyUsed();
|
bool isColorKeyUsed();
|
||||||
HANDLE mapPixelShader(HANDLE shader);
|
HANDLE mapPixelShader(HANDLE shader);
|
||||||
UINT mapRsValue(D3DDDIRENDERSTATETYPE state, UINT value);
|
UINT mapRsValue(D3DDDIRENDERSTATETYPE state, UINT value);
|
||||||
@ -245,10 +245,10 @@ namespace D3dDdi
|
|||||||
VertexDecl* m_vertexDecl;
|
VertexDecl* m_vertexDecl;
|
||||||
UINT m_changedStates;
|
UINT m_changedStates;
|
||||||
UINT m_maxChangedTextureStage;
|
UINT m_maxChangedTextureStage;
|
||||||
UINT m_usedTextureStages;
|
UINT m_texCoordIndexes;
|
||||||
BitSet<D3DDDIRS_ZENABLE, D3DDDIRS_BLENDOPALPHA> m_changedRenderStates;
|
BitSet<D3DDDIRS_ZENABLE, D3DDDIRS_BLENDOPALPHA> m_changedRenderStates;
|
||||||
std::array<BitSet<D3DDDITSS_TEXTUREMAP, D3DDDITSS_TEXTURECOLORKEYVAL>, 8> m_changedTextureStageStates;
|
std::array<BitSet<D3DDDITSS_TEXTUREMAP, D3DDDITSS_TEXTURECOLORKEYVAL>, 8> m_changedTextureStageStates;
|
||||||
std::unique_ptr<void, ResourceDeleter> m_vsVertexFixup;
|
std::map<UINT, std::unique_ptr<void, ResourceDeleter>> m_vsVertexFixups;
|
||||||
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;
|
PixelShader* m_pixelShader;
|
||||||
|
@ -359,6 +359,68 @@ namespace D3dDdi
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderAssembler::applyTexCoordIndexes(const std::array<UINT, 8>& texCoordIndexes)
|
||||||
|
{
|
||||||
|
LOG_FUNC("ShaderAssembler::applyTexCoordIndex", Compat::array(texCoordIndexes.data(), texCoordIndexes.size()));
|
||||||
|
LOG_DEBUG << "Original bytecode: " << Compat::hexDump(m_tokens.data(), m_tokens.size() * 4);
|
||||||
|
LOG_DEBUG << disassemble();
|
||||||
|
|
||||||
|
RestorePos restorePos(m_pos);
|
||||||
|
m_pos = 0;
|
||||||
|
std::array<UINT, 8> tcIndexToRegNum = {};
|
||||||
|
std::array<UINT, 16> regNumToTcIndex = {};
|
||||||
|
regNumToTcIndex.fill(UINT_MAX);
|
||||||
|
|
||||||
|
while (nextInstruction())
|
||||||
|
{
|
||||||
|
const auto instruction = getToken<InstructionToken>();
|
||||||
|
if (D3DSIO_DCL == instruction.opcode)
|
||||||
|
{
|
||||||
|
const auto usage = getToken<UINT32>(1);
|
||||||
|
if (D3DDECLUSAGE_TEXCOORD == (usage & D3DSP_DCL_USAGE_MASK))
|
||||||
|
{
|
||||||
|
const auto tcIndex = (usage & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
|
||||||
|
const auto dst = getToken<UINT32>(2);
|
||||||
|
const auto regNum = dst & D3DSP_REGNUM_MASK;
|
||||||
|
tcIndexToRegNum[tcIndex] = regNum;
|
||||||
|
regNumToTcIndex[regNum] = tcIndex;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto it = g_instructionMap.find(instruction.opcode);
|
||||||
|
if (it == g_instructionMap.end())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UINT i = 0; i < it->second.srcCount; ++i)
|
||||||
|
{
|
||||||
|
UINT& src = m_tokens[m_pos + 1 + it->second.dstCount + i];
|
||||||
|
const auto regType = getRegisterType(src);
|
||||||
|
if (D3DSPR_INPUT != regType)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto origRegNum = src & D3DSP_REGNUM_MASK;
|
||||||
|
const auto origTcIndex = regNumToTcIndex[origRegNum];
|
||||||
|
if (origTcIndex >= texCoordIndexes.size())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto mappedTcIndex = texCoordIndexes[origTcIndex] & 7;
|
||||||
|
const auto mappedRegNum = tcIndexToRegNum[mappedTcIndex];
|
||||||
|
src &= ~D3DSP_REGNUM_MASK;
|
||||||
|
src |= mappedRegNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG << "Modified bytecode: " << Compat::hexDump(m_tokens.data(), m_tokens.size() * 4);
|
||||||
|
LOG_DEBUG << disassemble();
|
||||||
|
}
|
||||||
|
|
||||||
std::string ShaderAssembler::disassemble()
|
std::string ShaderAssembler::disassemble()
|
||||||
{
|
{
|
||||||
if (Config::Settings::LogLevel::DEBUG != Compat::Log::getLogLevel())
|
if (Config::Settings::LogLevel::DEBUG != Compat::Log::getLogLevel())
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -15,6 +16,7 @@ namespace D3dDdi
|
|||||||
ShaderAssembler(const UINT* code, DWORD size);
|
ShaderAssembler(const UINT* code, DWORD size);
|
||||||
|
|
||||||
bool addAlphaTest(UINT alphaRef);
|
bool addAlphaTest(UINT alphaRef);
|
||||||
|
void applyTexCoordIndexes(const std::array<UINT, 8>& texCoordIndexes);
|
||||||
std::string disassemble();
|
std::string disassemble();
|
||||||
UINT getTextureStageCount();
|
UINT getTextureStageCount();
|
||||||
const std::vector<UINT>& getTokens() const { return m_tokens; }
|
const std::vector<UINT>& getTokens() const { return m_tokens; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user