load mipmaps from .dds, enable anisotropy

This commit is contained in:
Zack Buhman 2026-04-10 23:21:30 -05:00
parent 3061a1e09c
commit 466c7b030e
10 changed files with 422 additions and 34 deletions

View File

@ -39,7 +39,8 @@ OBJS = \
src/main.o \ src/main.o \
src/volk/volk.o \ src/volk/volk.o \
src/file.o \ src/file.o \
src/pack.o src/pack.o \
src/dds_validate.o
ifeq ($(UNAME),Darwin) ifeq ($(UNAME),Darwin)
LIBS = \ LIBS = \

BIN
checker.dds Normal file

Binary file not shown.

BIN
checker.idx Normal file

Binary file not shown.

BIN
checker.vtx Normal file

Binary file not shown.

View File

@ -1,4 +1,6 @@
shader/triangle.spv shader/triangle.spv
index.idx checker.idx
position_normal_texture.vtx checker.vtx
checker.data
checker.dds
sprite.data sprite.data

258
include/dds.h Normal file
View File

@ -0,0 +1,258 @@
//--------------------------------------------------------------------------------------
// dds.h
//
// This header defines constants and structures that are useful when parsing
// DDS files. DDS files were originally designed to use several structures
// and constants that are native to DirectDraw and are defined in ddraw.h,
// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar
// (compatible) constants and structures so that one can use DDS files
// without needing to include ddraw.h.
//--------------------------------------------------------------------------------------
#ifndef _DDS_H_
#define _DDS_H_
#pragma pack(push,1)
#define DDS_MAGIC 0x20534444 // "DDS "
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((unsigned int)(unsigned char)(ch0) | ((unsigned int)(unsigned char)(ch1) << 8) | \
((unsigned int)(unsigned char)(ch2) << 16) | ((unsigned int)(unsigned char)(ch3) << 24 ))
struct DDS_PIXELFORMAT
{
unsigned int dwSize;
unsigned int dwFlags;
unsigned int dwFourCC;
unsigned int dwRGBBitCount;
unsigned int dwRBitMask;
unsigned int dwGBitMask;
unsigned int dwBBitMask;
unsigned int dwABitMask;
};
#define DDS_FOURCC 0x00000004 // DDPF_FOURCC
#define DDS_RGB 0x00000040 // DDPF_RGB
#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS
#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE
#define DDS_ALPHA 0x00000002 // DDPF_ALPHA
const DDS_PIXELFORMAT DDSPF_DXT1 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_DXT2 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_DXT3 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_DXT4 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_DXT5 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 };
const DDS_PIXELFORMAT DDSPF_A8R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
const DDS_PIXELFORMAT DDSPF_A1R5G5B5 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 };
const DDS_PIXELFORMAT DDSPF_A4R4G4B4 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 };
const DDS_PIXELFORMAT DDSPF_R8G8B8 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 };
const DDS_PIXELFORMAT DDSPF_R5G6B5 =
{ sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 };
// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat)
const DDS_PIXELFORMAT DDSPF_DX10 =
{ sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 };
#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT
#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH
#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH
#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE
#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE
#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX
#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\
DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\
DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ )
#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
struct DDS_HEADER
{
unsigned int dwSize;
unsigned int dwHeaderFlags;
unsigned int dwHeight;
unsigned int dwWidth;
unsigned int dwPitchOrLinearSize;
unsigned int dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwHeaderFlags
unsigned int dwMipMapCount;
unsigned int dwReserved1[11];
DDS_PIXELFORMAT ddspf;
unsigned int dwSurfaceFlags;
unsigned int dwCubemapFlags;
unsigned int dwReserved2[3];
};
enum DXGI_FORMAT {
DXGI_FORMAT_UNKNOWN = 0,
DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
DXGI_FORMAT_R32G32B32A32_UINT = 3,
DXGI_FORMAT_R32G32B32A32_SINT = 4,
DXGI_FORMAT_R32G32B32_TYPELESS = 5,
DXGI_FORMAT_R32G32B32_FLOAT = 6,
DXGI_FORMAT_R32G32B32_UINT = 7,
DXGI_FORMAT_R32G32B32_SINT = 8,
DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
DXGI_FORMAT_R16G16B16A16_UNORM = 11,
DXGI_FORMAT_R16G16B16A16_UINT = 12,
DXGI_FORMAT_R16G16B16A16_SNORM = 13,
DXGI_FORMAT_R16G16B16A16_SINT = 14,
DXGI_FORMAT_R32G32_TYPELESS = 15,
DXGI_FORMAT_R32G32_FLOAT = 16,
DXGI_FORMAT_R32G32_UINT = 17,
DXGI_FORMAT_R32G32_SINT = 18,
DXGI_FORMAT_R32G8X24_TYPELESS = 19,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
DXGI_FORMAT_R10G10B10A2_UNORM = 24,
DXGI_FORMAT_R10G10B10A2_UINT = 25,
DXGI_FORMAT_R11G11B10_FLOAT = 26,
DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
DXGI_FORMAT_R8G8B8A8_UNORM = 28,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
DXGI_FORMAT_R8G8B8A8_UINT = 30,
DXGI_FORMAT_R8G8B8A8_SNORM = 31,
DXGI_FORMAT_R8G8B8A8_SINT = 32,
DXGI_FORMAT_R16G16_TYPELESS = 33,
DXGI_FORMAT_R16G16_FLOAT = 34,
DXGI_FORMAT_R16G16_UNORM = 35,
DXGI_FORMAT_R16G16_UINT = 36,
DXGI_FORMAT_R16G16_SNORM = 37,
DXGI_FORMAT_R16G16_SINT = 38,
DXGI_FORMAT_R32_TYPELESS = 39,
DXGI_FORMAT_D32_FLOAT = 40,
DXGI_FORMAT_R32_FLOAT = 41,
DXGI_FORMAT_R32_UINT = 42,
DXGI_FORMAT_R32_SINT = 43,
DXGI_FORMAT_R24G8_TYPELESS = 44,
DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
DXGI_FORMAT_R8G8_TYPELESS = 48,
DXGI_FORMAT_R8G8_UNORM = 49,
DXGI_FORMAT_R8G8_UINT = 50,
DXGI_FORMAT_R8G8_SNORM = 51,
DXGI_FORMAT_R8G8_SINT = 52,
DXGI_FORMAT_R16_TYPELESS = 53,
DXGI_FORMAT_R16_FLOAT = 54,
DXGI_FORMAT_D16_UNORM = 55,
DXGI_FORMAT_R16_UNORM = 56,
DXGI_FORMAT_R16_UINT = 57,
DXGI_FORMAT_R16_SNORM = 58,
DXGI_FORMAT_R16_SINT = 59,
DXGI_FORMAT_R8_TYPELESS = 60,
DXGI_FORMAT_R8_UNORM = 61,
DXGI_FORMAT_R8_UINT = 62,
DXGI_FORMAT_R8_SNORM = 63,
DXGI_FORMAT_R8_SINT = 64,
DXGI_FORMAT_A8_UNORM = 65,
DXGI_FORMAT_R1_UNORM = 66,
DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
DXGI_FORMAT_BC1_TYPELESS = 70,
DXGI_FORMAT_BC1_UNORM = 71,
DXGI_FORMAT_BC1_UNORM_SRGB = 72,
DXGI_FORMAT_BC2_TYPELESS = 73,
DXGI_FORMAT_BC2_UNORM = 74,
DXGI_FORMAT_BC2_UNORM_SRGB = 75,
DXGI_FORMAT_BC3_TYPELESS = 76,
DXGI_FORMAT_BC3_UNORM = 77,
DXGI_FORMAT_BC3_UNORM_SRGB = 78,
DXGI_FORMAT_BC4_TYPELESS = 79,
DXGI_FORMAT_BC4_UNORM = 80,
DXGI_FORMAT_BC4_SNORM = 81,
DXGI_FORMAT_BC5_TYPELESS = 82,
DXGI_FORMAT_BC5_UNORM = 83,
DXGI_FORMAT_BC5_SNORM = 84,
DXGI_FORMAT_B5G6R5_UNORM = 85,
DXGI_FORMAT_B5G5R5A1_UNORM = 86,
DXGI_FORMAT_B8G8R8A8_UNORM = 87,
DXGI_FORMAT_B8G8R8X8_UNORM = 88,
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
DXGI_FORMAT_BC6H_TYPELESS = 94,
DXGI_FORMAT_BC6H_UF16 = 95,
DXGI_FORMAT_BC6H_SF16 = 96,
DXGI_FORMAT_BC7_TYPELESS = 97,
DXGI_FORMAT_BC7_UNORM = 98,
DXGI_FORMAT_BC7_UNORM_SRGB = 99,
DXGI_FORMAT_AYUV = 100,
DXGI_FORMAT_Y410 = 101,
DXGI_FORMAT_Y416 = 102,
DXGI_FORMAT_NV12 = 103,
DXGI_FORMAT_P010 = 104,
DXGI_FORMAT_P016 = 105,
DXGI_FORMAT_420_OPAQUE = 106,
DXGI_FORMAT_YUY2 = 107,
DXGI_FORMAT_Y210 = 108,
DXGI_FORMAT_Y216 = 109,
DXGI_FORMAT_NV11 = 110,
DXGI_FORMAT_AI44 = 111,
DXGI_FORMAT_IA44 = 112,
DXGI_FORMAT_P8 = 113,
DXGI_FORMAT_A8P8 = 114,
DXGI_FORMAT_B4G4R4A4_UNORM = 115,
DXGI_FORMAT_P208 = 130,
DXGI_FORMAT_V208 = 131,
DXGI_FORMAT_V408 = 132,
DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE = 189,
DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE = 190,
DXGI_FORMAT_FORCE_UINT = 0xffffffff
};
enum D3D10_RESOURCE_DIMENSION {
D3D10_RESOURCE_DIMENSION_UNKNOWN = 0,
D3D10_RESOURCE_DIMENSION_BUFFER = 1,
D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2,
D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3,
D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4
};
struct DDS_HEADER_DXT10
{
DXGI_FORMAT dxgiFormat;
D3D10_RESOURCE_DIMENSION resourceDimension;
unsigned int miscFlag;
unsigned int arraySize;
unsigned int reserved;
};
#pragma pack(pop)
#endif // _DDS_H

11
include/dds_validate.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include "dds.h"
struct DDS_FILE {
unsigned int dwMagic;
DDS_HEADER header;
DDS_HEADER_DXT10 header10;
};
DDS_FILE const * dds_validate(void const * data, uint32_t size, uint32_t ** out_offsets, void ** out_data);

View File

@ -33,7 +33,7 @@ VSOutput VSMain(VSInput input)
VSOutput output = (VSOutput)0; VSOutput output = (VSOutput)0;
output.Position = mul(data.Transform, float4(input.Position.xyz, 1.0)); output.Position = mul(data.Transform, float4(input.Position.xyz, 1.0));
output.Normal = mul((float3x3)data.ModelView, input.Normal); output.Normal = mul((float3x3)data.ModelView, input.Normal);
output.Texture = input.Texture.xy; output.Texture = input.Texture.xy * 1.0;
float4 viewPosition = mul(data.ModelView, float4(input.Position.xyz, 1.0)); float4 viewPosition = mul(data.ModelView, float4(input.Position.xyz, 1.0));
output.LightDirection = (data.LightPosition - viewPosition).xyz; output.LightDirection = (data.LightPosition - viewPosition).xyz;
@ -56,6 +56,8 @@ float4 PSMain(VSOutput input) : SV_TARGET
const float specularIntensity = 0.8; const float specularIntensity = 0.8;
float3 specular = pow(max(dot(R, V), 0), a) * specularIntensity; float3 specular = pow(max(dot(R, V), 0), a) * specularIntensity;
float3 diffuse = max(dot(N, L), 0.001); float3 diffuse = max(dot(N, L), 0.001);
diffuse = 1.0;
specular = 0.0;
return float4(diffuse * color + specular, 1.0); return float4(diffuse * color + specular, 1.0);
} }

91
src/dds_validate.cpp Normal file
View File

@ -0,0 +1,91 @@
#include <assert.h>
#include <stdint.h>
#include "new.h"
#include "dds_validate.h"
static inline uint32_t max(uint32_t a, uint32_t b)
{
return (a > b) ? a : b;
}
struct dds_size_levels {
uint32_t const size;
uint32_t const levels;
};
static inline uint32_t dim(uint32_t d)
{
return max(1, (d / 4));
}
static inline uint32_t mip_size(DXGI_FORMAT dxgiFormat, uint32_t height, uint32_t width)
{
switch (dxgiFormat) {
case DXGI_FORMAT_BC1_TYPELESS: [[fallthrough]];
case DXGI_FORMAT_BC1_UNORM: [[fallthrough]];
case DXGI_FORMAT_BC1_UNORM_SRGB:
return dim(height) * dim(width) * 8;
case DXGI_FORMAT_R8G8B8A8_TYPELESS: [[fallthrough]];
case DXGI_FORMAT_R8G8B8A8_UNORM: [[fallthrough]];
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: [[fallthrough]];
case DXGI_FORMAT_R8G8B8A8_UINT: [[fallthrough]];
case DXGI_FORMAT_R8G8B8A8_SNORM: [[fallthrough]];
case DXGI_FORMAT_R8G8B8A8_SINT:
return height * width * 4;
default:
assert(false);
}
}
static inline dds_size_levels dds_mip_total_size(DXGI_FORMAT dxgiFormat,
uint32_t height,
uint32_t width,
uint32_t max_mip_levels,
uint32_t * offsets)
{
uint32_t mip_total_size = 0;
uint32_t mip_levels = 0;
while (true) {
offsets[mip_levels] = mip_total_size;
mip_levels += 1;
assert(mip_levels <= max_mip_levels);
uint32_t mip_offset = mip_size(dxgiFormat, height, width);
mip_total_size += mip_offset;
if (max_mip_levels == 1 || (width == 1 && height == 1))
break;
height = max(1, height / 2);
width = max(1, width / 2);
}
return {mip_total_size, mip_levels};
}
DDS_FILE const * dds_validate(void const * data, uint32_t size, uint32_t ** out_offsets, void ** out_data)
{
DDS_FILE const * const dds = (DDS_FILE const *)data;
assert(dds->dwMagic == DDS_MAGIC);
assert(dds->header.dwSize == 124);
assert(dds->header.ddspf.dwSize == 32);
assert(dds->header.ddspf.dwFlags == DDS_FOURCC);
//assert(dds->header.ddspf.dwFourCC == MAKEFOURCC('D','X','T','1'));
assert(dds->header.ddspf.dwFourCC == MAKEFOURCC('D','X','1','0'));
uint32_t * offsets = NewM<uint32_t>(dds->header.dwMipMapCount);
uintptr_t image_data = ((uintptr_t)dds) + (sizeof (DDS_FILE));
dds_size_levels ret = dds_mip_total_size(dds->header10.dxgiFormat,
dds->header.dwHeight,
dds->header.dwWidth,
dds->header.dwMipMapCount,
offsets);
assert(ret.size + (sizeof (DDS_FILE)) == size);
assert(ret.levels == dds->header.dwMipMapCount);
*out_offsets = offsets;
*out_data = (void *)image_data;
return dds;
}

View File

@ -9,6 +9,7 @@
#include "new.h" #include "new.h"
#include "file.h" #include "file.h"
#include "dds_validate.h"
template <typename T> template <typename T>
inline static constexpr T min(T a, T b) inline static constexpr T min(T a, T b)
@ -216,7 +217,7 @@ float theta = 0;
XMMATRIX currentModel() XMMATRIX currentModel()
{ {
theta += 0.01; theta += 0.01;
return XMMatrixTranslation(0, 0, -0.5) * XMMatrixRotationX(theta); return XMMatrixTranslation(0, 0, 0.0) * XMMatrixRotationX(theta) * XMMatrixRotationZ(XM_PI * 0.5f);
} }
void recreateSwapchain(VkSurfaceFormatKHR surfaceFormat, VkFormat depthFormat, VkPhysicalDeviceMemoryProperties const & memoryProperties, VkSurfaceCapabilitiesKHR const & surfaceCapabilities) void recreateSwapchain(VkSurfaceFormatKHR surfaceFormat, VkFormat depthFormat, VkPhysicalDeviceMemoryProperties const & memoryProperties, VkSurfaceCapabilitiesKHR const & surfaceCapabilities)
@ -446,6 +447,8 @@ int main()
printf(" maxSamplerAllocationCount %u\n", properties.properties.limits.maxSamplerAllocationCount); printf(" maxSamplerAllocationCount %u\n", properties.properties.limits.maxSamplerAllocationCount);
printf(" nonCoherentAtomSize %lu\n", properties.properties.limits.nonCoherentAtomSize); printf(" nonCoherentAtomSize %lu\n", properties.properties.limits.nonCoherentAtomSize);
printf(" minUniformBufferOffsetAlignment %lu\n", properties.properties.limits.minUniformBufferOffsetAlignment); printf(" minUniformBufferOffsetAlignment %lu\n", properties.properties.limits.minUniformBufferOffsetAlignment);
printf(" maxSamplerLodBias %f\n", properties.properties.limits.maxSamplerLodBias);
printf(" maxSamplerAnisotropy %f\n", properties.properties.limits.maxSamplerAnisotropy);
physicalDeviceProperties = properties.properties; physicalDeviceProperties = properties.properties;
} }
} }
@ -586,9 +589,9 @@ int main()
{ {
uint32_t vertexSize; uint32_t vertexSize;
void const * vertexStart = file::open("position_normal_texture.vtx", &vertexSize); void const * vertexStart = file::open("checker.vtx", &vertexSize);
uint32_t indexSize; uint32_t indexSize;
void const * indexStart = file::open("index.idx", &indexSize); void const * indexStart = file::open("checker.idx", &indexSize);
vertexBufferSize = vertexSize; vertexBufferSize = vertexSize;
indexBufferSize = indexSize; indexBufferSize = indexSize;
@ -709,14 +712,25 @@ int main()
// texture // texture
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
uint32_t checkerSize;
void const * checkerStart = file::open("checker.dds", &checkerSize);
void * checkerData;
uint32_t * mipOffsets;
DDS_FILE const * ddsFile = dds_validate(checkerStart, checkerSize, &mipOffsets, &checkerData);
uint32_t checkerDataSize = checkerSize - (sizeof (DDS_FILE));
VkFormat textureFormat{ VK_FORMAT_B8G8R8A8_SRGB }; VkFormat textureFormat{ VK_FORMAT_B8G8R8A8_SRGB };
VkImageCreateInfo textureImageCreateInfo{ VkImageCreateInfo textureImageCreateInfo{
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D, .imageType = VK_IMAGE_TYPE_2D,
.format = textureFormat, .format = textureFormat,
.extent = {.width = 858, .height = 858, .depth = 1 }, .extent = {
.mipLevels = 1, .width = ddsFile->header.dwWidth,
.height = ddsFile->header.dwHeight,
.depth = 1
},
.mipLevels = ddsFile->header.dwMipMapCount,
.arrayLayers = 1, .arrayLayers = 1,
.samples = VK_SAMPLE_COUNT_1_BIT, .samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = VK_IMAGE_TILING_OPTIMAL, .tiling = VK_IMAGE_TILING_OPTIMAL,
@ -748,7 +762,7 @@ int main()
.format = textureFormat, .format = textureFormat,
.subresourceRange{ .subresourceRange{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = 1, .levelCount = ddsFile->header.dwMipMapCount,
.layerCount = 1 .layerCount = 1
} }
}; };
@ -756,13 +770,10 @@ int main()
// texture transfer: source buffer // texture transfer: source buffer
uint32_t spriteSize;
void const * spriteStart = file::open("sprite.data", &spriteSize);
VkBuffer textureSourceBuffer{}; VkBuffer textureSourceBuffer{};
VkBufferCreateInfo textureSourceBufferCreateInfo{ VkBufferCreateInfo textureSourceBufferCreateInfo{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = spriteSize, .size = checkerDataSize,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
}; };
VK_CHECK(vkCreateBuffer(device, &textureSourceBufferCreateInfo, nullptr, &textureSourceBuffer)); VK_CHECK(vkCreateBuffer(device, &textureSourceBufferCreateInfo, nullptr, &textureSourceBuffer));
@ -783,7 +794,7 @@ int main()
void * textureSourceMappedData; void * textureSourceMappedData;
VK_CHECK(vkMapMemory(device, textureSourceBufferMemory, 0, textureSourceBufferCreateInfo.size, 0, &textureSourceMappedData)); VK_CHECK(vkMapMemory(device, textureSourceBufferMemory, 0, textureSourceBufferCreateInfo.size, 0, &textureSourceMappedData));
memcpy((void *)(((ptrdiff_t)textureSourceMappedData) + 0), spriteStart, spriteSize); memcpy((void *)(((ptrdiff_t)textureSourceMappedData) + 0), checkerData, checkerDataSize);
vkUnmapMemory(device, textureSourceBufferMemory); vkUnmapMemory(device, textureSourceBufferMemory);
VkFenceCreateInfo textureFenceCreateInfo{ VkFenceCreateInfo textureFenceCreateInfo{
@ -818,7 +829,7 @@ int main()
.image = textureImage, .image = textureImage,
.subresourceRange = { .subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = 1, .levelCount = ddsFile->header.dwMipMapCount,
.layerCount = 1 .layerCount = 1
} }
}; };
@ -828,16 +839,25 @@ int main()
.pImageMemoryBarriers = &barrierTextureImage .pImageMemoryBarriers = &barrierTextureImage
}; };
vkCmdPipelineBarrier2(textureCommandBuffer, &barrierTextureImageDependencyInfo); vkCmdPipelineBarrier2(textureCommandBuffer, &barrierTextureImageDependencyInfo);
VkBufferImageCopy copyRegion{ VkBufferImageCopy * copyRegions = NewM<VkBufferImageCopy>(ddsFile->header.dwMipMapCount);
.bufferOffset = 0, for (uint32_t level = 0; level < ddsFile->header.dwMipMapCount; level++) {
.imageSubresource{ copyRegions[level] = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .bufferOffset = mipOffsets[level],
.mipLevel = 0, .imageSubresource{
.layerCount = 1 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
}, .mipLevel = level,
.imageExtent{ .width = 858, .height = 858, .depth = 1 }, .layerCount = 1
}; },
vkCmdCopyBufferToImage(textureCommandBuffer, textureSourceBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copyRegion); .imageExtent{
.width = max(1u, ddsFile->header.dwWidth >> level),
.height = max(1u, ddsFile->header.dwHeight >> level),
.depth = 1
},
};
}
vkCmdCopyBufferToImage(textureCommandBuffer, textureSourceBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, ddsFile->header.dwMipMapCount, copyRegions);
free(mipOffsets);
free(copyRegions);
VkImageMemoryBarrier2 barrierTextureRead{ VkImageMemoryBarrier2 barrierTextureRead{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
@ -848,7 +868,7 @@ int main()
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL,
.image = textureImage, .image = textureImage,
.subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .levelCount = 1, .layerCount = 1 } .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .levelCount = ddsFile->header.dwMipMapCount, .layerCount = 1 }
}; };
VkDependencyInfo barrierTextureReadDependencyInfo{ VkDependencyInfo barrierTextureReadDependencyInfo{
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
@ -877,8 +897,11 @@ int main()
.magFilter = VK_FILTER_LINEAR, .magFilter = VK_FILTER_LINEAR,
.minFilter = VK_FILTER_LINEAR, .minFilter = VK_FILTER_LINEAR,
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
.anisotropyEnable = VK_FALSE, .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.maxLod = 1, .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.anisotropyEnable = VK_TRUE,
.maxAnisotropy = 16.0f,
.maxLod = (float)ddsFile->header.dwMipMapCount,
}; };
VK_CHECK(vkCreateSampler(device, &samplerCreateInfo, nullptr, &textureSampler)); VK_CHECK(vkCreateSampler(device, &samplerCreateInfo, nullptr, &textureSampler));
@ -1041,14 +1064,14 @@ int main()
VkVertexInputBindingDescription vertexBindingDescriptions[1]{ VkVertexInputBindingDescription vertexBindingDescriptions[1]{
{ {
.binding = 0, .binding = 0,
.stride = (3 * (sizeof (float)) * 3), .stride = ((3 + 3 + 2) * (sizeof (float))),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX .inputRate = VK_VERTEX_INPUT_RATE_VERTEX
} }
}; };
VkVertexInputAttributeDescription vertexAttributeDescriptions[3]{ VkVertexInputAttributeDescription vertexAttributeDescriptions[3]{
{ .location = 0, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = 3 * 4 * 0 }, { .location = 0, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = 3 * 4 * 0 },
{ .location = 1, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = 3 * 4 * 1 }, { .location = 1, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = 3 * 4 * 1 },
{ .location = 2, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = 3 * 4 * 2 }, { .location = 2, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = 3 * 4 * 2 },
}; };
VkPipelineVertexInputStateCreateInfo vertexInputState{ VkPipelineVertexInputStateCreateInfo vertexInputState{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
@ -1355,13 +1378,13 @@ int main()
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndexBuffer, &vertexOffset); vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndexBuffer, &vertexOffset);
VkDeviceSize indexOffset{ vertexBufferSize }; VkDeviceSize indexOffset{ vertexBufferSize };
vkCmdBindIndexBuffer(commandBuffer, vertexIndexBuffer, indexOffset, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(commandBuffer, vertexIndexBuffer, indexOffset, VK_INDEX_TYPE_UINT32);
VkDeviceSize indexCount{ 9216 }; VkDeviceSize indexCount{ 2400 };
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[MAIN_PIPELINE]); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[MAIN_PIPELINE]);
vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0); vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[OUTLINE_PIPELINE]); //vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[OUTLINE_PIPELINE]);
vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0); //vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0);
vkCmdEndRendering(commandBuffer); vkCmdEndRendering(commandBuffer);