dxgsg9: Fix some format handling, support for r32f and rgba32f textures

This commit is contained in:
rdb
2024-10-03 13:37:21 +02:00
parent 0ea0d5fa2b
commit beb49b3cd3
4 changed files with 93 additions and 22 deletions
+10 -1
View File
@@ -5249,7 +5249,7 @@ FrameBufferProperties DXGraphicsStateGuardian9::
calc_fb_properties(DWORD cformat, DWORD dformat,
DWORD multisampletype, DWORD multisamplequality) {
FrameBufferProperties props;
int index=0;
int index=0, isfloat=0;
int r=0, g=0, b=0, a=0;
switch (cformat) {
case D3DFMT_R8G8B8: r=8; g=8; b=8; a=0; break;
@@ -5263,10 +5263,19 @@ calc_fb_properties(DWORD cformat, DWORD dformat,
case D3DFMT_A8R3G3B2: r=3; g=3; b=2; a=8; break;
case D3DFMT_X4R4G4B4: r=4; g=4; b=4; a=0; break;
case D3DFMT_A2B10G10R10: r=10;g=10;b=10;a=2; break;
case D3DFMT_R16F: r=16; isfloat=1; break;
case D3DFMT_G16R16F: r=16; isfloat=1; break;
case D3DFMT_A16B16G16R16F:r=16; g=16; b=16; a=16; isfloat=1; break;
case D3DFMT_R32F: r=32; isfloat=1; break;
case D3DFMT_G32R32F: r=32; isfloat=1; break;
case D3DFMT_A32B32G32R32F:r=32; g=32; b=32; a=32; isfloat=1; break;
case D3DFMT_A8P8: index=8; a=8; break;
case D3DFMT_P8: index=8; a=0; break;
default: break;
}
if (isfloat > 0) {
props.set_float_color(true);
}
if (index > 0) {
props.set_rgb_color(0);
props.set_indexed_color(1);
+77 -19
View File
@@ -234,6 +234,8 @@ create_texture(DXScreenData &scrn) {
case 1:
if (num_alpha_bits > 0) {
_d3d_format = D3DFMT_A8;
} else if (tex->get_component_type() == Texture::T_float) {
_d3d_format = D3DFMT_R32F;
} else {
_d3d_format = D3DFMT_L8;
}
@@ -245,7 +247,11 @@ create_texture(DXScreenData &scrn) {
_d3d_format = D3DFMT_R8G8B8;
break;
case 4:
_d3d_format = D3DFMT_A8R8G8B8;
if (tex->get_component_type() == Texture::T_float) {
_d3d_format = D3DFMT_A32B32G32R32F;
} else {
_d3d_format = D3DFMT_A8R8G8B8;
}
break;
}
@@ -502,6 +508,13 @@ create_texture(DXScreenData &scrn) {
break;
}
if (num_color_channels == 1) {
CHECK_FOR_FMT(R32F);
CHECK_FOR_FMT(X8R8G8B8);
CHECK_FOR_FMT(R8G8B8);
break;
}
if (!((num_color_channels == 3) || (num_color_channels == 4)))
break; //bail
@@ -667,22 +680,7 @@ create_texture(DXScreenData &scrn) {
}
}
case 8:
if (needs_luminance) {
// don't bother handling those other 8bit lum fmts like 4-4, since 16
// 8-8 is usually supported too
nassertr(num_color_channels == 1, false);
// look for native lum fmt first
CHECK_FOR_FMT(L8);
CHECK_FOR_FMT(L8);
CHECK_FOR_FMT(R8G8B8);
CHECK_FOR_FMT(X8R8G8B8);
CHECK_FOR_FMT(R5G6B5);
CHECK_FOR_FMT(X1R5G5B5);
} else if (num_alpha_bits == 8) {
if (num_alpha_bits == 8) {
// look for 16bpp A8L8, else 32-bit ARGB, else 16-4444.
// skip 8bit alpha only (D3DFMT_A8), because I think only voodoo
@@ -693,6 +691,21 @@ create_texture(DXScreenData &scrn) {
CHECK_FOR_FMT(A8L8);
CHECK_FOR_FMT(A8R8G8B8);
CHECK_FOR_FMT(A4R4G4B4);
} else {
if (needs_luminance) {
// don't bother handling those other 8bit lum fmts like 4-4, since 16
// 8-8 is usually supported too
nassertr(num_color_channels == 1, false);
// look for native lum fmt first
CHECK_FOR_FMT(L8);
}
CHECK_FOR_FMT(R8G8B8);
CHECK_FOR_FMT(X8R8G8B8);
CHECK_FOR_FMT(R5G6B5);
CHECK_FOR_FMT(X1R5G5B5);
}
break;
@@ -1831,7 +1844,28 @@ HRESULT DXTextureContext9::fill_d3d_texture_mipmap_pixels(int mip_level, int dep
source_row_byte_length = width * sizeof(USHORT);
pixels = (BYTE*)temp_buffer;
}
else if (component_width != 1) {
else if (_d3d_format == D3DFMT_A32B32G32R32F && source_format == D3DFMT_A32B32G32R32F) {
size_t total_components = (size_t)width * (size_t)height * 4;
float *temp_buffer = new float[total_components];
if (!IS_VALID_PTR(temp_buffer)) {
dxgsg9_cat.error()
<< "FillDDTextureMipmapPixels couldnt alloc mem for temp pixbuf!\n";
goto exit_FillMipmapSurf;
}
using_temp_buffer = true;
// Swap red and blue components.
float *out_pixels = (float *)temp_buffer;
const float *source_pixels = (const float *)pixels;
for (size_t i = 0; i < total_components; i += 4) {
out_pixels[i] = source_pixels[i + 2];
out_pixels[i + 1] = source_pixels[i + 1];
out_pixels[i + 2] = source_pixels[i + 0];
out_pixels[i + 3] = source_pixels[i + 3];
}
pixels = (BYTE*)temp_buffer;
}
else if (component_width != 1 && _d3d_format != D3DFMT_R32F) {
// Convert from 16-bit per channel (or larger) format down to 8-bit per
// channel. This throws away precision in the original image, but dx8
// doesn't support high-precision images anyway.
@@ -2203,8 +2237,29 @@ fill_d3d_volume_texture_pixels(DXScreenData &scrn) {
source_row_byte_length = orig_width * sizeof(USHORT);
source_page_byte_length = orig_height * source_row_byte_length;
pixels = (BYTE*)temp_buffer;
}
else if (_d3d_format == D3DFMT_A32B32G32R32F && source_format == D3DFMT_A32B32G32R32F) {
size_t total_components = (size_t)orig_width * (size_t)orig_height * (size_t)orig_depth * 4;
float *temp_buffer = new float[total_components];
if (!IS_VALID_PTR(temp_buffer)) {
dxgsg9_cat.error()
<< "FillDDSurfaceTexturePixels couldnt alloc mem for temp pixbuf!\n";
goto exit_FillDDSurf;
}
using_temp_buffer = true;
} else if (component_width != 1) {
// Swap red and blue components.
float *out_pixels = (float *)temp_buffer;
const float *source_pixels = (const float *)pixels;
for (size_t i = 0; i < total_components; i += 4) {
out_pixels[i] = source_pixels[i + 2];
out_pixels[i + 1] = source_pixels[i + 1];
out_pixels[i + 2] = source_pixels[i + 0];
out_pixels[i + 3] = source_pixels[i + 3];
}
pixels = (BYTE*)temp_buffer;
}
else if (component_width != 1 && _d3d_format != D3DFMT_R32F) {
// Convert from 16-bit per channel (or larger) format down to 8-bit per
// channel. This throws away precision in the original image, but dx8
// doesn't support high-precision images anyway.
@@ -2350,6 +2405,9 @@ get_bits_per_pixel(Texture::Format format, int *alphbits) {
*alphbits = 32;
return 128;
case Texture::F_r32:
return 32;
case Texture::F_srgb:
return 24;
case Texture::F_srgb_alpha:
+1 -1
View File
@@ -169,7 +169,7 @@ typedef enum {
D24S8_FLAG = FLG(20),
D32_FLAG = FLG(21),
INTZ_FLAG = FLG(22),
W11V11U10_FLAG = FLG(23),
R32F_FLAG = FLG(23),
A2W10V10U10_FLAG = FLG(24),
ATI1_FLAG = FLG(25),
ATI2_FLAG = FLG(26),
+5 -1
View File
@@ -862,7 +862,7 @@ void Init_D3DFORMAT_map() {
INSERT_ELEM(D24S8);
INSERT_ELEM(D32);
INSERT_ELEM(INTZ);
// NOT IN DX9 INSERT_ELEM(W11V11U10);
INSERT_ELEM(R32F);
INSERT_ELEM(A2W10V10U10);
INSERT_ELEM(ATI1);
INSERT_ELEM(ATI2);
@@ -923,7 +923,11 @@ const char *D3DFormatStr(D3DFORMAT fmt) {
CASESTR(D3DFMT_VERTEXDATA);
CASESTR(D3DFMT_INDEX16);
CASESTR(D3DFMT_INDEX32);
CASESTR(D3DFMT_R16F);
CASESTR(D3DFMT_G16R16F);
CASESTR(D3DFMT_A16B16G16R16F);
CASESTR(D3DFMT_R32F);
CASESTR(D3DFMT_G32R32F);
CASESTR(D3DFMT_A32B32G32R32F);
}