diff --git a/Makefile b/Makefile index 2d1f575..9183de2 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,8 @@ OBJS = \ src/main.o \ src/volk/volk.o \ src/file.o \ - src/pack.o + src/pack.o \ + src/dds_validate.o ifeq ($(UNAME),Darwin) LIBS = \ diff --git a/checker.dds b/checker.dds new file mode 100644 index 0000000..694ad56 Binary files /dev/null and b/checker.dds differ diff --git a/checker.idx b/checker.idx new file mode 100644 index 0000000..a4762df Binary files /dev/null and b/checker.idx differ diff --git a/checker.vtx b/checker.vtx new file mode 100644 index 0000000..2d05491 Binary files /dev/null and b/checker.vtx differ diff --git a/filenames.txt b/filenames.txt index f07897c..01b8172 100644 --- a/filenames.txt +++ b/filenames.txt @@ -1,4 +1,6 @@ shader/triangle.spv -index.idx -position_normal_texture.vtx +checker.idx +checker.vtx +checker.data +checker.dds sprite.data diff --git a/include/dds.h b/include/dds.h new file mode 100644 index 0000000..456ffde --- /dev/null +++ b/include/dds.h @@ -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 diff --git a/include/dds_validate.h b/include/dds_validate.h new file mode 100644 index 0000000..4c96346 --- /dev/null +++ b/include/dds_validate.h @@ -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); diff --git a/shader/triangle.hlsl b/shader/triangle.hlsl index 3cb3d53..d47a4dd 100644 --- a/shader/triangle.hlsl +++ b/shader/triangle.hlsl @@ -33,7 +33,7 @@ VSOutput VSMain(VSInput input) VSOutput output = (VSOutput)0; output.Position = mul(data.Transform, float4(input.Position.xyz, 1.0)); 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)); output.LightDirection = (data.LightPosition - viewPosition).xyz; @@ -56,6 +56,8 @@ float4 PSMain(VSOutput input) : SV_TARGET const float specularIntensity = 0.8; float3 specular = pow(max(dot(R, V), 0), a) * specularIntensity; float3 diffuse = max(dot(N, L), 0.001); + diffuse = 1.0; + specular = 0.0; return float4(diffuse * color + specular, 1.0); } diff --git a/src/dds_validate.cpp b/src/dds_validate.cpp new file mode 100644 index 0000000..3e99edd --- /dev/null +++ b/src/dds_validate.cpp @@ -0,0 +1,91 @@ +#include +#include + +#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(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; +} diff --git a/src/main.cpp b/src/main.cpp index feb7c22..bed4345 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,7 @@ #include "new.h" #include "file.h" +#include "dds_validate.h" template inline static constexpr T min(T a, T b) @@ -216,7 +217,7 @@ float theta = 0; XMMATRIX currentModel() { 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) @@ -446,6 +447,8 @@ int main() printf(" maxSamplerAllocationCount %u\n", properties.properties.limits.maxSamplerAllocationCount); printf(" nonCoherentAtomSize %lu\n", properties.properties.limits.nonCoherentAtomSize); 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; } } @@ -586,9 +589,9 @@ int main() { uint32_t vertexSize; - void const * vertexStart = file::open("position_normal_texture.vtx", &vertexSize); + void const * vertexStart = file::open("checker.vtx", &vertexSize); uint32_t indexSize; - void const * indexStart = file::open("index.idx", &indexSize); + void const * indexStart = file::open("checker.idx", &indexSize); vertexBufferSize = vertexSize; indexBufferSize = indexSize; @@ -709,14 +712,25 @@ int main() // 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 }; VkImageCreateInfo textureImageCreateInfo{ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .imageType = VK_IMAGE_TYPE_2D, .format = textureFormat, - .extent = {.width = 858, .height = 858, .depth = 1 }, - .mipLevels = 1, + .extent = { + .width = ddsFile->header.dwWidth, + .height = ddsFile->header.dwHeight, + .depth = 1 + }, + .mipLevels = ddsFile->header.dwMipMapCount, .arrayLayers = 1, .samples = VK_SAMPLE_COUNT_1_BIT, .tiling = VK_IMAGE_TILING_OPTIMAL, @@ -748,7 +762,7 @@ int main() .format = textureFormat, .subresourceRange{ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .levelCount = 1, + .levelCount = ddsFile->header.dwMipMapCount, .layerCount = 1 } }; @@ -756,13 +770,10 @@ int main() // texture transfer: source buffer - uint32_t spriteSize; - void const * spriteStart = file::open("sprite.data", &spriteSize); - VkBuffer textureSourceBuffer{}; VkBufferCreateInfo textureSourceBufferCreateInfo{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = spriteSize, + .size = checkerDataSize, .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT }; VK_CHECK(vkCreateBuffer(device, &textureSourceBufferCreateInfo, nullptr, &textureSourceBuffer)); @@ -783,7 +794,7 @@ int main() void * 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); VkFenceCreateInfo textureFenceCreateInfo{ @@ -818,7 +829,7 @@ int main() .image = textureImage, .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .levelCount = 1, + .levelCount = ddsFile->header.dwMipMapCount, .layerCount = 1 } }; @@ -828,16 +839,25 @@ int main() .pImageMemoryBarriers = &barrierTextureImage }; vkCmdPipelineBarrier2(textureCommandBuffer, &barrierTextureImageDependencyInfo); - VkBufferImageCopy copyRegion{ - .bufferOffset = 0, - .imageSubresource{ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .layerCount = 1 - }, - .imageExtent{ .width = 858, .height = 858, .depth = 1 }, - }; - vkCmdCopyBufferToImage(textureCommandBuffer, textureSourceBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region); + VkBufferImageCopy * copyRegions = NewM(ddsFile->header.dwMipMapCount); + for (uint32_t level = 0; level < ddsFile->header.dwMipMapCount; level++) { + copyRegions[level] = { + .bufferOffset = mipOffsets[level], + .imageSubresource{ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = level, + .layerCount = 1 + }, + .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{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, @@ -848,7 +868,7 @@ int main() .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, .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{ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, @@ -877,8 +897,11 @@ int main() .magFilter = VK_FILTER_LINEAR, .minFilter = VK_FILTER_LINEAR, .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, - .anisotropyEnable = VK_FALSE, - .maxLod = 1, + .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .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)); @@ -1041,14 +1064,14 @@ int main() VkVertexInputBindingDescription vertexBindingDescriptions[1]{ { .binding = 0, - .stride = (3 * (sizeof (float)) * 3), + .stride = ((3 + 3 + 2) * (sizeof (float))), .inputRate = VK_VERTEX_INPUT_RATE_VERTEX } }; VkVertexInputAttributeDescription vertexAttributeDescriptions[3]{ { .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 = 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{ .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, @@ -1355,13 +1378,13 @@ int main() vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexIndexBuffer, &vertexOffset); VkDeviceSize indexOffset{ vertexBufferSize }; vkCmdBindIndexBuffer(commandBuffer, vertexIndexBuffer, indexOffset, VK_INDEX_TYPE_UINT32); - VkDeviceSize indexCount{ 9216 }; + VkDeviceSize indexCount{ 2400 }; vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[MAIN_PIPELINE]); vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0); - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[OUTLINE_PIPELINE]); - vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0); + //vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[OUTLINE_PIPELINE]); + //vkCmdDrawIndexed(commandBuffer, indexCount, 3, 0, 0, 0); vkCmdEndRendering(commandBuffer);