Browse Source

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

rdb 1 year ago
parent
commit
beb49b3cd3

+ 10 - 1
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -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
panda/src/dxgsg9/dxTextureContext9.cxx

@@ -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
panda/src/dxgsg9/dxgsg9base.h

@@ -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
panda/src/dxgsg9/wdxGraphicsPipe9.cxx

@@ -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);
   }