Implement 3D textures for D3D9 as well

This commit is contained in:
Henrik Rydgård 2022-07-30 20:41:31 +02:00
parent 0262fbc70a
commit f87b4cf232
5 changed files with 72 additions and 24 deletions

View File

@ -208,6 +208,9 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
if (enableFog) {
WRITE(p, "float3 u_fogcolor : register(c%i);\n", CONST_PS_FOGCOLOR);
}
if (texture3D) {
WRITE(p, "float u_mipBias : register(c%i);\n", CONST_PS_MIPBIAS);
}
} else {
WRITE(p, "SamplerState samp : register(s0);\n");
if (texture3D) {
@ -565,10 +568,18 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
}
}
} else if (compat.shaderLanguage == HLSL_D3D9) {
if (doTextureProjection) {
WRITE(p, " vec4 t = tex2Dproj(tex, vec4(v_texcoord.x, v_texcoord.y, 0, v_texcoord.z))%s;\n", bgraTexture ? ".bgra" : "");
if (texture3D) {
if (doTextureProjection) {
WRITE(p, " vec4 t = tex3Dproj(tex, vec4(v_texcoord.x, v_texcoord.y, u_mipBias, v_texcoord.z))%s;\n", bgraTexture ? ".bgra" : "");
} else {
WRITE(p, " vec4 t = tex3D(tex, vec3(%s.x, %s.y, u_mipBias))%s;\n", texcoord, texcoord, bgraTexture ? ".bgra" : "");
}
} else {
WRITE(p, " vec4 t = tex2D(tex, %s.xy)%s;\n", texcoord, bgraTexture ? ".bgra" : "");
if (doTextureProjection) {
WRITE(p, " vec4 t = tex2Dproj(tex, vec3(v_texcoord.x, v_texcoord.y, v_texcoord.z))%s;\n", bgraTexture ? ".bgra" : "");
} else {
WRITE(p, " vec4 t = tex2D(tex, %s.xy)%s;\n", texcoord, bgraTexture ? ".bgra" : "");
}
}
} else {
// Note that here we're relying on the filter to be linear. We would have to otherwise to do two samples and manually filter in Z.

View File

@ -34,8 +34,9 @@ struct FShaderID;
#define CONST_PS_FBOTEXSIZE 7
#define CONST_PS_TEXCLAMP 8
#define CONST_PS_TEXCLAMPOFF 9
#define CONST_PS_MIPBIAS 10
// For stencil upload
#define CONST_PS_STENCILVALUE 10
#define CONST_PS_STENCILVALUE 11
bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLanguageDesc &compat, Draw::Bugs bugs, uint64_t *uniformMask, std::string *errorString);

View File

@ -314,6 +314,11 @@ void ShaderManagerDX9::PSUpdateUniforms(u64 dirtyUniforms) {
};
PSSetFloatArray(CONST_PS_TEXCLAMP, texclamp, 4);
PSSetFloatArray(CONST_PS_TEXCLAMPOFF, texclampoff, 2);
float mipBias = (float)gstate.getTexLevelOffset16() * (1.0 / 16.0f);
mipBias = (mipBias + 0.5f) / (float)(gstate.getTextureMaxLevel() + 1);
PSSetFloatArray(CONST_PS_MIPBIAS, &mipBias, 1);
}
}

View File

@ -98,7 +98,7 @@ void TextureCacheDX9::SetFramebufferManager(FramebufferManagerDX9 *fbManager) {
}
void TextureCacheDX9::ReleaseTexture(TexCacheEntry *entry, bool delete_them) {
LPDIRECT3DTEXTURE9 &texture = DxTex(entry);
LPDIRECT3DBASETEXTURE9 &texture = DxTex(entry);
if (texture) {
texture->Release();
texture = nullptr;
@ -205,7 +205,7 @@ void TextureCacheDX9::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase
}
void TextureCacheDX9::BindTexture(TexCacheEntry *entry) {
LPDIRECT3DTEXTURE9 texture = DxTex(entry);
LPDIRECT3DBASETEXTURE9 texture = DxTex(entry);
if (texture != lastBoundTexture) {
device_->SetTexture(0, texture);
lastBoundTexture = texture;
@ -425,10 +425,20 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) {
// We don't yet have mip generation, so clamp the number of levels to the ones we can load directly.
int levels = std::min(plan.levelsToCreate, plan.levelsToLoad);
LPDIRECT3DTEXTURE9 &texture = DxTex(entry);
LPDIRECT3DBASETEXTURE9 &texture = DxTex(entry);
D3DPOOL pool = D3DPOOL_DEFAULT;
int usage = D3DUSAGE_DYNAMIC;
HRESULT hr = device_->CreateTexture(tw, th, levels, usage, dstFmt, pool, &texture, NULL);
HRESULT hr;
if (plan.depth == 1) {
LPDIRECT3DTEXTURE9 tex;
hr = device_->CreateTexture(tw, th, levels, usage, dstFmt, pool, &tex, nullptr);
texture = tex;
} else {
LPDIRECT3DVOLUMETEXTURE9 tex;
hr = device_->CreateVolumeTexture(tw, th, plan.depth, 1, usage, dstFmt, pool, &tex, nullptr);
texture = tex;
}
if (FAILED(hr)) {
INFO_LOG(G3D, "Failed to create D3D texture: %dx%d", tw, th);
@ -443,24 +453,45 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) {
Draw::DataFormat texFmt = FromD3D9Format(dstFmt);
// Mipmapping is only enabled when texture scaling is disabled.
for (int i = 0; i < levels; i++) {
int dstLevel = i;
HRESULT result;
uint32_t lockFlag = dstLevel == 0 ? D3DLOCK_DISCARD : 0; // Can only discard the top level
D3DLOCKED_RECT rect{};
result = texture->LockRect(dstLevel, &rect, NULL, lockFlag);
if (plan.depth == 1) {
// Regular loop.
for (int i = 0; i < levels; i++) {
int dstLevel = i;
HRESULT result;
uint32_t lockFlag = dstLevel == 0 ? D3DLOCK_DISCARD : 0; // Can only discard the top level
D3DLOCKED_RECT rect{};
result = ((LPDIRECT3DTEXTURE9)texture)->LockRect(dstLevel, &rect, NULL, lockFlag);
if (FAILED(result)) {
ERROR_LOG(G3D, "Failed to lock D3D 2D texture at level %d: %dx%d", i, plan.w, plan.h);
return;
}
uint8_t *data = (uint8_t *)rect.pBits;
int stride = rect.Pitch;
LoadTextureLevel(*entry, data, stride, *plan.replaced, (i == 0) ? plan.baseLevelSrc : i, plan.scaleFactor, texFmt, false);
((LPDIRECT3DTEXTURE9)texture)->UnlockRect(dstLevel);
}
} else {
// 3D loop.
D3DLOCKED_BOX box;
HRESULT result = ((LPDIRECT3DVOLUMETEXTURE9)texture)->LockBox(0, &box, nullptr, D3DLOCK_DISCARD);
if (FAILED(result)) {
ERROR_LOG(G3D, "Failed to lock D3D texture at level %d: %dx%d", i, plan.w, plan.h);
ERROR_LOG(G3D, "Failed to lock D3D 2D texture: %dx%dx%d", plan.w, plan.h, plan.depth);
return;
}
uint8_t *data = (uint8_t *)rect.pBits;
int stride = rect.Pitch;
uint8_t *data = (uint8_t *)box.pBits;
int stride = box.RowPitch;
for (int i = 0; i < plan.depth; i++) {
LoadTextureLevel(*entry, data, stride, *plan.replaced, (i == 0) ? plan.baseLevelSrc : i, plan.scaleFactor, texFmt, false);
data += box.SlicePitch;
}
((LPDIRECT3DVOLUMETEXTURE9)texture)->UnlockBox(0);
}
LoadTextureLevel(*entry, data, stride, *plan.replaced, (i == 0) ? plan.baseLevelSrc : i, plan.scaleFactor, texFmt, false);
texture->UnlockRect(dstLevel);
// Signal that we support depth textures so use it as one.
if (plan.depth > 1) {
entry->status |= TexCacheEntry::STATUS_3D;
}
if (plan.replaced->Valid()) {

View File

@ -68,8 +68,8 @@ private:
void ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, GETextureFormat texFormat, FramebufferNotificationChannel channel) override;
void BuildTexture(TexCacheEntry *const entry) override;
LPDIRECT3DTEXTURE9 &DxTex(TexCacheEntry *entry) {
return *(LPDIRECT3DTEXTURE9 *)&entry->texturePtr;
LPDIRECT3DBASETEXTURE9 &DxTex(TexCacheEntry *entry) {
return *(LPDIRECT3DBASETEXTURE9 *)&entry->texturePtr;
}
LPDIRECT3DDEVICE9 device_;
@ -77,7 +77,7 @@ private:
LPDIRECT3DVERTEXDECLARATION9 pFramebufferVertexDecl;
LPDIRECT3DTEXTURE9 lastBoundTexture;
LPDIRECT3DBASETEXTURE9 lastBoundTexture;
float maxAnisotropyLevel;
FramebufferManagerDX9 *framebufferManagerDX9_;