diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 779d3a5..1bcf204 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -74,7 +74,9 @@ enum class AlphaTestMode : uint32_t struct SharedConstants { - uint32_t textureIndices[16]{}; + uint32_t texture2DIndices[16]{}; + uint32_t texture3DIndices[16]{}; + uint32_t textureCubeIndices[16]{}; uint32_t samplerIndices[16]{}; AlphaTestMode alphaTestMode{}; float alphaThreshold{}; @@ -169,10 +171,18 @@ static GuestSurface* g_backBuffer; struct std::unique_ptr g_textureDescriptorSet; struct std::unique_ptr g_samplerDescriptorSet; +enum +{ + TEXTURE_DESCRIPTOR_NULL_TEXTURE_2D, + TEXTURE_DESCRIPTOR_NULL_TEXTURE_3D, + TEXTURE_DESCRIPTOR_NULL_TEXTURE_CUBE, + TEXTURE_DESCRIPTOR_NULL_COUNT +}; + struct TextureDescriptorAllocator { Mutex mutex; - uint32_t capacity = 0; + uint32_t capacity = TEXTURE_DESCRIPTOR_NULL_COUNT; std::vector freed; uint32_t allocate() @@ -187,7 +197,8 @@ struct TextureDescriptorAllocator } else { - value = ++capacity; + value = capacity; + ++capacity; } return value; @@ -201,6 +212,9 @@ struct TextureDescriptorAllocator } }; +static std::unique_ptr g_blankTextures[TEXTURE_DESCRIPTOR_NULL_COUNT]; +static std::unique_ptr g_blankTextureViews[TEXTURE_DESCRIPTOR_NULL_COUNT]; + static TextureDescriptorAllocator g_textureDescriptorAllocator; static std::unique_ptr g_pipelineLayout; @@ -845,7 +859,55 @@ static void CreateHostDevice() descriptorSetBuilder.end(true, TEXTURE_DESCRIPTOR_SIZE); g_textureDescriptorSet = descriptorSetBuilder.create(g_device.get()); - g_textureDescriptorSet->setTexture(0, nullptr, RenderTextureLayout::SHADER_READ); + + for (size_t i = 0; i < TEXTURE_DESCRIPTOR_NULL_COUNT; i++) + { + auto& texture = g_blankTextures[i]; + auto& textureView = g_blankTextureViews[i]; + + RenderTextureDesc desc; + desc.width = 1; + desc.height = 1; + desc.depth = 1; + desc.mipLevels = 1; + desc.format = RenderFormat::R8_UNORM; + + RenderTextureViewDesc viewDesc; + viewDesc.format = desc.format; + viewDesc.componentMapping = RenderComponentMapping(RenderSwizzle::ZERO, RenderSwizzle::ZERO, RenderSwizzle::ZERO, RenderSwizzle::ZERO); + viewDesc.mipLevels = 1; + + switch (i) + { + case TEXTURE_DESCRIPTOR_NULL_TEXTURE_2D: + desc.dimension = RenderTextureDimension::TEXTURE_2D; + desc.arraySize = 1; + viewDesc.dimension = RenderTextureViewDimension::TEXTURE_2D; + break; + + case TEXTURE_DESCRIPTOR_NULL_TEXTURE_3D: + desc.dimension = RenderTextureDimension::TEXTURE_3D; + desc.arraySize = 1; + viewDesc.dimension = RenderTextureViewDimension::TEXTURE_3D; + break; + + case TEXTURE_DESCRIPTOR_NULL_TEXTURE_CUBE: + desc.dimension = RenderTextureDimension::TEXTURE_2D; + desc.arraySize = 6; + desc.flags = RenderTextureFlag::CUBE; + viewDesc.dimension = RenderTextureViewDimension::TEXTURE_CUBE; + break; + + default: + assert(false && "Unknown null descriptor dimension"); + break; + } + + texture = g_device->createTexture(desc); + textureView = texture->createTextureView(viewDesc); + + g_textureDescriptorSet->setTexture(i, texture.get(), RenderTextureLayout::SHADER_READ, textureView.get()); + } pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder); pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder); @@ -966,6 +1028,13 @@ static void BeginCommandList() g_backBuffer->layout = RenderTextureLayout::UNKNOWN; + for (size_t i = 0; i < 16; i++) + { + g_sharedConstants.texture2DIndices[i] = TEXTURE_DESCRIPTOR_NULL_TEXTURE_2D; + g_sharedConstants.texture3DIndices[i] = TEXTURE_DESCRIPTOR_NULL_TEXTURE_3D; + g_sharedConstants.textureCubeIndices[i] = TEXTURE_DESCRIPTOR_NULL_TEXTURE_CUBE; + } + g_sharedConstants.enableGIBicubicFiltering = (Config::GITextureFiltering == EGITextureFiltering::Bicubic); auto& commandList = g_commandLists[g_frame]; @@ -990,6 +1059,12 @@ static uint32_t CreateDevice(uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, BeginCommandList(); + RenderTextureBarrier blankTextureBarriers[TEXTURE_DESCRIPTOR_NULL_COUNT]; + for (size_t i = 0; i < TEXTURE_DESCRIPTOR_NULL_COUNT; i++) + blankTextureBarriers[i] = RenderTextureBarrier(g_blankTextures[i].get(), RenderTextureLayout::SHADER_READ); + + g_commandLists[g_frame]->barriers(RenderBarrierStage::NONE, blankTextureBarriers, std::size(blankTextureBarriers)); + auto device = g_userHeap.AllocPhysical(); memset(device, 0, sizeof(*device)); @@ -1424,6 +1499,7 @@ static GuestTexture* CreateTexture(uint32_t width, uint32_t height, uint32_t dep texture->height = height; texture->depth = depth; texture->format = desc.format; + texture->viewDimension = viewDesc.dimension; texture->descriptorIndex = g_textureDescriptorAllocator.allocate(); g_textureDescriptorSet->setTexture(texture->descriptorIndex, texture->texture, RenderTextureLayout::SHADER_READ, texture->textureView.get()); @@ -1862,7 +1938,17 @@ static void ProcSetTexture(const RenderCommand& cmd) const auto& args = cmd.setTexture; AddBarrier(args.texture, RenderTextureLayout::SHADER_READ); - SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.textureIndices[args.index], args.texture != nullptr ? args.texture->descriptorIndex : NULL); + + auto viewDimension = args.texture != nullptr ? args.texture->viewDimension : RenderTextureViewDimension::UNKNOWN; + + SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.texture2DIndices[args.index], + viewDimension == RenderTextureViewDimension::TEXTURE_2D ? args.texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_2D); + + SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.texture3DIndices[args.index], args.texture != nullptr && + viewDimension == RenderTextureViewDimension::TEXTURE_3D ? args.texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_3D); + + SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.textureCubeIndices[args.index], args.texture != nullptr && + viewDimension == RenderTextureViewDimension::TEXTURE_CUBE ? args.texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_CUBE); } static void SetScissorRect(GuestDevice* device, GuestRect* rect) @@ -3172,6 +3258,8 @@ static void MakePictureData(GuestPictureData* pictureData, uint8_t* data, uint32 texture->descriptorIndex = g_textureDescriptorAllocator.allocate(); g_textureDescriptorSet->setTexture(texture->descriptorIndex, texture->texture, RenderTextureLayout::SHADER_READ, texture->textureView.get()); + texture->viewDimension = viewDesc.dimension; + struct Slice { uint32_t width; @@ -3261,6 +3349,7 @@ static void MakePictureData(GuestPictureData* pictureData, uint8_t* data, uint32 const auto texture = g_userHeap.AllocPhysical(ResourceType::Texture); texture->textureHolder = g_device->createTexture(RenderTextureDesc::Texture2D(width, height, 1, RenderFormat::R8G8B8A8_UNORM)); texture->texture = texture->textureHolder.get(); + texture->viewDimension = RenderTextureViewDimension::TEXTURE_2D; texture->layout = RenderTextureLayout::COPY_DEST; texture->descriptorIndex = g_textureDescriptorAllocator.allocate(); diff --git a/UnleashedRecomp/gpu/video.h b/UnleashedRecomp/gpu/video.h index ca12711..48b324e 100644 --- a/UnleashedRecomp/gpu/video.h +++ b/UnleashedRecomp/gpu/video.h @@ -118,6 +118,7 @@ struct GuestBaseTexture : GuestResource struct GuestTexture : GuestBaseTexture { uint32_t depth = 0; + RenderTextureViewDimension viewDimension = RenderTextureViewDimension::UNKNOWN; void* mappedMemory = nullptr; std::unique_ptr framebuffer; }; diff --git a/thirdparty/ShaderRecomp b/thirdparty/ShaderRecomp index 25b4f60..5f6a8e6 160000 --- a/thirdparty/ShaderRecomp +++ b/thirdparty/ShaderRecomp @@ -1 +1 @@ -Subproject commit 25b4f604af274645255fa8afc7455b3b77bc5f3d +Subproject commit 5f6a8e6c2ad2a1dfc94a5196d5437176ea0a78db