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_changedStates(0)
|
||||
, m_maxChangedTextureStage(0)
|
||||
, m_texCoordIndexes(0)
|
||||
, m_changedTextureStageStates{}
|
||||
, m_vsVertexFixup(createVertexShader(g_vsVertexFixup))
|
||||
, m_textureResource{}
|
||||
, m_pixelShader(nullptr)
|
||||
, m_isLocked(false)
|
||||
@ -187,6 +187,7 @@ namespace D3dDdi
|
||||
{
|
||||
m_current.textureStageState[i].fill(UNINITIALIZED_STATE);
|
||||
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.
|
||||
// Setting this to CLAMP makes them behave as expected, instead of as WRAP,
|
||||
@ -224,11 +225,11 @@ namespace D3dDdi
|
||||
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 = {};
|
||||
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;
|
||||
}
|
||||
@ -326,6 +327,26 @@ namespace D3dDdi
|
||||
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()
|
||||
{
|
||||
if (!m_app.renderState[D3DDDIRS_COLORKEYENABLE])
|
||||
@ -669,6 +690,12 @@ namespace D3dDdi
|
||||
m_changedRenderStates.set(D3DDDIRS_COLORKEYENABLE);
|
||||
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_changedTextureStageStates[data->Stage].set(data->State);
|
||||
@ -1203,14 +1230,7 @@ namespace D3dDdi
|
||||
{
|
||||
setPixelShader(mapPixelShader(m_app.pixelShader));
|
||||
setVertexShaderDecl(m_app.vertexShaderDecl);
|
||||
if (getVertexDecl().isTransformed)
|
||||
{
|
||||
setVertexShaderFunc(m_vsVertexFixup.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
setVertexShaderFunc(m_app.vertexShaderFunc);
|
||||
}
|
||||
setVertexShaderFunc(getVertexDecl().isTransformed ? getVsVertexFixup() : m_app.vertexShaderFunc);
|
||||
}
|
||||
|
||||
void DeviceState::updateStreamSource()
|
||||
|
@ -156,7 +156,6 @@ namespace D3dDdi
|
||||
Resource* getTextureResource(UINT stage);
|
||||
UINT getTextureStageCount() const;
|
||||
const VertexDecl& getVertexDecl() const;
|
||||
HANDLE getVertexFixupDecl() const { return m_vsVertexFixup.get(); }
|
||||
bool isLocked() const { return m_isLocked; }
|
||||
void onDestroyResource(Resource* resource, HANDLE resourceHandle);
|
||||
void updateConfig();
|
||||
@ -183,13 +182,14 @@ namespace D3dDdi
|
||||
template <int 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(APIENTRY* origDeleteShaderFunc)(HANDLE, HANDLE));
|
||||
|
||||
HANDLE getVsVertexFixup();
|
||||
bool isColorKeyUsed();
|
||||
HANDLE mapPixelShader(HANDLE shader);
|
||||
UINT mapRsValue(D3DDDIRENDERSTATETYPE state, UINT value);
|
||||
@ -245,10 +245,10 @@ namespace D3dDdi
|
||||
VertexDecl* m_vertexDecl;
|
||||
UINT m_changedStates;
|
||||
UINT m_maxChangedTextureStage;
|
||||
UINT m_usedTextureStages;
|
||||
UINT m_texCoordIndexes;
|
||||
BitSet<D3DDDIRS_ZENABLE, D3DDDIRS_BLENDOPALPHA> m_changedRenderStates;
|
||||
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::map<HANDLE, PixelShader> m_pixelShaders;
|
||||
PixelShader* m_pixelShader;
|
||||
|
@ -359,6 +359,68 @@ namespace D3dDdi
|
||||
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()
|
||||
{
|
||||
if (Config::Settings::LogLevel::DEBUG != Compat::Log::getLogLevel())
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
@ -15,6 +16,7 @@ namespace D3dDdi
|
||||
ShaderAssembler(const UINT* code, DWORD size);
|
||||
|
||||
bool addAlphaTest(UINT alphaRef);
|
||||
void applyTexCoordIndexes(const std::array<UINT, 8>& texCoordIndexes);
|
||||
std::string disassemble();
|
||||
UINT getTextureStageCount();
|
||||
const std::vector<UINT>& getTokens() const { return m_tokens; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user